商户入驻后增加了设置提现模式:自动结算余额

This commit is contained in:
Jack 2025-09-26 08:58:47 +08:00
parent 07a420c1e6
commit 36c10c53db
6 changed files with 298 additions and 39 deletions

View File

@ -50,4 +50,19 @@ public interface AccountBaseConfigService extends IBaseService<AccountBaseConfig
boolean saveOrUpdate(Collection<AccountBaseConfig> configs);
boolean saveOrUpdate(AccountBaseConfig config);
/**
* 获取系统配置
*
* @param configKey
* @return
*/
String getSystemConfig(String configKey);
/**
* 获取平台内部最低配送费单位
*
* @return
*/
Integer getInnerMinDeliveryFee();
}

View File

@ -56,4 +56,33 @@ public interface ShopBaseDistrictService extends IBaseService<ShopBaseDistrict>
*/
String joinDistrict(List<ShopBaseDistrict> list, Integer joinKey, Boolean hasSeparator, String separator);
/**
* 省市区ID路径和名称路径相互转换
* 支持根据ID路径获取名称路径或根据名称路径获取ID路径
*
* @param areaIds 省市区ID路径格式如"450000/450800/450881"
* @param areaNames 省市区名称路径格式如"广西壮族自治区/贵港市/桂平市"
* @return String数组第一个元素为处理后的ID路径第二个元素为处理后的名称路径
*/
String[] convertDistrictPath(String areaIds, String areaNames);
/**
* 根据省市区ID路径获取对应的名称路径
* 例如450000/450800/450881 -> 广西壮族自治区/贵港市/桂平市
*
* @param districtIdPath 省市区ID路径格式如"450000/450800/450881"
* @return 省市区名称路径格式如"广西壮族自治区/贵港市/桂平市"
*/
String getDistrictNamePathByIdPath(String districtIdPath);
/**
* 根据省市区名称路径获取对应的ID路径
* 例如广西壮族自治区/贵港市/桂平市 -> 450000/450800/450881
*
* @param districtNamePath 省市区名称路径格式如"省/市/区"
* @return 省市区ID路径格式如"450000/450800/450881"
*/
String getDistrictIdPathByNamePath(String districtNamePath);
}

View File

