Merge branch 'main' into dev

This commit is contained in:
liyj 2025-12-16 15:39:04 +08:00
commit 0d58584b13
34 changed files with 1557 additions and 436 deletions

View File

@ -326,12 +326,12 @@ public interface ShopService {
/**
* 获取店铺的内部运费 shopping_fee_inner 远程调用用途
*
* @param store_id
* @param order_id
* @return
*/
@ApiOperation(value = "获取店铺的内部运费 shopping_fee_inner", notes = "获取店铺的内部运费 shopping_fee_inner (远程调用用途)")
@RequestMapping(value = "/admin/shop/shop-store-info/shopping-fee-inner", method = RequestMethod.POST)
Integer storeShoppingFeeInner(@RequestParam(name = "store_id") Integer store_id);
Integer storeShoppingFeeInner(@RequestParam(name = "order_id") String order_id);
@GetMapping(value = "/admin/shop/shop-store-employee-rights-base/queryByRightsIds")

View File

@ -0,0 +1,47 @@
package com.suisung.mall.common.pojo.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value = "OrderDeliveryInfoDTO", description = "计算订单内部配送费参数实体类")
public class OrderCacDeliveryFeeDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "订单ID")
private String order_id;
@ApiModelProperty(value = "店铺ID")
private Integer store_id;
@ApiModelProperty(value = "配送方式Id")
private Integer delivery_type_id;
@ApiModelProperty(value = "订单商品金额")
private BigDecimal order_product_amount;
@ApiModelProperty(value = "订单支付金额")
private BigDecimal order_payment_amount;
@ApiModelProperty(value = "订单折扣金额")
private BigDecimal order_discount_amount;
@ApiModelProperty(value = "订单重量(克)")
private Integer order_weight_gram;
@ApiModelProperty(value = "配送地址经度")
private String da_longitude;
@ApiModelProperty(value = "配送地址纬度")
private String da_latitude;
}

View File

@ -90,11 +90,19 @@ public class CommonService {
* @return 配送方式名称
*/
public static String getDeliveryExpressName(Integer deliveryTypeId) {
if (deliveryTypeId == null) return "其他配送";
String name = StateCode.DELIVERY_TYPE_MAP.get(deliveryTypeId);
return name != null ? name : "其他配送";
// 当配送方式ID为空时默认返回顺丰同城
if (deliveryTypeId == null) {
log.debug("配送方式ID为空返回默认配送方式顺丰同城");
return "顺丰同城";
}
// 从配送方式映射表中获取名称如果未找到则返回默认值顺丰同城
String deliveryName = StateCode.DELIVERY_TYPE_MAP.getOrDefault(deliveryTypeId, "顺丰同城");
log.debug("获取配送方式名称deliveryTypeId={} deliveryName={}", deliveryTypeId, deliveryName);
return deliveryName;
}
/**
* 判断配送方式是否为同城配送
*

View File

@ -50,9 +50,9 @@ public interface AccountBaseConfigService extends IBaseService<AccountBaseConfig
/**
* 获取店铺或平台内部最低配送费单位
*
* @param storeId 店铺Id
* @param orderId 店铺Id
* @return 配送费单位分
*/
Integer getInnerMinDeliveryFee(Integer storeId);
Integer getInnerMinDeliveryFee(String orderId);
}

View File

