feat(quotation): 支持多区域报价功能及相关数据结构扩展

- 在AdminRoleService及Mapper中新增hasBindCode方法,判断用户角色绑定状态
- AdminUserVO中添加区域id列表areaIds属性并赋值
- 方案默认系数接口调整为返回区域比例列表DefaultRatioVO
- PlanSearchItemVO新增areaId字段支持区域区分
- 方案查询中根据用户角色判断多区域报价权限,区分不同区域报价价格设定
- 添加canMultiRegionQuotations接口以校验用户多区域报价权限
- QuotationUserPlanDefault及QuotationUserPlanModelItem实体类新增areaId字段
- 相关SQL查询语句增加area_id字段处理
- 重构报价方案业务逻辑,兼容多区域报价的价格和数据聚合处理
This commit is contained in:
曹鹏飞 2026-05-14 18:10:15 +08:00
parent 3cc0019d98
commit dd1eebafaa
12 changed files with 131 additions and 16 deletions

View File

@ -96,5 +96,10 @@ public class AdminUserVO {
*/
private String categoryName;
/**
* 区域id列表
*/
private List<Integer> areaIds;
private List<AdminUserVO> children = new ArrayList<>();
}

View File

@ -38,6 +38,11 @@ public class PlanSearchItemVO {
@NotNull
private BigDecimal ratio;
/**
* 区域国内/国外字典id
*/
private Long areaId;
/**
* 是否默认
*/

View File

@ -11,6 +11,7 @@ import com.nflg.mobilebroken.common.pojo.vo.ModelPriceVO;
import com.nflg.mobilebroken.common.pojo.vo.PlanSearchItemVO;
import com.nflg.mobilebroken.common.util.*;
import com.nflg.mobilebroken.quotation.controller.ControllerBase;
import com.nflg.mobilebroken.quotation.pojo.vo.DefaultRatioVO;
import com.nflg.mobilebroken.quotation.pojo.vo.PlanSearchVO;
import com.nflg.mobilebroken.quotation.pojo.vo.QuotationModelRatioVO;
import com.nflg.mobilebroken.repository.entity.*;
@ -60,16 +61,29 @@ public class PlanController extends ControllerBase {
@Resource
private IQuotationModelRatioDirectItemService ratioDirectItemService;
@Resource
private IAdminRoleService adminRoleService;
@Resource
private IDictionaryItemService dictionaryItemService;
/**
* 获取方案默认系数
*/
@GetMapping("/getDefaultRatio")
public ApiResult<BigDecimal> getDefaultRatio() {
QuotationUserPlanDefault planDefault = planDefaultService.lambdaQuery()
.eq(QuotationUserPlanDefault::getCreateByType, AppUserUtil.isAgent() ? 1 : 0)
.eq(QuotationUserPlanDefault::getCreateById, AppUserUtil.getUserId())
.one();
return ApiResult.success(Objects.isNull(planDefault) ? null : planDefault.getRatio());
public ApiResult<List<DefaultRatioVO>> getDefaultRatio() {
return ApiResult.success(
planDefaultService.lambdaQuery()
.eq(QuotationUserPlanDefault::getCreateByType, AppUserUtil.isAgent() ? 1 : 0)
.eq(QuotationUserPlanDefault::getCreateById, AppUserUtil.getUserId())
.list()
.stream()
.map(pd -> new DefaultRatioVO()
.setAreaId(pd.getAreaId())
.setRatio(pd.getRatio())
)
.collect(Collectors.toList())
);
}
/**
@ -120,15 +134,38 @@ public class PlanController extends ControllerBase {
List<PlanSearchItemVO> datas = new ArrayList<>();
pageData.setItems(datas);
vo.setDatas(pageData);
Long categoryId = getCategoryId();
boolean multiRegionQuotations = isMultiRegionQuotationsUser();
List<Long> categoryIds = new ArrayList<>();
if (multiRegionQuotations) {
categoryIds = dictionaryItemService.getListByDictionaryCode("MultiRegionQuotationsSupplier")
.stream()
.map(DictionaryItem::getId)
.collect(Collectors.toList());
} else {
categoryIds.add(getCategoryId());
}
List<ModelPriceVO> prices = priceService.getAllModelPrice();
Map<Long, List<PlanSearchItemVO>> fgroup = items.stream().collect(Collectors.groupingBy(PlanSearchItemVO::getModelId));
for (Map.Entry<Long, List<PlanSearchItemVO>> entry : fgroup.entrySet()) {
if (index >= startIndex && index < endIndex) {
BigDecimal salePrice = getSalePrice(entry.getKey(), categoryId, prices);
entry.getValue().forEach(item -> {
item.setStandardPrice(salePrice);
datas.add(item);
categoryIds.forEach(categoryId -> {
BigDecimal salePrice = getSalePrice(entry.getKey(), categoryId, prices);
List<PlanSearchItemVO> vos = entry.getValue()
.stream()
.filter(pv -> Objects.equals(pv.getAreaId(), categoryId))
.collect(Collectors.toList());
if (CollectionUtil.isEmpty(vos)) {
entry.getValue().forEach(item -> {
item.setStandardPrice(salePrice);
item.setAreaId(categoryId);
datas.add(item);
});
} else {
vos.forEach(item -> {
item.setStandardPrice(salePrice);
datas.add(item);
});
}
});
}
}
@ -235,8 +272,8 @@ public class PlanController extends ControllerBase {
List<QuotationUserPlanModelItem> items = Objects.isNull(planId)
? new ArrayList<>()
: planModelItemService.lambdaQuery()
.eq(QuotationUserPlanModelItem::getPlanId, planId)
.list();
.eq(QuotationUserPlanModelItem::getPlanId, planId)
.list();
if (Objects.nonNull(planId)) {
QuotationUserPlanModel oldPlan = planModelService.getById(planId);
planModelService.lambdaUpdate()
@ -298,4 +335,20 @@ public class PlanController extends ControllerBase {
planModelItemService.saveBatch(items);
return ApiResult.success();
}
/**
* 当前用户是否可以多区域报价
*/
@GetMapping("/canMultiRegionQuotations")
public ApiResult<Boolean> canMultiRegionQuotations() {
return ApiResult.success(isMultiRegionQuotationsUser());
}
private Boolean isMultiRegionQuotationsUser() {
if (AppUserUtil.isAgent() || AppUserUtil.isEndUser()) {
return false;
} else {
return adminRoleService.hasBindCode(AppUserUtil.getUserId(), "MultiRegionQuotationsSupplier");
}
}
}

View File

@ -0,0 +1,21 @@
package com.nflg.mobilebroken.quotation.pojo.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@Data
@Accessors(chain = true)
public class DefaultRatioVO {
/**
* 比例
*/
private BigDecimal ratio;
/**
* 区域国内/国外字典id
*/
private Long areaId;
}

View File

@ -31,6 +31,11 @@ public class QuotationUserPlanDefault implements Serializable {
*/
private BigDecimal ratio;
/**
* 区域国内/国外字典id
*/
private Long areaId;
/**
* 用户类型0内部人员1代理商
*/

View File

@ -46,6 +46,11 @@ public class QuotationUserPlanModelItem implements Serializable {
*/
private BigDecimal ratio;
/**
* 区域国内/国外字典id
*/
private Long areaId;
/**
* 是否默认
*/

View File

@ -28,4 +28,6 @@ public interface AdminRoleMapper extends BaseMapper<AdminRole> {
IPage<RoleVO> search(RoleSearchRequest request, Page<?> page);
List<ButtonVO> getButtonsByMenuId(Integer userId,Long menuId);
Boolean hasBindCode(Integer userId, String roleCode);
}

View File

@ -36,4 +36,6 @@ public interface IAdminRoleService extends IService<AdminRole> {
IPage<RoleVO> search(RoleSearchRequest request);
List<ButtonVO> getButtonsByMenuId(Integer userId,Long menuId);
Boolean hasBindCode(Integer userId, String roleCode);
}

View File

@ -113,4 +113,9 @@ public class AdminRoleServiceImpl extends ServiceImpl<AdminRoleMapper, AdminRole
public List<ButtonVO> getButtonsByMenuId(Integer userId,Long menuId) {
return baseMapper.getButtonsByMenuId(userId,menuId);
}
@Override
public Boolean hasBindCode(Integer userId, String roleCode) {
return baseMapper.hasBindCode(userId, roleCode);
}
}

View File

@ -255,7 +255,8 @@ public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUser
.filter(r -> rmaps.contains(r.getId()))
.map(r -> new RoleSimpleVO().setId(r.getId()).setName(r.getName()))
.collect(Collectors.toSet())
);
)
.setAreaIds(Arrays.stream(StrUtil.splitToInt(u.getAreaIds(),",")).boxed().collect(Collectors.toList()));
}).collect(Collectors.toList()));
return pageData;
}

