商户入驻后增加了设置提现模式:自动结算余额
This commit is contained in:
parent
07a420c1e6
commit
36c10c53db
@ -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();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -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._("订单低于平台最低配送金额!"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 订单总计运费
|
||||
|
||||
@ -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, "你真好看!");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user