@ -263,27 +263,34 @@ public class AccountBaseConfigServiceImpl extends BaseServiceImpl<AccountBaseCon
/**
* 获取店铺或平台内部最低配送费单位
*
* @param storeId 店铺Id
* @param orderId 订单Id
* @return 配送费单位分
*/
@Override
public Integer getInnerMinDeliveryFee(Integer storeId) {
// 如果storeId无效直接使用平台默认配置
if (storeId == null || storeId <= 0) {
return getDefaultMinDeliveryFee();
public Integer getInnerMinDeliveryFee(String orderId) {
// 参数校验
if (StrUtil.isBlank(orderId)) {
log.warn("[内部配送费] 订单ID为空");
return 0;
}
// 获取店铺内部运费
Integer storeFee = shopService.storeShoppingFeeInner(storeId);
try {
// 获取店铺内部运费
Integer storeFee = shopService.storeShoppingFeeInner(orderId);
// 如果店铺未设置有效运费则使用平台默认配置
if (storeFee == null || storeFee <= 0) {
return getDefaultMinDeliveryFee();
// 如果店铺未设置有效运费则使用平台默认配置
if (storeFee == null || storeFee <= 0) {
return getDefaultMinDeliveryFee();
}
return storeFee;
} catch (Exception e) {
log.error("[内部配送费] 计算异常orderId: {}", orderId, e);
return 0;
}
return storeFee;
}
/**
* 获取平台默认最低配送费
*

View File

@ -250,9 +250,9 @@ public class LakalaPayServiceImpl implements LakalaPayService {
return respBody;
}
// 平台最低配送费单位
Integer innerMinDeliverFee = accountBaseConfigService.getInnerMinDeliveryFee(Convert.toInt(storeId));
reqData.set("shopping_fee_inner", innerMinDeliverFee); // 重要平台内部最低配送费单位
// 重要平台内部最低配送费单位
Integer innerMinDeliverFee = accountBaseConfigService.getInnerMinDeliveryFee(orderId);
reqData.set("shopping_fee_inner", innerMinDeliverFee);
log.info("[拉卡拉预下单] 支付成功,准备保存订单记录, orderId={}", orderId);
// 新增一个拉卡拉订单记录 shop_order_lkl

View File

@ -678,7 +678,7 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
}
// 平台最低配送费单位
Integer innerMinDeliverFee = accountBaseConfigService.getInnerMinDeliveryFee(storeId);
Integer innerMinDeliverFee = accountBaseConfigService.getInnerMinDeliveryFee(out_trade_no);
logger.debug("预支付时,查到的订单{},商家配送费:{}元,平台最低配送费要求:{}分", out_trade_no, shippingFee, innerMinDeliverFee);
// 平台最低配送费单位

View File

@ -62,8 +62,24 @@ public interface AccountBaseConfigService extends IBaseService<AccountBaseConfig
/**
* 获取店铺或平台内部最低配送费单位
*
* @param storeId 店铺Id
* @param orderId 店铺Id
* @return 配送费单位分
*/
Integer getInnerMinDeliveryFee(Integer storeId);
Integer getInnerMinDeliveryFee(String orderId);
/**
* (下单前获取店铺或平台内部最低配送费单位
*
* @param deliveryTypeId 配送方式Id
* @param storeId 店铺Id
* @param orderLongitude 订单经度
* @param orderLatitude 订单纬度
* @param orderWeightGram 订单商品重量
* @param orderProductAmount 订单商品金额
* @param orderDiscountAmount 订单优惠金额
* @param orderPayAmount 订单支付金额
* @return
*/
Integer getInnerMinDeliveryFee(Integer deliveryTypeId, Integer storeId, String orderLongitude, String orderLatitude, Integer orderWeightGram, BigDecimal orderProductAmount, BigDecimal orderDiscountAmount, BigDecimal orderPayAmount);
}

View File

@ -14,6 +14,7 @@ import com.suisung.mall.common.exception.ApiException;
import com.suisung.mall.common.feignService.AccountService;
import com.suisung.mall.common.modules.account.AccountBaseConfig;
import com.suisung.mall.common.modules.account.AccountUserInfo;
import com.suisung.mall.common.pojo.dto.OrderCacDeliveryFeeDTO;
import com.suisung.mall.common.utils.CheckUtil;
import com.suisung.mall.common.utils.CommonUtil;
import com.suisung.mall.common.utils.I18nUtil;
@ -22,7 +23,9 @@ import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.base.mapper.AccountBaseConfigMapper;
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
import com.suisung.mall.shop.config.CookieUtil;
import com.suisung.mall.shop.order.service.ShopOrderInfoService;
import com.suisung.mall.shop.store.service.ShopStoreInfoService;
import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
@ -58,6 +61,14 @@ public class AccountBaseConfigServiceImpl extends BaseServiceImpl<AccountBaseCon
@Autowired
private ShopStoreInfoService shopStoreInfoService;
@Lazy
@Autowired
private ShopOrderInfoService shopOrderInfoService;
@Lazy
@Autowired
private ShopStoreSameCityTransportBaseService shopStoreSameCityTransportBaseService;
@Autowired
private RedisService redisService;
@ -376,29 +387,146 @@ public class AccountBaseConfigServiceImpl extends BaseServiceImpl<AccountBaseCon
}
/**
* 获取店铺或平台内部最低配送费单位
* 下单后获取店铺或平台内部最低配送费单位
*
* @param storeId 店铺Id
* @param orderId 订单Id
* @return 配送费单位分
*/
@Override
public Integer getInnerMinDeliveryFee(Integer storeId) {
// 如果storeId无效直接使用平台默认配置
if (storeId == null || storeId <= 0) {
return getDefaultMinDeliveryFee();
public Integer getInnerMinDeliveryFee(String orderId) {
// 参数校验
if (StrUtil.isBlank(orderId)) {
log.warn("[内部配送费] 订单ID为空");
return 0;
}
// 获取店铺内部运费
Integer storeFee = shopStoreInfoService.getStoreShippingFeeInner(storeId);
try {
// 根据订单号获取计算配送费参数
OrderCacDeliveryFeeDTO args = shopOrderInfoService.getOrderCacDeliveryFeeArgs(orderId);
if (args == null || args.getStore_id() == null || args.getDelivery_type_id() == null) {
log.warn("[内部配送费] 订单参数获取失败orderId: {}", orderId);
return 0;
}
// 如果店铺未设置有效运费则使用平台默认配置
if (storeFee == null || storeFee <= 0) {
return getDefaultMinDeliveryFee();
// 根据配送方式确定是否有内部配送费(只有同城配送才有内部配送费)
if (!shopOrderInfoService.hasInnerMinDeliveryFee(args.getDelivery_type_id())) {
log.debug("[内部配送费] 非同城配送方式无需计算内部配送费orderId: {}, deliveryTypeId: {}", orderId, args.getDelivery_type_id());
return 0;
}
// 调用通用计算方法
Integer innerDeliveryFee = calculateInnerMinDeliveryFee(
args.getStore_id(),
args.getDa_longitude(),
args.getDa_latitude(),
args.getOrder_weight_gram(),
args.getOrder_product_amount(),
args.getOrder_discount_amount(),
args.getOrder_payment_amount()
);
log.debug("[内部配送费] 计算完成orderId: {}, storeId: {}, fee: {}", orderId, args.getStore_id(), innerDeliveryFee);
return innerDeliveryFee;
} catch (Exception e) {
log.error("[内部配送费] 计算异常orderId: {}", orderId, e);
return 0;
}
return storeFee;
}
/**
* (下单前获取店铺或平台内部最低配送费单位
*
* @param deliveryTypeId 配送方式ID
* @param storeId 店铺ID
* @param orderLongitude 订单经度
* @param orderLatitude 订单纬度
* @param orderWeightGram 订单重量()
* @param orderProductAmount 订单商品金额
* @param orderDiscountAmount 订单折扣金额
* @param orderPayAmount 订单支付金额
* @return 内部配送费(单位 : )如果不需要内部配送费则返回0
*/
@Override
public Integer getInnerMinDeliveryFee(Integer deliveryTypeId, Integer storeId, String orderLongitude,
String orderLatitude, Integer orderWeightGram, BigDecimal orderProductAmount,
BigDecimal orderDiscountAmount, BigDecimal orderPayAmount) {
log.debug("[内部配送费] 计算开始deliveryTypeId: {}, storeId: {}, orderLongitude: {}, orderLatitude: {}, orderWeightGram: {}, orderProductAmount: {}, orderDiscountAmount: {}, orderPayAmount: {}",
deliveryTypeId, storeId, orderLongitude, orderLatitude, orderWeightGram, orderProductAmount, orderDiscountAmount, orderPayAmount);
// 参数校验
if (deliveryTypeId == null || storeId == null) {
log.warn("[内部配送费] 参数校验失败deliveryTypeId: {}storeId: {}", deliveryTypeId, storeId);
return 0;
}
// 根据配送方式确定是否有内部配送费(只有同城配送才有内部配送费)
if (!shopOrderInfoService.hasInnerMinDeliveryFee(deliveryTypeId)) {
log.debug("[内部配送费] 非同城配送方式无需计算内部配送费deliveryTypeId: {}", deliveryTypeId);
return 0;
}
try {
// 调用通用计算方法
Integer innerDeliveryFee = calculateInnerMinDeliveryFee(
storeId,
orderLongitude,
orderLatitude,
orderWeightGram,
orderProductAmount,
orderDiscountAmount,
orderPayAmount
);
log.debug("[内部配送费] 计算完成storeId: {}, deliveryTypeId: {}, fee: {}", storeId, deliveryTypeId, innerDeliveryFee);
return innerDeliveryFee;
} catch (Exception e) {
log.error("[内部配送费] 计算异常storeId: {}, deliveryTypeId: {}", storeId, deliveryTypeId, e);
return 0;
}
}
/**
* 通用内部最低配送费计算方法
*
* @param storeId 店铺ID
* @param orderLongitude 订单经度
* @param orderLatitude 订单纬度
* @param orderWeightGram 订单重量()
* @param orderProductAmount 订单商品金额
* @param orderDiscountAmount 订单折扣金额
* @param orderPayAmount 订单支付金额
* @return 内部配送费(单位 : )
*/
private Integer calculateInnerMinDeliveryFee(Integer storeId, String orderLongitude,
String orderLatitude, Integer orderWeightGram, BigDecimal orderProductAmount,
BigDecimal orderDiscountAmount, BigDecimal orderPayAmount) {
// 根据配置计算平台配送费
Integer innerDeliveryFee = shopStoreSameCityTransportBaseService.computeSameCityInnerDeliveryFee(
storeId,
orderLongitude,
orderLatitude,
orderWeightGram,
orderProductAmount,
orderDiscountAmount,
orderPayAmount
);
// 如果平台配送费为空或0则尝试获取店铺单独配置的内部运费
if (innerDeliveryFee == null || innerDeliveryFee <= 0) {
log.debug("[内部配送费] 平台配送费为空尝试获取店铺单独配置storeId: {}", storeId);
innerDeliveryFee = shopStoreInfoService.getStoreShippingFeeInner(storeId);
}
// 如果店铺单独配置的内部运费也为空或0则使用平台默认最低配送费
if (innerDeliveryFee == null || innerDeliveryFee <= 0) {
log.debug("[内部配送费] 店铺配送费为空使用平台默认配置storeId: {}", storeId);
innerDeliveryFee = getDefaultMinDeliveryFee();
}
return innerDeliveryFee != null ? innerDeliveryFee : 0;
}
/**
* 获取平台默认最低配送费
*

View File

@ -91,7 +91,7 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
@Resource
private OssService ossService;
/**
* 根据双方营业执照号码(或个人身份证)填充合同模版生成合同文件地址
* <p>
@ -109,47 +109,47 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
}
// 2. 获取平台方信息
EsignPlatformInfo esignPlatformInfo = esignPlatformInfoService.getEsignPlatformInfo(0, "");
if (ObjectUtils.isEmpty(esignPlatformInfo)) {
EsignPlatformInfo platformInfo = esignPlatformInfoService.getEsignPlatformInfo(0, "");
if (ObjectUtils.isEmpty(platformInfo)) {
log.error("[合同生成] 平台方(代理商方)信息缺失,请先配置平台信息");
return false;
}
if (StrUtil.isBlank(esignPlatformInfo.getDoc_template())) {
if (StrUtil.isBlank(platformInfo.getDoc_template())) {
log.error("[合同生成] 平台方合同模板信息为空,无法继续生成合同");
return false;
}
// 3. 获取入驻商家(审批通过的)的信息
ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByStoreId(storeId);
if (shopMchEntry == null) {
ShopMchEntry mchEntry = shopMchEntryService.getShopMerchEntryByStoreId(storeId);
if (mchEntry == null) {
log.error("[合同生成] 找不到商家入驻信息, storeId: {}", storeId);
return false;
}
// 4. 检查商家审批状态
if (!CommonConstant.MCH_APPR_STA_PASS.equals(shopMchEntry.getApproval_status())) {
log.error("[合同生成] 商家入驻审批未通过,当前状态: {}, storeId: {}", shopMchEntry.getApproval_status(), storeId);
if (!CommonConstant.MCH_APPR_STA_PASS.equals(mchEntry.getApproval_status())) {
log.error("[合同生成] 商家入驻审批未通过,当前状态: {}, storeId: {}", mchEntry.getApproval_status(), storeId);
return false;
}
ShopStoreBase shopStoreBase = shopStoreBaseService.getShopStoreBaseByStoreId(storeId);
if (ObjectUtils.isEmpty(shopStoreBase)) {
ShopStoreBase storeBase = shopStoreBaseService.getShopStoreBaseByStoreId(storeId);
if (ObjectUtils.isEmpty(storeBase)) {
log.error("[合同生成] 缺少商家店铺信息, storeId: {}", storeId);
return false;
}
BigDecimal splitRatio = shopStoreBase.getSplit_ratio();
BigDecimal splitRatio = storeBase.getSplit_ratio();
if (CheckUtil.isEmpty(splitRatio)) {
log.warn("[合同生成] 店铺分账比例为空,将使用入驻申请时设置的比例, storeId: {}", storeId);
splitRatio = shopMchEntry.getSplit_ratio();
splitRatio = mchEntry.getSplit_ratio();
}
// 5. 获取代理商信息
EsignPlatformInfo distributor = esignPlatformInfoService.getDistributorInfoById(shopMchEntry.getDistributor_id());
EsignPlatformInfo distributor = esignPlatformInfoService.getDistributorInfoById(mchEntry.getDistributor_id());
// 6. 获取平台方合同模版信息
JSONArray templates = JSONUtil.parseArray(esignPlatformInfo.getDoc_template());
JSONArray templates = JSONUtil.parseArray(platformInfo.getDoc_template());
if (templates == null || templates.isEmpty()) {
log.error("[合同生成] 平台方(代理商方)合同模板信息缺失");
return false;
@ -158,27 +158,27 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
// 7. 准备基础数据
String today = DateUtil.format(new Date(), "yyyy年MM月dd日");
// 甲方公司名称甲方是个人的时候没有公司名直接用店铺名个人实名
String mchCompany = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type())
? shopMchEntry.getBiz_license_company()
: shopMchEntry.getStore_name() + "" + shopMchEntry.getContact_name() + ")";
String platCompany = esignPlatformInfo.getLicense_company();
String mchCompany = CommonConstant.MCH_ENTITY_TYPE_QY.equals(mchEntry.getEntity_type())
? mchEntry.getBiz_license_company()
: mchEntry.getStore_name() + "" + mchEntry.getContact_name() + ")";
String platCompany = platformInfo.getLicense_company();
// 甲方法人姓名甲方是个人的时候没有法人直接用个人实名
String legalPersonName = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type())
? shopMchEntry.getLegal_person_name()
: shopMchEntry.getContact_name();
String legalPersonMobile = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type())
? shopMchEntry.getLegal_person_mobile()
: shopMchEntry.getLogin_mobile();
String legalPersonName = CommonConstant.MCH_ENTITY_TYPE_QY.equals(mchEntry.getEntity_type())
? mchEntry.getLegal_person_name()
: mchEntry.getContact_name();
String legalPersonMobile = CommonConstant.MCH_ENTITY_TYPE_QY.equals(mchEntry.getEntity_type())
? mchEntry.getLegal_person_mobile()
: mchEntry.getLogin_mobile();
// 甲方法人身份证号甲方是个人的时候没有法人直接用个人身份证
String legalPersonIdNumber = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type())
? shopMchEntry.getLegal_person_id_number()
: shopMchEntry.getIndividual_id_number();
String legalPersonIdNumber = CommonConstant.MCH_ENTITY_TYPE_QY.equals(mchEntry.getEntity_type())
? mchEntry.getLegal_person_id_number()
: mchEntry.getIndividual_id_number();
String contractNumber = StringUtils.genLklOrderNo(4);
int successCnt = 0;
log.info("[合同生成] 开始为商家生成入驻合同文件, storeId: {}, 商家手机号: {}", storeId, shopMchEntry.getLogin_mobile());
log.info("[合同生成] 开始为商家生成入驻合同文件, storeId: {}, 商家手机号: {}", storeId, mchEntry.getLogin_mobile());
// 8. 遍历模版文件生成合同模版文件里有三份合同顺序排列的: 1.平台商户入驻服务框架协议 2.小发同城服务费结算 3.结算授权委托书
for (JSONObject template : templates.jsonIter()) {
@ -195,11 +195,11 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
fillJson.put("docTemplateId", templateId)
.put("fileName", fileName);
JSONArray list = new JSONArray();
JSONArray componentList = new JSONArray();
// 10. 填充合同组件数据
// 平台合同名称
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "plat_contracts");
put("componentValue", "《平台商户入驻服务框架协议》和《小发同城服务费结算》");
}});
@ -207,7 +207,7 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
// 签署时间甲方
for (int i = 1; i <= 3; i++) {
int finalI = i;
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "mch_sign_date" + finalI);
put("componentValue", today);
}});
@ -216,34 +216,34 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
// 签署时间乙方
for (int i = 1; i <= 3; i++) {
int finalI = i;
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "plat_sign_date" + finalI);
put("componentValue", today);
}});
}
// 甲方公司名称
int mchCompanyCount = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type()) ? 17 : 16;
int mchCompanyCount = CommonConstant.MCH_ENTITY_TYPE_QY.equals(mchEntry.getEntity_type()) ? 17 : 16;
for (int i = 1; i <= mchCompanyCount; i++) {
int finalI = i;
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "mch_company" + finalI);
put("componentValue", mchCompany);
}});
}
// 特殊处理甲方收款账户方企业是公司名个人是个人实名
if (!CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type())) {
list.add(new HashMap<String, Object>() {{
if (!CommonConstant.MCH_ENTITY_TYPE_QY.equals(mchEntry.getEntity_type())) {
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "mch_company17");
put("componentValue", shopMchEntry.getContact_name());
put("componentValue", mchEntry.getContact_name());
}});
}
// 甲方法人姓名
for (int i = 1; i <= 4; i++) {
int finalI = i;
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "mch_legal_person_name" + finalI);
put("componentValue", legalPersonName);
}});
@ -252,63 +252,63 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
// 甲方法人手机号
for (int i = 1; i <= 3; i++) {
int finalI = i;
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "mch_legal_person_mobile" + finalI);
put("componentValue", legalPersonMobile);
}});
}
// 甲方身份证号码
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "mch_legal_person_id_number1");
put("componentValue", legalPersonIdNumber);
}});
// 甲方店铺名称
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "mch_store_name1");
put("componentValue", shopMchEntry.getStore_name());
put("componentValue", mchEntry.getStore_name());
}});
// 规则编号
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "rule_no");
put("componentValue", 3);
}});
// 分账比例
BigDecimal finalSplitRatio = splitRatio;
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "mch_ratio");
put("componentValue", finalSplitRatio);
}});
// 结算方式
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "settlement_method");
put("componentValue", shopMchEntry.getSettlement_method());
put("componentValue", mchEntry.getSettlement_method());
}});
// 甲方地址
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "mch_address1");
put("componentValue", shopMchEntry.getStore_address());
put("componentValue", mchEntry.getStore_address());
}});
// 甲方银行
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "mch_bank1");
put("componentValue", shopMchEntry.getBank_name());
put("componentValue", mchEntry.getBank_name());
}});
// 甲方账户号
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "mch_account_number1");
put("componentValue", shopMchEntry.getAccount_number());
put("componentValue", mchEntry.getAccount_number());
}});
// 乙方公司名称
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "plat_company1");
put("componentValue", platCompany + "和代理商");
}});
@ -316,7 +316,7 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
// 其他乙方公司名称
for (int i = 2; i <= 5; i++) {
int finalI = i;
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "plat_company" + finalI);
put("componentValue", platCompany);
}});
@ -325,58 +325,58 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
// 乙方手机号
for (int i = 1; i <= 2; i++) {
int finalI = i;
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "plat_mobile" + finalI);
put("componentValue", esignPlatformInfo.getLegal_person_mobile());
put("componentValue", platformInfo.getLegal_person_mobile());
}});
}
// 乙方邮箱重复填充但保持原逻辑
for (int i = 0; i < 6; i++) {
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "plat_email1");
put("componentValue", esignPlatformInfo.getEmail());
put("componentValue", platformInfo.getEmail());
}});
}
// 乙方银行
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "plat_bank1");
put("componentValue", esignPlatformInfo.getRec_acc_bank_name());
put("componentValue", platformInfo.getRec_acc_bank_name());
}});
// 乙方账户号
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "plat_account_number1");
put("componentValue", esignPlatformInfo.getRec_acc_card_no());
put("componentValue", platformInfo.getRec_acc_card_no());
}});
// 11. 处理代理商相关数据
if (distributor != null) {
// 有代理商的时候填充代理商的信息
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "distr_company1");
put("componentValue", distributor.getLicense_company());
}});
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "distr_mobile1");
put("componentValue", distributor.getLegal_person_mobile());
}});
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "distr_company2");
put("componentValue", distributor.getLicense_company());
}});
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "distr_bank1");
put("componentValue", distributor.getRec_acc_bank_name());
}});
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "distr_account_number1");
put("componentValue", distributor.getRec_acc_card_no());
}});
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "distr_sign_date1");
put("componentValue", today);
}});
@ -384,24 +384,24 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
log.debug("[合同生成] 已填充代理商信息: {}", distributor.getLicense_company());
} else {
// 无代理商时填充默认值
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "distr_company1");
put("componentValue", "");
}});
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "distr_mobile1");
put("componentValue", "");
}});
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "distr_company2");
put("componentValue", "");
}});
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "distr_bank1");
put("componentValue", "");
}});
list.add(new HashMap<String, Object>() {{
componentList.add(new HashMap<String, Object>() {{
put("componentKey", "distr_account_number1");
put("componentValue", "");
}});
@ -409,7 +409,7 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
log.debug("[合同生成] 未配置代理商信息,使用默认值");
}
fillJson.put("components", list);
fillJson.put("components", componentList);
String jsonParam = fillJson.toString();
String apiAddr = "/v3/files/create-by-doc-template";
@ -420,19 +420,19 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
appId, appSecret, jsonParam, requestType.name(), apiAddr, debug);
// 发起接口请求
EsignHttpResponse createByDocTemplate = EsignHttpHelper.doCommHttp(
EsignHttpResponse response = EsignHttpHelper.doCommHttp(
serverUrl, apiAddr, requestType, jsonParam, header, debug);
log.info("[合同生成] 调用电子签约服务生成合同文件: status={}, response={}",
createByDocTemplate.getStatus(), createByDocTemplate.getBody());
response.getStatus(), response.getBody());
if (createByDocTemplate.getStatus() != 200) {
log.error("[合同生成] 调用电子签约服务生成合同文件失败, HTTP状态码: {}", createByDocTemplate.getStatus());
if (response.getStatus() != 200) {
log.error("[合同生成] 调用电子签约服务生成合同文件失败, HTTP状态码: {}", response.getStatus());
continue; // 继续处理下一个模版
}
// 13. 解析API返回结果
JSONObject jsonObject = JSONUtil.parseObj(createByDocTemplate.getBody()).getJSONObject("data");
JSONObject jsonObject = JSONUtil.parseObj(response.getBody()).getJSONObject("data");
String fileDownloadUrl = jsonObject.getStr("fileDownloadUrl");
String fileId = jsonObject.getStr("fileId");
@ -442,13 +442,13 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
}
// 14. 创建合同填充文件记录
EsignContractFillingFile esignContractFillingFile = new EsignContractFillingFile();
esignContractFillingFile.setUnsigned_contract_url(fileDownloadUrl);
esignContractFillingFile.setFile_id(fileId);
EsignContractFillingFile contractFillingFile = new EsignContractFillingFile();
contractFillingFile.setUnsigned_contract_url(fileDownloadUrl);
contractFillingFile.setFile_id(fileId);
// 15. 上传合同文件到OSS
String cosFileName = TENGXUN_DEFAULT_DIR.concat("/contract/")
.concat(shopMchEntry.getLogin_mobile()).concat("/")
.concat(mchEntry.getLogin_mobile()).concat("/")
.concat(fileId).concat(".pdf");
String localFileUrl = ossService.uploadObject4OSS(fileDownloadUrl, cosFileName);
@ -457,42 +457,42 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
continue;
}
esignContractFillingFile.setUnsigned_contract_local_url(localFileUrl);
esignContractFillingFile.setDoc_template_id(templateId);
esignContractFillingFile.setContract_number(contractNumber + seq);
esignContractFillingFile.setContract_name("商户入驻小发同城平台合同协议");
esignContractFillingFile.setStore_id(Convert.toStr(storeId));
esignContractFillingFile.setMobile(shopMchEntry.getLogin_mobile());
esignContractFillingFile.setDoc_template_filling_values(jsonParam);
esignContractFillingFile.setSeq(seq);
esignContractFillingFile.setStatus(CommonConstant.Enable);
contractFillingFile.setUnsigned_contract_local_url(localFileUrl);
contractFillingFile.setDoc_template_id(templateId);
contractFillingFile.setContract_number(contractNumber + seq);
contractFillingFile.setContract_name("商户入驻小发同城平台合同协议");
contractFillingFile.setStore_id(Convert.toStr(storeId));
contractFillingFile.setMobile(mchEntry.getLogin_mobile());
contractFillingFile.setDoc_template_filling_values(jsonParam);
contractFillingFile.setSeq(seq);
contractFillingFile.setStatus(CommonConstant.Enable);
// 16. 获取印章位置信息
Map<String, JSONArray> signPositionMap = getSignPosition(templateId, fileId);
if (signPositionMap != null) {
if (signPositionMap.get("mch") != null) {
esignContractFillingFile.setMch_sign_position(signPositionMap.get("mch").toString());
contractFillingFile.setMch_sign_position(signPositionMap.get("mch").toString());
}
if (signPositionMap.get("plat") != null) {
esignContractFillingFile.setPlat_sign_position(signPositionMap.get("plat").toString());
contractFillingFile.setPlat_sign_position(signPositionMap.get("plat").toString());
}
if (distributor != null && signPositionMap.get("distr") != null) {
// 如果有代理商则把代理商的印章位置信息写入数据库
esignContractFillingFile.setDistri_sign_position(signPositionMap.get("distr").toString());
contractFillingFile.setDistri_sign_position(signPositionMap.get("distr").toString());
}
}
// 17. 保存合同填充记录并预创建签署流程
if (esignContractFillingFileService.trySaveRecord(esignContractFillingFile)) {
if (esignContractFillingFileService.trySaveRecord(contractFillingFile)) {
successCnt += 1;
log.debug("[合同生成] 合同记录保存成功, fileId: {}", fileId);
// 预新增一个签署合同记录
boolean preCreateResult = esignContractService.preCreateSignFlow(
esignContractFillingFile.getMobile(), esignContractFillingFile.getDoc_template_id());
contractFillingFile.getMobile(), contractFillingFile.getDoc_template_id());
log.debug("[合同生成] 预创建签署流程结果: {}, 商家手机号: {}, 模板ID: {}",
preCreateResult, esignContractFillingFile.getMobile(), esignContractFillingFile.getDoc_template_id());
preCreateResult, contractFillingFile.getMobile(), contractFillingFile.getDoc_template_id());
} else {
log.error("[合同生成] 保存合同记录失败, fileId: {}", fileId);
}

View File

@ -167,61 +167,77 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
@Override
public Pair<Boolean, String> innerSignFlowCreateByFile(Integer storeId) {
// 1. 参数校验
if (CheckUtil.isEmpty(storeId)) {
return Pair.of(false, "缺少必要参数!");
}
// 组织和填充商家店铺的模版数据
// 2. 组织和填充商家店铺的模版数据
Boolean isFill = esignContractFillingFileService.fillDocTemplate(storeId);
if (!isFill) {
return Pair.of(false, "合同信息未准备好,请检查商家入驻手续是否已完成!");
}
// 3. 获取商家合同信息
EsignContract esignContract = getEsignContractByStoreId(storeId);
if (esignContract == null) {
return Pair.of(false, "未找到商家合同信息");
}
// 检查商户入驻信息是否被审核通过
// 检查店铺是否已经申请过入驻
// 4. 检查商户入驻信息是否被审核通过
Integer apprStatus = shopMchEntryService.getApprovalStatus(esignContract.getMch_mobile());
if (!CommonConstant.MCH_APPR_STA_PASS.equals(apprStatus)) {
return Pair.of(false, "请先审核商家入驻信息");
}
//"{\"docs\":[{\"fileId\":\"ab30d2c5600441f4a7daf512e4d69157\",\"fileName\":\"小发同城平台商户合作协议.pdf\"}],\"signFlowConfig\":{\"signFlowTitle\":\"小发同城平台商户合作协议\",\"signFlowExpireTime\":1746844718000,\"autoFinish\":true,\"notifyUrl\":\"https://mall.gpxscs.cn/asyn/notify\",\"redirectConfig\":{\"redirectUrl\":\"https://mall.gpxscs.cn/\"}},\"signers\":[{\"signConfig\":{\"signOrder\":1},\"noticeConfig\":{\"noticeTypes\":\"1\"},\"signerType\":0,\"psnSignerInfo\":{\"psnAccount\":\"13128997057\",\"psnInfo\":{\"psnName\":\"潘军杰\"}},\"signFields\":[{\"fileId\":\"ab30d2c5600441f4a7daf512e4d69157\",\"normalSignFieldConfig\":{\"signFieldStyle\":1,\"signFieldPosition\":{\"positionPage\":40,\"positionX\":472.3607,\"positionY\":277.19104}}},{\"fileId\":\"ab30d2c5600441f4a7daf512e4d69157\",\"normalSignFieldConfig\":{\"signFieldStyle\":1,\"signFieldPosition\":{\"positionPage\":5,\"positionX\":470.58798,\"positionY\":589.14496}}}]},{\"signConfig\":{\"signOrder\":2},\"noticeConfig\":{\"noticeTypes\":\"1\"},\"signerType\":1,\"orgSignerInfo\":{\"orgName\":\"桂平发发网络有限公司\",\"orgInfo\":{\"orgIDCardNum\":\"91450881MADEQ92533\",\"orgIDCardType\":\"CRED_ORG_USCC\"},\"transactorInfo\":{\"psnAccount\":\"17777525395\",\"psnInfo\":{\"psnName\":\"谢能坤\"}}},\"signFields\":[{\"fileId\":\"ab30d2c5600441f4a7daf512e4d69157\",\"normalSignFieldConfig\":{\"signFieldStyle\":1,\"signFieldPosition\":{\"positionPage\":2,\"positionX\":479.04996,\"positionY\":357.2327}}},{\"fileId\":\"ab30d2c5600441f4a7daf512e4d69157\",\"normalSignFieldConfig\":{\"signFieldStyle\":1,\"signFieldPosition\":{\"positionPage\":5,\"positionX\":255.96832,\"positionY\":588.4553}}}]}]}";
// esignContractService.
// 5. 获取签署请求参数
String jsonParams = esignContract.getReq_params();
if (StrUtil.isBlank(jsonParams)) {
return Pair.of(false, "合同请求参数为空");
}
try {
//请求方法
// 6. 调用E签宝API创建签署流程
EsignRequestType requestType = EsignRequestType.POST;
String apiAddr = "/v3/sign-flow/create-by-file";
Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(appId, appSecret, jsonParams, requestType.name(), apiAddr, true);
//发起接口请求
EsignHttpResponse createByDocTemplate = EsignHttpHelper.doCommHttp(serverUrl, apiAddr, requestType, jsonParams, header, debug);
log.info("发起合同签署流程返回消息:{},{}", createByDocTemplate.getStatus(), createByDocTemplate.getBody());
if (createByDocTemplate.getStatus() != 200) {
if (createByDocTemplate.getBody() != null) {
JSONObject resBody = JSONUtil.parseObj(createByDocTemplate.getBody());
log.error("e签宝请求失败返回状态码{}, {}", createByDocTemplate.getStatus(), resBody.getStr("message"));
return Pair.of(false, "e签宝请求失败{}" + resBody.getStr("message"));
Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(
appId, appSecret, jsonParams, requestType.name(), apiAddr, true);
EsignHttpResponse response = EsignHttpHelper.doCommHttp(
serverUrl, apiAddr, requestType, jsonParams, header, debug);
log.info("发起合同签署流程返回消息status={}, body={}", response.getStatus(), response.getBody());
// 7. 处理API响应结果
if (response.getStatus() != HttpStatus.OK.value()) {
String errorMsg = "E签宝请求失败";
if (response.getBody() != null) {
try {
JSONObject resBody = JSONUtil.parseObj(response.getBody());
errorMsg += "" + resBody.getStr("message", "未知错误");
} catch (Exception parseException) {
log.warn("解析E签宝错误响应失败{}", response.getBody());
}
}
return Pair.of(false, "e签宝请求失败!");
log.error("E签宝请求失败返回状态码{}", response.getStatus());
return Pair.of(false, errorMsg);
}
JSONObject jsonObject = JSONUtil.parseObj(createByDocTemplate.getBody());
// 8. 解析成功响应数据
JSONObject jsonObject = JSONUtil.parseObj(response.getBody());
Integer code = jsonObject.getInt("code");
String signFlowId = (String) jsonObject.getByPath("data.signFlowId");
String signFlowId = jsonObject.getByPath("data.signFlowId", String.class);
if (code == null || code != 0 || StrUtil.isBlank(signFlowId)) {
log.error("e签宝请求失败返回status码{}", code);
return Pair.of(false, "e签宝请求失败!");
log.error("E签宝请求失败返回 code 码:{}", code);
return Pair.of(false, "E签宝请求失败!");
}
//合同签署状态-1预备数据阶段0-等待签署1-已部分签署2-已完成所有签署方完成签署3-已撤销发起方撤销签署任务5-已过期签署截止日到期后触发7-已拒签签署方拒绝签署
Boolean success = updateContractFlowIdAndFileUrl(esignContract.getId(), signFlowId, CommonConstant.CONTRACT_SIGN_STA_ING, null);
// 9. 更新合同流程状态
Boolean success = updateContractFlowIdAndFileUrl(
esignContract.getId(), signFlowId, CommonConstant.CONTRACT_SIGN_STA_ING, null);
if (!success) {
log.error("更新合同流程状态失败");
return Pair.of(false, "更新合同流程状态失败");
@ -229,12 +245,13 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
return Pair.of(true, "合同流程创建成功合同流程ID" + signFlowId);
} catch (EsignDemoException e) {
} catch (Exception e) {
log.error("发起签署电子合同请求失败:", e);
return Pair.of(false, "发起签署电子合同请求失败!");
}
}
/**
* 签署流程结束通知
*
@ -251,14 +268,14 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
String timestamp = request.getHeader("X-Tsign-Open-TIMESTAMP");
if (StrUtil.isBlank(reqAppId) || StrUtil.isBlank(signature) || StrUtil.isBlank(timestamp)) {
log.warn("e签宝异步通知缺少必要参数: reqAppId={}, signature={}, timestamp={}", reqAppId, signature, timestamp);
log.warn("E签宝异步通知缺少必要参数: reqAppId={}, signature={}, timestamp={}", reqAppId, signature, timestamp);
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new JSONObject().put("code", 400).put("msg", "缺少必要参数").toString());
}
// 2. 验证AppId是否匹配
if (!reqAppId.equals(appId)) {
log.warn("e签宝异步通知AppId不匹配: 请求AppId={}, 配置AppId={}", reqAppId, appId);
log.warn("E签宝异步通知AppId不匹配: 请求AppId={}, 配置AppId={}", reqAppId, appId);
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new JSONObject().put("code", 400).put("msg", "appId 有误").toString());
}
@ -278,7 +295,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
log.debug("header里面的签名值---------->>>>>> {}", signature);
if (!mySignature.equals(signature)) {
log.warn("e签宝异步通知签名校验失败: 计算签名={}, 请求签名={}", mySignature, signature);
log.warn("E签宝异步通知签名校验失败: 计算签名={}, 请求签名={}", mySignature, signature);
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new JSONObject().put("code", 400).put("msg", "签名校验失败").toString());
}
@ -288,7 +305,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
try {
reqBodyJSON = JSONUtil.parseObj(requestBody);
} catch (Exception e) {
log.error("解析e签宝异步通知请求体失败: requestBody={}", requestBody, e);
log.error("解析E签宝异步通知请求体失败: requestBody={}", requestBody, e);
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new JSONObject().put("code", 400).put("msg", "请求体格式错误").toString());
}
@ -298,7 +315,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
Integer signResult = reqBodyJSON.getInt("signResult");
if (StrUtil.isBlank(action) || StrUtil.isBlank(signFlowId)) {
log.warn("e签宝异步通知缺少必要业务参数: action={}, signFlowId={}", action, signFlowId);
log.warn("E签宝异步通知缺少必要业务参数: action={}, signFlowId={}", action, signFlowId);
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new JSONObject().put("code", 400).put("msg", "返回数据有误").toString());
}
@ -391,7 +408,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
return ResponseEntity.ok(new JSONObject().put("code", 200).put("msg", "success").toString());
}
} catch (Exception e) {
log.error("处理e签宝异步通知异常: action={}, signFlowId={}", action, signFlowId, e);
log.error("处理E签宝异步通知异常: action={}, signFlowId={}", action, signFlowId, e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new JSONObject().put("code", 500).put("msg", "处理通知异常").toString());
}
@ -728,7 +745,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
}
/**
* e签宝官网根据合同流程ID获取完成签署生效的合同文件地址
* E签宝官网根据合同流程ID获取完成签署生效的合同文件地址
* <p>
* 收到异步通知签署完成之后获取合同文件地址保存并上传到 oss
*
@ -837,7 +854,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
}
// e签宝签名相关方法
// E签宝签名相关方法
/**
* 根据商家的注册手机号新增或更新签署合同记录

View File

@ -137,33 +137,47 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@DistributedLock(
key = "CREATENEXTSEQ_LOCK", // 锁的key
waitTime = 3, // 等待3秒
leaseTime = 10, // 锁持有10秒
waitTime = 3, // 等待3秒
leaseTime = 10, // 锁持有10秒
errorMsg = "生成ID繁忙请稍后重试" // 自定义错误消息
)
public synchronized Pair<Long, String> createNextSeqPair(String prefix) {
String ymd = DateUtil.format(new Date(), "yyyyMMdd");
String id = String.format("%s_%s_", prefix, ymd);
ShopNumberSeq shopNumberSeq = this.baseMapper.selectById(id);
if (shopNumberSeq == null) {
shopNumberSeq = new ShopNumberSeq();
shopNumberSeq.setPrefix(id);
shopNumberSeq.setNumber(1L);
if (!save(shopNumberSeq)) {
return null;
// 参数校验
if (prefix == null || prefix.trim().isEmpty()) {
return null;
}
try {
String ymd = DateUtil.format(new Date(), "yyyyMMdd");
String seqId = String.format("%s_%s_", prefix, ymd);
// 查询或创建序列记录
ShopNumberSeq shopNumberSeq = this.baseMapper.selectById(seqId);
if (shopNumberSeq == null) {
shopNumberSeq = new ShopNumberSeq();
shopNumberSeq.setPrefix(seqId);
shopNumberSeq.setNumber(1L);
if (!save(shopNumberSeq)) {
return null;
}
}
}
String order_id = String.format("%s_%s_%s", prefix, ymd, shopNumberSeq.getNumber());
shopNumberSeq.setPrefix(id);
boolean flag = edit(shopNumberSeq);
if (flag) {
return Pair.of(shopNumberSeq.getNumber(), order_id);
}
// 获取当前序列号
Long number = shopNumberSeq.getNumber();
String orderId = String.format("%s_%s_%s", prefix, ymd, number);
return null;
// 增加序列号并更新
// shopNumberSeq.setNumber(number + 1);
shopNumberSeq.setPrefix(seqId);
return edit(shopNumberSeq) ? Pair.of(number, orderId) : null;
} catch (Exception e) {
log.error("生成序列号失败prefix: {}", prefix, e);
return null;
}
}
/**
* 得到下一个Id
*

View File

@ -1,6 +1,8 @@
package com.suisung.mall.shop.order.controller.mobile;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.api.ResultCode;
@ -15,10 +17,7 @@ import com.suisung.mall.shop.order.vo.OrderReturnVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* <p>
@ -57,7 +56,7 @@ public class UserReturnController extends BaseControllerImpl {
return shopOrderReturnService.returnItem();
}
@ApiOperation(value = "添加退款退货-部分退货,卖家也可以决定不退货退款,买家申请退款不支持。卖家可以主动退款。", notes = "添加退款退货-发货退货,卖家也可以决定不退货退款,买家申请退款不支持。卖家可以主动退款。")
@ApiOperation(value = "添加退款退货-部分退货", notes = "添加退款退货-发货退货,卖家也可以决定不退货退款,买家申请退款不支持。卖家可以主动退款。")
@RequestMapping(value = "/addItem", method = RequestMethod.GET)
public CommonResult addItem(OrderReturnVo orderReturnVo) {
UserDto user = getCurrentUser();
@ -77,6 +76,26 @@ public class UserReturnController extends BaseControllerImpl {
return shopOrderReturnService.addItem(orderReturnInputVo, true);
}
@ApiOperation(value = "批量添加退款退货(支持多个商品)", notes = "添加退款退货-发货退货,卖家也可以决定不退货退款,买家申请退款不支持。卖家可以主动退款。")
@RequestMapping(value = "/addItemBatch", method = RequestMethod.POST)
public CommonResult addItemBatch(@RequestBody JSONObject orderReturnVoJSON) {
if (orderReturnVoJSON == null) {
return CommonResult.failed("请求参数不能为空");
}
OrderReturnInputVo orderReturnInputVo = JSONUtil.toBean(orderReturnVoJSON, OrderReturnInputVo.class);
if (orderReturnInputVo == null) {
return CommonResult.failed("请求参数格式不正确");
}
UserDto user = getCurrentUser();
if (user == null) {
return CommonResult.failed(ResultCode.NEED_LOGIN);
}
return shopOrderReturnService.tryAddItemBatch(orderReturnInputVo);
}
@ApiOperation(value = "添加退款退货-整单退货", notes = "添加退款退货-整单退货")
@RequestMapping(value = "/addWholeItems", method = RequestMethod.POST)
public CommonResult addWholeItems(@RequestParam(name = "order_id") String order_id) {

View File

@ -2,6 +2,8 @@ package com.suisung.mall.shop.order.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.suisung.mall.common.modules.order.ShopOrderInfo;
import com.suisung.mall.common.pojo.dto.OrderCacDeliveryFeeDTO;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@ -35,4 +37,28 @@ public interface ShopOrderInfoMapper extends BaseMapper<ShopOrderInfo> {
*/
Long getOrderCountByStoreId(Integer storeId, List<Integer> orderStatusIdList, List<Integer> orderRefundStatusIdList, List<Integer> deliveryTypeList, Long expireSeconds);
/**
* 根据订单ID获取计算配送费所需的订单信息
* <p>
* 查询逻辑说明:
* 1. 从订单基础信息表获取订单ID店铺ID和商品总额
* 2. 从订单数据表计算实际支付金额(订单支付金额 - 运费金额)
* 3. 从订单数据表计算折扣金额(商品零售总额 - 折扣金额 - 优惠券金额 - 调整金额 - 积分抵扣金额)
* 4. 从订单配送地址表获取配送地址的经纬度
*
* @param orderId 订单ID
* @return OrderCacDeliveryFeeDTO 订单配送费计算参数实体
*/
@Select("SELECT sob.order_id,sob.store_id,sob.order_product_amount,sob.order_payment_amount," +
"(sob.order_product_amount-sod.order_discount_amount-sod.voucher_price-sod.order_adjust_fee-sod.order_points_fee) as order_discount_amount," +
"0 as order_weight_gram," +
"aoda.da_longitude,aoda.da_latitude, soi.delivery_type_id " +
"FROM shop_order_base sob " +
"JOIN shop_order_data sod ON sob.order_id=sod.order_id " +
"JOIN shop_order_info soi ON sob.order_id=soi.order_id " +
"JOIN shop_order_delivery_address aoda ON sob.order_id=aoda.order_id " +
"WHERE sob.order_id=#{orderId}")
OrderCacDeliveryFeeDTO getOrderCacDeliveryFeeArgs(String orderId);
}

View File

@ -459,20 +459,20 @@ public interface ShopOrderBaseService extends IBaseService<ShopOrderBase> {
*
* @param order_id
* @param shopOrderInfo
* @param check_paid_flag
* @param checkPaidState 订单是否未支付默认值 true
* @return
*/
boolean cancel(String order_id, ShopOrderInfo shopOrderInfo, boolean check_paid_flag);
boolean cancel(String order_id, ShopOrderInfo shopOrderInfo, boolean checkPaidState);
/**
* 取消订单
*
* @param order_ids
* @param order_rows
* @param check_paid_flag
* @param isNotPaid 订单是否未支付默认值 true
* @return
*/
boolean cancel(List<String> order_ids, List<Map> order_rows, boolean check_paid_flag);
boolean cancel(List<String> order_ids, List<Map> order_rows, boolean isNotPaid);
void exportFile(HttpServletResponse response, ShopOrderBase shopOrderBase, List<String> order_ids);

View File

@ -3,6 +3,7 @@ package com.suisung.mall.shop.order.service;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.modules.order.ShopOrderInfo;
import com.suisung.mall.common.pojo.dto.BookingArgDTO;
import com.suisung.mall.common.pojo.dto.OrderCacDeliveryFeeDTO;
import com.suisung.mall.core.web.service.IBaseService;
import org.springframework.data.util.Pair;
@ -145,11 +146,33 @@ public interface ShopOrderInfoService extends IBaseService<ShopOrderInfo> {
List<BookingArgDTO> genBookingOrderArgList(String storeId);
/**
* 获取某个活动订单成功数量
* 获取某个活动订单成功数量(目前砍价用途)
*
* @param activityId 活动ID
* @param activityTypeId 活动类型ID 可选参数
* @return
*/
long fetchActivityOrderSuccessCount(String activityId, String activityTypeId);
/**
* 获取某个订单是否存在满足内部配送费
*
* @param deliveryTypeId 店铺ID
* @return Pair第一个元素表示是否满足内部配送费条件第二个元素为内部配送费金额
*/
Boolean hasInnerMinDeliveryFee(Integer deliveryTypeId);
/**
* 根据订单ID获取计算配送费所需的订单信息
* <p>
* 查询逻辑说明:
* 1. 从订单基础信息表获取订单ID店铺ID和商品总额
* 2. 从订单数据表计算实际支付金额(订单支付金额 - 运费金额)
* 3. 从订单数据表计算折扣金额(商品总额 - 折扣金额 - 调整金额 - 积分抵扣金额)
* 4. 从订单配送地址表获取配送地址的经纬度
*
* @param orderId 订单ID
* @return OrderCacDeliveryFeeDTO 订单配送费计算参数实体
*/
OrderCacDeliveryFeeDTO getOrderCacDeliveryFeeArgs(String orderId);
}

View File

@ -50,6 +50,14 @@ public interface ShopOrderReturnService extends IBaseService<ShopOrderReturn> {
*/
CommonResult addItem(OrderReturnInputVo orderReturnInputVo, Boolean needSendMsg);
/**
* 尝试批量添加退款退货申请自动使用最大可退数量和金额等待商家审核处理同意或不同意
*
* @param orderReturnInputVo 退款申请输入参数支持订单多个商品退款
* @return CommonResult 退款申请结果
*/
CommonResult tryAddItemBatch(OrderReturnInputVo orderReturnInputVo);
Map getReturnDetail(String return_id);
boolean processReviewList(ShopOrderReturn shopOrderReturn, Integer receiving_address);

View File

@ -768,7 +768,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
throw new ApiException(I18nUtil._("无该订单访问权限!"));
}
// 是否禁止退款
// 订单是否禁止退款
int isOrderDenyReturn = shopOrderReturnService.isOrderDenyReturn(order_id) ? 1 : 2;
data.put("is_deny_return", isOrderDenyReturn);
@ -917,6 +917,8 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
unit_rows = Convert.toList(Map.class, productUnitList);
}
boolean is_denyreturn = true;
for (Map item_row : items) {
Integer product_id = Convert.toInt(item_row.get("product_id"));
Optional<Map> productBaseOpl = product_rows.stream().filter(s -> ObjectUtil.equal(product_id, Convert.toInt(s.get("product_id")))).findFirst();
@ -961,9 +963,8 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
item_row.put("product_number", product_number);
}
// 不支持退货
boolean is_denyreturn = shopOrderReturnService.ifDenyReturn(order_item_id);
// 订单是否禁止退货
is_denyreturn = shopOrderReturnService.isOrderDenyReturn(order_id); //shopOrderReturnService.ifDenyReturn(order_item_id);
item_row.put("contains", is_denyreturn);
item_row.put("is_denyreturn", is_denyreturn);
@ -1087,7 +1088,8 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
}
base_row.put("if_lock", base_row.get("order_lock_status"));
base_row.put("if_buyer_cancel", ifCancel(order_state_id, order_is_paid));
// 待支付订单可取消商品非禁止退货的也可以取消
base_row.put("if_buyer_cancel", isOrderCancelable(order_state_id, order_is_paid) || !is_denyreturn);
base_row.put("if_logistics", ifLogistics(order_state_id));
base_row.put("if_receive", ifReceive(order_state_id));
@ -4127,114 +4129,138 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
* 取消订单
* 流程订单状态积分众宝库存礼包优惠券 有就统统退还
*
* @param order_ids 订单id
* @param order_rows 订单数据
* @param check_paid_flag 默认值 true
* @param orderIds 订单id列表
* @param orderRows 订单数据
* @param checkPaidState 实付检查订单支付状态默认值 true
*/
@Transactional
public boolean cancel(List<String> order_ids, List<Map> order_rows, boolean check_paid_flag) {
List<String> cancel_id_row = new ArrayList<>(order_ids.size());
public boolean cancel(List<String> orderIds, List<Map> orderRows, boolean checkPaidState) {
List<String> cancelIdRow = new ArrayList<>(orderIds.size());
// 检测数据是否合法,过滤允许修改的数据
if (CollUtil.isEmpty(order_ids)) {
if (CollUtil.isEmpty(orderIds)) {
throw new ApiException(I18nUtil._("请选择需要取消的订单"));
}
if (CollUtil.isEmpty(order_rows)) {
order_rows = Convert.toList(Map.class, shopOrderInfoService.gets(order_ids));
if (CollUtil.isEmpty(orderRows)) {
orderRows = Convert.toList(Map.class, shopOrderInfoService.gets(orderIds));
}
for (String order_id : order_ids) {
Optional<Map> orderOpl = order_rows.stream().filter(s -> ObjectUtil.equal(order_id, Convert.toStr(s.get("order_id")))).findFirst();
Map order = orderOpl.orElseGet(HashMap::new);
// 筛选可取消的订单
for (String orderId : orderIds) {
Optional<Map> orderOpt = orderRows.stream()
.filter(s -> ObjectUtil.equal(orderId, Convert.toStr(s.get("order_id"))))
.findFirst();
Map order = orderOpt.orElseGet(HashMap::new);
// 订单状态(LIST):2011-待订单审核;2013-待财务审核;2020-待配货/待出库审核;2030-待发货;2040-已发货/待收货确认;2060-已完成/已签收;2070-已取消/已作废;
Integer order_state_id = (Integer) order.get("order_state_id");
Integer orderStateId = (Integer) order.get("order_state_id");
// 付款状态(ENUM):3010-未付款;3011-付款待审核;3012-部分付款;3013-已付款
Integer order_is_paid = (Integer) order.get("order_is_paid");
// 要检查订单付款状态
if (check_paid_flag) {
if (ifCancel(order_state_id, order_is_paid)) {
// 未付款未配送的订单才能取消订单
cancel_id_row.add(order_id);
Integer orderIsPaid = (Integer) order.get("order_is_paid");
// 根据是否检查支付状态来判断订单是否可取消
if (checkPaidState) {
// 检查订单是否可以取消未付款且处于特定状态
if (isOrderCancelable(orderStateId, orderIsPaid)) {
cancelIdRow.add(orderId);
} else {
// 订单已支付检查是否允许退款
boolean isOrderDenyReturn = shopOrderReturnService.isOrderDenyReturn(orderId);
if (!isOrderDenyReturn) {
// 支付的订单允许退款立即发起退款流程再由商家审核
CommonResult refundResult = shopOrderReturnService.addRemainingItems(orderId, false, "用户取消订单");
if (refundResult == null || refundResult.getStatus() != 200L) {
logger.error("用户提交取消订单失败!");
return false;
}
// 提交成功之后再由商家审核通过之后会继续完成以下的操作
return true;
}
}
} else {
// 不检查订单付款状态
cancel_id_row.add(order_id);
// 不检查订单付款状态直接加入可取消列表
cancelIdRow.add(orderId);
}
}
if (CollUtil.isEmpty(cancel_id_row)) {
if (CollUtil.isEmpty(cancelIdRow)) {
throw new ApiException(I18nUtil._("无符合取消条件的订单!"));
}
order_ids = cancel_id_row;
orderIds = cancelIdRow;
// 更新订单主表状态为已取消
ShopOrderBase orderBase = new ShopOrderBase();
orderBase.setOrder_state_id(StateCode.ORDER_STATE_CANCEL);
QueryWrapper<ShopOrderBase> baseQueryWrapper = new QueryWrapper<>();
baseQueryWrapper.in("order_id", order_ids);
baseQueryWrapper.in("order_id", orderIds);
baseQueryWrapper.ne("order_state_id", StateCode.ORDER_STATE_CANCEL); // 2070-已取消
if (!edit(orderBase, baseQueryWrapper)) {// 批量更改状态
if (!edit(orderBase, baseQueryWrapper)) { // 批量更改状态
throw new ApiException(ResultCode.FAILED);
}
// 更新订单信息表状态为已取消
ShopOrderInfo shopOrderInfo = new ShopOrderInfo();
shopOrderInfo.setOrder_state_id(StateCode.ORDER_STATE_CANCEL);
QueryWrapper<ShopOrderInfo> infoQueryWrapper = new QueryWrapper<>();
infoQueryWrapper.in("order_id", cancel_id_row);
infoQueryWrapper.in("order_id", cancelIdRow);
infoQueryWrapper.ne("order_state_id", StateCode.ORDER_STATE_CANCEL);
if (!shopOrderInfoService.edit(shopOrderInfo, infoQueryWrapper)) {
throw new ApiException(String.format("订单:%s 取消状态有误!", CollUtil.join(cancel_id_row, ",")));
throw new ApiException(String.format("订单:%s 取消状态有误!", CollUtil.join(cancelIdRow, ",")));
}
// 积分退还 order_resource_ext1 默认为积分
List<ShopOrderData> order_data_rows = shopOrderDataService.gets(order_ids);
for (ShopOrderData order_data_row : order_data_rows) {
String orderId = order_data_row.getOrder_id();
List<ShopOrderData> orderDataRows = shopOrderDataService.gets(orderIds);
for (ShopOrderData orderDataRow : orderDataRows) {
String orderId = orderDataRow.getOrder_id();
Optional<Map> orderOpl = order_rows.stream().filter(s -> ObjectUtil.equal(orderId, Convert.toStr(s.get("order_id")))).findFirst();
Map order = orderOpl.orElseGet(HashMap::new);
Optional<Map> orderOpt = orderRows.stream()
.filter(s -> ObjectUtil.equal(orderId, Convert.toStr(s.get("order_id"))))
.findFirst();
Map order = orderOpt.orElseGet(HashMap::new);
Integer buyer_user_id = (Integer) order.get("buyer_user_id");
BigDecimal order_resource_ext1 = order_data_row.getOrder_resource_ext1();// 积分
BigDecimal order_resource_ext2 = order_data_row.getOrder_resource_ext2();// 众宝
Integer buyerUserId = (Integer) order.get("buyer_user_id");
BigDecimal orderResourceExt1 = orderDataRow.getOrder_resource_ext1(); // 积分
BigDecimal orderResourceExt2 = orderDataRow.getOrder_resource_ext2(); // 众宝
if (ObjectUtil.compare(order_resource_ext1, BigDecimal.ZERO) > 0 && CheckUtil.isNotEmpty(buyer_user_id)) {
Integer store_id = (Integer) order.get("store_id");
// 退还积分
if (ObjectUtil.compare(orderResourceExt1, BigDecimal.ZERO) > 0 && CheckUtil.isNotEmpty(buyerUserId)) {
Integer storeId = (Integer) order.get("store_id");
// 扣除积分
String desc = String.format("%s 积分退还,订单号 %s", order_resource_ext1, order_data_row.getOrder_id());
if (!payService.points(buyer_user_id, order_resource_ext1, PointsType.POINTS_TYPE_CONSUME_RETRUN, desc, store_id, null, order_data_row.getOrder_id())) {
String desc = String.format("%s 积分退还,订单号 %s", orderResourceExt1, orderDataRow.getOrder_id());
if (!payService.points(buyerUserId, orderResourceExt1, PointsType.POINTS_TYPE_CONSUME_RETRUN, desc, storeId, null, orderDataRow.getOrder_id())) {
throw new ApiException(I18nUtil._("积分操作失败!"));
}
}
// 程序没有编写完成缺失众宝积分退回功能
//if (ObjectUtil.compare(order_resource_ext2, BigDecimal.ZERO) > 0 && CheckUtil.isNotEmpty(buyer_user_id)) {
// String desc = String.format("%s 众宝退还", order_resource_ext2);
// todo shopUserPointsHistoryService.sp(buyer_user_id,order_resource_ext2,SpType.SP_TYPE_CONSUME_RETRUN, desc);
//}
// if (ObjectUtil.compare(orderResourceExt2, BigDecimal.ZERO) > 0 && CheckUtil.isNotEmpty(buyerUserId)) {
// String desc = String.format("%s 众宝退还", orderResourceExt2);
// todo shopUserPointsHistoryService.sp(buyerUserId, orderResourceExt2, SpType.SP_TYPE_CONSUME_RETRUN, desc);
// }
}
// 限购商品数量退还
QueryWrapper<ShopOrderItem> itemQueryWrapper = new QueryWrapper<>();
itemQueryWrapper.in("order_id", order_ids);
List<ShopOrderItem> order_item_rows = shopOrderItemService.find(itemQueryWrapper);
for (ShopOrderItem order_item_row : order_item_rows) {
itemQueryWrapper.in("order_id", orderIds);
List<ShopOrderItem> orderItemRows = shopOrderItemService.find(itemQueryWrapper);
for (ShopOrderItem orderItemRow : orderItemRows) {
// 退还用户购买数量限制
QueryWrapper<ShopUserProductBuy> buyQueryWrapper = new QueryWrapper<>();
buyQueryWrapper.eq("product_id", order_item_row.getProduct_id());
buyQueryWrapper.eq("item_id", order_item_row.getItem_id());
buyQueryWrapper.eq("user_id", order_item_row.getBuyer_id());
buyQueryWrapper.eq("product_id", orderItemRow.getProduct_id());
buyQueryWrapper.eq("item_id", orderItemRow.getItem_id());
buyQueryWrapper.eq("user_id", orderItemRow.getBuyer_id());
List<ShopUserProductBuy> productBuyList = shopUserProductBuyService.find(buyQueryWrapper);
Integer order_item_quantity = order_item_row.getOrder_item_quantity();
Integer orderItemQuantity = orderItemRow.getOrder_item_quantity();
if (CollUtil.isNotEmpty(productBuyList)) {
// 减少用户的已购买数量
for (ShopUserProductBuy productBuy : productBuyList) {
productBuy.setProduct_buy_num(productBuy.getProduct_buy_num() - order_item_quantity);
productBuy.setProduct_buy_num(productBuy.getProduct_buy_num() - orderItemQuantity);
}
if (!shopUserProductBuyService.saveOrUpdate(productBuyList)) {
@ -4242,29 +4268,29 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
}
}
// start 释放冻结库存
// 释放冻结库存
// order_item_inventory_lock: 库存锁定(ENUM):1001-下单锁定;1002-支付锁定;
Integer order_item_inventory_lock = order_item_row.getOrder_item_inventory_lock();
if (ObjectUtil.equal(order_item_inventory_lock, 1001) || ObjectUtil.equal(order_item_inventory_lock, 1002)) {
Long item_id = order_item_row.getItem_id();
ShopProductItem shopProductItem = shopProductItemService.get(item_id);
Integer orderItemInventoryLock = orderItemRow.getOrder_item_inventory_lock();
if (ObjectUtil.equal(orderItemInventoryLock, 1001) || ObjectUtil.equal(orderItemInventoryLock, 1002)) {
Long itemId = orderItemRow.getItem_id();
ShopProductItem shopProductItem = shopProductItemService.get(itemId);
if (shopProductItem != null && CheckUtil.isNotEmpty(shopProductItem.getItem_src_id())) {
shopProductItem.setItem_quantity_frozen(shopProductItem.getItem_quantity_frozen() - order_item_quantity);
shopProductItem.setItem_quantity_frozen(shopProductItem.getItem_quantity_frozen() - orderItemQuantity);
if (!shopProductItemService.edit(shopProductItem)) {
throw new ApiException(String.format(I18nUtil._("释放: %s 冻结库存失败!"), order_item_row.getItem_id()));
throw new ApiException(String.format(I18nUtil._("释放: %s 冻结库存失败!"), orderItemRow.getItem_id()));
}
log.debug("释放库存Item_src_id:{},数量:{}", shopProductItem.getItem_src_id(), order_item_quantity);
log.debug("释放库存Item_src_id:{},数量:{}", shopProductItem.getItem_src_id(), orderItemQuantity);
// RMK 第三方数据同步相关redis 给这个商品加上对应的库存
// Map<String, Integer> stockDeltaMap = new HashMap<>();
// stockDeltaMap.put(shopProductItem.getItem_src_id() + "-" + order_item_row.getOrder_id(), order_item_quantity);
// syncThirdDataService.incrProductStockToRedis(stockDeltaMap);
// Map<String, Integer> stockDeltaMap = new HashMap<>();
// stockDeltaMap.put(shopProductItem.getItem_src_id() + "-" + orderItemRow.getOrder_id(), orderItemQuantity);
// syncThirdDataService.incrProductStockToRedis(stockDeltaMap);
}
}
// 退还礼包活动
if (order_item_row.getActivity_type_id().equals(StateCode.ACTIVITY_TYPE_GIFTPACK)) {
if (orderItemRow.getActivity_type_id().equals(StateCode.ACTIVITY_TYPE_GIFTPACK)) {
QueryWrapper<ShopStoreActivityCode> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("exchange_code", order_item_row.getActivity_code());
queryWrapper.eq("exchange_code", orderItemRow.getActivity_code());
ShopStoreActivityCode shopStoreActivityCode = shopStoreActivityCodeService.findOne(queryWrapper);
shopStoreActivityCode.setUser_id(0);
shopStoreActivityCode.setOrder_id("");
@ -4277,18 +4303,21 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
// 退还优惠券
QueryWrapper<ShopUserVoucher> voucherQueryWrapper = new QueryWrapper<>();
voucherQueryWrapper.in("order_id", order_ids);
voucherQueryWrapper.in("order_id", orderIds);
List<ShopUserVoucher> userVouchers = shopUserVoucherService.find(voucherQueryWrapper);
if (CollUtil.isNotEmpty(userVouchers)) {
userVouchers = userVouchers.stream().map(userVoucher -> userVoucher.setVoucher_state_id(StateCode.VOUCHER_STATE_UNUSED)).collect(Collectors.toList());
// 将已使用的优惠券状态重置为未使用
userVouchers = userVouchers.stream()
.map(userVoucher -> userVoucher.setVoucher_state_id(StateCode.VOUCHER_STATE_UNUSED))
.collect(Collectors.toList());
if (!shopUserVoucherService.edit(userVouchers)) {
throw new ApiException(I18nUtil._("退还优惠券失败!"));
}
}
// 取消拼团
for (String order_id : order_ids) {
cancelActivity(order_id);
// 取消拼团活动
for (String orderId : orderIds) {
cancelActivity(orderId);
}
return true;
@ -5227,7 +5256,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
}
/**
* 取消订单
* 用户C端发起取消订单操作2025年改进支付前后都可以取消订单
*
* @param order_id
* @return
@ -5250,7 +5279,8 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
List<ShopOrderInfo> shopOrderInfos = shopOrderInfoService.gets(order_ids);
List<Map> rows = Convert.toList(Map.class, shopOrderInfos);
// 检查登录用户和订单店铺是否有权限操作取消动作
if (CheckUtil.checkDataRights(user_id, rows, "buyer_user_id") || CheckUtil.checkDataRights(Convert.toInt(user.getStore_id()), rows, "store_id")) {
if (CheckUtil.checkDataRights(user_id, rows, "buyer_user_id")
|| CheckUtil.checkDataRights(Convert.toInt(user.getStore_id()), rows, "store_id")) {
cancel(order_ids, rows, true);
} else {
throw new ApiException(ResultCode.FORBIDDEN);
@ -5267,12 +5297,12 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
*
* @param order_id
* @param shopOrderInfo
* @param check_paid_flag 默认true
* @param checkPaidState 是否检查订单支付状态 默认true
* @return
*/
@Override
@Transactional
public boolean cancel(String order_id, ShopOrderInfo shopOrderInfo, boolean check_paid_flag) {
public boolean cancel(String order_id, ShopOrderInfo shopOrderInfo, boolean checkPaidState) {
// 检测数据是否合法,过滤允许修改的数据
if (StrUtil.isBlank(order_id)) {
throw new ApiException(I18nUtil._("请选择需要取消的订单!"));
@ -5285,7 +5315,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
Integer order_state_id = shopOrderInfo.getOrder_state_id();
Integer order_is_paid = shopOrderInfo.getOrder_is_paid();
if (check_paid_flag && !ifCancel(order_state_id, order_is_paid)) {
if (checkPaidState && !isOrderCancelable(order_state_id, order_is_paid)) {
throw new ApiException(I18nUtil._("无符合取消条件的订单!"));
}
@ -5315,7 +5345,6 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
// 取消顺丰同城配送订单
// === 7. 特殊场景顺丰同城配送且全单退的时候才触发顺丰同城订单取消 ===
if (shopOrderInfo.getDelivery_type_id() != null
&& StateCode.DELIVERY_TYPE_SAME_CITY == shopOrderInfo.getDelivery_type_id().intValue()) {
try {
@ -5329,7 +5358,6 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
}
} catch (Exception e) {
log.error("顺丰同城取消订单异常orderId: {}", order_id, e);
// 可以考虑添加补偿机制或异步重试
}
}
@ -6421,7 +6449,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
type_code = StrUtil.isBlank(type_code) ? "DD" : type_code;
String xid = RootContext.getXID();
RootContext.unbind();
Pair<Long, String> seqPair = shopNumberSeqService.createNextSeqPair(type_code);// 位数的序号 DD_20251205_1 2025-12-05 1
Pair<Long, String> seqPair = shopNumberSeqService.createNextSeqPair(type_code);// 位数的序号 DD_20251205_12-> pair 12, 2025-12-05
String order_id = seqPair.getSecond();
Long seqNo = seqPair.getFirst(); // 序号 DD_20251205_1 得出 1
RootContext.bind(xid);
@ -6582,7 +6610,9 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
order_payment_amount = NumberUtil.max(order_payment_amount, BigDecimal.valueOf(0));
// 订单原价商品金额
base_row.put("order_product_amount", Convert.toBigDecimal(store_item.get("productMoneyOriginGoods")));
BigDecimal order_product_amount = Convert.toBigDecimal(store_item.get("productMoneyOriginGoods"));
// log.info("订单原价商品金额计算:{}", order_payment_amount);
base_row.put("order_product_amount", order_product_amount);
//重要应付款金额计算
base_row.put("order_payment_amount", order_payment_amount);
@ -6622,6 +6652,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
base_row.put("buyer_user_name", buyer_user_name);
ShopOrderBase baseRow = Convert.convert(ShopOrderBase.class, base_row);
// logger.info("【重要】订单基础信息保存:{}", base_row);
// 重要订单基础信息保存
boolean flag = saveOrUpdate(baseRow);
@ -6906,7 +6937,6 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
Integer activity_double_points_id = 0;
//均分组合套餐 其余活动可视情况使用此处
BigDecimal deduct_discount = BigDecimal.ZERO;
BigDecimal reduction_discount = BigDecimal.ZERO;
BigDecimal reduction_again_discount = BigDecimal.ZERO;
@ -6928,7 +6958,6 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
Integer cart_quantity = Convert.toInt(_item.get("cart_quantity"));
BigDecimal item_unit_sp = Convert.toBigDecimal(_item.get("item_unit_sp"));
BigDecimal item_unit_points = Convert.toBigDecimal(_item.get("item_unit_points"));
BigDecimal item_share_redemption = BigDecimal.ZERO;
// 均分优惠券
@ -7832,8 +7861,29 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
// 店铺统一设置的打包费
data_row.setPacking_fee(packingFee);
// 平台最低配送费单位
Integer innerMinDeliverFee = accountBaseConfigService.getInnerMinDeliveryFee(store_id);
Integer innerMinDeliverFee = 0;
Map address = (Map) cart_data.get("address_row");
if (CollUtil.isNotEmpty(address)) {
String longitude = Convert.toStr(address.get("ud_longitude"));
String latitude = Convert.toStr(address.get("ud_latitude"));
log.info("平台内部配送费计算:经纬度:{}", longitude + ":" + latitude);
// 检查经纬度是否有效
if (StrUtil.isNotBlank(longitude) && StrUtil.isNotBlank(latitude)) {
// 平台最低配送费单位
innerMinDeliverFee = accountBaseConfigService.getInnerMinDeliveryFee(
delivery_type_id,
store_id,
longitude,
latitude,
0,
order_product_amount,
order_payment_amount.subtract(_freight),
order_payment_amount
);
}
}
// 平台最低配送费单位
BigDecimal shoppingFeeInner = Convert.toBigDecimal(innerMinDeliverFee).divide(BigDecimal.valueOf(100));
@ -8373,7 +8423,9 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
Integer payment_type_id = Convert.toInt(order_info_row.get("payment_type_id"));
Integer order_is_paid = Convert.toInt(order_info_row.get("order_is_paid"));
order_info_row.put("if_buyer_cancel", ifCancel(order_state_id, order_is_paid));
// 订单是否禁止退货
boolean is_denyreturn = shopOrderReturnService.isOrderDenyReturn(Convert.toStr(order_info_row.get("order_id"))); //shopOrderReturnService.ifDenyReturn(Convert.toLong(order_info_row.get("order_item_id")));
order_info_row.put("if_buyer_cancel", isOrderCancelable(order_state_id, order_is_paid) || !is_denyreturn);
order_info_row.put("if_logistics", ifLogistics(order_state_id));
order_info_row.put("order_shipping_fee", order_data_row.get("order_shipping_fee"));
order_info_row.put("order_payment_name", shopBaseStateCodeService.getText(payment_type_id, null));
@ -8408,17 +8460,26 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
}
/**
* 检查是否可以取消
* 检查订单是否可以取消
* 只有未付款且处于特定状态的订单才能取消
*
* @param order_state_id 订单状态
* @param order_is_paid
* @return boolean true-false-不可
* @param orderStateId 订单状态ID
* @param orderIsPaid 订单付款状态
* @return boolean true-以取消false-不可以取消
*/
private boolean ifCancel(Integer order_state_id, Integer order_is_paid) {
// 订单状态2010-待付款;2011-待订单审核;2013-待财务审核;2020-待配货;2030-待发货
List<Integer> order_states = Arrays.asList(StateCode.ORDER_STATE_WAIT_PAY, StateCode.ORDER_STATE_WAIT_REVIEW, StateCode.ORDER_STATE_WAIT_FINANCE_REVIEW, StateCode.ORDER_STATE_PICKING, StateCode.ORDER_STATE_WAIT_SHIPPING);
// 3010-未付款未付款的订单才能取消
return order_states.contains(order_state_id) && ObjectUtil.equal(order_is_paid, StateCode.ORDER_PAID_STATE_NO);
private boolean isOrderCancelable(Integer orderStateId, Integer orderIsPaid) {
// 可以取消订单的状态列表待付款待审核待财务审核待配货待发货
List<Integer> cancelableStates = Arrays.asList(
StateCode.ORDER_STATE_WAIT_PAY,
StateCode.ORDER_STATE_WAIT_REVIEW,
StateCode.ORDER_STATE_WAIT_FINANCE_REVIEW,
StateCode.ORDER_STATE_PICKING,
StateCode.ORDER_STATE_WAIT_SHIPPING
);
// 订单必须处于可取消状态且未付款才能取消
return cancelableStates.contains(orderStateId) &&
ObjectUtil.equal(orderIsPaid, StateCode.ORDER_PAID_STATE_NO);
}
// QueryWrapper<ShopOrderInfo> queryWrapper,
@ -8855,7 +8916,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
m.put("delivery_time", DateUtil.offsetSecond(paymentTime, mchOrderExpireSeconds.intValue()));
// 配送方式
String deliveryTypeName = StateCode.DELIVERY_TYPE_MAP.getOrDefault(m.getOrDefault("delivery_type_id", StateCode.DELIVERY_TYPE_SAME_CITY), "普通快递");
String deliveryTypeName = CommonService.getDeliveryExpressName(Convert.toInt(m.get("delivery_type_id")));
m.put("delivery_type_name", deliveryTypeName);
// 预留字段
@ -8908,7 +8969,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
ShopStoreBase shopStoreBase = shopStoreBaseService.get(storeId);
ShopStoreInfo shopStoreInfo = shopStoreInfoService.get(storeId);
ShopOrderDeliveryAddress shopOrderDeliveryAddress = shopOrderDeliveryAddressService.selectByOrderId(shopOrderId);
ShopStoreSameCityTransportBase shopStoreSameCityTransportBase = shopStoreSameCityTransportBaseService.getShopStoreSameCityTransportBaseById(storeId.longValue());
ShopStoreSameCityTransportBase shopStoreSameCityTransportBase = shopStoreSameCityTransportBaseService.getShopStoreSameCityTransportBaseById(storeId.longValue(), CommonConstant.Disable2);
if (shopStoreBase == null || shopStoreInfo == null || shopOrderDeliveryAddress == null || shopStoreSameCityTransportBase == null) {
logger.error("构建顺丰订单失败无法获取店铺信息订单ID={}storeId={}", shopOrderId, storeId);
return null;

View File

@ -30,6 +30,7 @@ import com.suisung.mall.common.modules.product.ShopProductComment;
import com.suisung.mall.common.modules.store.ShopStoreBase;
import com.suisung.mall.common.modules.store.ShopStoreInfo;
import com.suisung.mall.common.pojo.dto.BookingArgDTO;
import com.suisung.mall.common.pojo.dto.OrderCacDeliveryFeeDTO;
import com.suisung.mall.common.pojo.res.ThirdApiRes;
import com.suisung.mall.common.utils.CheckUtil;
import com.suisung.mall.common.utils.CommonUtil;
@ -376,7 +377,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
* @param orderId 订单ID
* @return 取货单号
*/
// @Transactional
@Transactional
@Override
public Long isPaidOrderGenPickNumAndPrint(Integer storeId, String orderId) {
logger.info("####开始处理订单{}的取单号生成和打印####", orderId);
@ -426,7 +427,6 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
orderInfo.setOrder_id(orderId);
orderInfo.setOrder_pickup_num(orderPickupNum);
orderInfo.setOrder_express_print(CommonConstant.Enable); // 打印标记 1-已打印
if (!edit(orderInfo)) {
logger.error("更新订单取单号失败: orderId={}", orderId);
return 0L;
@ -1287,6 +1287,53 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
}
}
/**
* 判断订单是否满足收取内部配送费条件
* <p>
* 内部配送费仅适用于同城配送方式该方法通过检查配送方式是否为同城配送来判断是否满足条件
*
* @param deliveryTypeId 配送方式ID
* @return Boolean 是否满足内部配送费条件
*/
@Override
public Boolean hasInnerMinDeliveryFee(Integer deliveryTypeId) {
// 参数校验
if (CheckUtil.isEmpty(deliveryTypeId)) {
logger.warn("[获取内部配送费] 配送方式ID为空deliveryTypeId: {}", deliveryTypeId);
return false;
}
// 检查配送方式是否为同城配送只有同城配送才有内部配送费
boolean isSameCityDelivery = StateCode.DELIVERY_TYPE_MAP.containsKey(deliveryTypeId)
&& ObjectUtil.equal(StateCode.DELIVERY_TYPE_SAME_CITY, deliveryTypeId);
logger.debug("[获取内部配送费] 配送方式检查结果, deliveryTypeId: {}, isSameCityDelivery: {}",
deliveryTypeId, isSameCityDelivery);
return isSameCityDelivery;
}
/**
* 根据订单ID获取计算配送费所需的订单信息
* <p>
* 查询逻辑说明:
* 1. 从订单基础信息表获取订单ID店铺ID和商品总额
* 2. 从订单数据表计算实际支付金额(订单支付金额 - 运费金额)
* 3. 从订单数据表计算折扣金额(商品总额 - 折扣金额 - 调整金额 - 积分抵扣金额)
* 4. 从订单配送地址表获取配送地址的经纬度
*
* @param orderId 订单ID
* @return OrderCacDeliveryFeeDTO 订单配送费计算参数实体
*/
@Override
public OrderCacDeliveryFeeDTO getOrderCacDeliveryFeeArgs(String orderId) {
if (StrUtil.isBlank(orderId)) {
return null;
}
return shopOrderInfoMapper.getOrderCacDeliveryFeeArgs(orderId);
}
/**
* 根据一个或多个店铺id获取有效店铺的有效营业时间段

View File

@ -488,7 +488,6 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
returnItemQueryWrapper.in("order_item_id", order_item_ids)
.in("return_id", return_ids);
List<ShopOrderReturnItem> order_return_items = orderReturnItemService.find(returnItemQueryWrapper);
if (CollUtil.isNotEmpty(order_return_items)) {
throw new ApiException(I18nUtil._("此订单商品正在退款审核!"));
}
@ -568,17 +567,16 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
// 构建退款单明细
ShopOrderReturnItem orderReturnItem = new ShopOrderReturnItem();
Integer return_item_num = returnItemInputVo.getReturn_item_num();
Integer return_item_num = returnItemInputVo.getReturn_item_num(); //用户当前申请退款的商品数量
if (return_item_num <= 0) {
throw new ApiException("退款数量必须大于0请检查商品 " + shopOrderItem.getItem_name() + " 的退款数量");
}
// 检查退款数量是否超过可退数量
Integer order_item_quantity = shopOrderItem.getOrder_item_quantity();
Integer order_item_return_agree_num = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_num(), 0);
Integer available_return_num = order_item_quantity - order_item_return_agree_num;
Integer order_item_quantity = shopOrderItem.getOrder_item_quantity(); // 订单中该商品的原始购买数量
Integer order_item_return_agree_num = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_num(), 0); // 订单中该商品已经同意退货的数量
Integer available_return_num = order_item_quantity - order_item_return_agree_num; // 当前还可以申请退款的商品数量
if (return_item_num > available_return_num) {
throw new ApiException(String.format("商品 %s 的退款数量超过可退数量,最多可退 %d 件",
shopOrderItem.getItem_name(), available_return_num));
@ -650,6 +648,208 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
return CommonResult.success(data);
}
// @Override
/**
* 尝试批量添加退款退货申请自动使用最大可退数量和金额
*
* @param orderReturnInputVo 退款申请输入参数支持订单多个商品退款
* @return CommonResult 退款申请结果
*/
@Override
@Transactional
public CommonResult tryAddItemBatch(OrderReturnInputVo orderReturnInputVo) {
Map<String, Object> data = new HashMap<>();
// 获取用户ID
Integer user_id = orderReturnInputVo.getUser_id();
if (CheckUtil.isEmpty(user_id)) {
UserDto user = getCurrentUser();
if (user == null) {
throw new ApiUserException(I18nUtil._("用户信息异常!"));
}
user_id = user.getId();
}
// 获取买家店铺ID如果有
Integer buyer_store_id = shopStoreBaseService.getStoreId(user_id);
// 获取订单信息
String order_id = orderReturnInputVo.getOrder_id();
List<Long> order_item_ids = orderReturnInputVo.getReturn_items().stream()
.map(OrderReturnItemInputVo::getOrder_item_id)
.distinct()
.collect(Collectors.toList());
ShopOrderInfo shopOrderInfo = shopOrderInfoService.get(order_id);
if (shopOrderInfo == null) {
throw new ApiException(I18nUtil._("此订单信息数据有误!"));
}
ShopOrderBase orderBase = shopOrderBaseService.get(order_id);
if (orderBase == null) {
throw new ApiException(I18nUtil._("此订单详细信息数据有误!"));
}
// 判断此订单商品是否有正在审核的退款单
QueryWrapper<ShopOrderReturn> returnQueryWrapper = new QueryWrapper<>();
returnQueryWrapper.eq("order_id", order_id)
.eq("return_state_id", StateCode.RETURN_PROCESS_CHECK);
List<ShopOrderReturn> order_return_rows = find(returnQueryWrapper);
if (CollUtil.isNotEmpty(order_return_rows)) {
List<String> return_ids = order_return_rows.stream()
.map(ShopOrderReturn::getReturn_id)
.collect(Collectors.toList());
QueryWrapper<ShopOrderReturnItem> returnItemQueryWrapper = new QueryWrapper<>();
returnItemQueryWrapper.in("order_item_id", order_item_ids)
.in("return_id", return_ids);
List<ShopOrderReturnItem> order_return_items = orderReturnItemService.find(returnItemQueryWrapper);
if (CollUtil.isNotEmpty(order_return_items)) {
throw new ApiException(I18nUtil._("此订单商品正在退款审核!"));
}
}
// 检查数据权限
if (!CheckUtil.checkDataRights(user_id, orderBase, ShopOrderBase::getBuyer_user_id)) {
throw new ApiException(ResultCode.FORBIDDEN);
}
// 获取退款申请参数
String return_id = orderReturnInputVo.getReturn_id();
Integer return_reason_id = orderReturnInputVo.getReturn_reason_id() == null ? 0 : orderReturnInputVo.getReturn_reason_id();
String return_buyer_message = orderReturnInputVo.getReturn_buyer_message();
Integer store_id = Convert.toInt(orderBase.getStore_id());
String return_tel = orderReturnInputVo.getReturn_tel();
// 手机号验证
if (StrUtil.isNotBlank(return_tel) && !PhoneUtil.isMobile(return_tel)) {
throw new ApiException(I18nUtil._("手机号输入有误!"));
}
Date curTime = new Date();
// 构建退款单主表信息
ShopOrderReturn orderReturn = new ShopOrderReturn();
orderReturn.setReturn_id(return_id);
orderReturn.setOrder_id(order_id);
orderReturn.setBuyer_user_id(user_id);
orderReturn.setBuyer_store_id(buyer_store_id);
orderReturn.setReturn_reason_id(return_reason_id);
orderReturn.setReturn_buyer_message(return_buyer_message);
orderReturn.setStore_id(store_id);
orderReturn.setReturn_refund_amount(BigDecimal.ZERO);
orderReturn.setReturn_commision_fee(BigDecimal.ZERO);
orderReturn.setReturn_state_id(StateCode.RETURN_PROCESS_CHECK);
orderReturn.setReturn_tel(return_tel);
orderReturn.setReturn_year(DateUtil.year(curTime)); // 退单年份-索引查询
orderReturn.setReturn_month(DateUtil.month(curTime) + 1); // 退单月份-索引查询
orderReturn.setReturn_day(DateUtil.dayOfMonth(curTime)); // 退单日-索引查询
orderReturn.setReturn_reason_id(0); // 注意这里覆盖了前面设置的return_reason_id
orderReturn.setReturn_store_user_id(0);
orderReturn.setReturn_mobile(0L);
orderReturn.setReturn_telephone("");
orderReturn.setSubsite_id(shopOrderInfo.getSubsite_id());
// 构建退款单明细信息
List<ShopOrderReturnItem> shopOrderReturnItems = new ArrayList<>();
for (OrderReturnItemInputVo returnItemInputVo : orderReturnInputVo.getReturn_items()) {
// 获取订单商品信息
ShopOrderItem shopOrderItem = shopOrderItemService.get(returnItemInputVo.getOrder_item_id());
if (shopOrderItem == null) {
throw new ApiException("订单商品不存在请检查商品ID是否正确: " + returnItemInputVo.getOrder_item_id());
}
// 验证是否为当前订单的商品
if (!order_id.equals(shopOrderItem.getOrder_id())) {
throw new ApiException("商品ID " + returnItemInputVo.getOrder_item_id() + " 不属于订单 " + order_id);
}
// 获取商品索引信息
ShopProductIndex shopProductIndex = shopProductIndexService.get(shopOrderItem.getProduct_id());
if (shopProductIndex == null) {
throw new ApiException("商品信息不存在请检查商品ID是否正确: " + shopOrderItem.getProduct_id());
}
// 检查是否允许退货
boolean is_denyreturn = ifDenyReturn(shopOrderInfo, shopOrderItem, shopProductIndex);
if (is_denyreturn) {
// 获取更详细的拒绝退货原因
String denyReason = getDenyReturnReason(shopOrderInfo, shopOrderItem, shopProductIndex);
if (StrUtil.isBlank(denyReason)) {
denyReason = "此商品不允许退货!";
}
throw new ApiException(denyReason);
}
// 构建退款单明细
ShopOrderReturnItem orderReturnItem = new ShopOrderReturnItem();
// 检查退款数量是否超过可退数量
Integer order_item_quantity = shopOrderItem.getOrder_item_quantity(); // 订单中该商品的原始购买数量
Integer order_item_return_agree_num = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_num(), 0); // 订单中该商品已经同意退货的数量
Integer available_return_num = order_item_quantity - order_item_return_agree_num; // 当前还可以申请退款的商品数量
if (available_return_num <= 0) {
throw new ApiException(String.format("商品 %s 已无可退数量", shopOrderItem.getItem_name()));
}
// 检查退款金额是否合理
BigDecimal order_item_payment_amount = shopOrderItem.getOrder_item_payment_amount();
BigDecimal order_item_return_agree_amount = ObjectUtil.defaultIfNull(shopOrderItem.getOrder_item_return_agree_amount(), BigDecimal.ZERO);
BigDecimal available_return_amount = order_item_payment_amount.subtract(order_item_return_agree_amount);
if (available_return_amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new ApiException(String.format("商品 %s 已无可退金额", shopOrderItem.getItem_name()));
}
String return_item_image = ObjectUtil.defaultIfBlank(
orderReturnInputVo.getRefund_pic(),
orderReturnInputVo.getUpload_img());
orderReturnItem.setOrder_item_id(returnItemInputVo.getOrder_item_id());
orderReturnItem.setOrder_id(order_id);
orderReturnItem.setReturn_item_num(available_return_num);
orderReturnItem.setReturn_item_subtotal(available_return_amount);
orderReturnItem.setReturn_reason_id(return_reason_id);
orderReturnItem.setReturn_item_note(return_buyer_message);
orderReturnItem.setReturn_item_image(return_item_image);
orderReturnItem.setReturn_state_id(StateCode.RETURN_PROCESS_CHECK);
shopOrderReturnItems.add(orderReturnItem);
}
// 保存退款单
if (!addReturnByItem(orderReturn, shopOrderReturnItems)) {
throw new ApiException(ResultCode.FAILED);
}
data.put("return", orderReturn);
data.put("items", shopOrderReturnItems);
// 打票机打印退款订单到店(异步执行)
shopStorePrinterService.printShopStoreReturnOrder(return_id);
// 发送消息通知, 退款提醒商家
String message_id = "refund-reminder";
Map<String, Object> args = new HashMap<>();
args.put("order_id", orderReturn.getReturn_id());
messageService.sendNoticeMsg(0, store_id, message_id, args);
// 发送unipush消息
String title = "您有一个退款的订单,请及时前往后台审核!";
String content = String.format("订单号:%s 退单号:[%s],时间:%s请及时前往后台审核",
order_id, orderReturn.getReturn_id(),
DateTimeUtils.formatDateTime(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss"));
JSONObject payload = JSONUtil.createObj();
payload.set("category", CommonConstant.PUSH_MSG_CATE_MCH_RETURN_ORDER_LIST);
payload.set("orderId", order_id);
payload.set("returnId", orderReturn.getReturn_id());
pushMessageService.noticeMerchantEmployeeOrderAction(store_id, order_id, title, content, payload);
data.put("order_item_ids", order_item_ids);
return CommonResult.success(data);
}
/**
* 取消退货
@ -2287,20 +2487,20 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
public boolean ifDenyReturn(ShopOrderInfo shopOrderInfo, ShopOrderItem shopOrderItem, ShopProductIndex shopProductIndex) {
// 1. 参数校验
if (shopOrderInfo == null) {
log.debug("[是否禁止退货] 订单信息为空,禁止退货");
log.info("[是否禁止退货] 订单信息为空,禁止退货");
return true;
}
String orderId = shopOrderInfo.getOrder_id();
Integer orderStateId = shopOrderInfo.getOrder_state_id();
if (StrUtil.isBlank(orderId) || CheckUtil.isEmpty(orderStateId)) {
log.debug("[是否禁止退货] 订单ID或订单状态为空禁止退货");
log.info("[是否禁止退货] 订单ID或订单状态为空禁止退货");
return true;
}
if (orderStateId.intValue() == StateCode.ORDER_STATE_CANCEL ||
orderStateId.intValue() == StateCode.ORDER_STATE_WAIT_PAY) {
log.debug("[是否禁止退货] 订单状态为已取消或未支付禁止退货order_id: {}, orderStateId: {}", orderId, orderStateId);
log.info("[是否禁止退货] 订单状态为已取消或未支付禁止退货order_id: {}, orderStateId: {}", orderId, orderStateId);
return true;
}
@ -2315,12 +2515,12 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
// 检查是否超过退货期限
if (orderDealTime != null && withdrawTime.compareTo(orderDealTime) > 0) {
log.debug("[是否禁止退货] 订单已超过退货期限禁止退货order_id: {}, orderDealTime: {}, withdrawTime: {}",
log.info("[是否禁止退货] 订单已超过退货期限禁止退货order_id: {}, orderDealTime: {}, withdrawTime: {}",
orderId, orderDealTime, withdrawTime);
return true;
}
} catch (Exception e) {
log.error("[是否禁止退货] 检查订单退货期限时发生异常禁止退货order_id: {}", orderId, e);
log.info("[是否禁止退货] 检查订单退货期限时发生异常禁止退货order_id: {}", orderId, e);
return true;
}
}
@ -2333,19 +2533,19 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
boolean isLklProcessed = isSeparated && isDrawn;
if (isLklProcessed) {
log.debug("[是否禁止退货] 拉卡拉分账订单已提现禁止退货order_id: {}, separated: {}, drawed: {}",
log.info("[是否禁止退货] 拉卡拉分账订单已提现禁止退货order_id: {}, separated: {}, drawed: {}",
orderId, isSeparated, isDrawn);
return true;
}
}
} catch (Exception e) {
log.error("[是否禁止退货] 检查拉卡拉分账状态时发生异常禁止退货order_id: {}", orderId, e);
return true;
return false;
}
// 如果没有商品相关信息则只检查订单级别
if (shopOrderItem == null && shopProductIndex == null) {
log.debug("[是否禁止退货] 无商品信息仅检查订单级别允许退货order_id: {}", orderId);
log.info("[是否禁止退货] 无商品信息仅检查订单级别允许退货order_id: {}", orderId);
return false;
}
@ -2362,7 +2562,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
}
if (productIndex == null) {
log.debug("[是否禁止退货] 商品索引信息不存在允许退货order_id: {}", orderId);
log.info("[是否禁止退货] 商品索引信息不存在允许退货order_id: {}", orderId);
return false;
}
@ -2372,7 +2572,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
try {
List<Integer> contractTypeIds = Convert.toList(Integer.class, contractTypeIdsStr);
if (contractTypeIds != null && contractTypeIds.contains(StateCode.CONTRACT_TYPE_DENY_RETURN)) {
log.debug("[是否禁止退货] 商品设置了禁止退货标识禁止退货order_id: {}, product_id: {}", orderId, productIndex.getProduct_id());
log.info("[是否禁止退货] 商品设置了禁止退货标识禁止退货order_id: {}, product_id: {}", orderId, productIndex.getProduct_id());
return true;
}
} catch (Exception e) {
@ -2381,8 +2581,13 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
}
}
if (shopOrderItem != null && CheckUtil.isNotEmpty(shopOrderItem.getOrder_item_id()) && !ifCanReturnOrderItem(shopOrderItem)) {
// 3.2 检查商品退款详情里是否已经提交过退款申请, 且数量大于订单数量或金额大于订单金额
return true;
}
// 默认允许退货
log.debug("[是否禁止退货] 商品允许退货order_id: {}, product_id: {}", orderId, productIndex.getProduct_id());
log.info("[是否禁止退货] 商品允许退货order_id: {}, product_id: {}", orderId, productIndex.getProduct_id());
return false;
}
@ -2488,26 +2693,52 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
* 若商品索引为空抛出异常
* 调用另一个重载方法 ifDenyReturn(...) 进行具体的退货规则判断
*
* @param order_item_id
* @return
* @param order_item_id 订单商品ID
* @return 是否禁止退货
*/
@Override
public boolean ifDenyReturn(Long order_item_id) {
ShopOrderItem shopOrderItem = shopOrderItemService.get(order_item_id);
if (shopOrderItem == null) {
throw new ApiException(I18nUtil._("此订单商品订单数据有误!"));
// 参数校验
if (order_item_id == null) {
logger.warn("[禁止退货检查] 订单商品ID为空");
return true;
}
String order_id = shopOrderItem.getOrder_id();
try {
ShopOrderItem shopOrderItem = shopOrderItemService.get(order_item_id);
if (shopOrderItem == null) {
logger.warn("[禁止退货检查] 订单商品不存在orderItemId: {}", order_item_id);
// throw new ApiException(I18nUtil._("此订单商品订单数据有误!"));
return true;
}
ShopOrderInfo shopOrderInfo = shopOrderInfoService.get(order_id);
ShopProductIndex shopProductIndex = shopProductIndexService.get(shopOrderItem.getProduct_id());
String order_id = shopOrderItem.getOrder_id();
if (StrUtil.isBlank(order_id)) {
logger.warn("[禁止退货检查] 订单ID为空orderItemId: {}", order_item_id);
// throw new ApiException(I18nUtil._("订单信息异常!"));
return true;
}
if (shopProductIndex == null) {
throw new ApiException(I18nUtil._("此订单商品数据有误!"));
ShopOrderInfo shopOrderInfo = shopOrderInfoService.get(order_id);
if (shopOrderInfo == null) {
logger.warn("[禁止退货检查] 订单信息不存在orderId: {}", order_id);
// throw new ApiException(I18nUtil._("订单信息不存在!"));
return true;
}
ShopProductIndex shopProductIndex = shopProductIndexService.get(shopOrderItem.getProduct_id());
if (shopProductIndex == null) {
logger.warn("[禁止退货检查] 商品索引信息不存在productId: {}", shopOrderItem.getProduct_id());
// throw new ApiException(I18nUtil._("此订单商品数据有误!"));
return true;
}
return ifDenyReturn(shopOrderInfo, shopOrderItem, shopProductIndex);
} catch (Exception e) {
logger.error("[禁止退货检查] 处理异常orderItemId: {}", order_item_id, e);
// 为保证系统稳定性异常情况下默认禁止退货
return true;
}
return ifDenyReturn(shopOrderInfo, shopOrderItem, shopProductIndex);
}
/**
@ -3099,4 +3330,59 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
return "商品不支持退货";
}
/**
* 判断订单子项是否可以退款
* 条件
* 1. 订单子项必须存在
* 2. 可退数量 > 0 (订单商品数量 > 已退货数量)
* 3. 可退金额 > 0 (订单商品金额 > 已同意退款金额)
*
* @param orderItemId 订单子项ID
* @return boolean 是否可以退款
*/
private boolean ifCanReturnOrderItem(Long orderItemId) {
// 查询订单子项是否存在
ShopOrderItem orderItem = shopOrderItemService.get(orderItemId);
return ifCanReturnOrderItem(orderItem);
}
/**
* 判断订单子项是否可以退款
* 条件
* 1. 订单子项必须存在
* 2. 可退数量 > 0 (订单商品数量 > 已退货数量)
* 3. 可退金额 > 0 (订单商品金额 > 已同意退款金额)
*
* @param orderItem 订单子项
* @return boolean 是否可以退款
*/
private boolean ifCanReturnOrderItem(ShopOrderItem orderItem) {
// 如果订单子项不存在不能退款
if (orderItem == null) {
log.info("订单子项为空,无法退款");
return false;
}
// 获取订单子项的相关字段使用默认值避免空指针
Integer orderItemQuantity = ObjectUtil.defaultIfNull(orderItem.getOrder_item_quantity(), 0);
Integer orderItemReturnNum = ObjectUtil.defaultIfNull(orderItem.getOrder_item_return_num(), 0);
BigDecimal orderItemAmount = ObjectUtil.defaultIfNull(orderItem.getOrder_item_amount(), BigDecimal.ZERO);
BigDecimal orderItemReturnAgreeAmount = ObjectUtil.defaultIfNull(orderItem.getOrder_item_return_agree_amount(), BigDecimal.ZERO);
// 记录调试信息
log.info("订单子项退款检查 - 商品ID: {}, 订单数量: {}, 已退数量: {}, 商品金额: {}, 已同意退款金额: {}",
orderItem.getProduct_id(), orderItemQuantity, orderItemReturnNum, orderItemAmount, orderItemReturnAgreeAmount);
// 判断是否可以退款
// 1. 可退数量 > 0 (订单商品数量 > 已退货数量)
boolean canReturnQuantity = orderItemQuantity > orderItemReturnNum;
// 2. 可退金额 > 0 (订单商品金额 > 已同意退款金额)
boolean canReturnAmount = orderItemAmount.compareTo(orderItemReturnAgreeAmount) > 0;
log.info("退款条件检查结果 - 可退数量: {}, 可退金额: {}", canReturnQuantity, canReturnAmount);
return canReturnQuantity && canReturnAmount;
}
}

View File

@ -269,12 +269,12 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
// 3. 获取或初始化商家配送信息
ShopStoreSameCityTransportBase transportBase = shopStoreSameCityTransportBaseService
.getShopStoreSameCityTransportBaseById(Long.valueOf(storeId));
.getShopStoreSameCityTransportBaseById(Long.valueOf(storeId), CommonConstant.Disable2);
if (transportBase == null) {
// 如果没有商家配送运费设置则初始化
shopStoreSameCityTransportBaseService.initDefaultSameCityTransport(storeId);
transportBase = shopStoreSameCityTransportBaseService.getShopStoreSameCityTransportBaseById(Long.valueOf(storeId));
transportBase = shopStoreSameCityTransportBaseService.getShopStoreSameCityTransportBaseById(Long.valueOf(storeId), CommonConstant.Disable2);
}
if (transportBase == null) {
@ -963,7 +963,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
return new ThirdApiRes().fail(1003, "缺少店铺 Id");
}
ShopStoreSameCityTransportBase shopStoreSameCityTransportBase = shopStoreSameCityTransportBaseService.getShopStoreSameCityTransportBaseById(storeId);
ShopStoreSameCityTransportBase shopStoreSameCityTransportBase = shopStoreSameCityTransportBaseService.getShopStoreSameCityTransportBaseById(storeId, CommonConstant.Disable2);
if (shopStoreSameCityTransportBase == null) {
logger.error("无法获取顺丰店铺 Id");
return new ThirdApiRes().fail(1003, "无法获取店铺Id");

View File

@ -5,10 +5,12 @@ import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.domain.UserDto;
import com.suisung.mall.common.modules.store.ShopStoreInfo;
import com.suisung.mall.common.service.impl.BaseControllerImpl;
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
import com.suisung.mall.shop.store.service.ShopStoreInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@ -30,6 +32,12 @@ public class ShopStoreInfoController extends BaseControllerImpl {
@Autowired
private ShopStoreInfoService shopStoreInfoService;
@Lazy
@Autowired
private AccountBaseConfigService accountBaseConfigService;
/**
* 分页列表查询
*
@ -83,13 +91,13 @@ public class ShopStoreInfoController extends BaseControllerImpl {
/**
* 获取店铺的内部运费 shopping_fee_inner 远程调用用途
*
* @param store_id
* @param order_id
* @return
*/
@ApiOperation(value = "获取店铺的内部运费 shopping_fee_inner", notes = "获取店铺的内部运费 shopping_fee_inner (远程调用用途)")
@RequestMapping(value = "/shopping-fee-inner", method = RequestMethod.POST)
public Integer storeShoppingFeeInner(@RequestParam(name = "store_id") Integer store_id) {
return shopStoreInfoService.getStoreShippingFeeInner(store_id);
public Integer storeShoppingFeeInner(@RequestParam(name = "order_id") String order_id) {
return accountBaseConfigService.getInnerMinDeliveryFee(order_id);
}
}

View File

@ -10,8 +10,6 @@ import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@Api(tags = "同城配送运费设置控制器")
@RestController
@RequestMapping("/admin/shop/store/same-city-transport")
@ -25,8 +23,8 @@ public class ShopStoreSameCityTransportBaseController {
@ApiOperation(value = "获取同城配送运费设置详情", notes = "获取同城配送运费设置详情")
@RequestMapping(value = "/detail", method = {RequestMethod.GET})
public CommonResult shopStoreSameCityTransportBaseDetail() {
return transportBaseService.ShopStoreSameCityTransportBaseDetail();
public CommonResult shopStoreSameCityTransportBaseDetail(@RequestParam(name = "store_id", required = false, defaultValue = "0") Long store_id) {
return transportBaseService.ShopStoreSameCityTransportBaseDetail(store_id);
}
@ApiOperation(value = "保存(新增或修改)同城配送运费设置", notes = "保存(新增或修改)同城配送运费设置")

View File

@ -10,8 +10,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "同城配送运费设置控制器")
@RestController
@RequestMapping("/mobile/shop/store/same-city-transport")
@ -22,7 +20,7 @@ public class ShopStoreSameCityTransportBaseMobileController {
@ApiOperation(value = "下单前检测同城订单配送是否符合要求", notes = "下单前检测同城订单配送是否符合要求")
@RequestMapping(value = "/check/same-city/delivery", method = {RequestMethod.POST})
public CommonResult checkSameCityDelivery(@RequestParam(name = "store_id", defaultValue = "0") Integer storeId) {
return transportBaseService.ShopStoreSameCityTransportBaseDetail();
public CommonResult checkSameCityDelivery(@RequestParam(name = "store_id", required = false, defaultValue = "0") Long store_id) {
return transportBaseService.ShopStoreSameCityTransportBaseDetail(store_id);
}
}

View File

@ -21,9 +21,10 @@ public interface ShopStoreSameCityTransportBaseService {
/**
* 获取同城配送设置详情信息
*
* @param storeId
* @return
*/
CommonResult ShopStoreSameCityTransportBaseDetail();
CommonResult ShopStoreSameCityTransportBaseDetail(Long storeId);
/**
* 保存或更新同城配送各项设置
@ -52,17 +53,19 @@ public interface ShopStoreSameCityTransportBaseService {
* 根据店铺 Id 获取同城配送设置详情信息
*
* @param storeId
* @param isPlatform 1-平台 2-店铺
* @return
*/
ShopStoreSameCityTransportBaseDTO getShopStoreSameCityTransportBaseDTOById(Long storeId);
ShopStoreSameCityTransportBaseDTO getShopStoreSameCityTransportBaseDTOById(Long storeId, Integer isPlatform);
/**
* 根据店铺Id获取同城配送基础运费记录
*
* @param storeId
* @param isPlatform 1-平台 2-店铺
* @return
*/
ShopStoreSameCityTransportBase getShopStoreSameCityTransportBaseById(Long storeId);
ShopStoreSameCityTransportBase getShopStoreSameCityTransportBaseById(Long storeId, Integer isPlatform);
/**
* 保存同城配送基础设置存在更新不存在新增
@ -96,4 +99,25 @@ public interface ShopStoreSameCityTransportBaseService {
*/
SameCityDeliveryFeeRespDTO computeSameCityTransportFee(Long storeId, String orderLongitude, String orderLatitude, Integer weightGram, BigDecimal orderProductAmount, BigDecimal orderDiscountAmount, BigDecimal orderPayAmount, Boolean canThrow);
/**
* 平台计算同城订单的内部配送费仅仅作用于平台内部配送费计算商家配送费忽略此方法只对下单成功的订单起效果
*
* @param orderId 订单ID
* @return 配送费单位为分
*/
Integer computeSameCityInnerDeliveryFeeByOrderId(String orderId);
/**
* 平台计算同城订单的内部配送费仅仅作用于平台内部配送费计算商家配送费忽略此方法下单前可以查询
*
* @param storeId 店铺Id
* @param orderLongitude 订单送达地目的地经度
* @param orderLatitude 订单送达地目的地维度
* @param orderWeightGram 订单重量单位克
* @param orderProductAmount 订单商品原价金额
* @param orderDiscountAmount 订单商品折扣金额订单原价减去每个商品折扣费
* @param orderPayAmount 订单实际支付金额折扣金额-优惠券-积分扣-人工干预扣费不包含运费
* @return 配送费单位为分
*/
Integer computeSameCityInnerDeliveryFee(Integer storeId, String orderLongitude, String orderLatitude, Integer orderWeightGram, BigDecimal orderProductAmount, BigDecimal orderDiscountAmount, BigDecimal orderPayAmount);
}

View File

@ -22,13 +22,21 @@ public interface ShopStoreSameCityTransportService {
*/
CommonResult deleteShopStoreSameCityTransport(Long transportId);
/**
* 根据店铺 Id 获取同城配送扩展设置列表
*
* @param storeId
* @return
*/
List<ShopStoreSameCityTransport> selectShopStoreSameCityTransportList(Long storeId);
/**
* 根据同城配送基础配置自增 Id 获取同城配送扩展设置列表
*
* @param transportBaseId
* @return
*/
List<ShopStoreSameCityTransport> selectShopStoreSameCityTransportList(Long transportBaseId);
List<ShopStoreSameCityTransport> selectShopStoreSameCityTransportListByTransportBaseId(Long transportBaseId);
/**
* 保存同城配送扩展设置列表存在就更新不存在就新增

View File

@ -1564,7 +1564,15 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
public Map getBase(Integer store_id) {
UserDto user = getCurrentUser();
if (store_id == null) {
if (user == null) {
throw new ApiException(ResultCode.NEED_LOGIN);
}
if (user.isPlatform()) {
if (CheckUtil.isEmpty(store_id)) {
throw new ApiException("平台操作,请传入店铺 Id");
}
} else {
store_id = Convert.toInt(user.getStore_id());
}

View File

@ -131,7 +131,7 @@ public class ShopStoreInfoServiceImpl extends BaseServiceImpl<ShopStoreInfoMappe
/**
* 获取店铺的内部运费 shopping_fee_inner
* <p>
* 店铺内部运费单位0-使用平台的内部运费>0 使用店铺的内部运费
* 店铺内部运费单位使用店铺的内部运费<=0 的时候
*
* @param storeId 店铺ID
* @return 内部运费单位分
@ -147,7 +147,6 @@ public class ShopStoreInfoServiceImpl extends BaseServiceImpl<ShopStoreInfoMappe
QueryWrapper<ShopStoreInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("store_id", storeId).select("shopping_fee_inner");
ShopStoreInfo shopStoreInfo = getOne(queryWrapper);
if (shopStoreInfo == null || CheckUtil.isEmpty(shopStoreInfo.getShopping_fee_inner())) {
return 0;
}

View File

@ -25,13 +25,16 @@ import com.suisung.mall.common.modules.store.ShopStoreBase;
import com.suisung.mall.common.modules.store.ShopStoreSameCityTransport;
import com.suisung.mall.common.modules.store.ShopStoreSameCityTransportBase;
import com.suisung.mall.common.pojo.dto.DeliveryFeeResultDTO;
import com.suisung.mall.common.pojo.dto.OrderCacDeliveryFeeDTO;
import com.suisung.mall.common.pojo.dto.SameCityDeliveryFeeRespDTO;
import com.suisung.mall.common.pojo.dto.ShopStoreSameCityTransportBaseDTO;
import com.suisung.mall.common.utils.CheckUtil;
import com.suisung.mall.common.utils.CommonUtil;
import com.suisung.mall.common.utils.I18nUtil;
import com.suisung.mall.common.utils.PositionUtil;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
import com.suisung.mall.shop.order.service.ShopOrderInfoService;
import com.suisung.mall.shop.store.mapper.ShopStoreSameCityTransportBaseMapper;
import com.suisung.mall.shop.store.service.ShopStoreBaseService;
import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService;
@ -64,6 +67,11 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
@Autowired
private ShopStoreBaseService shopStoreBaseService;
@Lazy
@Autowired
private ShopOrderInfoService shopOrderInfoService;
@Resource
private AccountBaseConfigService accountBaseConfigService;
@ -71,74 +79,123 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
/**
* 获取同城配送设置详情信息
*
* @return
* @param storeId 店铺ID平台操作时必传
* @return 同城配送设置详情
*/
@Override
public CommonResult ShopStoreSameCityTransportBaseDetail() {
// 判断有没有权限
public CommonResult ShopStoreSameCityTransportBaseDetail(Long storeId) {
// 权限校验
UserDto user = getCurrentUser();
if (user == null || !user.isStore()) {
if (user == null) {
logger.warn("用户未登录,无法获取同城配送设置详情");
return CommonResult.failed(ResultCode.FORBIDDEN.getMessage());
}
Long storeId = Convert.toLong(user.getStore_id());
ShopStoreSameCityTransportBaseDTO retDTO = getShopStoreSameCityTransportBaseDTOById(storeId);
if (retDTO == null) {
return CommonResult.failed("商家未设置店铺地址,请先设置店铺地址!");
// 平台用户必须传入店铺ID商户用户自动获取自己的店铺ID
Integer isPlatform = CommonConstant.Disable2;
if (user.isPlatform()) {
if (CheckUtil.isEmpty(storeId)) {
logger.warn("平台用户操作时未传入店铺ID");
return CommonResult.failed("平台操作请传入店铺Id");
}
isPlatform = CommonConstant.Enable;
} else {
storeId = Convert.toLong(user.getStore_id());
if (storeId == null || storeId <= 0) {
logger.error("商户用户店铺ID无效: {}", user.getStore_id());
return CommonResult.failed("用户店铺信息异常");
}
}
// 获取同城配送设置详情
ShopStoreSameCityTransportBaseDTO retDTO = getShopStoreSameCityTransportBaseDTOById(storeId, isPlatform);
if (retDTO == null) {
logger.warn("店铺 {} 未设置店铺地址及经纬度相关信息", storeId);
return CommonResult.failed("商家未设置店铺地址及经纬度相关信息,请先设置再试!");
}
logger.debug("成功获取店铺 {} 的同城配送设置详情", storeId);
return CommonResult.success(retDTO);
}
/**
* 保存或更新同城配送各项设置
*
* @param shopStoreSameCityTransportBaseDTO
* @return
* @param shopStoreSameCityTransportBaseDTO 同城配送设置数据传输对象
* @return 操作结果
*/
@Override
public CommonResult saveOrUpdateSameCityTransport(ShopStoreSameCityTransportBaseDTO shopStoreSameCityTransportBaseDTO) {
// 判断有没有权限
UserDto user = getCurrentUser();
if (user == null || !user.isStore()) {
return CommonResult.failed("无权限操作!");
}
Integer userId = user.getId();
Long storeId = Convert.toLong(user.getStore_id());
shopStoreSameCityTransportBaseDTO.getTransportBase().setStore_id(storeId);
// 参数校验
if (shopStoreSameCityTransportBaseDTO == null || shopStoreSameCityTransportBaseDTO.getTransportBase() == null) {
logger.warn("保存或更新同城配送设置参数校验失败: DTO为空或基础设置为空");
return CommonResult.failed("参数有误");
}
ShopStoreBase store = shopStoreBaseService.getById(storeId);
if (store == null || StrUtil.isBlank(store.getStore_longitude()) || StrUtil.isBlank(store.getStore_latitude())) {
CommonResult.failed("无法获取店铺信息!");
// 权限校验
UserDto user = getCurrentUser();
if (user == null) {
logger.warn("用户未登录,无法保存或更新同城配送设置");
return CommonResult.failed("无权限操作!");
}
// 获取店铺ID并校验用户权限
Long storeId;
int isPlatform = user.isPlatform() ? CommonConstant.Enable : CommonConstant.Disable2;
if (isPlatform == CommonConstant.Enable) {
// 平台用户必须传入店铺ID
if (CheckUtil.isEmpty(shopStoreSameCityTransportBaseDTO.getTransportBase().getStore_id())) {
logger.warn("平台用户操作时未传入店铺ID");
return CommonResult.failed("平台管理请传入店铺Id");
}
storeId = Convert.toLong(shopStoreSameCityTransportBaseDTO.getTransportBase().getStore_id());
} else {
// 商户用户使用自己的店铺ID
storeId = Convert.toLong(user.getStore_id());
if (storeId == null || storeId <= 0) {
logger.error("商户用户店铺ID无效: {}", user.getStore_id());
return CommonResult.failed("用户店铺信息异常");
}
shopStoreSameCityTransportBaseDTO.getTransportBase().setStore_id(storeId);
}
// 获取店铺基本信息并校验
ShopStoreBase store = shopStoreBaseService.getById(storeId);
if (store == null || StrUtil.isBlank(store.getStore_longitude()) || StrUtil.isBlank(store.getStore_latitude())) {
logger.warn("无法获取店铺 {} 的位置信息", storeId);
return CommonResult.failed("无法获取店铺信息!");
}
// 设置基础信息
ShopStoreSameCityTransportBase transportBase = shopStoreSameCityTransportBaseDTO.getTransportBase();
transportBase.setUpdated_by(userId);
transportBase.setUpdated_by(user.getId());
transportBase.setStore_longitude(store.getStore_longitude());
transportBase.setStore_latitude(store.getStore_latitude());
transportBase.setStore_address(store.getStore_address());
transportBase.setIs_platform(isPlatform);
// 新增或更新同城配送基础设置
Pair<Long, String> pair = saveOrUpdateShopStoreSameCityTransportBase(transportBase);
// 新增或更新同城配送扩展设置列表
shopStoreSameCityTransportBaseDTO.setTransportBase(transportBase);
shopStoreSameCityTransportBaseDTO.rebuildTransportList();
shopStoreSameCityTransportService.saveOrUpdateShopStoreSameCityTransportList(shopStoreSameCityTransportBaseDTO.getTransportList());
if (pair.getFirst() > 0) {
return CommonResult.success(null, pair.getSecond());
// 保存或更新同城配送基础设置
Pair<Long, String> saveResult = saveOrUpdateShopStoreSameCityTransportBase(transportBase);
if (saveResult.getFirst() <= 0) {
logger.error("保存或更新同城配送基础设置失败, storeId={}, errorMsg={}", storeId, saveResult.getSecond());
return CommonResult.failed(saveResult.getSecond());
}
return CommonResult.failed(pair.getSecond());
// 更新DTO中的基础设置和运输列表
shopStoreSameCityTransportBaseDTO.setTransportBase(transportBase);
shopStoreSameCityTransportBaseDTO.rebuildTransportList();
// 保存或更新同城配送扩展设置列表
int updateCount = shopStoreSameCityTransportService.saveOrUpdateShopStoreSameCityTransportList(shopStoreSameCityTransportBaseDTO.getTransportList());
logger.debug("保存或更新同城配送扩展设置列表完成, storeId={}, 更新条数={}", storeId, updateCount);
logger.info("成功保存或更新店铺 {} 的同城配送设置", storeId);
return CommonResult.success(shopStoreSameCityTransportBaseDTO, saveResult.getSecond());
}
/**
* 店铺主营商品类型
*
@ -225,58 +282,93 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
/**
* 根据店铺 Id 获取同城配送设置详情信息
*
* @param storeId
* @return
* @param storeId 店铺ID
* @param isPlatform 是否平台操作标识
* @return 同城配送设置详情DTO
*/
@Override
public ShopStoreSameCityTransportBaseDTO getShopStoreSameCityTransportBaseDTOById(Long storeId) {
public ShopStoreSameCityTransportBaseDTO getShopStoreSameCityTransportBaseDTOById(Long storeId, Integer isPlatform) {
// 参数校验
if (storeId == null || storeId <= 0) {
logger.warn("获取同城配送设置详情失败店铺ID无效storeId={}", storeId);
return null;
}
// 店铺基本信息
// 获取店铺基本信息
ShopStoreBase shopStoreBase = shopStoreBaseService.getShopStoreBaseByStoreId(storeId.intValue());
if (shopStoreBase == null) {
logger.warn("获取同城配送设置详情失败店铺基本信息不存在storeId={}", storeId);
return null;
}
ShopStoreSameCityTransportBase transportBase = getShopStoreSameCityTransportBaseById(storeId);
// 获取同城配送基础设置记录
ShopStoreSameCityTransportBase transportBase = getShopStoreSameCityTransportBaseById(storeId, isPlatform);
// 如果未找到对应记录则根据不同角色处理
if (transportBase == null) {
transportBase = new ShopStoreSameCityTransportBase();
transportBase.setStore_id(storeId);
if (isPlatform == CommonConstant.Enable) {
// 平台用户尝试从商家店铺配送设置中获取记录
transportBase = getShopStoreSameCityTransportBaseById(storeId, CommonConstant.Disable2);
if (transportBase == null) {
logger.warn("获取同城配送设置详情失败平台和商家配送设置均不存在storeId={}", storeId);
return null;
} else {
// 复用商家设置但需要重置平台相关字段
transportBase.setIs_platform(CommonConstant.Disable);
transportBase.setTransport_base_id(null);
transportBase.setStore_id(storeId);
logger.debug("平台用户复用商家配送设置storeId={}", storeId);
}
} else {
// 商家用户创建默认配送设置
transportBase = new ShopStoreSameCityTransportBase();
transportBase.setStore_id(storeId);
transportBase.setIs_platform(isPlatform);
// 没有记录时指定默认值
transportBase.setArea_type(1);
transportBase.setBasis(1);
transportBase.setDistance_base(5);
transportBase.setWeight_base(5);
transportBase.setDelivery_base_fee(BigDecimal.valueOf(5));
transportBase.setDistance_increase_km(1);
transportBase.setDistance_increase_fee(BigDecimal.valueOf(1));
transportBase.setWeight_increase_kg(1);
transportBase.setWeight_increase_fee(BigDecimal.valueOf(1));
transportBase.setStatus(CommonConstant.Enable);
// 设置默认值
transportBase.setArea_type(1);
transportBase.setBasis(1);
transportBase.setDistance_base(5);
transportBase.setWeight_base(5);
transportBase.setDelivery_base_fee(BigDecimal.valueOf(5));
transportBase.setDistance_increase_km(1);
transportBase.setDistance_increase_fee(BigDecimal.valueOf(1));
transportBase.setWeight_increase_kg(1);
transportBase.setWeight_increase_fee(BigDecimal.valueOf(1));
transportBase.setStatus(CommonConstant.Enable);
Date now = new Date();
transportBase.setCreated_at(now);
transportBase.setUpdated_at(transportBase.getCreated_at());
// 设置时间戳
Date now = new Date();
transportBase.setCreated_at(now);
transportBase.setUpdated_at(now);
// shop_store_base 表获取店铺的地址和经纬度
transportBase.setStore_address(StrUtil.removeAll(shopStoreBase.getStore_area(), "/") + shopStoreBase.getStore_address());
transportBase.setStore_longitude(shopStoreBase.getStore_longitude());
transportBase.setStore_latitude(shopStoreBase.getStore_latitude());
// 从店铺基本信息中获取地址和经纬度
transportBase.setStore_address(StrUtil.removeAll(shopStoreBase.getStore_area(), "/") + shopStoreBase.getStore_address());
transportBase.setStore_longitude(shopStoreBase.getStore_longitude());
transportBase.setStore_latitude(shopStoreBase.getStore_latitude());
logger.debug("为商家创建默认配送设置storeId={}", storeId);
}
}
// 构造返回DTO
ShopStoreSameCityTransportBaseDTO shopStoreSameCityTransportBaseDTO = new ShopStoreSameCityTransportBaseDTO();
shopStoreSameCityTransportBaseDTO.setTransportBase(transportBase);
// 多个店铺同城快递运费设置起送条件+优惠条件
List<ShopStoreSameCityTransport> transportList = shopStoreSameCityTransportService.selectShopStoreSameCityTransportList(transportBase.getStore_id());
// 获取配送扩展设置列表
List<ShopStoreSameCityTransport> transportList;
if (CheckUtil.isEmpty(transportBase.getTransport_base_id())) {
transportList = shopStoreSameCityTransportService.selectShopStoreSameCityTransportList(transportBase.getStore_id());
} else {
transportList = shopStoreSameCityTransportService.selectShopStoreSameCityTransportListByTransportBaseId(transportBase.getTransport_base_id());
}
shopStoreSameCityTransportBaseDTO.setTransportList(transportList);
logger.debug("成功获取店铺 {} 的同城配送设置详情", storeId);
return shopStoreSameCityTransportBaseDTO;
}
/**
* 根据店铺Id获取同城配送基础运费记录
*
@ -284,25 +376,46 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
* @return
*/
@Override
public ShopStoreSameCityTransportBase getShopStoreSameCityTransportBaseById(Long storeId) {
public ShopStoreSameCityTransportBase getShopStoreSameCityTransportBaseById(Long storeId, Integer isPlatform) {
if (storeId == null || storeId <= 0) {
return null;
}
if (isPlatform == null || isPlatform < 0 || isPlatform > 2) {
isPlatform = 2;
}
QueryWrapper<ShopStoreSameCityTransportBase> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("store_id", storeId);
queryWrapper.eq("is_platform", isPlatform);
queryWrapper.eq("status", CommonConstant.Enable);
return getOne(queryWrapper);
}
/**
* 保存或更新同城配送基础设置
* 注意同一个 store_id + is_platform + status=Enable 的组合只能存在一条记录
*
* @param transportBase 同城配送基础设置实体
* @return 操作结果 Pair<记录ID, 操作消息>
*/
public Pair<Long, String> saveOrUpdateShopStoreSameCityTransportBase(ShopStoreSameCityTransportBase transportBase) {
try {
// 参数校验
if (transportBase == null || transportBase.getStore_id() == null || transportBase.getStore_id() <= 0) {
log.warn("保存或更新同城配送基础信息参数校验失败: transportBase={}", transportBase);
return Pair.of(0L, "缺少店铺Id必要参数");
}
// 设置默认值
// 校验并设置平台标识默认值
Integer isPlatform = transportBase.getIs_platform();
if (isPlatform == null || isPlatform < 0 || isPlatform > 2) {
isPlatform = CommonConstant.Disable2; // 默认为商户级别
transportBase.setIs_platform(isPlatform);
}
// 设置默认值 - 确保数值合理性
if (transportBase.getDistance_base() == null || transportBase.getDistance_base() < 0) {
transportBase.setDistance_base(0);
}
@ -325,38 +438,58 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
transportBase.setWeight_increase_fee(BigDecimal.ZERO);
}
// 构建查询条件确保同一店铺同一平台标识下只有一条启用记录
QueryWrapper<ShopStoreSameCityTransportBase> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("store_id", transportBase.getStore_id());
queryWrapper.eq("is_platform", transportBase.getIs_platform());
queryWrapper.eq("status", CommonConstant.Enable);
// 先尝试查找已存在的记录
ShopStoreSameCityTransportBase exist = getOne(queryWrapper);
Date now = new Date();
if (exist == null) {
// 新增
// 新增操作
log.debug("开始新增同城配送基础信息, storeId={}, isPlatform={}", transportBase.getStore_id(), transportBase.getIs_platform());
transportBase.setCreated_by(transportBase.getUpdated_by());
transportBase.setCreated_at(now);
transportBase.setUpdated_at(now);
transportBase.setStatus(CommonConstant.Enable); // 确保状态为启用
if (add(transportBase)) {
// 确保获取到ID
Long transportBaseId = transportBase.getTransport_base_id();
if (transportBaseId == null || transportBaseId <= 0) {
// 补偿机制若transportBase.getTransport_base_id()==null重新查询数据
// 补偿机制若新增后ID仍为空重新查询获取ID
log.debug("新增后ID为空重新查询获取ID, storeId={}", transportBase.getStore_id());
exist = getOne(queryWrapper);
if (exist != null) {
transportBaseId = exist.getTransport_base_id();
}
}
log.info("新增同城配送基础信息成功, transportBaseId={}, storeId={}", transportBaseId, transportBase.getStore_id());
return Pair.of(transportBaseId, "添加成功!");
} else {
log.error("新增同城配送基础信息失败, storeId={}", transportBase.getStore_id());
return Pair.of(0L, "添加失败!");
}
} else {
// 更新
// 更新操作 - 确保唯一性约束
log.debug("开始更新同城配送基础信息, transportBaseId={}, storeId={}", exist.getTransport_base_id(), transportBase.getStore_id());
transportBase.setTransport_base_id(exist.getTransport_base_id());
transportBase.setUpdated_at(now);
transportBase.setStatus(CommonConstant.Enable); // 确保状态为启用
if (updateById(transportBase)) {
log.info("更新同城配送基础信息成功, transportBaseId={}, storeId={}", transportBase.getTransport_base_id(), transportBase.getStore_id());
return Pair.of(transportBase.getTransport_base_id(), "更新成功!");
} else {
log.error("更新同城配送基础信息失败, transportBaseId={}, storeId={}", transportBase.getTransport_base_id(), transportBase.getStore_id());
return Pair.of(0L, "更新失败!");
}
}
} catch (Exception e) {
log.error("保存或更新同城配送基础信息异常: ", e);
log.error("保存或更新同城配送基础信息异常, storeId={}", transportBase != null ? transportBase.getStore_id() : "unknown", e);
return Pair.of(0L, "系统内部错误");
}
}
@ -406,6 +539,11 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
return Pair.of(false, "缺少同城配送基础设置!");
}
Integer isPlatform = transportBase.getIs_platform();
if (isPlatform == null || isPlatform <= 0 || isPlatform > 2) {
isPlatform = 2;
}
transportBase.setIs_platform(isPlatform);
transportBase.setStore_id(Convert.toLong(storeBase.getStore_id()));
transportBase.setStore_longitude(storeBase.getStore_longitude());
transportBase.setStore_latitude(storeBase.getStore_latitude());
@ -461,7 +599,6 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
// 2.如果能配送再订单总重量订单原价金额订单折后金额订单实付金额
// 3.根据两点经纬度计算配送距离结合订单总重量计算基础运费
// 4.查看是否有运费优惠设置如果有就直接从基础运费中扣除优惠运费得出最终的订单配送费
if (storeId == null || orderLongitude == null || orderLatitude == null || storeId <= 0) {
logger.error("同城配送费计算时,缺少必要参数。");
if (canThrow) {
@ -490,8 +627,8 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
return new SameCityDeliveryFeeRespDTO(false, false, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, "无法获取" + storeName + "的具体位置,请联系商家。");
}
// 获取基础运费设置记录
ShopStoreSameCityTransportBase transportBase = getShopStoreSameCityTransportBaseById(storeId);
// 获取店铺商家的基础运费设置记录
ShopStoreSameCityTransportBase transportBase = getShopStoreSameCityTransportBaseById(storeId, CommonConstant.Disable2);
if (transportBase == null) {
logger.error("{}同城配送费计算:无法获取基础运费设置记录。", storeName);
if (canThrow) {
@ -671,7 +808,7 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
BigDecimal times = BigDecimal.ZERO;
if (transportBase.getWeight_increase_kg() > 0 && diffWeightKg.intValue() > transportBase.getWeight_increase_kg()) {
// 末尾非零进位比如2.1将是3 2.0将是22.001将是3
times = NumberUtil.div(diffWeightKg, transportBase.getDistance_increase_km()).setScale(0, RoundingMode.UP);
times = NumberUtil.div(diffWeightKg, transportBase.getWeight_increase_kg()).setScale(0, RoundingMode.UP);
}
deliveryBaseFee = deliveryBaseFee.add(transportBase.getWeight_increase_fee().multiply(times));
@ -690,4 +827,213 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
return new SameCityDeliveryFeeRespDTO(canDelivery, isFee, deliveryBaseFee, reduceDeliveryFee, isFee ? BigDecimal.ZERO : deliveryFee, "");
}
/**
* 平台计算同城订单的内部配送费仅仅作用于平台内部配送费计算商家配送费忽略此方法只对下单成功的订单起效果
*
* @param orderId 订单ID
* @return 配送费单位为分
*/
@Override
public Integer computeSameCityInnerDeliveryFeeByOrderId(String orderId) {
// 参数校验
if (orderId == null || orderId.trim().isEmpty()) {
logger.warn("计算同城配送费失败订单ID不能为空");
return 0;
}
// 获取计算配送费所需的订单信息
OrderCacDeliveryFeeDTO orderCacDeliveryFeeArgs = shopOrderInfoService.getOrderCacDeliveryFeeArgs(orderId);
// 检查返回结果是否为空
if (orderCacDeliveryFeeArgs == null) {
logger.warn("计算同城配送费失败:未能获取订单[{}]的配送费计算参数", orderId);
return 0;
}
// 调用计算方法计算配送费
return computeSameCityInnerDeliveryFee(
orderCacDeliveryFeeArgs.getStore_id(),
orderCacDeliveryFeeArgs.getDa_longitude(),
orderCacDeliveryFeeArgs.getDa_latitude(),
orderCacDeliveryFeeArgs.getOrder_weight_gram(),
orderCacDeliveryFeeArgs.getOrder_product_amount(),
orderCacDeliveryFeeArgs.getOrder_discount_amount(),
orderCacDeliveryFeeArgs.getOrder_payment_amount());
}
/**
* 平台计算同城订单的内部配送费仅仅作用于平台内部配送费计算商家配送费忽略此方法下单前可以查询
*
* @param storeId 店铺Id
* @param orderLongitude 订单送达地目的地经度
* @param orderLatitude 订单送达地目的地维度
* @param orderWeightGram 订单重量单位克
* @param orderProductAmount 订单商品原价金额
* @param orderDiscountAmount 订单商品折扣金额订单原价减去每个商品折扣费
* @param orderPayAmount 订单实际支付金额折扣金额-优惠券-积分扣-人工干预扣费不包含运费
* @return 配送费单位为分
*/
@Override
public Integer computeSameCityInnerDeliveryFee(Integer storeId, String orderLongitude, String orderLatitude, Integer orderWeightGram, BigDecimal orderProductAmount, BigDecimal orderDiscountAmount, BigDecimal orderPayAmount) {
// 参数校验
if (storeId == null || orderLongitude == null || orderLatitude == null || storeId <= 0) {
logger.warn("同城配送缺少必要参数,无法计算配送费。");
return 0;
}
// 获取店铺基本信息
ShopStoreBase storeBase = shopStoreBaseService.get(storeId);
if (storeBase == null) {
logger.warn("同城配送缺少店铺基本信息,无法计算配送费。");
return 0;
}
String storeName = storeBase.getStore_name();
String storeLng = storeBase.getStore_longitude();
String storeLat = storeBase.getStore_latitude();
if (StrUtil.isBlank(storeLng) || StrUtil.isBlank(storeLat)) {
logger.warn("无法获取{}的具体位置,请联系商家。", storeName);
return 0;
}
// 获取平台的基础运费设置记录
ShopStoreSameCityTransportBase transportBase = getShopStoreSameCityTransportBaseById(Convert.toLong(storeId), CommonConstant.Enable);
if (transportBase == null) {
logger.warn("商家{}尚未完成同城配送设置,无法计算配送费。", storeName);
return 0;
}
// 设置默认值
if (transportBase.getDistance_base() == null) {
transportBase.setDistance_base(0);
}
if (transportBase.getWeight_base() == null) {
transportBase.setWeight_base(0);
}
if (transportBase.getDelivery_base_fee() == null) {
transportBase.setDelivery_base_fee(BigDecimal.ZERO);
}
// 计算两点的距离(单位米)
Double distanceD = PositionUtil.getDistance1(Convert.toDouble(storeLng), Convert.toDouble(storeLat), Convert.toDouble(orderLongitude), Convert.toDouble(orderLatitude));
Integer distance = (distanceD != null) ? distanceD.intValue() : 0;
// 基础配送费计算
BigDecimal deliveryBaseFee = Convert.toBigDecimal(transportBase.getDelivery_base_fee(), BigDecimal.ZERO);
// 获取运费配送范围信息
List<ShopStoreSameCityTransport> transportList = shopStoreSameCityTransportService.selectShopStoreSameCityTransportList(Convert.toLong(storeId));
if (CollUtil.isEmpty(transportList)) {
// 没有配送范围规则的时候直接以基础配送费来配送
return deliveryBaseFee.multiply(BigDecimal.valueOf(100)).intValue();
}
// 判断配送范围和起送金额条件
String canNotDeliveryReason = "";
boolean canDelivery = false;
// 优先处理距离和金额都满足的规则
for (ShopStoreSameCityTransport transport : transportList) {
// 判断订单距离是否在配送范围内
if (transport.getMax_delivery_radius() >= distance) {
// 距离在配送范围内判断金额是否符合起配金额额度
boolean moneyPassed = false;
if (CommonConstant.Delivery_Amount_Comput_Type_Original.equals(transport.getMin_delivery_amount_type())) {
moneyPassed = orderProductAmount != null && transport.getMin_delivery_amount().compareTo(orderProductAmount) <= 0;
} else if (CommonConstant.Delivery_Amount_Comput_Type_Discounted.equals(transport.getMin_delivery_amount_type())) {
moneyPassed = orderDiscountAmount != null && transport.getMin_delivery_amount().compareTo(orderDiscountAmount) <= 0;
} else if (CommonConstant.Delivery_Amount_Comput_Type_Payment.equals(transport.getMin_delivery_amount_type())) {
moneyPassed = orderPayAmount != null && transport.getMin_delivery_amount().compareTo(orderPayAmount) <= 0;
}
// 距离和金额都满足条件
if (moneyPassed) {
canDelivery = true;
break;
}
}
}
// 如果没有找到完全满足条件的规则再详细检查找出失败原因
if (!canDelivery) {
for (ShopStoreSameCityTransport transport : transportList) {
// 判断订单距离是否在配送范围内
if (transport.getMax_delivery_radius() < distance) {
// 记录距离不满足的原因
canNotDeliveryReason = storeName + "的订单不在配送范围内,订单无法配送。";
} else {
// 距离在配送范围内判断金额是否符合起配金额额度
if (CommonConstant.Delivery_Amount_Comput_Type_Original.equals(transport.getMin_delivery_amount_type())) {
if (orderProductAmount != null && transport.getMin_delivery_amount().compareTo(orderProductAmount) > 0) {
BigDecimal diffMoney = transport.getMin_delivery_amount().subtract(orderProductAmount);
canNotDeliveryReason = String.format("%s商品原价金额还差%.2f元,才满足配送条件,请检查订单。", storeName, diffMoney);
} else {
canDelivery = true;
break;
}
} else if (CommonConstant.Delivery_Amount_Comput_Type_Discounted.equals(transport.getMin_delivery_amount_type())) {
if (orderDiscountAmount != null && transport.getMin_delivery_amount().compareTo(orderDiscountAmount) > 0) {
BigDecimal diffMoney = transport.getMin_delivery_amount().subtract(orderDiscountAmount);
canNotDeliveryReason = String.format("%s订单折后金额还差%.2f元,才满足配送条件,请检查订单。", storeName, diffMoney);
} else {
canDelivery = true;
break;
}
} else if (CommonConstant.Delivery_Amount_Comput_Type_Payment.equals(transport.getMin_delivery_amount_type())) {
if (orderPayAmount != null && transport.getMin_delivery_amount().compareTo(orderPayAmount) > 0) {
BigDecimal diffMoney = transport.getMin_delivery_amount().subtract(orderPayAmount);
canNotDeliveryReason = String.format("%s订单应支付金额还差%.2f元,才满足配送条件,请检查订单。", storeName, diffMoney);
} else {
canDelivery = true;
break;
}
}
}
}
}
// 如果仍然不能配送记录日志并返回0
if (!canDelivery) {
logger.warn(canNotDeliveryReason.isEmpty() ? (storeName + "订单不在配送范围内或未达起送金额,请检查!") : canNotDeliveryReason);
return 0;
}
// 额外配送费计算
// 每增加一个距离累加运费
if (transportBase.getDistance_increase_km() != null && transportBase.getDistance_increase_fee() != null && distance > transportBase.getDistance_base() * 1000) {
// 实际配送距离超出基础距离单位km
BigDecimal diffDistanceM = CommonUtil.DecimalRoundHalfUp(BigDecimal.valueOf(distance - transportBase.getDistance_base() * 1000).divide(BigDecimal.valueOf(1000)));
// 倍数
BigDecimal times = BigDecimal.ZERO;
if (transportBase.getDistance_increase_km() > 0 && diffDistanceM.intValue() > transportBase.getDistance_increase_km()) {
// 末尾非零进位比如2.1将是3 2.0将是22.001将是3
times = NumberUtil.div(diffDistanceM, transportBase.getDistance_increase_km()).setScale(0, RoundingMode.UP);
}
// 超过基础运费距离后累加上运费
deliveryBaseFee = deliveryBaseFee.add(transportBase.getDistance_increase_fee().multiply(times));
}
// 每增加一个重量累加运费重量暂时忽略,配置的时候设置0
if (transportBase.getWeight_increase_kg() != null && transportBase.getWeight_increase_fee() != null && orderWeightGram != null && orderWeightGram > transportBase.getWeight_base() * 1000) {
// 实际配送重量超出基础重量单位kg
BigDecimal diffWeightKg = CommonUtil.DecimalRoundHalfUp(BigDecimal.valueOf(orderWeightGram - transportBase.getWeight_base() * 1000).divide(BigDecimal.valueOf(1000)));
// 倍数
BigDecimal times = BigDecimal.ZERO;
if (transportBase.getWeight_increase_kg() > 0 && diffWeightKg.intValue() > transportBase.getWeight_increase_kg()) {
// 末尾非零进位比如2.1将是3 2.0将是22.001将是3
times = NumberUtil.div(diffWeightKg, transportBase.getWeight_increase_kg()).setScale(0, RoundingMode.UP); // 修正应该除以weight_increase_kg而不是distance_increase_km
}
deliveryBaseFee = deliveryBaseFee.add(transportBase.getWeight_increase_fee().multiply(times));
}
// 返回单位为分的配送费
return deliveryBaseFee.multiply(BigDecimal.valueOf(100)).intValue();
}
}

View File

@ -62,6 +62,31 @@ public class ShopStoreSameCityTransportServiceImpl extends BaseServiceImpl<ShopS
return CommonResult.success();
}
/**
* 根据同城配送基础配置自增 Id 获取同城配送扩展设置列表
*
* @param transportBaseId
* @return
*/
@Override
public List<ShopStoreSameCityTransport> selectShopStoreSameCityTransportListByTransportBaseId(Long transportBaseId) {
if (transportBaseId == null || transportBaseId <= 0) {
return Collections.emptyList();
}
QueryWrapper<ShopStoreSameCityTransport> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("transport_base_id", transportBaseId);
queryWrapper.eq("status", CommonConstant.Enable);
queryWrapper.orderByAsc("transport_id");
List<ShopStoreSameCityTransport> shopStoreSameCityTransportList = list(queryWrapper);
if (CollectionUtil.isEmpty(shopStoreSameCityTransportList)) {
shopStoreSameCityTransportList = Collections.emptyList();
}
return shopStoreSameCityTransportList;
}
/**
* 根据同城配送基础配置自增 Id 获取同城配送扩展设置列表
*

View File

@ -2644,7 +2644,7 @@ public class ShopUserCartServiceImpl extends BaseServiceImpl<ShopUserCartMapper,
// 订单折扣后金额
BigDecimal orderSelDiscountAmount = Convert.toBigDecimal(store_row.get("productMoneySelGoods"));
// 订单最终应付金额
BigDecimal orderPaymentAmount = Convert.toBigDecimal(store_row.get("productMoneySelGoods"));
BigDecimal orderPaymentAmount = Convert.toBigDecimal(store_row.get("order_money_select_items"));
// 同城配送运费检查和计算(只返回数据不能配送不抛异常)
SameCityDeliveryFeeRespDTO sameCityDeliveryFeeResp = shopStoreSameCityTransportBaseService.computeSameCityTransportFee(storeId, orderLng, orderLat, 0, productMoneyOriginGoods, orderSelDiscountAmount, orderPaymentAmount, canThrow);
@ -2671,7 +2671,7 @@ public class ShopUserCartServiceImpl extends BaseServiceImpl<ShopUserCartMapper,
}
// RMK 平台最低配送费单位add:2025-09-26
Integer innerMinDeliverFee = accountBaseConfigService.getInnerMinDeliveryFee(Convert.toInt(storeId));
Integer innerMinDeliverFee = accountBaseConfigService.getInnerMinDeliveryFee(delivery_type_id, storeId.intValue(), orderLng, orderLat, 0, productMoneyOriginGoods, orderSelDiscountAmount, orderPaymentAmount);
if (canThrow
&& CheckUtil.isNotEmpty(innerMinDeliverFee)
&& CheckUtil.isNotEmpty(orderSelMoneyAmount)
@ -2681,6 +2681,8 @@ public class ShopUserCartServiceImpl extends BaseServiceImpl<ShopUserCartMapper,
throw new ApiException(I18nUtil._("订单低于平台最低配送金额!"));
}
// 这个店铺订单的平台最低配送费单位
store_row.put("innerMinDeliverFee", innerMinDeliverFee);
}
// 订单总计运费

View File

@ -819,10 +819,10 @@
<!--总计优惠金额 order_discount_amount + order_voucher_price + order_points_fee + order_adjust_fee-->
(od.order_discount_amount + od.voucher_price + od.order_points_fee + od.order_adjust_fee) as
total_discount_amount,
<!--预计收入:订单原价金额-总计优惠金额-配送费-平台费+打包费-->
(ob.order_product_amount-od.order_discount_amount-od.voucher_price-od.order_points_fee-od.order_adjust_fee-od.platform_fee-order_shipping_fee_inner+od.packing_fee)
<!--预计收入:订单原价金额-总计优惠金额-配送费-平台费-拉卡拉手续费+打包费-->
(od.order_item_amount-od.order_discount_amount-od.voucher_price-od.order_points_fee-od.order_adjust_fee-od.platform_fee-order_shipping_fee_inner-lkl_fee+od.packing_fee)
as order_income_amount,
(od.platform_fee+lkl_fee) as platform_fee,
od.platform_fee,
od.packing_fee,
od.order_message,
sb.store_id,

View File

@ -62,7 +62,7 @@
订单编号:${order_id}<BR>
订单来源:微信小程序<BR>
支付方式:微信支付<BR>
配送来源:顺丰同城<BR>
配送来源:${deliver_type_name!'顺丰同城'}<BR>
付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}<BR>
--------------------------------<BR>
<L>商品名称 数量 金额</L><BR>
@ -103,4 +103,4 @@
<CB>${store_name}</CB><BR>--------------------------------<BR><CB>#${order_pickup_num_str}</CB><BR><L>买家备注:${order_message!'-'}</L><BR><BOLD>配送时间:${payment_time?string('MM-dd HH:mm')}${delivery_time?string('HH:mm')}</BOLD><BR>--------------------------------<BR>订单编号:${order_id}<BR>订单来源:微信小程序<BR>支付方式:微信支付<BR>配送来源:顺丰同城<BR>付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}<BR>--------------------------------<BR><L>商品名称 数量 金额</L><BR>--------------------------------<BR><#list order_items as item><L>${item.s_name}</L><L><BOLD>${item.s_quantity}</BOLD></L><L>${item.s_amount}</L><BR><#if item.s_name_segs??><#list item.s_name_segs as seg><L>${seg}</L><BR></#list></#if><BOLD><#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}</BOLD><BR></#if></#list>--------------------------------<BR>商品总件数:<BOLD>${order_items_count!0}</BOLD><BR>商品总额:<BOLD>¥${order_product_amount?string('0.00')}</BOLD><BR>运费:<BOLD>¥${order_shipping_fee?string('0.00')}</BOLD><BR><#if packing_fee?? && (packing_fee > 0)>打包费:<BOLD>¥${packing_fee?string('0.00')}</BOLD><BR></#if>优惠金额:<BOLD>-¥${(quanyi!0)?string('0.00')}</BOLD><BR>实付金额:<BOLD>¥${order_payment_amount?string('0.00')}</BOLD><BR><#if seller_message?default("")?trim?length gt 1>--------------------------------<BR><BOLD>商家备注:${seller_message!'-'}</BOLD><BR></#if>--------------------------------<BR><BOLD>收货人:${buyer_user_name!''}</BOLD><BR><BOLD>收货人手机:${da_mobile!'-'}</BOLD><BR><BOLD>收货地址:${da_province!'-'}${da_city!'-'}${da_address!'-'}</BOLD><BR>--------------------------------<BR>门店:${store_name}<BR>门店电话:<BOLD>${store_tel!'-'}</BOLD><BR>收银员:${cashier!'店长'}<BR>
第三版带变量的模版(有预约订单)
<#if is_booking_order><CB><B>【预约订单】<BR></B></CB></#if><CB>${store_name}</CB><BR>--------------------------------<BR><CB>#${order_pickup_num_str}</CB><BR><L>买家备注:${order_message!'-'}</L><BR><BOLD>配送时间:${payment_time?string('MM-dd HH:mm')}${delivery_time?string('HH:mm')}</BOLD><BR>--------------------------------<BR>订单编号:${order_id}<BR>订单来源:微信小程序<BR>支付方式:微信支付<BR>配送来源:顺丰同城<BR>付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}<BR>--------------------------------<BR><L>商品名称 数量 金额</L><BR>--------------------------------<BR><#list order_items as item><L>${item.s_name}</L><L><BOLD>${item.s_quantity}</BOLD></L><L>${item.s_amount}</L><BR><#if item.s_name_segs??><#list item.s_name_segs as seg><L>${seg}</L><BR></#list></#if><BOLD><#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}</BOLD><BR></#if><BR></#list>--------------------------------<BR>商品总件数:<BOLD>${order_items_count!0}</BOLD><BR>商品总额:<BOLD>¥${order_product_amount?string('0.00')}</BOLD><BR>运费:<BOLD>¥${order_shipping_fee?string('0.00')}</BOLD><BR><#if packing_fee?? && (packing_fee > 0)>打包费:<BOLD>¥${packing_fee?string('0.00')}</BOLD><BR></#if>优惠金额:<BOLD>-¥${(quanyi!0)?string('0.00')}</BOLD><BR>实付金额:<BOLD>¥${order_payment_amount?string('0.00')}</BOLD><BR><#if seller_message?default("")?trim?length gt 1>--------------------------------<BR><BOLD>商家备注:${seller_message!'-'}</BOLD><BR></#if>--------------------------------<BR><BOLD>收货人:${buyer_user_name!''}</BOLD><BR><BOLD>收货人手机:${da_mobile!'-'}</BOLD><BR><BOLD>收货地址:${da_province!'-'}${da_city!'-'}${da_address!'-'}</BOLD><BR>--------------------------------<BR>门店:${store_name}<BR>门店电话:<BOLD>${store_tel!'-'}</BOLD><BR>收银员:${cashier!'店长'}<BR>
<#if is_booking_order><CB><B>【预约订单】<BR></B></CB></#if><CB>${store_name}</CB><BR>--------------------------------<BR><CB>#${order_pickup_num_str}</CB><BR><L>买家备注:${order_message!'-'}</L><BR><BOLD>配送时间:${payment_time?string('MM-dd HH:mm')}${delivery_time?string('HH:mm')}</BOLD><BR>--------------------------------<BR>订单编号:${order_id}<BR>订单来源:微信小程序<BR>支付方式:微信支付<BR>配送来源:${deliver_type_name!'顺丰同城'}<BR>付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}<BR>--------------------------------<BR><L>商品名称 数量 金额</L><BR>--------------------------------<BR><#list order_items as item><L>${item.s_name}</L><L><BOLD>${item.s_quantity}</BOLD></L><L>${item.s_amount}</L><BR><#if item.s_name_segs??><#list item.s_name_segs as seg><L>${seg}</L><BR></#list></#if><BOLD><#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}</BOLD><BR></#if><BR></#list>--------------------------------<BR>商品总件数:<BOLD>${order_items_count!0}</BOLD><BR>商品总额:<BOLD>¥${order_product_amount?string('0.00')}</BOLD><BR>运费:<BOLD>¥${order_shipping_fee?string('0.00')}</BOLD><BR><#if packing_fee?? && (packing_fee > 0)>打包费:<BOLD>¥${packing_fee?string('0.00')}</BOLD><BR></#if>优惠金额:<BOLD>-¥${(quanyi!0)?string('0.00')}</BOLD><BR>实付金额:<BOLD>¥${order_payment_amount?string('0.00')}</BOLD><BR><#if seller_message?default("")?trim?length gt 1>--------------------------------<BR><BOLD>商家备注:${seller_message!'-'}</BOLD><BR></#if>--------------------------------<BR><BOLD>收货人:${buyer_user_name!''}</BOLD><BR><BOLD>收货人手机:${da_mobile!'-'}</BOLD><BR><BOLD>收货地址:${da_province!'-'}${da_city!'-'}${da_address!'-'}</BOLD><BR>--------------------------------<BR>门店:${store_name}<BR>门店电话:<BOLD>${store_tel!'-'}</BOLD><BR>收银员:${cashier!'店长'}<BR>

12
pom.xml
View File

@ -539,11 +539,6 @@
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
@ -571,7 +566,9 @@
<goal>build</goal>
</goals>
</execution>
</executions>
</executions>
<configuration>
<!--定义镜像名称-->
<imageName>${docker.registry}/mall/${project.artifactId}:${project.version}</imageName>
@ -592,7 +589,7 @@
<forceTags>true</forceTags>
<imageTags>
<imageTag>${project.version}</imageTag>
<!-- <imageTag>latest</imageTag>-->
<imageTag>latest</imageTag>
</imageTags>
<!--定义容器启动命令,注意不能换行-->
@ -609,6 +606,7 @@
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>