View File

@ -52,4 +52,13 @@
INNER JOIN admin_user_role_map urm ON urm.role_id=r.id
WHERE mb.`enable`=1 AND mb.menu_id=#{menuId} AND urm.user_id=#{userId}
</select>
<select id="hasBindCode" resultType="java.lang.Boolean">
SELECT EXISTS(
SELECT 1
FROM admin_user_role_map aurm
INNER JOIN admin_role ar ON aurm.role_id=ar.id
WHERE aurm.user_id=#{userId} AND ar.code=#{roleCode}
)
</select>
</mapper>

View File

@ -10,11 +10,13 @@
</select>
<select id="search" resultType="com.nflg.mobilebroken.common.pojo.vo.PlanSearchItemVO">
SELECT qupmi.id,qupmi.plan_id,pm.batch_number as 'modelId',pm.`no` as 'modelNo',qupmi.`name`,qupmi.ratio,qupmi.is_default
SELECT qupmi.id,qupmi.plan_id,pm.batch_number as 'modelId',pm.`no` as
'modelNo',qupmi.`name`,qupmi.ratio,qupmi.is_default,qupmi.area_id
FROM v_quotation_model_price vqmp
inner join product_model pm on vqmp.model_id=pm.batch_number
LEFT JOIN quotation_user_plan_model_item qupmi ON qupmi.model_id=pm.batch_number
left join quotation_user_plan_model qupm on qupmi.plan_id=qupm.id and qupm.`status`=1 and qupm.create_by_type=#{userType} and qupm.create_by_id=#{userId}
left join quotation_user_plan_model qupm on qupmi.plan_id=qupm.id and qupm.`status`=1 and
qupm.create_by_type=#{userType} and qupm.create_by_id=#{userId}
WHERE pm.state=1
<if test="request.no!=null and request.no!=''">
and pm.no like CONCAT('%', #{request.no}, '%')