@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.suisung.mall.common.constant.CommonConstant;
import com.suisung.mall.common.constant.ConfigConstant;
import com.suisung.mall.common.constant.RedisConstant;
import com.suisung.mall.common.exception.ApiException;
@ -341,6 +342,44 @@ public class AccountBaseConfigServiceImpl extends BaseServiceImpl<AccountBaseCon
return saveOrUpdate(configs);
}
/**
* 获取系统配置值
* <p>
* 根据配置键获取对应的配置值如果配置值为空则返回空字符串
* </p>
*
* @param configKey 配置键
* @return 配置值如果找不到或为空则返回空字符串
*/
@Override
public String getSystemConfig(String configKey) {
// 参数校验
if (StrUtil.isBlank(configKey)) {
log.warn("[系统配置] 参数校验失败:配置键不能为空");
return "";
}
try {
String configValue = accountService.getAccountBaseConfigValue(configKey);
return StrUtil.blankToDefault(configValue, "0");
} catch (Exception e) {
log.error("[系统配置] 获取配置值异常configKey={}", configKey, e);
return "";
}
}
/**
* 获取平台内部最低配送费单位
*
* @return
*/
@Override
public Integer getInnerMinDeliveryFee() {
String v = getSystemConfig(CommonConstant.Inner_Min_DeliveryFee_Key);
return NumberUtil.isNumber(v) ? Convert.toInt(v) : 0;
}
@Override
@Async
public void run(String... args) throws Exception {

View File

@ -13,6 +13,7 @@ import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.base.mapper.ShopBaseDistrictMapper;
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
import com.suisung.mall.shop.base.service.ShopBaseDistrictService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
@ -30,6 +31,7 @@ import java.util.*;
* @author Xinze
* @since 2021-06-28
*/
@Slf4j
@Service
public class ShopBaseDistrictServiceImpl extends BaseServiceImpl<ShopBaseDistrictMapper, ShopBaseDistrict> implements ShopBaseDistrictService {
@ -339,4 +341,204 @@ public class ShopBaseDistrictServiceImpl extends BaseServiceImpl<ShopBaseDistric
return district_id_row;
}
/**
* 省市区ID路径和名称路径相互转换
* 支持根据ID路径获取名称路径或根据名称路径获取ID路径
*
* @param areaIds 省市区ID路径格式如"450000/450800/450881"
* @param areaNames 省市区名称路径格式如"广西壮族自治区/贵港市/桂平市"
* @return String数组第一个元素为处理后的ID路径第二个元素为处理后的名称路径
*/
@Override
public String[] convertDistrictPath(String areaIds, String areaNames) {
// 参数校验至少一个参数不能为空
if (StrUtil.isBlank(areaIds) && StrUtil.isBlank(areaNames)) {
log.warn("[地区转换] 参数校验失败areaIds和areaNames不能同时为空");
return new String[]{"", ""};
}
try {
String resultAreaIds = areaIds;
String resultAreaNames = areaNames;
// 如果两个参数都有值直接返回原始值
if (StrUtil.isNotBlank(areaIds) && StrUtil.isNotBlank(areaNames)) {
log.debug("[地区转换] 两个参数都有值,直接返回原始值: areaIds={}, areaNames={}", areaIds, areaNames);
return new String[]{resultAreaIds, resultAreaNames};
}
// 如果只有areaIds不为空根据ID路径获取名称路径
if (StrUtil.isNotBlank(areaIds)) {
log.debug("[地区转换] 根据ID路径获取名称路径: {}", areaIds);
resultAreaNames = getDistrictNamePathByIdPath(areaIds);
}
// 如果只有areaNames不为空根据名称路径获取ID路径
if (StrUtil.isNotBlank(areaNames)) {
log.debug("[地区转换] 根据名称路径获取ID路径: {}", areaNames);
resultAreaIds = getDistrictIdPathByNamePath(areaNames);
}
return new String[]{resultAreaIds, resultAreaNames};
} catch (Exception e) {
log.error("[地区转换] 转换过程中发生异常", e);
return new String[]{"", ""};
}
}
/**
* 根据省市区ID路径获取对应的名称路径
* 例如450000/450800/450881 -> 广西壮族自治区/贵港市/桂平市
*
* @param districtIdPath 省市区ID路径格式如"450000/450800/450881"
* @return 省市区名称路径格式如"广西壮族自治区/贵港市/桂平市"
*/
@Override
public String getDistrictNamePathByIdPath(String districtIdPath) {
if (StrUtil.isBlank(districtIdPath)) {
return "";
}
String[] idStrs = districtIdPath.split("/");
List<String> names = new ArrayList<>(idStrs.length);
List<ShopBaseDistrict> districts = new ArrayList<>(idStrs.length);
// 先获取所有地区对象
for (String idStr : idStrs) {
Integer districtId = Convert.toInt(idStr);
if (districtId == null) {
log.warn("[地区转换] ID格式不正确: {}", idStr);
return "";
}
ShopBaseDistrict district = get(districtId);
if (district == null) {
log.warn("[地区转换] 未找到对应地区信息, districtId: {}", districtId);
return "";
}
districts.add(district);
}
// 按照层级关系重新排序
List<ShopBaseDistrict> sortedDistricts = sortDistrictsByHierarchy(districts);
// 提取名称
for (ShopBaseDistrict district : sortedDistricts) {
names.add(district.getDistrict_name());
}
return String.join("/", names);
}
/**
* 根据省市区名称路径获取对应的ID路径
* 例如广西壮族自治区/贵港市/桂平市 -> 450000/450800/450881
*
* @param districtNamePath 省市区名称路径格式如"省/市/区"
* @return 省市区ID路径格式如"450000/450800/450881"
*/
@Override
public String getDistrictIdPathByNamePath(String districtNamePath) {
if (StrUtil.isBlank(districtNamePath)) {
return "";
}
String[] names = districtNamePath.split("/");
List<ShopBaseDistrict> districts = new ArrayList<>(names.length);
// 先根据名称获取所有地区对象不考虑顺序
for (String name : names) {
if (StrUtil.isBlank(name)) {
log.warn("[地区转换] 名称不能为空");
return "";
}
QueryWrapper<ShopBaseDistrict> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("district_name", name.trim());
ShopBaseDistrict district = findOne(queryWrapper);
if (district == null) {
log.warn("[地区转换] 未找到对应地区信息, name: {}", name);
return "";
}
districts.add(district);
}
// 按照层级关系重新排序
List<ShopBaseDistrict> sortedDistricts = sortDistrictsByHierarchy(districts);
// 提取ID
List<String> ids = new ArrayList<>(sortedDistricts.size());
for (ShopBaseDistrict district : sortedDistricts) {
ids.add(district.getDistrict_id().toString());
}
return String.join("/", ids);
}
/**
* 根据层级关系对地区进行排序
*
* @param districts 地区列表
* @return 按层级排序后的地区列表
*/
private List<ShopBaseDistrict> sortDistrictsByHierarchy(List<ShopBaseDistrict> districts) {
if (districts.size() <= 1) {
return districts;
}
// 构建ID到地区的映射
Map<Integer, ShopBaseDistrict> districtMap = new HashMap<>();
for (ShopBaseDistrict district : districts) {
districtMap.put(district.getDistrict_id(), district);
}
// 构建层级关系
List<ShopBaseDistrict> result = new ArrayList<>(districts.size());
Set<Integer> processedIds = new HashSet<>();
// 找到最顶级的地区parent_id为0或者parent不在列表中的
for (ShopBaseDistrict district : districts) {
if (district.getDistrict_parent_id() == 0 || !districtMap.containsKey(district.getDistrict_parent_id())) {
result.add(district);
processedIds.add(district.getDistrict_id());
break;
}
}
// 逐级查找子地区
while (result.size() < districts.size()) {
ShopBaseDistrict lastDistrict = result.get(result.size() - 1);
boolean found = false;
for (ShopBaseDistrict district : districts) {
if (!processedIds.contains(district.getDistrict_id()) &&
district.getDistrict_parent_id().equals(lastDistrict.getDistrict_id())) {
result.add(district);
processedIds.add(district.getDistrict_id());
found = true;
break;
}
}
// 如果找不到下一级则添加剩余未处理的地区
if (!found) {
for (ShopBaseDistrict district : districts) {
if (!processedIds.contains(district.getDistrict_id())) {
result.add(district);
processedIds.add(district.getDistrict_id());
}
}
break;
}
}
return result;
}
}

