✨ 角色管理分页,并修复多甲方合同应收明细未生成
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+6
-4
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springblade.system.controller;
|
package org.springblade.system.controller;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
@@ -37,6 +38,7 @@ import jakarta.validation.Valid;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.springblade.core.boot.ctrl.BladeController;
|
import org.springblade.core.boot.ctrl.BladeController;
|
||||||
import org.springblade.core.cache.utils.CacheUtil;
|
import org.springblade.core.cache.utils.CacheUtil;
|
||||||
|
import org.springblade.core.mp.support.Query;
|
||||||
import org.springblade.core.secure.BladeUser;
|
import org.springblade.core.secure.BladeUser;
|
||||||
import org.springblade.core.secure.annotation.IsAdmin;
|
import org.springblade.core.secure.annotation.IsAdmin;
|
||||||
import org.springblade.core.secure.annotation.PreAuth;
|
import org.springblade.core.secure.annotation.PreAuth;
|
||||||
@@ -85,7 +87,7 @@ public class RoleController extends BladeController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 列表
|
* 分页列表(按树形根节点分页)
|
||||||
*/
|
*/
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
@Parameters({
|
@Parameters({
|
||||||
@@ -93,9 +95,9 @@ public class RoleController extends BladeController {
|
|||||||
@Parameter(name = "roleAlias", description = "角色别名", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
|
@Parameter(name = "roleAlias", description = "角色别名", in = ParameterIn.QUERY, schema = @Schema(type = "string"))
|
||||||
})
|
})
|
||||||
@ApiOperationSupport(order = 2)
|
@ApiOperationSupport(order = 2)
|
||||||
@Operation(summary = "列表", description = "传入role")
|
@Operation(summary = "分页", description = "传入role")
|
||||||
public R<List<RoleVO>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> role) {
|
public R<IPage<RoleVO>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> role, Query query) {
|
||||||
return R.data(roleService.selectList(role));
|
return R.data(roleService.selectPage(role, query));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+10
@@ -27,6 +27,7 @@ package org.springblade.system.service;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.springblade.core.mp.support.Query;
|
||||||
import org.springblade.system.pojo.entity.Role;
|
import org.springblade.system.pojo.entity.Role;
|
||||||
import org.springblade.system.pojo.vo.RoleVO;
|
import org.springblade.system.pojo.vo.RoleVO;
|
||||||
|
|
||||||
@@ -58,6 +59,15 @@ public interface IRoleService extends IService<Role> {
|
|||||||
*/
|
*/
|
||||||
List<RoleVO> selectList(Map<String, Object> role);
|
List<RoleVO> selectList(Map<String, Object> role);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色分页(按树形根节点分页,子节点随根节点返回)
|
||||||
|
*
|
||||||
|
* @param role 查询条件 Map
|
||||||
|
* @param query 分页参数
|
||||||
|
* @return 角色分页结果,非超管时仅命中当前会话租户
|
||||||
|
*/
|
||||||
|
IPage<RoleVO> selectPage(Map<String, Object> role, Query query);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义角色分页查询
|
* 自定义角色分页查询
|
||||||
*
|
*
|
||||||
|
|||||||
+22
@@ -33,6 +33,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.springblade.core.log.exception.ServiceException;
|
import org.springblade.core.log.exception.ServiceException;
|
||||||
import org.springblade.core.mp.support.Condition;
|
import org.springblade.core.mp.support.Condition;
|
||||||
|
import org.springblade.core.mp.support.Query;
|
||||||
import org.springblade.core.secure.utils.AuthUtil;
|
import org.springblade.core.secure.utils.AuthUtil;
|
||||||
import org.springblade.core.tenant.TenantGuard;
|
import org.springblade.core.tenant.TenantGuard;
|
||||||
import org.springblade.core.tool.constant.BladeConstant;
|
import org.springblade.core.tool.constant.BladeConstant;
|
||||||
@@ -92,9 +93,30 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IR
|
|||||||
public List<RoleVO> selectList(Map<String, Object> role) {
|
public List<RoleVO> selectList(Map<String, Object> role) {
|
||||||
QueryWrapper<Role> queryWrapper = Condition.getQueryWrapper(role, Role.class);
|
QueryWrapper<Role> queryWrapper = Condition.getQueryWrapper(role, Role.class);
|
||||||
applyTenantScope(queryWrapper);
|
applyTenantScope(queryWrapper);
|
||||||
|
queryWrapper.lambda().orderByAsc(Role::getSort).orderByAsc(Role::getId);
|
||||||
return RoleWrapper.build().listNodeVO(list(queryWrapper));
|
return RoleWrapper.build().listNodeVO(list(queryWrapper));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IPage<RoleVO> selectPage(Map<String, Object> role, Query query) {
|
||||||
|
List<RoleVO> tree = selectList(role);
|
||||||
|
IPage<RoleVO> page = Condition.getPage(query);
|
||||||
|
long total = tree.size();
|
||||||
|
page.setTotal(total);
|
||||||
|
if (total == 0L || page.getSize() < 1L) {
|
||||||
|
page.setRecords(Collections.emptyList());
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
int fromIndex = (int) ((page.getCurrent() - 1L) * page.getSize());
|
||||||
|
if (fromIndex >= tree.size()) {
|
||||||
|
page.setRecords(Collections.emptyList());
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
int toIndex = (int) Math.min(fromIndex + page.getSize(), tree.size());
|
||||||
|
page.setRecords(new ArrayList<>(tree.subList(fromIndex, toIndex)));
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IPage<RoleVO> selectRolePage(IPage<RoleVO> page, RoleVO role) {
|
public IPage<RoleVO> selectRolePage(IPage<RoleVO> page, RoleVO role) {
|
||||||
return page.setRecords(baseMapper.selectRolePage(page, role));
|
return page.setRecords(baseMapper.selectRolePage(page, role));
|
||||||
|
|||||||
+27
-4
@@ -1329,6 +1329,7 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 应付客商取运单选择的承运商,避免写成项目内其他承运商合同的乙方。
|
* 应付客商取运单选择的承运商,避免写成项目内其他承运商合同的乙方。
|
||||||
|
* 应收客商优先取运单客户;多方汇总名称时改用命中计费方案绑定的甲方,避免写入顿号拼接串。
|
||||||
*/
|
*/
|
||||||
private String resolveCounterpartyName(Waybill waybill, ContractManage contract, String settlementType) {
|
private String resolveCounterpartyName(Waybill waybill, ContractManage contract, String settlementType) {
|
||||||
if ("payable".equals(settlementType)) {
|
if ("payable".equals(settlementType)) {
|
||||||
@@ -1338,10 +1339,31 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
}
|
}
|
||||||
return contract == null ? null : contract.getPartyB();
|
return contract == null ? null : contract.getPartyB();
|
||||||
}
|
}
|
||||||
if (contract != null && Func.isNotEmpty(contract.getPartyA())) {
|
String waybillCustomer = trimToNull(waybill == null ? null : waybill.getCustomerName());
|
||||||
return contract.getPartyA();
|
if (waybillCustomer != null && !waybillCustomer.contains("、")) {
|
||||||
|
return waybillCustomer;
|
||||||
}
|
}
|
||||||
return waybill == null ? null : waybill.getCustomerName();
|
if (contract != null && waybill != null) {
|
||||||
|
List<Map<String, Object>> plans = billingPlansForWaybill(contract, waybill);
|
||||||
|
Map<String, Object> plan = resolveDefaultBillingPlan(plans, waybill.getTransportType());
|
||||||
|
if (plan != null) {
|
||||||
|
String planCustomer = trimToNull(stringValue(plan, "customerName"));
|
||||||
|
if (planCustomer != null) {
|
||||||
|
return planCustomer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String firstParty = ContractPartySupport.firstPartyName(contract.getPartyAJson(), null);
|
||||||
|
if (firstParty != null) {
|
||||||
|
return firstParty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (contract != null) {
|
||||||
|
String partyA = trimToNull(contract.getPartyA());
|
||||||
|
if (partyA != null && !partyA.contains("、")) {
|
||||||
|
return partyA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return waybillCustomer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1486,7 +1508,8 @@ public class ReceivablePayableDetailServiceImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String matchedPlanId(Waybill waybill, ContractManage contract) {
|
private String matchedPlanId(Waybill waybill, ContractManage contract) {
|
||||||
List<Map<String, Object>> plans = parseList(contract.getBillingPlanJson());
|
// 与费用计算共用客商过滤,避免多方汇总客户名先判定命中、再按客商滤空后静默跳过
|
||||||
|
List<Map<String, Object>> plans = billingPlansForWaybill(contract, waybill);
|
||||||
if (plans.isEmpty()) return null;
|
if (plans.isEmpty()) return null;
|
||||||
Map<String, Object> plan = resolveDefaultBillingPlan(plans, waybill.getTransportType());
|
Map<String, Object> plan = resolveDefaultBillingPlan(plans, waybill.getTransportType());
|
||||||
if (plan == null) return null;
|
if (plan == null) return null;
|
||||||
|
|||||||
+46
-5
@@ -279,10 +279,39 @@ public final class ContractPartySupport {
|
|||||||
if (plans.isEmpty()) {
|
if (plans.isEmpty()) {
|
||||||
return plans;
|
return plans;
|
||||||
}
|
}
|
||||||
|
List<Map<String, Object>> matched = matchBillingPlans(plans, customerId, customerName, partyRowId);
|
||||||
|
if (!matched.isEmpty()) {
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
// 运单客户名为合同多方汇总(顿号拼接)时,按各客商名称分别匹配绑定方案
|
||||||
|
if (Func.isEmpty(partyRowId) && customerId == null && Func.isNotEmpty(customerName) && customerName.contains("、")) {
|
||||||
|
Map<String, Map<String, Object>> deduped = new LinkedHashMap<>();
|
||||||
|
for (String part : customerName.split("、")) {
|
||||||
|
String segment = trimToNull(part);
|
||||||
|
if (Func.isEmpty(segment)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (Map<String, Object> plan : matchBillingPlans(plans, null, segment, null)) {
|
||||||
|
deduped.putIfAbsent(billingPlanKey(plan), plan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!deduped.isEmpty()) {
|
||||||
|
return new ArrayList<>(deduped.values());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 历史方案未绑定客商时,不强制过滤,避免老数据无法计费
|
||||||
|
if (plans.stream().noneMatch(ContractPartySupport::hasCustomerBinding)) {
|
||||||
|
return plans;
|
||||||
|
}
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Map<String, Object>> matchBillingPlans(List<Map<String, Object>> plans, Long customerId,
|
||||||
|
String customerName, String partyRowId) {
|
||||||
String normalizedName = normalizePartyName(customerName);
|
String normalizedName = normalizePartyName(customerName);
|
||||||
String normalizedPartyRowId = trimToNull(partyRowId);
|
String normalizedPartyRowId = trimToNull(partyRowId);
|
||||||
String customerIdText = customerId == null ? null : String.valueOf(customerId);
|
String customerIdText = customerId == null ? null : String.valueOf(customerId);
|
||||||
List<Map<String, Object>> matched = plans.stream()
|
return plans.stream()
|
||||||
.filter(plan -> {
|
.filter(plan -> {
|
||||||
if (Func.isNotEmpty(normalizedPartyRowId)
|
if (Func.isNotEmpty(normalizedPartyRowId)
|
||||||
&& Objects.equals(trimToNull(plan.get("partyRowId")), normalizedPartyRowId)) {
|
&& Objects.equals(trimToNull(plan.get("partyRowId")), normalizedPartyRowId)) {
|
||||||
@@ -296,11 +325,23 @@ public final class ContractPartySupport {
|
|||||||
&& Objects.equals(normalizePartyName(trimToNull(plan.get("customerName"))), normalizedName);
|
&& Objects.equals(normalizePartyName(trimToNull(plan.get("customerName"))), normalizedName);
|
||||||
})
|
})
|
||||||
.collect(Collectors.toCollection(ArrayList::new));
|
.collect(Collectors.toCollection(ArrayList::new));
|
||||||
// 历史方案未绑定客商时,不强制过滤,避免老数据无法计费
|
}
|
||||||
if (matched.isEmpty() && plans.stream().noneMatch(ContractPartySupport::hasCustomerBinding)) {
|
|
||||||
return plans;
|
private static String billingPlanKey(Map<String, Object> plan) {
|
||||||
|
if (plan == null) {
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
return matched;
|
String id = trimToNull(plan.get("id"));
|
||||||
|
if (Func.isNotEmpty(id)) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
String planId = trimToNull(plan.get("planId"));
|
||||||
|
if (Func.isNotEmpty(planId)) {
|
||||||
|
return planId;
|
||||||
|
}
|
||||||
|
return String.valueOf(trimToNull(plan.get("customerName"))) + "|"
|
||||||
|
+ String.valueOf(trimToNull(plan.get("name"))) + "|"
|
||||||
|
+ String.valueOf(trimToNull(plan.get("planName")));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<LoadingCarrierContractVO> expandCarrierOptions(Collection<ContractManage> contracts) {
|
public static List<LoadingCarrierContractVO> expandCarrierOptions(Collection<ContractManage> contracts) {
|
||||||
|
|||||||
Reference in New Issue
Block a user