Merge branch 'dev_20260429' into dev_WMS20260401

This commit is contained in:
秦鸿展
2026-05-16 16:14:57 +08:00
9 changed files with 217 additions and 97 deletions
@@ -275,64 +275,16 @@ public class ContractManageApplicationService {
.eq(ContractManage::getTopOrganizationId, topOrganizationId)
.eq(ContractManage::getCommonContractFlag, 2));
if (UserContractManages != null && UserContractManages.size() > 0) {
}else{
//用户合同计费策略
calucateSubjectAndPriceStrategy(UserContractManages, organizationId, topOrganizationId, sunjectCode, result);
} else {
//通用合同计费策略
List<ContractManage> commonContractManages = contractManageMapper.selectList(new LambdaQueryWrapper<ContractManage>()
.eq(ContractManage::getDelFlag, 1)
.eq(ContractManage::getOrganizationId, organizationId)
.eq(ContractManage::getTopOrganizationId, topOrganizationId)
.eq(ContractManage::getCommonContractFlag, 1));
if (commonContractManages != null && commonContractManages.size() > 0) {
ContractManage contractManage = commonContractManages.get(0);
Long contractManageId = contractManage.getContractManageId();
List<ContractManageDetail> contractManageDetails = contractManageDetailMapper.selectList(new LambdaQueryWrapper<ContractManageDetail>()
.eq(ContractManageDetail::getContractManageId, contractManageId)
.eq(ContractManageDetail::getDelFlag, 1));
if (contractManageDetails != null && contractManageDetails.size() > 0) {
for (ContractManageDetail contractManageDetail : contractManageDetails) {
String code = contractManageDetail.getFirstSubjectCode();
if (sunjectCode.equals(code)) {
Long accountingStrategyId = contractManageDetail.getAccountingStrategyId();
BillingRulesPO billingRule = contractManageDetailMapper.getBillingRules(accountingStrategyId);
if (billingRule != null) {
Long billingRulesId = billingRule.getBillingRulesId();
List<BillingParamsPO> billingParams = contractManageDetailMapper.getBillingParams(billingRulesId);
if (billingParams != null && billingParams.size() > 0) {
BillingParamsPO billingParam = billingParams.get(0);
String billingParamsJson = billingParam.getBillingParamsJson();
String preSetRules = billingParam.getPreSetRules();
Long billingParamsId = billingParam.getBillingParamsId();
List<Map<String, Object>> preSetRulesList = JSON.parseObject(preSetRules, new TypeReference<List<Map<String, Object>>>() {});
List<Map<String, Object>> billingParamsList = JSON.parseObject(billingParamsJson, new TypeReference<List<Map<String, Object>>>() {});
Map<String, Object> stringObjectMap1 = preSetRulesList.get(0);
for (Map<String, Object> stringObjectMap : billingParamsList) {
String fieldsName = (String) stringObjectMap.get("fieldsName");
String isShow = (String) stringObjectMap.get("isShow");
String isFee = (String) stringObjectMap.get("isFee");
String isPush = (String) stringObjectMap.get("isPush");
if ("1".equals(isFee)) {
Integer sort = (Integer) stringObjectMap.get("sort");
String chargingId = (String) stringObjectMap.get("chargingId");
String fields = (String) stringObjectMap.get("fields");
String price = (String) stringObjectMap1.get("fields" + sort);
SubjectAndPriceReturn subjectAndPriceReturn = new SubjectAndPriceReturn();
subjectAndPriceReturn.setName(fieldsName);
subjectAndPriceReturn.setPrice(new BigDecimal(price));
subjectAndPriceReturn.setChargingId(chargingId);
subjectAndPriceReturn.setFields(fields);
subjectAndPriceReturn.setBillingRulesId(billingRulesId);
subjectAndPriceReturn.setIsShow(isShow);
subjectAndPriceReturn.setIsFee(isFee);
subjectAndPriceReturn.setIsPush(isPush);
subjectAndPriceReturn.setRulesId(billingParamsId);
result.add(subjectAndPriceReturn);
}
}
}
}
}
}
}
}
calucateSubjectAndPriceStrategy(commonContractManages, organizationId, topOrganizationId, sunjectCode, result);
}
return result;
}
@@ -509,52 +461,60 @@ public class ContractManageApplicationService {
.eq(ContractManage::getTopOrganizationId, topOrganizationId)
.eq(ContractManage::getCommonContractFlag, 2));
if (UserContractManages != null && UserContractManages.size() > 0) {
//用户合同计费策略
calucateSubjectStrategy(UserContractManages, organizationId, topOrganizationId, sunjectCode, result);
}else{
//通用合同计费策略
List<ContractManage> commonContractManages = contractManageMapper.selectList(new LambdaQueryWrapper<ContractManage>()
.eq(ContractManage::getDelFlag, 1)
.eq(ContractManage::getOrganizationId, organizationId)
.eq(ContractManage::getTopOrganizationId, topOrganizationId)
.eq(ContractManage::getCommonContractFlag, 1));
if (commonContractManages != null && commonContractManages.size() > 0) {
ContractManage contractManage = commonContractManages.get(0);
Long contractManageId = contractManage.getContractManageId();
List<ContractManageDetail> contractManageDetails = contractManageDetailMapper.selectList(new LambdaQueryWrapper<ContractManageDetail>()
.eq(ContractManageDetail::getContractManageId, contractManageId)
.eq(ContractManageDetail::getDelFlag, 1));
if (contractManageDetails != null && contractManageDetails.size() > 0) {
for (ContractManageDetail contractManageDetail : contractManageDetails) {
String code = contractManageDetail.getFirstSubjectCode();
if (sunjectCode.equals(code)) {
Long accountingStrategyId = contractManageDetail.getAccountingStrategyId();
BillingRulesPO billingRule = contractManageDetailMapper.getBillingRules(accountingStrategyId);
if (billingRule != null) {
Long billingRulesId = billingRule.getBillingRulesId();
List<BillingParamsPO> billingParams = contractManageDetailMapper.getBillingParams(billingRulesId);
if (billingParams != null && billingParams.size() > 0) {
BillingParamsPO billingParam = billingParams.get(0);
String billingParamsJson = billingParam.getBillingParamsJson();
String preSetRules = billingParam.getPreSetRules();
Long billingParamsId = billingParam.getBillingParamsId();
List<Map<String, Object>> billingParamsList = JSON.parseObject(billingParamsJson, new TypeReference<List<Map<String, Object>>>() {});
for (Map<String, Object> stringObjectMap : billingParamsList) {
String fieldsName = (String) stringObjectMap.get("fieldsName");
String isShow = (String) stringObjectMap.get("isShow");
String isFee = (String) stringObjectMap.get("isFee");
String isPush = (String) stringObjectMap.get("isPush");
if ("1".equals(isShow)) {
String chargingId = (String) stringObjectMap.get("chargingId");
String fields = (String) stringObjectMap.get("fields");
SubjectAndPriceReturn subjectAndPriceReturn = new SubjectAndPriceReturn();
subjectAndPriceReturn.setName(fieldsName);
subjectAndPriceReturn.setChargingId(chargingId);
subjectAndPriceReturn.setFields(fields);
subjectAndPriceReturn.setBillingRulesId(billingRulesId);
subjectAndPriceReturn.setIsShow(isShow);
subjectAndPriceReturn.setIsFee(isFee);
subjectAndPriceReturn.setIsPush(isPush);
subjectAndPriceReturn.setRulesId(billingParamsId);
result.add(subjectAndPriceReturn);
}
calucateSubjectStrategy(commonContractManages, organizationId, topOrganizationId, sunjectCode, result);
}
return result;
}
private void calucateSubjectStrategy(List<ContractManage> commonContractManages, Long organizationId, Long topOrganizationId, String sunjectCode, List<SubjectAndPriceReturn> result) {
if (commonContractManages != null && commonContractManages.size() > 0) {
ContractManage contractManage = commonContractManages.get(0);
Long contractManageId = contractManage.getContractManageId();
List<ContractManageDetail> contractManageDetails = contractManageDetailMapper.selectList(new LambdaQueryWrapper<ContractManageDetail>()
.eq(ContractManageDetail::getContractManageId, contractManageId)
.eq(ContractManageDetail::getDelFlag, 1));
if (contractManageDetails != null && contractManageDetails.size() > 0) {
for (ContractManageDetail contractManageDetail : contractManageDetails) {
String code = contractManageDetail.getFirstSubjectCode();
if (sunjectCode.equals(code)) {
Long accountingStrategyId = contractManageDetail.getAccountingStrategyId();
BillingRulesPO billingRule = contractManageDetailMapper.getBillingRules(accountingStrategyId);
if (billingRule != null) {
Long billingRulesId = billingRule.getBillingRulesId();
List<BillingParamsPO> billingParams = contractManageDetailMapper.getBillingParams(billingRulesId);
if (billingParams != null && billingParams.size() > 0) {
BillingParamsPO billingParam = billingParams.get(0);
String billingParamsJson = billingParam.getBillingParamsJson();
String preSetRules = billingParam.getPreSetRules();
Long billingParamsId = billingParam.getBillingParamsId();
List<Map<String, Object>> billingParamsList = JSON.parseObject(billingParamsJson, new TypeReference<List<Map<String, Object>>>() {});
for (Map<String, Object> stringObjectMap : billingParamsList) {
String fieldsName = (String) stringObjectMap.get("fieldsName");
String isShow = (String) stringObjectMap.get("isShow");
String isFee = (String) stringObjectMap.get("isFee");
String isPush = (String) stringObjectMap.get("isPush");
if ("1".equals(isShow)) {
String chargingId = (String) stringObjectMap.get("chargingId");
String fields = (String) stringObjectMap.get("fields");
SubjectAndPriceReturn subjectAndPriceReturn = new SubjectAndPriceReturn();
subjectAndPriceReturn.setName(fieldsName);
subjectAndPriceReturn.setChargingId(chargingId);
subjectAndPriceReturn.setFields(fields);
subjectAndPriceReturn.setBillingRulesId(billingRulesId);
subjectAndPriceReturn.setIsShow(isShow);
subjectAndPriceReturn.setIsFee(isFee);
subjectAndPriceReturn.setIsPush(isPush);
subjectAndPriceReturn.setRulesId(billingParamsId);
result.add(subjectAndPriceReturn);
}
}
}
@@ -563,9 +523,62 @@ public class ContractManageApplicationService {
}
}
}
return result;
}
private void calucateSubjectAndPriceStrategy(List<ContractManage> contractManages, Long organizationId, Long topOrganizationId, String sunjectCode, List<SubjectAndPriceReturn> result) {
if (contractManages != null && contractManages.size() > 0) {
ContractManage contractManage = contractManages.get(0);
Long contractManageId = contractManage.getContractManageId();
List<ContractManageDetail> contractManageDetails = contractManageDetailMapper.selectList(new LambdaQueryWrapper<ContractManageDetail>()
.eq(ContractManageDetail::getContractManageId, contractManageId)
.eq(ContractManageDetail::getDelFlag, 1));
if (contractManageDetails != null && contractManageDetails.size() > 0) {
for (ContractManageDetail contractManageDetail : contractManageDetails) {
String code = contractManageDetail.getFirstSubjectCode();
if (sunjectCode.equals(code)) {
Long accountingStrategyId = contractManageDetail.getAccountingStrategyId();
BillingRulesPO billingRule = contractManageDetailMapper.getBillingRules(accountingStrategyId);
if (billingRule != null) {
Long billingRulesId = billingRule.getBillingRulesId();
List<BillingParamsPO> billingParams = contractManageDetailMapper.getBillingParams(billingRulesId);
if (billingParams != null && billingParams.size() > 0) {
BillingParamsPO billingParam = billingParams.get(0);
String billingParamsJson = billingParam.getBillingParamsJson();
String preSetRules = billingParam.getPreSetRules();
Long billingParamsId = billingParam.getBillingParamsId();
List<Map<String, Object>> preSetRulesList = JSON.parseObject(preSetRules, new TypeReference<List<Map<String, Object>>>() {});
List<Map<String, Object>> billingParamsList = JSON.parseObject(billingParamsJson, new TypeReference<List<Map<String, Object>>>() {});
Map<String, Object> stringObjectMap1 = preSetRulesList.get(0);
for (Map<String, Object> stringObjectMap : billingParamsList) {
String fieldsName = (String) stringObjectMap.get("fieldsName");
String isShow = (String) stringObjectMap.get("isShow");
String isFee = (String) stringObjectMap.get("isFee");
String isPush = (String) stringObjectMap.get("isPush");
if ("1".equals(isFee)) {
Integer sort = (Integer) stringObjectMap.get("sort");
String chargingId = (String) stringObjectMap.get("chargingId");
String fields = (String) stringObjectMap.get("fields");
String price = (String) stringObjectMap1.get("fields" + sort);
SubjectAndPriceReturn subjectAndPriceReturn = new SubjectAndPriceReturn();
subjectAndPriceReturn.setName(fieldsName);
subjectAndPriceReturn.setPrice(new BigDecimal(price));
subjectAndPriceReturn.setChargingId(chargingId);
subjectAndPriceReturn.setFields(fields);
subjectAndPriceReturn.setBillingRulesId(billingRulesId);
subjectAndPriceReturn.setIsShow(isShow);
subjectAndPriceReturn.setIsFee(isFee);
subjectAndPriceReturn.setIsPush(isPush);
subjectAndPriceReturn.setRulesId(billingParamsId);
result.add(subjectAndPriceReturn);
}
}
}
}
}
}
}
}
}
/**
* 新增合同管理
@@ -18,9 +18,11 @@ import com.mhd.common.core.enums.DictCode;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException;
import com.mhd.common.core.exception.digitalLogisticsException.UserError;
import com.mhd.common.core.domain.po.SettlementCustomersPO;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.BmsServiceFeign;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.model.LoginUser;
import com.mhd.common.core.domain.po.UserPo;
@@ -51,12 +53,15 @@ public class ExpenseAccountApplicationService {
private ContractManageApplicationService contractManageApplicationService;
@Autowired
private SystemServiceFeign systemServiceFeign;
@Autowired
private BmsServiceFeign bmsServiceFeign;
/**
* 入库/出库费用登记等场景:按仓储合同「仓库进出仓单」结算行取科目(二级编码优先,否则一级),再关联费用科目主数据。
* <p>科目范围以合同结算设置为准;若 {@code expenseAccountDO.inOrderDisplay} 或 {@code expenseAccountDO.outOrderDisplay} 非空,
* 再按主数据「入库单是否固定显示 / 出库单是否固定显示」(0-否 1-是)与入参相等过滤,二者同时传则同时满足(AND)。</p>
* settlementCustomersCode 不传或为空时使用通用仓储合同。
* <p>若 {@code settlementCustomersCode} 为空且 {@code expenseAccountDO.settlementEntityId} 非空,则通过 BMS 按结算主体ID解析结算对象编码后再查合同(编码仍为空则走通用合同)。</p>
*/
public List<ExpenseAccountPO> queryListFromContractWarehouseInOutSettlement(ExpenseAccountDO expenseAccountDO, String settlementCustomersCode) {
Long topOrgIdForExpense = expenseAccountDO.getTopOrganizationId();
@@ -66,8 +71,15 @@ public class ExpenseAccountApplicationService {
topOrgIdForExpense = lu.getUserPo().getTopOrganizationId();
}
}
String effectiveSettlementCode = settlementCustomersCode;
if (StringUtils.isEmpty(effectiveSettlementCode) && expenseAccountDO.getSettlementEntityId() != null) {
effectiveSettlementCode = resolveSettlementCustomersCodeByEntityId(
expenseAccountDO.getSettlementEntityId(), topOrgIdForExpense);
log.info("按结算主体ID解析结算对象编码:settlementEntityId={},解析得到 settlementCustomersCode={}",
expenseAccountDO.getSettlementEntityId(), effectiveSettlementCode);
}
List<String> orderedCodes = contractManageApplicationService.listSecondSubjectCodesBySettlementAndDocumentType(
settlementCustomersCode,
effectiveSettlementCode,
expenseAccountDO.getOrganizationId(),
topOrgIdForExpense,
ContractManageApplicationService.DOCUMENT_TYPE_CODE_WAREHOUSE_IN_OUT_ORDER);
@@ -92,6 +104,27 @@ public class ExpenseAccountApplicationService {
return result;
}
/**
* 通过 BMS 按 settlement_entity_id 取结算对象编码,供合同匹配;失败返回 null(走通用合同)。
*/
private String resolveSettlementCustomersCodeByEntityId(Long settlementEntityId, Long topOrganizationId) {
try {
AjaxResult ajaxResult = bmsServiceFeign.getCustomersInfoBySettlementEntityId(settlementEntityId, topOrganizationId);
if (ajaxResult == null || !"200".equals(String.valueOf(ajaxResult.get("code"))) || ajaxResult.get("data") == null) {
log.warn("按 settlementEntityId 查询结算对象未成功:code={}", ajaxResult != null ? ajaxResult.get("code") : null);
return null;
}
SettlementCustomersPO po = JSON.parseObject(JSON.toJSONString(ajaxResult.get("data")), SettlementCustomersPO.class);
if (po == null || StringUtils.isEmpty(po.getSettlementCustomersCode())) {
return null;
}
return po.getSettlementCustomersCode().trim();
} catch (Exception e) {
log.warn("按 settlementEntityId 解析结算对象编码异常", e);
return null;
}
}
/**
* 合同路径下可选:与主数据 in_order_display / out_order_display 一致才保留(入参为 null 的维度不参与过滤)。
*/
@@ -181,4 +181,7 @@ public class ExpenseAccountDO extends BaseVOEntity{
/** 查询参数:结算主体编码(货主编码等) */
private String settlementCustomersCode;
/** 查询参数:结算主体ID(货主ID等,对应 settlement_customers.settlement_entity_id */
private Long settlementEntityId;
}
@@ -169,4 +169,11 @@ public class ExpenseAccountDTO extends BaseVOEntity{
@ApiModelProperty("结算主体编码(通常为货主编码);不传则按通用仓储合同的结算设置取科目")
private String settlementCustomersCode;
/**
* 结算主体ID(货主等业务主体ID,与 BMS settlement_customers.settlement_entity_id 一致)。
* 与 settlementCustomersCode 二选一:编码优先;仅传本字段时在 BMS 解析出结算对象编码后再走合同(有客户合同用客户,无则通用)。
*/
@ApiModelProperty("结算主体ID(货主ID等,对应 settlement_entity_id);与 settlementCustomersCode 二选一,编码优先")
private Long settlementEntityId;
}
@@ -53,6 +53,7 @@ public class ExpenseAccountApi extends BaseController{
*
* <p>入库/出库费用登记等场景传 {@code contractSettlementQuery=true}(与单据类型「仓库进出仓单」合同结算行一致),
* 科目来源、结算主体为空走通用合同等逻辑<strong>入库与出库相同</strong>。
* 可传 {@code settlementCustomersCode},或仅传 {@code settlementEntityId}(货主/结算主体ID,对应 BMS settlement_entity_id)由服务端解析结算编码后再匹配合同(有客户合同用客户,无则通用;编码优先)。
* 先按合同结算行取科目,再关联主数据;若请求中传入 {@code inOrderDisplay} 或 {@code outOrderDisplay}0-否 1-是),
* 则再按主数据「入库单 / 出库单是否固定显示」与入参相等过滤(二者都传则同时满足)。不传则不在此维度过滤。</p>
*/
@@ -70,8 +71,9 @@ public class ExpenseAccountApi extends BaseController{
if (Boolean.TRUE.equals(expenseAccountDTO.getContractSettlementQuery())) {
ExpenseAccountDO contractQueryDO = new ExpenseAccountDO();
BeanUtils.copyProperties(expenseAccountDTO, contractQueryDO);
logger.info("按合同结算设置查询费用科目,settlementCustomersCode={}inOrderDisplay={}outOrderDisplay={}",
logger.info("按合同结算设置查询费用科目,settlementCustomersCode={}settlementEntityId={}inOrderDisplay={}outOrderDisplay={}",
expenseAccountDTO.getSettlementCustomersCode(),
expenseAccountDTO.getSettlementEntityId(),
expenseAccountDTO.getInOrderDisplay(), expenseAccountDTO.getOutOrderDisplay());
List<ExpenseAccountPO> contractList =
expenseAccountApplicationService.queryListFromContractWarehouseInOutSettlement(