View File

@ -2653,12 +2653,24 @@ public class ShopUserCartServiceImpl extends BaseServiceImpl<ShopUserCartMapper,
store_row.put("freight", freight); // 运费金额
store_row.put("postFreeBalance", postFreeBalance); // 还需postFreeBalance元即可免邮费
// 订单的总运费 + 本次订单的运费
// 订单的总金额 + 本次订单的运费
orderSelFreightAmount = orderSelFreightAmount.add(Convert.toBigDecimal(sameCityDeliveryFeeResp.getDeliveryFee())); // 重要订单运费金额
if (canDelivery) {
// 如果能配送最终支付金额+本次订单的运费
orderSelMoneyAmount = orderSelMoneyAmount.add(freight);// 重要
}
// RMK 平台最低配送费单位add:2025-09-26
Integer innerMinDeliverFee = accountBaseConfigService.getInnerMinDeliveryFee();
if (canThrow
&& CheckUtil.isNotEmpty(innerMinDeliverFee)
&& CheckUtil.isNotEmpty(orderSelMoneyAmount)
&& orderSelMoneyAmount.multiply(BigDecimal.valueOf(100)).compareTo(BigDecimal.valueOf(innerMinDeliverFee)) <= 0) {
logger.warn("[订单校验] 订单金额低于平台最低配送金额,订单金额:{}分,最低配送金额:{}分",
orderSelMoneyAmount.multiply(BigDecimal.valueOf(100)).longValue(), innerMinDeliverFee);
throw new ApiException(I18nUtil._("订单低于平台最低配送金额!"));
}
}
// 订单总计运费

View File

@ -1,38 +0,0 @@
package com.suisung.mall.shop;
import com.suisung.mall.common.constant.MqConstant;
import com.suisung.mall.shop.message.service.MqMessageService;
import com.suisung.mall.shop.order.service.ShopOrderBaseService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MallProductApplicationTests {
@Autowired
ShopOrderBaseService shopOrderBaseService;
@Autowired
private MqMessageService mqMessageService;
@Test
void contextLoads() {
}
/**
* 自动确认收货测试
*/
@Test
public void receiveTest() {
shopOrderBaseService.autoReceive();
}
@Test
public void test01() {
mqMessageService.sendMqMsg(MqConstant.SHOP_EXCHANGE, MqConstant.SHOP_MSG_ROUTING_KEY, "你真好看!");
}
}