Merge branch 'main' into dev

This commit is contained in:
liyj 2025-10-29 10:17:56 +08:00
commit 6885640533
30 changed files with 803 additions and 316 deletions

View File

@ -1950,10 +1950,10 @@ public class AccountUserBaseServiceImpl extends BaseServiceImpl<AccountUserBaseM
}
if (StrUtil.isNotBlank(user_mobile) && userIsAdmin.equals(CommonConstant.USER_TYPE_MCH)) {
// 如果是商家首次注册 SMS_481085172 发送短信通知用户告知用户随机密码您已成功注册密码${password}密码可用于登录商家APP登录后请尽快修改密码
// 如果是商家首次注册 恭喜您成功注册了商家账号您的初始密码为${password}密码可登录商家 APP登录后请尽快修改密码
Map<String, Object> smsArgs = new HashMap<>();
smsArgs.put("password", user_password_src);
sendSmsMessage(PhoneNumberUtils.cleanPhoneNumber(user_mobile), "SMS_481085172", smsArgs);
sendSmsMessage(PhoneNumberUtils.cleanPhoneNumber(user_mobile), "SMS_496910525", smsArgs); // SMS_496910525
}
//初次注册发送消息

View File

@ -45,10 +45,13 @@ public class ShopOrderItem implements Serializable {
@ApiModelProperty(value = "产品编号")
private Long product_id;
@ApiModelProperty(value = "货品编号")
private Long item_id;
@ApiModelProperty(value = "产品条形码(唯一码)")
private String item_barcode;
@ApiModelProperty(value = "商品名称")
private String item_name;

View File

@ -95,4 +95,16 @@ public class MchOrderInfoDTO implements Serializable {
private Integer is_deny_return;
@ApiModelProperty(value = "异常订单操作流程,0-可操作自行发货1-可操作订单完成2-订单完成不可操作")
private String operate_flag;
@ApiModelProperty(value = "订单配送预约状态1-立即配送2-预约配送")
private Integer booking_state;
@ApiModelProperty(value = "预约送达起始时间格式如yyyy-MM-dd HH:mm:ss")
private Date booking_begin_time;
@ApiModelProperty(value = "预约送达截止时间格式如yyyy-MM-dd HH:mm:ss")
private Date booking_end_time;
@ApiModelProperty(value = "预订单到达时间戳(秒)")
private Long booking_at;
}

View File

@ -0,0 +1,78 @@
package com.suisung.mall.common.pojo.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
* 预订参数DTO实体类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "预约订单参数DTO", description = "预约订单参数DTO")
public class BookingArgDTO {
/**
* 日期标题"今天(周二)"
*/
@ApiModelProperty(value = "日期标题")
private String date_title;
/**
* 日期字符串"01月09日"
*/
@ApiModelProperty(value = "日期字符串")
private String date_str;
/**
* 日期"2025-01-09"
*/
@ApiModelProperty(value = "日期")
private String date;
/**
* 时间项列表
*/
@ApiModelProperty(value = "时间项列表")
private List<BookingArgItem> items;
/**
* 预订时间项实体类
*/
@Data
public static class BookingArgItem {
/**
* 时间标题"立即送出""09:15-09:45"
*/
@ApiModelProperty(value = "时间标题")
private String time_title;
/**
* 预订时间戳
*/
@ApiModelProperty(value = "预订时间戳")
private Long booking_at;
/**
* 预订状态
*/
@ApiModelProperty(value = "预订状态1-立即下单2-预约下单;")
private Integer booking_state;
/**
* 预订开始时间
*/
@ApiModelProperty(value = "预订开始时间")
private String booking_begin_time;
/**
* 预订结束时间
*/
@ApiModelProperty(value = "预订结束时间")
private String booking_end_time;
}
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2024. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.common.pojo.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
/**
* 标准的地址实体类
*/
public class StoreBizTimeInfoDTO implements Serializable {
private Integer store_id;
private String store_name;
private Integer store_biz_state;
private String store_opening_hours;
private String store_close_hours;
}

View File

@ -178,6 +178,23 @@ public class DateTimeUtils {
}
}
/**
* 根据日期获取星期几
*
* @param date 日期
* @return 星期几
*/
public static String getWeekOfDate(Date date) {
String[] weekDays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
if (w < 0) {
w = 0;
}
return weekDays[w];
}
/**
* 将多种日期格式转换为 yyyy-MM-dd
@ -473,6 +490,7 @@ public class DateTimeUtils {
}
}
/**
* 判断时间字符串是否与格式模式匹配
*

View File

@ -352,6 +352,8 @@ public class PhoneNumberUtils {
System.out.println(cleanPhoneNumber("+3541234567")); // 期望输出: 1234567
System.out.println(cleanPhoneNumber("+85298765432"));
System.out.println(PhoneNumberUtils.checkPhoneNumber("+8617777525395"));
}
}

View File

@ -73,4 +73,12 @@ public interface EsignPlatformInfoService {
* @return
*/
EsignPlatformInfo getMch2ndAgentWithShippingFee(Long mchId);
/**
* 根据代理商ID获取供应商 商家ID
*
* @param agentId
* @return
*/
String getSupplierIdByAgentId(Long agentId);
}

View File

@ -122,7 +122,7 @@ public class EsignPlatformInfoServiceImpl extends BaseServiceImpl<EsignPlatformI
} else {
log.debug("[获取平台和代理商信息] 未找到一级代理parent_id: {}", agent2nd.getParent_id());
}
log.debug("[获取平台和代理商信息] 查询完成,共获取 {} 条记录", esignPlatformInfos.size());
return esignPlatformInfos;
}
@ -178,26 +178,44 @@ public class EsignPlatformInfoServiceImpl extends BaseServiceImpl<EsignPlatformI
/**
* 获取平台方手机号和营业执照号
*
* @return
* @return Pair<String, String> 手机号和营业执照号的键值对获取失败时返回null
*/
@Override
public Pair<String, String> getEsignPlatformMobileAndLicenseNumber() {
QueryWrapper<EsignPlatformInfo> queryWrapper = new QueryWrapper();
queryWrapper.eq("level", 0).select("telephone", "license_number", "legal_person_mobile");
List<EsignPlatformInfo> esignPlatformInfos = list(queryWrapper);
if (CollectionUtil.isEmpty(esignPlatformInfos)) {
log.debug("[获取平台方信息] 开始获取平台方手机号和营业执照号");
try {
QueryWrapper<EsignPlatformInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("level", 0)
.eq("status", CommonConstant.Enable)
.select("telephone", "license_number", "legal_person_mobile");
EsignPlatformInfo esignPlatformInfo = findOne(queryWrapper);
if (esignPlatformInfo == null) {
log.warn("[获取平台方信息] 未找到有效的平台方记录");
return null;
}
// 优先使用telephone字段如验证失败则使用legal_person_mobile
String mobile = esignPlatformInfo.getTelephone();
if (!PhoneNumberUtils.checkPhoneNumber(mobile)
&& StrUtil.isNotBlank(esignPlatformInfo.getLegal_person_mobile())
&& PhoneNumberUtils.checkPhoneNumber(esignPlatformInfo.getLegal_person_mobile())) {
log.debug("[获取平台方信息] 主手机号验证失败,使用法人手机号");
mobile = esignPlatformInfo.getLegal_person_mobile();
}
log.debug("[获取平台方信息] 成功获取平台方信息,手机号:{},营业执照号:{}",
mobile, esignPlatformInfo.getLicense_number());
return Pair.of(mobile, esignPlatformInfo.getLicense_number());
} catch (Exception e) {
log.error("[获取平台方信息] 查询平台方信息时发生异常", e);
return null;
}
EsignPlatformInfo esignPlatformInfo = esignPlatformInfos.get(0);
String mobile = esignPlatformInfo.getTelephone();
if (!PhoneNumberUtils.checkPhoneNumber(mobile) && StrUtil.isNotBlank(esignPlatformInfo.getLegal_person_mobile())) {
mobile = esignPlatformInfo.getLegal_person_mobile();
}
return Pair.of(mobile, esignPlatformInfo.getLicense_number());
}
/**
* 根据入驻编号获取商户的二级代理
*
@ -294,4 +312,46 @@ public class EsignPlatformInfoServiceImpl extends BaseServiceImpl<EsignPlatformI
return null;
}
/**
* 根据代理商ID获取供应商商家ID
*
* @param agentId 代理商ID
* @return 供应商商家ID未找到时返回空字符串
*/
@Override
public String getSupplierIdByAgentId(Long agentId) {
// 参数校验
if (agentId == null || agentId <= 0) {
log.warn("[获取供应商ID] 参数校验失败代理商ID为空或无效agentId={}", agentId);
return "";
}
try {
log.debug("[获取供应商ID] 开始查询供应商信息agentId={}", agentId);
// 构建查询条件
QueryWrapper<EsignPlatformInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", agentId)
.eq("level", CommonConstant.Agent_Level_2nd)
.eq("status", CommonConstant.Enable)
.select("supplier_id");
// 查询记录
EsignPlatformInfo result = getOne(queryWrapper);
// 检查结果并返回
if (result != null && StrUtil.isNotBlank(result.getSupplier_id())) {
log.debug("[获取供应商ID] 成功获取供应商IDagentId={}, supplierId={}", agentId, result.getSupplier_id());
return result.getSupplier_id();
} else {
log.debug("[获取供应商ID] 未找到有效的供应商IDagentId={}", agentId);
return "";
}
} catch (Exception e) {
log.error("[获取供应商ID] 查询过程中发生异常agentId={}", agentId, e);
return "";
}
}
}

View File

@ -90,7 +90,9 @@ public class LakalaController extends BaseControllerImpl {
@RequestMapping(value = "/testcase", method = RequestMethod.POST)
public Object testcase(@RequestBody JSONObject paramsJSON) {
return lklLedgerReceiverService.selectAgentAndPlatformByMchId(36L);
// return lklLedgerReceiverService.selectAgentAndPlatformByMchId(36L);
return lakalaApiService.ewalletWithDrawNotify(null, paramsJSON.getStr("a"), paramsJSON.getStr("b"));
}
@ApiOperation(value = "批量发送推送消息 - 测试案例", notes = "批量发送推送消息 - 测试案例")

View File

@ -115,4 +115,5 @@ public interface LklLedgerReceiverService extends IBaseService<LklLedgerReceiver
* @return
*/
LklLedgerReceiver getMch2ndAgent(Long mchId);
}

View File

@ -1838,8 +1838,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 10. 检查商户绑定状态是否完成 更改总的审核状态
shopMchEntryService.checkMerchEntryFinished(mchId);
// 11. 日志记录并返回成功响应
log.info("商家绑定分账接收方异步通知处理完成mchId:{} merCupNo{}", mchId, merCupNo);
return JSONUtil.createObj().set("code", "SUCCESS").set("message", "分账接收方绑定成功");
@ -2924,7 +2923,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 3. 提取关键参数并校验 - 确保必要参数完整
String logNo = paramsJson.getStr("log_no"); // 合单订单是子单确认收货流水号非合单时是主单确认收货流水号
String separateNo = paramsJson.getStr("separate_no");
String outSeparateNo = paramsJson.getStr("out_separate_no");
String outSeparateNo = paramsJson.getStr("out_separate_no"); // 商城的订单号
String status = paramsJson.getStr("status");
String finalStatus = paramsJson.getStr("final_status");
@ -3758,17 +3757,17 @@ public class LakalaApiServiceImpl implements LakalaApiService {
request.setMerchantNo(mercId);
request.setMerOrderNo(merOrderNo);
request.setPayType(payType);
request.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/ewallet/drawNotify");
// 分转元保留两位小数点不要四舍五入
String drawAmtYuan = drawAmtDecimal.divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN).toString();
request.setDrawAmt(drawAmtYuan); // 单位
request.setRemark(remark);
if (StrUtil.isNotBlank(summary)) {
request.setSummary(summary);
}
request.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/ewallet/drawNotify");
// 4. 发送请求
String responseStr = LKLSDK.httpPost(request);
if (StrUtil.isBlank(responseStr)) {
@ -3840,16 +3839,19 @@ public class LakalaApiServiceImpl implements LakalaApiService {
*/
@Override
public JSONObject ewalletWithDrawNotify(HttpServletRequest request, String merchantNo, String drawJnl) {
log.debug("[拉卡拉D1提现结果通知] 开始处理拉卡拉提现结果通知");
String signTag = "[拉卡拉提现结果通知]";
log.debug("{} 开始处理", signTag);
try {
JSONObject paramsJSON;
Pair<Boolean, String> signCheckResult = null;
if (request != null) {
// 1. 验签处理 - 验证通知来源的合法性
signCheckResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath, false);
if (signCheckResult != null && !signCheckResult.getFirst()) {
log.warn("[拉卡拉D1提现结果通知] 验签失败: {}", signCheckResult.getSecond());
log.warn("{} 验签失败: {}", signTag, signCheckResult.getSecond());
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", signCheckResult.getSecond());
@ -3859,12 +3861,12 @@ public class LakalaApiServiceImpl implements LakalaApiService {
paramsJSON = JSONUtil.parseObj(signCheckResult.getSecond());
} else {
// 补偿机制主动从拉卡拉上获取提现结果
signTag = "[查询拉卡拉提现结果补偿]";
paramsJSON = ewalletWithdrawQuery(merchantNo, drawJnl);
}
if (JSONUtil.isNull(paramsJSON)) {
log.warn("[拉卡拉D1提现结果通知] 回调参数解析失败");
log.warn("{} 回调参数解析失败", signTag);
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", "回调参数解析失败");
@ -3875,10 +3877,10 @@ public class LakalaApiServiceImpl implements LakalaApiService {
String merOrderNo = paramsJSON.getStr("merOrderNo");
String drawJnlRemote = paramsJSON.getStr("drawJnl");
log.info("[拉卡拉D1提现结果通知] 提现通知参数: drawState={}, mercId={}, merOrderNo={},drawJnlRemote={}", drawState, mercId, merOrderNo, drawJnlRemote);
log.info("{} 提现通知参数: drawState={}, mercId={}, merOrderNo={},drawJnlRemote={}", signTag, drawState, mercId, merOrderNo, drawJnlRemote);
if (StrUtil.hasBlank(mercId, merOrderNo, drawJnl, drawState)) {
log.warn("[拉卡拉提现结果通知] 回调参数缺失: drawState={}, mercId={}, merOrderNo={}, drawJnlRemote={}", drawState, mercId, merOrderNo, drawJnlRemote);
log.warn("{} 回调参数缺失: drawState={}, mercId={}, merOrderNo={}, drawJnlRemote={}", signTag, drawState, mercId, merOrderNo, drawJnlRemote);
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", "回调参数错误");
@ -3886,7 +3888,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
Boolean isCompensate = lklOrderDrawService.isOrderDrawed(mercId, drawJnl);
if (isCompensate) {
log.warn("[拉卡拉D1提现结果通知] 提现结果通知已处理,忽略处理: mercId={}, merOrderNo={}, drawJnl={}", mercId, merOrderNo, drawJnl);
log.warn("{} 提现结果通知已处理,忽略处理: mercId={}, merOrderNo={}, drawJnl={}", signTag, mercId, merOrderNo, drawJnl);
return JSONUtil.createObj()
.set("code", "SUCCESS")
.set("message", "提现结果通知已处理");
@ -3894,16 +3896,16 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 只处理成功的提现状态
if (!"DRAW.SUCCESS".equals(drawState)) {
log.debug("[拉卡拉D1提现结果通知] 提现状态未成功,忽略处理: drawState={}", drawState);
log.debug("{} 提现状态未成功,忽略处理: drawState={}", signTag, drawState);
return JSONUtil.createObj()
.set("code", "FAIL") // 返回成功避免重复通知
.set("message", "状态未成功,忽略处理");
}
// 3. 转换参数并更新数据
String snakeCaseJson = StringUtils.convertCamelToSnake(signCheckResult.getSecond());
String snakeCaseJson = StringUtils.convertCamelToSnake(paramsJSON.toString());
if (StringUtils.isBlank(snakeCaseJson)) {
log.error("[拉卡拉D1提现结果通知] 回调参数转换失败mercId={} merOrderNo={}", mercId, merOrderNo);
log.error("{} 回调参数转换失败mercId={} merOrderNo={}", signTag, mercId, merOrderNo);
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", "回调参数转换失败");
@ -3911,21 +3913,23 @@ public class LakalaApiServiceImpl implements LakalaApiService {
LklOrderDraw lklOrderDraw = JSONUtil.toBean(snakeCaseJson, LklOrderDraw.class);
if (lklOrderDraw == null) {
log.error("[拉卡拉D1提现结果通知] 回调参数转换为对象失败mercId={} merOrderNo={}", mercId, merOrderNo);
log.error("{} 回调参数转换为对象失败mercId={} merOrderNo={}", signTag, mercId, merOrderNo);
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", "回调参数转换失败");
}
lklOrderDraw.setRemark(lklOrderDraw.getRemark() + " " + signTag);
lklOrderDraw.setSummary(null);
boolean isSuccess = lklOrderDrawService.addOrUpdateByMercIdAndMerOrderNo(lklOrderDraw);
if (!isSuccess) {
log.error("[拉卡拉D1提现结果通知] 数据更新失败mercId={} merOrderNo={}", mercId, merOrderNo);
log.error("{} 数据更新失败mercId={} merOrderNo={}", signTag, mercId, merOrderNo);
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", "数据更新失败");
}
log.info("[拉卡拉D1提现结果通知] 拉卡拉提现结果通知处理成功mercId={} merOrderNo={}", mercId, merOrderNo);
log.info("{} 拉卡拉提现结果通知处理成功mercId={} merOrderNo={}", signTag, mercId, merOrderNo);
// 4. 返回成功响应
return JSONUtil.createObj()
@ -3933,7 +3937,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
.set("message", "处理成功");
} catch (Exception e) {
log.error("[拉卡拉D1提现结果通知] 处理拉卡拉提现结果通知异常", e);
log.error(signTag + " 处理拉卡拉提现结果通知异常", e);
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", "系统处理异常");

View File

@ -25,7 +25,6 @@ import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.esign.service.EsignPlatformInfoService;
import com.suisung.mall.shop.lakala.mapper.LklLedgerReceiverMapper;
import com.suisung.mall.shop.lakala.service.LakalaApiService;
import com.suisung.mall.shop.lakala.service.LklLedgerMemberService;
import com.suisung.mall.shop.lakala.service.LklLedgerReceiverService;
import com.suisung.mall.shop.store.service.ShopMchEntryService;
import lombok.extern.slf4j.Slf4j;
@ -49,10 +48,6 @@ public class LklLedgerReceiverServiceImpl extends BaseServiceImpl<LklLedgerRecei
@Resource
private LakalaApiService lakalaApiService;
@Lazy
@Resource
private LklLedgerMemberService lklLedgerMemberService;
@Autowired
private ShopMchEntryService shopMchEntryService;
@ -481,7 +476,7 @@ public class LklLedgerReceiverServiceImpl extends BaseServiceImpl<LklLedgerRecei
result = findOne(queryWrapper);
log.debug("[获取二级代理] 使用区域信息查询districtId={}", shopMchEntry.getStore_district());
}
if (result == null) {
log.info("[获取二级代理] 未找到匹配的二级代理信息mchId={}", mchId);
} else {
@ -495,4 +490,5 @@ public class LklLedgerReceiverServiceImpl extends BaseServiceImpl<LklLedgerRecei
return null;
}
}
}

View File

@ -342,6 +342,7 @@ public class ShopOrderBaseController extends BaseControllerImpl {
params.getInt("delivery"),
status,
params.getInt("logistics_status"),
params.getInt("booking_state"),
mchOrderExpireSeconds,
params.getLong("begin_time"),
params.getLong("end_time"),

View File

@ -12,6 +12,7 @@ import com.suisung.mall.common.api.StateCode;
import com.suisung.mall.common.domain.UserDto;
import com.suisung.mall.common.exception.ApiException;
import com.suisung.mall.common.modules.order.*;
import com.suisung.mall.common.pojo.dto.BookingArgDTO;
import com.suisung.mall.common.service.impl.BaseControllerImpl;
import com.suisung.mall.common.utils.CheckUtil;
import com.suisung.mall.shop.order.service.*;
@ -321,6 +322,13 @@ public class UserOrderController extends BaseControllerImpl {
return CommonResult.success(data);
}
@ApiOperation(value = "可预约订单的时间槽", notes = "可预约订单的时间槽")
@RequestMapping(value = "/booking_time_args", method = RequestMethod.GET)
public CommonResult listInvoice(@RequestParam(name = "store_id", defaultValue = "0") Integer store_id) {
List<BookingArgDTO> list = shopOrderInfoService.genBookingOrderArgList(store_id);
return CommonResult.success(list);
}
}

View File

@ -71,13 +71,14 @@ public interface ShopOrderBaseMapper extends BaseMapper<ShopOrderBase> {
* @param delivery 配送方式1-同城配送2-物流配送
* @param status 同城配送订单状态delivery=1时才生效无值 or 0-全部订单1-进行中订单2-异常超时订单3-退款订单9-已完成订单
* @param logisticsStatus 普通快递订单状态delivery=2时才生效无值 or 0-全部订单1-待支付订单2-待发货订单3-待接收订单9-已完成订单
* @param bookingState 订单配送预约状态1-立即配送2-预约配送
* @param expireSeconds 配送超时的秒数单位秒
* @param beginTime 开始时间戳13位毫秒级别
* @param endTime 截止时间戳13位毫秒级别
* @param page 分页参数
* @return
*/
IPage<MchOrderInfoDTO> selectMchOrderPageList(@Param("storeId") Integer storeId, @Param("keyword") String keyword, @Param("delivery") Integer delivery, @Param("status") Integer status, @Param("logisticsStatus") Integer logisticsStatus, @Param("expireSeconds") Long expireSeconds, @Param("beginTime") Long beginTime, @Param("endTime") Long endTime, IPage<MchOrderInfoDTO> page);
IPage<MchOrderInfoDTO> selectMchOrderPageList(@Param("storeId") Integer storeId, @Param("keyword") String keyword, @Param("delivery") Integer delivery, @Param("status") Integer status, @Param("logisticsStatus") Integer logisticsStatus, @Param("bookingState") Integer bookingState, @Param("expireSeconds") Long expireSeconds, @Param("beginTime") Long beginTime, @Param("endTime") Long endTime, IPage<MchOrderInfoDTO> page);
/**
@ -97,12 +98,13 @@ public interface ShopOrderBaseMapper extends BaseMapper<ShopOrderBase> {
* @param delivery 配送方式1-同城配送2-物流配送
* @param status 同城配送订单状态delivery=1时才生效无值 or 0-全部订单1-进行中订单2-异常超时订单3-退款订单9-已完成订单
* @param logisticsStatus 普通快递订单状态delivery=2时才生效无值 or 0-全部订单1-待支付订单2-待发货订单3-待接收订单9-已完成订单
* @param bookingState 订单配送预约状态1-立即配送2-预约配送
* @param expireSeconds 配送超时的秒数单位秒
* @param beginTime 开始时间戳13位毫秒级别
* @param endTime 截止时间戳13位毫秒级别
* @return
*/
Long countMchOrderByCondition(@Param("storeId") Integer storeId, @Param("keyword") String keyword, @Param("delivery") Integer delivery, @Param("status") Integer status, @Param("logisticsStatus") Integer logisticsStatus, @Param("expireSeconds") Long expireSeconds, @Param("beginTime") Long beginTime, @Param("endTime") Long endTime);
Long countMchOrderByCondition(@Param("storeId") Integer storeId, @Param("keyword") String keyword, @Param("delivery") Integer delivery, @Param("status") Integer status, @Param("logisticsStatus") Integer logisticsStatus, @Param("bookingState") Integer bookingState, @Param("expireSeconds") Long expireSeconds, @Param("beginTime") Long beginTime, @Param("endTime") Long endTime);
/**

View File

@ -544,6 +544,7 @@ public interface ShopOrderBaseService extends IBaseService<ShopOrderBase> {
* @param delivery 配送方式1-同城配送2-物流配送
* @param status 同城配送订单状态delivery=1时才生效无值 or 0-全部订单1-进行中订单2-异常超时订单3-退款订单9-已完成订单
* @param logisticsStatus 普通快递订单状态delivery=2时才生效无值 or 0-全部订单1-待支付订单2-待发货订单3-待接收订单9-已完成订单
* @param bookingState 订单配送预约状态1-立即配送2-预约配送
* @param expireSeconds 配送超时的秒数单位秒
* @param beginTime 开始时间戳13位毫秒级别
* @param endTime 截止时间戳13位毫秒级别
@ -551,7 +552,7 @@ public interface ShopOrderBaseService extends IBaseService<ShopOrderBase> {
* @param pageSize 页大小
* @return
*/
IPage<MchOrderInfoDTO> selectMchOrderPageList(Integer storeId, String keyword, Integer delivery, Integer status, Integer logisticsStatus, Long expireSeconds, Long beginTime, Long endTime, Integer pageNum, Integer pageSize);
IPage<MchOrderInfoDTO> selectMchOrderPageList(Integer storeId, String keyword, Integer delivery, Integer status, Integer logisticsStatus, Integer bookingState, Long expireSeconds, Long beginTime, Long endTime, Integer pageNum, Integer pageSize);
/**
* 商家版根据条件查询订单条数
@ -561,12 +562,13 @@ public interface ShopOrderBaseService extends IBaseService<ShopOrderBase> {
* @param delivery 配送方式1-同城配送2-物流配送
* @param status 同城配送订单状态delivery=1时才生效无值 or 0-全部订单1-进行中订单2-异常超时订单3-退款订单9-已完成订单
* @param logisticsStatus 普通快递订单状态delivery=2时才生效无值 or 0-全部订单1-待支付订单2-待发货订单3-待接收订单9-已完成订单
* @param bookingState 订单配送预约状态1-立即配送2-预约配送
* @param expireSeconds 配送超时的秒数单位秒
* @param beginTime 开始时间戳13位毫秒级别
* @param endTime 截止时间戳13位毫秒级别
* @return
*/
Long countMchOrderByCondition(Integer storeId, String keyword, Integer delivery, Integer status, Integer logisticsStatus, Long expireSeconds, Long beginTime, Long endTime);
Long countMchOrderByCondition(Integer storeId, String keyword, Integer delivery, Integer status, Integer logisticsStatus, Integer bookingState, Long expireSeconds, Long beginTime, Long endTime);
/**
* 获取商家订单详情

View File

@ -2,6 +2,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.core.web.service.IBaseService;
import org.springframework.data.util.Pair;
@ -133,4 +134,13 @@ public interface ShopOrderInfoService extends IBaseService<ShopOrderInfo> {
* @return
*/
Pair<Boolean, String> runBookingOrder2SfExpressOrder(String orderId);
/**
* 根据店铺的营业时间范围生成可预约下单的参数
*
* @param storeId 店铺ID
* @return
*/
List<BookingArgDTO> genBookingOrderArgList(Integer storeId);
}

View File

@ -573,10 +573,16 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
Integer order_state_id = ordeListVo.getState_type();
Integer kind_id = ordeListVo.getKind_id();
Integer card_kind_id = ordeListVo.getCard_kind_id();
Integer booking_state = getParameter("booking_state", 0);
Map params = new HashMap();
params.put("order_time:desc", "");
/*订单配送预约状态:无值 or 0-立即和预约订单1-立即配送2-预约配送*/
if (CheckUtil.isNotEmpty(booking_state)) {
params.put("booking_state:eq", booking_state);
}
if (CheckUtil.isNotEmpty(order_state_id)) {
params.put("order_state_id:eq", order_state_id);
}
@ -1604,20 +1610,22 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
}
}
// 预约订单检测
Integer bookingState = Convert.toInt(getParameter("booking_state"));
if (CheckUtil.isNotEmpty(bookingState) && CommonConstant.Order_Booking_State_YY.equals(bookingState)) {
String bookingBeginTime = getParameter("booking_begin_time");
String bookingEndTime = getParameter("booking_end_time");
Pair<Boolean, String> pair = shopOrderInfoService.checkBookingOrderArgs(checkedStore, bookingState, bookingBeginTime, bookingEndTime);
if (!pair.getFirst()) {
throw new ApiException(I18nUtil._(pair.getSecond()));
}
cartData.put("booking_state", bookingState);
cartData.put("booking_begin_time", bookingBeginTime);
cartData.put("booking_end_time", bookingEndTime);
}
// // 预约订单检测
// Integer bookingState = Convert.toInt(getParameter("booking_state"));
// if (CheckUtil.isNotEmpty(bookingState) && CommonConstant.Order_Booking_State_YY.equals(bookingState)) {
// String bookingBeginTime = getParameter("booking_begin_time");
// String bookingEndTime = getParameter("booking_end_time");
// Long bookingAt = getParameter("booking_at", 0L);
// Pair<Boolean, String> pair = shopOrderInfoService.checkBookingOrderArgs(checkedStore, bookingState, bookingBeginTime, bookingEndTime);
// if (!pair.getFirst()) {
// throw new ApiException(I18nUtil._(pair.getSecond()));
// }
//
// cartData.put("booking_state", bookingState);
// cartData.put("booking_begin_time", bookingBeginTime);
// cartData.put("booking_end_time", bookingEndTime);
// cartData.put("booking_at", bookingAt);
// }
// 添加保存订单关键方法
List<String> orderIdRow = addOrder(cartData, true, false, null);
@ -1666,7 +1674,6 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
} else {
//未绑定手机返回参数封装,与前端约定该代码代表未绑定手机异常77011
return CommonResult.failed(I18nUtil._("请先绑定手机!"), 77011);
//throw new ApiException(I18nUtil._("请先绑定手机!"));
}
// 优惠券使用提醒
@ -6300,14 +6307,23 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
}
}
// 遍历多个店铺的订单记录
for (Map store_item : items) {
// 判断店铺状态关闭状态不可以下单
Integer currStoreId = Convert.toInt(store_item.get("store_id"));
Boolean store_is_open = Convert.toBool(store_item.get("store_is_open"));
if (!store_is_open) {
throw new ApiException(I18nUtil._("店铺关闭中,不可以下单!"));
}
// 判断是否为虚拟订单
// 判断店铺是否打烊打烊不能下单
Pair<Integer, String> storeBizState = shopStoreBaseService.getStoreBizState(currStoreId);
if (storeBizState != null && CommonConstant.Disable2.equals(storeBizState.getFirst())) {
throw new ApiException(I18nUtil._(storeBizState.getSecond() + ",无法提交订单。"));
}
// 每个订单记录的商品列表
List<Map> item_items = (List<Map>) store_item.get("items");
Map activitys = (Map) ObjectUtil.defaultIfNull(store_item.get("activitys"), new HashMap());
@ -6318,6 +6334,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
Map item = CollUtil.isEmpty(item_items) ? new HashMap() : item_items.get(0);
Integer kind_id = Convert.toInt(item.get("kind_id"));
// 判断是否为虚拟订单
List<Integer> kinds = Arrays.asList(StateCode.PRODUCT_KIND_FUWU, StateCode.PRODUCT_KIND_CARD);
// 是否为虚拟商品订单
boolean isVirtualGoods = kinds.contains(kind_id);
@ -6630,23 +6647,46 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
info_row.setCoupon_type_id(shopProductIndex.getCoupon_type_id());
}
// 预约订单关键字段保存处理
Integer bookingState = Convert.toInt(cart_data.get("booking_state"));
Date bookingBeginTime = DateTimeUtils.tryParseDateTimeToDate(Convert.toStr(cart_data.get("booking_begin_time")));
Date bookingEndTime = DateTimeUtils.tryParseDateTimeToDate(Convert.toStr(cart_data.get("booking_end_time")));
if (CommonConstant.Order_Booking_State_YY.equals(bookingState) && bookingBeginTime != null && bookingEndTime != null) {
// 预约订单检测
Integer bookingState = Convert.toInt(getParameter("booking_state"));
if (CheckUtil.isNotEmpty(bookingState) && CommonConstant.Order_Booking_State_YY.equals(bookingState)) {
String bookingBeginTimeStr = getParameter("booking_begin_time", "");
String bookingEndTimeStr = getParameter("booking_end_time", "");
Long bookingAt = getParameter("booking_at", 0L);
// 参数校验
if (StrUtil.isBlank(bookingBeginTimeStr)) {
throw new ApiException(I18nUtil._("预约下单时间参数不能为空!"));
}
Pair<Boolean, String> pair = shopOrderInfoService.checkBookingOrderArgs(info_row.getStore_id(), bookingState, bookingBeginTimeStr, bookingEndTimeStr);
if (!pair.getFirst()) {
throw new ApiException(I18nUtil._(pair.getSecond()));
}
Date bookingBeginTime = DateTimeUtils.tryParseDateTimeToDate(bookingBeginTimeStr);
Date bookingEndTime = DateTimeUtils.tryParseDateTimeToDate(bookingEndTimeStr);
if (bookingBeginTime == null) {
throw new ApiException(I18nUtil._("预约下单时间格式有误!"));
}
// 设置预约时间戳
if (CheckUtil.isEmpty(bookingAt)) {
bookingAt = bookingBeginTime.getTime() / 1000; // 预订单到达时间戳
}
info_row.setBooking_state(bookingState);
info_row.setBooking_at(bookingBeginTime.getTime() / 1000); // 预订单到达时间戳
info_row.setBooking_at(bookingAt);
info_row.setBooking_begin_time(bookingBeginTime);
info_row.setBooking_end_time(bookingEndTime);
// 重要预约订单任务创建处理
Boolean isSuccess = shopOrderBookingService.setupRedisBookingTask(info_row.getOrder_id(), info_row.getBooking_at());
if (!isSuccess) {
if (!shopOrderBookingService.setupRedisBookingTask(info_row.getOrder_id(), info_row.getBooking_at())) {
throw new ApiException(I18nUtil._("保存预约订单任务失败!"));
}
}
info_row.setActivity_json(JSONUtil.toJsonStr(store_item.get("discount_detail_rows")));
info_row.setPayment_form_id(payment_form_id);
UserDto user = getCurrentUser();
@ -6880,13 +6920,13 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
cart_ids.add(cart_id);
}
// 如果商品在售中
Boolean is_on_sale = Convert.toBool(_item.get("is_on_sale"));
if (is_on_sale || CollUtil.isNotEmpty(giftbag)) {
ShopOrderItem item_row = new ShopOrderItem();
Long product_id = Convert.toLong(_item.get("product_id"));
Long item_id = Convert.toLong(_item.get("item_id"));
String item_barcode = Convert.toStr(_item.get("item_barcode"));
String item_src_id = Convert.toStr(_item.get("item_src_id")); // 商品 SKU id
if (CheckUtil.isEmpty(item_src_id)) {
item_src_id = String.valueOf(item_id);
@ -6926,6 +6966,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
item_row.setBuyer_id((Integer) base_row.get("buyer_user_id")); // 买家user_id 冗余
item_row.setStore_id((Integer) base_row.get("store_id")); // 店铺ID
item_row.setProduct_id(product_id); // 产品id
item_row.setItem_barcode(item_barcode);// 商品条形码(唯一码)
item_row.setItem_id(item_id); // 货品id
item_row.setItem_src_id(item_src_id); // 商品 SKU id
item_row.setItem_name(product_item_name); // 商品名称
@ -7549,6 +7590,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
}
}
// 保存订单商品信息
if (!shopOrderItemService.saveOrUpdate(item_rows)) {
throw new ApiException(I18nUtil._("保存订单信息数据失败!"));
}
@ -8945,6 +8987,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
* @param delivery 配送方式1-同城配送2-物流配送
* @param status 同城配送订单状态delivery=1时才生效无值 or 0-全部订单1-进行中订单2-异常超时订单3-退款订单9-已完成订单
* @param logisticsStatus 普通快递订单状态delivery=2时才生效无值 or 0-全部订单1-待支付订单2-待发货订单3-待接收订单9-已完成订单
* @param bookingState 订单配送预约状态1-立即配送2-预约配送
* @param expireSeconds 配送超时的秒数单位秒
* @param beginTime 开始时间戳13位毫秒级别
* @param endTime 截止时间戳13位毫秒级别
@ -8953,14 +8996,14 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
* @return
*/
@Override
public IPage<MchOrderInfoDTO> selectMchOrderPageList(Integer storeId, String keyword, Integer delivery, Integer status, Integer logisticsStatus, Long expireSeconds, Long beginTime, Long endTime, Integer pageNum, Integer pageSize) {
public IPage<MchOrderInfoDTO> selectMchOrderPageList(Integer storeId, String keyword, Integer delivery, Integer status, Integer logisticsStatus, Integer bookingState, Long expireSeconds, Long beginTime, Long endTime, Integer pageNum, Integer pageSize) {
try {
// 初始化分页对象
Page<MchOrderInfoDTO> page = new Page<>(pageNum, pageSize);
// 查询订单基础数据
IPage<MchOrderInfoDTO> pageList = shopOrderBaseMapper.selectMchOrderPageList(
storeId, keyword, delivery, status, logisticsStatus, expireSeconds, beginTime, endTime, page);
storeId, keyword, delivery, status, logisticsStatus, bookingState, expireSeconds, beginTime, endTime, page);
if (CollUtil.isEmpty(pageList.getRecords())) {
return pageList;
@ -9036,14 +9079,15 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
* @param delivery 配送方式1-同城配送2-物流配送
* @param status 同城配送订单状态delivery=1时才生效无值 or 0-全部订单1-进行中订单2-异常超时订单3-退款订单9-已完成订单
* @param logisticsStatus 普通快递订单状态delivery=2时才生效无值 or 0-全部订单1-待支付订单2-待发货订单3-待接收订单9-已完成订单
* @param bookingState 订单配送预约状态1-立即配送2-预约配送
* @param expireSeconds 配送超时的秒数单位秒
* @param beginTime 开始时间戳13位毫秒级别
* @param endTime 截止时间戳13位毫秒级别
* @return
*/
@Override
public Long countMchOrderByCondition(Integer storeId, String keyword, Integer delivery, Integer status, Integer logisticsStatus, Long expireSeconds, Long beginTime, Long endTime) {
return shopOrderBaseMapper.countMchOrderByCondition(storeId, keyword, delivery, status, logisticsStatus, expireSeconds, beginTime, endTime);
public Long countMchOrderByCondition(Integer storeId, String keyword, Integer delivery, Integer status, Integer logisticsStatus, Integer bookingState, Long expireSeconds, Long beginTime, Long endTime) {
return shopOrderBaseMapper.countMchOrderByCondition(storeId, keyword, delivery, status, logisticsStatus, bookingState, expireSeconds, beginTime, endTime);
}
/**
@ -9174,121 +9218,30 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
// 2080-ORDER_STATE_SELF_PICKUP自提
// 全部订单总数量
jsonObject.put("all_order_count", countMchOrderByCondition(storeId, "", 0, 0, 0, 0L, beginTime, endTime));
jsonObject.put("all_order_count", countMchOrderByCondition(storeId, "", 0, 0, 0, 0, 0L, beginTime, endTime));
// 同城配送订单总数量
jsonObject.put("same_city_order_count", countMchOrderByCondition(storeId, "", 1, 0, 0, expireSeconds, beginTime, endTime));
jsonObject.put("same_city_order_count", countMchOrderByCondition(storeId, "", 1, 0, 0, 0, expireSeconds, beginTime, endTime));
// 同城配送进行中订单数量
jsonObject.putByPath("same_city_order.progress_count", countMchOrderByCondition(storeId, "", 1, 1, 0, expireSeconds, beginTime, endTime));
jsonObject.putByPath("same_city_order.progress_count", countMchOrderByCondition(storeId, "", 1, 1, 0, 0, expireSeconds, beginTime, endTime));
// 同城配送超时订单数量
jsonObject.putByPath("same_city_order.overtime_count", countMchOrderByCondition(storeId, "", 1, 2, 0, expireSeconds, beginTime, endTime));
jsonObject.putByPath("same_city_order.overtime_count", countMchOrderByCondition(storeId, "", 1, 2, 0, 0, expireSeconds, beginTime, endTime));
// 同城配送退款订单数量
jsonObject.putByPath("same_city_order.refund_count", countMchOrderByCondition(storeId, "", 1, 3, 0, 0L, beginTime, endTime));
jsonObject.putByPath("same_city_order.refund_count", countMchOrderByCondition(storeId, "", 1, 3, 0, 0, 0L, beginTime, endTime));
// 同城配送退款订单数量
jsonObject.putByPath("same_city_order.finish_count", countMchOrderByCondition(storeId, "", 1, 9, 0, 0L, beginTime, endTime));
jsonObject.putByPath("same_city_order.finish_count", countMchOrderByCondition(storeId, "", 1, 9, 0, 0, 0L, beginTime, endTime));
// 普通物流订单总数量
jsonObject.put("logistics_order_count", countMchOrderByCondition(storeId, "", 2, 0, 0, 0L, beginTime, endTime));
jsonObject.put("logistics_order_count", countMchOrderByCondition(storeId, "", 2, 0, 0, 0, 0L, beginTime, endTime));
// 普通物流待支付订单数量
jsonObject.putByPath("logistics_order.wait_pay_count", countMchOrderByCondition(storeId, "", 2, 0, 1, 0L, beginTime, endTime));
jsonObject.putByPath("logistics_order.wait_pay_count", countMchOrderByCondition(storeId, "", 2, 0, 1, 0, 0L, beginTime, endTime));
// 普通物流待发货订单数量
jsonObject.putByPath("logistics_order.wait_shipping_count", countMchOrderByCondition(storeId, "", 2, 0, 2, 0L, beginTime, endTime));
jsonObject.putByPath("logistics_order.wait_shipping_count", countMchOrderByCondition(storeId, "", 2, 0, 2, 0, 0L, beginTime, endTime));
// 普通物流待收货订单数量
jsonObject.putByPath("logistics_order.receiving_count", countMchOrderByCondition(storeId, "", 2, 0, 3, 0L, beginTime, endTime));
jsonObject.putByPath("logistics_order.receiving_count", countMchOrderByCondition(storeId, "", 2, 0, 3, 0, 0L, beginTime, endTime));
// 普通物流已完成订单数量
jsonObject.putByPath("logistics_order.finished_count", countMchOrderByCondition(storeId, "", 2, 0, 9, 0L, beginTime, endTime));
// 全部订单总数量
// jsonObject.put("all_order_count", shopOrderInfoService.getOrderCountByStoreId(storeId, null, null, null, null));
//
// // 同城配送订单总数量
// jsonObject.put("same_city_order_count", shopOrderInfoService.getOrderCountByStoreId(storeId, null, null,
// Collections.singletonList(StateCode.DELIVERY_TYPE_SAME_CITY),
// null
// ));
//
// // 同城配送进行中订单数量
// jsonObject.putByPath("same_city_order.progress_count", shopOrderInfoService.getOrderCountByStoreId(storeId,
// Arrays.asList(StateCode.ORDER_STATE_WAIT_REVIEW, StateCode.ORDER_STATE_WAIT_FINANCE_REVIEW,
// StateCode.ORDER_STATE_WAIT_PAID, StateCode.ORDER_STATE_PICKING,
// StateCode.ORDER_STATE_WAIT_SHIPPING, StateCode.ORDER_STATE_SHIPPED),
// Collections.singletonList(0),
// Collections.singletonList(StateCode.DELIVERY_TYPE_SAME_CITY),
// null
// ));
//
// // 同城配送超时订单数量
// jsonObject.putByPath("same_city_order.overtime_count", shopOrderInfoService.getOrderCountByStoreId(storeId,
// Arrays.asList(StateCode.ORDER_STATE_WAIT_REVIEW,
// StateCode.ORDER_STATE_WAIT_FINANCE_REVIEW,
// StateCode.ORDER_STATE_WAIT_PAID,
// StateCode.ORDER_STATE_PICKING,
// StateCode.ORDER_STATE_WAIT_SHIPPING,
// StateCode.ORDER_STATE_SHIPPED),
//
// Collections.singletonList(0),
// Collections.singletonList(StateCode.DELIVERY_TYPE_SAME_CITY),
// 120L
// ));
//
// // 同城配送退款订单数量
// jsonObject.putByPath("same_city_order.refund_count", shopOrderInfoService.getOrderCountByStoreId(storeId,
// null,
// Arrays.asList(1, 2),
// Collections.singletonList(StateCode.DELIVERY_TYPE_SAME_CITY),
// null
// ));
//
//
// // 普通物流订单总数量
// jsonObject.put("logistics_order_count", shopOrderInfoService.getOrderCountByStoreId(storeId, null, null,
// Arrays.asList(StateCode.DELIVERY_TYPE_EXPRESS, StateCode.DELIVERY_TYPE_EXP),
// null
// ));
//
// // 普通物流待支付订单数量
// jsonObject.putByPath("logistics_order.wait_pay_count", shopOrderInfoService.getOrderCountByStoreId(storeId,
// Collections.singletonList(StateCode.ORDER_STATE_WAIT_PAY),
//
// Collections.singletonList(0),
//
// Arrays.asList(StateCode.DELIVERY_TYPE_EXPRESS, StateCode.DELIVERY_TYPE_EXP),
// null
// ));
//
// // 普通物流待发货订单数量
// jsonObject.putByPath("logistics_order.wait_shipping_count", shopOrderInfoService.getOrderCountByStoreId(storeId,
// Arrays.asList(StateCode.ORDER_STATE_WAIT_REVIEW,
// StateCode.ORDER_STATE_WAIT_FINANCE_REVIEW,
// StateCode.ORDER_STATE_WAIT_PAID,
// StateCode.ORDER_STATE_PICKING,
// StateCode.ORDER_STATE_WAIT_SHIPPING),
//
// Collections.singletonList(0),
//
// Arrays.asList(StateCode.DELIVERY_TYPE_EXPRESS, StateCode.DELIVERY_TYPE_EXP),
// null
// ));
//
// // 普通物流待收货订单数量
// jsonObject.putByPath("logistics_order.receiving_count", shopOrderInfoService.getOrderCountByStoreId(storeId,
// Collections.singletonList(StateCode.ORDER_STATE_SHIPPED),
//
// Collections.singletonList(0),
//
// Arrays.asList(StateCode.DELIVERY_TYPE_EXPRESS, StateCode.DELIVERY_TYPE_EXP),
// null
// ));
//
// // 普通物流已完成订单数量
// jsonObject.putByPath("logistics_order.finished_count", shopOrderInfoService.getOrderCountByStoreId(storeId,
// Arrays.asList(StateCode.ORDER_STATE_RECEIVED, StateCode.ORDER_STATE_FINISH),
//
// Collections.singletonList(0),
// Arrays.asList(StateCode.DELIVERY_TYPE_EXPRESS, StateCode.DELIVERY_TYPE_EXP),
// null
// ));
jsonObject.putByPath("logistics_order.finished_count", countMchOrderByCondition(storeId, "", 2, 0, 9, 0, 0L, beginTime, endTime));
// todo 预订单数量相关数
@ -9323,64 +9276,12 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
if (StringUtils.isBlank(value)) {
return defaultValue;
}
// 使用 Long.valueOf 替代 Long.parseLong同时处理 NumberFormatException 异常
return Long.valueOf(value.trim());
} catch (NumberFormatException e) {
// 当配置值不是有效数字时记录警告日志并返回默认值
logger.warn("Same city order expire seconds config value is not a valid number, using default value: {}", defaultValue);
return defaultValue;
return Convert.toLong(value.trim());
} catch (Exception e) {
// 捕获其他可能的异常确保方法总是返回一个有效值
logger.error("Error getting same city order expire seconds, using default value: {}", defaultValue, e);
logger.error("获取同城配送最大有效值失败, 使用默认值: {}", defaultValue, e);
return defaultValue;
}
}
/**
* 取货单号格式化
*
* @param pickNum 一般是 Long 类型
* @return
*/
/**
* 计算平台与代理商的总分账金额
*
* @param storeId 店铺ID
* @param pendingAmount 待分账金额 =订单实际支付金额单位减去运费
* @return 分账给平台和代理商的总金额单位
*/
public BigDecimal calculatePlatformAndAgentShareAmount(Integer storeId, BigDecimal pendingAmount) {
// 检查参数有效性
if (storeId == null || storeId <= 0 || pendingAmount == null || pendingAmount.compareTo(BigDecimal.ZERO) <= 0) {
logger.warn("计算分账金额参数无效: storeId={}, pendingAmount={}", storeId, pendingAmount);
return BigDecimal.ZERO;
}
try {
// 获取店铺的分账比例例如 5 表示 5%
BigDecimal storeSplitRatio = shopStoreBaseService.getStoreSplitRatio(storeId, false);
if (storeSplitRatio == null) {
logger.warn("获取店铺分账比例失败storeId: {}", storeId);
return BigDecimal.ZERO;
}
// 确保比例在合理范围 [0, 100]
storeSplitRatio = storeSplitRatio.max(BigDecimal.ZERO).min(new BigDecimal(100));
// 分账金额 = 支付金额 × 平台和代理商分账比例 ÷ 100 将百分比转换为小数
BigDecimal result = pendingAmount.multiply(new BigDecimal(100).subtract(storeSplitRatio))
.divide(new BigDecimal(100), 2, RoundingMode.HALF_DOWN); // 保留两位小数
logger.debug("计算分账金额: storeId={}, pendingAmount={}, ratio={}, result={}",
storeId, pendingAmount, storeSplitRatio, result);
return result;
} catch (Exception e) {
logger.error("计算平台与代理商分账金额异常storeId: {}, pendingAmount: {}", storeId, pendingAmount, e);
return BigDecimal.ZERO;
}
}
}

View File

@ -26,6 +26,7 @@ import com.suisung.mall.common.modules.pay.PayPlantformResource;
import com.suisung.mall.common.modules.plantform.ShopPlantformFeedback;
import com.suisung.mall.common.modules.product.ShopProductComment;
import com.suisung.mall.common.modules.store.ShopStoreInfo;
import com.suisung.mall.common.pojo.dto.BookingArgDTO;
import com.suisung.mall.common.pojo.res.ThirdApiRes;
import com.suisung.mall.common.utils.CheckUtil;
import com.suisung.mall.common.utils.CommonUtil;
@ -137,6 +138,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
@Autowired
private ThreadPoolExecutor executor;
@Override
public Map dashboard() {
@ -197,7 +199,6 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
return Convert.toList(String.class, findKey(queryWrapper));
}
/**
* 获取能自动确认收货的订单号
*
@ -826,7 +827,6 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
return data;
}
@Override
public List<String> getAutoCancelOrderIdByPage(Integer pageNum, Integer pageSize) {
QueryWrapper<ShopOrderInfo> queryWrapper = new QueryWrapper<>();
@ -879,18 +879,18 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
}
// 3. 时间格式检查
if (StrUtil.hasBlank(bookingBeginTimeStr, bookingEndTimeStr)) {
if (StrUtil.isBlank(bookingBeginTimeStr)) {
return Pair.of(false, "[预约订单校验] 预约时间不能为空");
}
Date bookingBeginTime = DateTimeUtils.tryParseDateTimeToDate(bookingBeginTimeStr);
Date bookingEndTime = DateTimeUtils.tryParseDateTimeToDate(bookingEndTimeStr);
if (bookingBeginTime == null || bookingEndTime == null) {
if (bookingBeginTime == null) {
return Pair.of(false, "[预约订单校验] 预约时间格式有误");
}
// 4. 时间逻辑检查 - 开始时间不能晚于结束时间
if (bookingBeginTime.after(bookingEndTime)) {
if (bookingEndTime != null && bookingBeginTime.after(bookingEndTime)) {
return Pair.of(false, "[预约订单校验] 开始时间不能晚于截止时间");
}
@ -901,16 +901,19 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
}
if (StrUtil.isBlank(shopStoreInfo.getStore_opening_hours()) || StrUtil.isBlank(shopStoreInfo.getStore_close_hours())) {
return Pair.of(false, "[预约订单校验] 店铺营业时间未设置,请联系商家");
shopStoreInfo.setStore_opening_hours("09:00");
shopStoreInfo.setStore_close_hours("06:00");
logger.warn("[预约订单校验] 店铺营业时间未设置,请联系商家,默认指定 {}-{}", shopStoreInfo.getStore_opening_hours(), shopStoreInfo.getStore_close_hours());
}
// 6. 店铺营业时间检查
if (!DateTimeUtils.isTimeInRange(shopStoreInfo.getStore_opening_hours(), shopStoreInfo.getStore_close_hours(), bookingBeginTime)) {
return Pair.of(false, "[预约订单校验] 请在店铺营业时间内预约下单");
String message = StrUtil.format("[预约订单校验] 请在 {}-{} 店铺营业时间内预约下单", shopStoreInfo.getStore_opening_hours(), shopStoreInfo.getStore_close_hours());
return Pair.of(false, message);
}
// 7. 预约时间范围检查 - 仅能预约50分钟后的订单
Date fortyFiveMinutesLater = DateUtil.offsetMinute(new Date(), 50);
// 7. 预约时间范围检查 - 仅能预约50分钟后的订单防止用户在下单页面停留太长45分钟也是可以通过的
Date fortyFiveMinutesLater = DateUtil.offsetMinute(new Date(), 45);
if (!bookingBeginTime.after(fortyFiveMinutesLater)) {
return Pair.of(false, "[预约订单校验] 请预约50分后的订单");
}
@ -1011,5 +1014,198 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
}
}
/**
* 根据店铺的营业时间范围生成可预约下单的参数
*
* @param storeId 店铺ID
* @return 预约参数列表
*/
@Override
public List<BookingArgDTO> genBookingOrderArgList(Integer storeId) {
// 初始化默认营业时间
String openingHours = "09:00";
String closeHours = "18:00";
// 如果storeId不为空则尝试获取店铺信息
if (storeId != null) {
try {
ShopStoreInfo shopStoreInfo = shopStoreInfoService.getShopStoreInfoByStoreId(storeId);
if (shopStoreInfo != null) {
// 检查并使用店铺设置的营业时间
if (StrUtil.isNotBlank(shopStoreInfo.getStore_opening_hours())) {
openingHours = shopStoreInfo.getStore_opening_hours();
}
if (StrUtil.isNotBlank(shopStoreInfo.getStore_close_hours())) {
closeHours = shopStoreInfo.getStore_close_hours();
}
logger.debug("[生成预约参数] 使用店铺营业时间storeId: {}, opening: {}, close: {}", storeId, openingHours, closeHours);
} else {
logger.warn("[生成预约参数] 未找到店铺信息使用默认营业时间storeId: {}", storeId);
}
} catch (Exception e) {
logger.error("[生成预约参数] 获取店铺信息异常使用默认营业时间storeId: {}", storeId, e);
}
} else {
logger.warn("[生成预约参数] 店铺ID为空使用默认营业时间");
}
List<BookingArgDTO> result = new ArrayList<>();
// 生成未来7天的数据
Date now = new Date();
for (int i = 0; i < 7; i++) {
Date currentDate = DateUtil.offsetDay(now, i);
BookingArgDTO bookingArgDTO = new BookingArgDTO();
// 设置日期相关信息
String dateStr = DateUtil.format(currentDate, "yyyy-MM-dd");
String displayDateStr = DateUtil.format(currentDate, "MM月dd日");
// 安全获取星期信息
String weekStr = "未知";
try {
weekStr = DateTimeUtils.getWeekOfDate(currentDate);
} catch (Exception e) {
logger.warn("[生成预约参数] 获取星期信息异常使用默认值date: {}", dateStr);
}
// 设置date_title
if (i == 0) {
bookingArgDTO.setDate_title("今天(" + weekStr + "");
} else if (i == 1) {
bookingArgDTO.setDate_title("明天(" + weekStr + "");
} else {
bookingArgDTO.setDate_title(displayDateStr + "" + weekStr + "");
}
bookingArgDTO.setDate_str(displayDateStr);
bookingArgDTO.setDate(dateStr);
// 生成时间项
List<BookingArgDTO.BookingArgItem> items = generateTimeSlots(dateStr, openingHours, closeHours, i == 0);
bookingArgDTO.setItems(items != null ? items : new ArrayList<>());
result.add(bookingArgDTO);
}
logger.debug("[生成预约参数] 成功生成预约参数storeId: {}, opening: {}, close: {}, 参数数量: {}",
storeId, openingHours, closeHours, result.size());
return result;
}
/**
* 生成时间槽列表
*
* @param dateStr 日期字符串 yyyy-MM-dd
* @param openingHours 开始营业时间 HH:mm
* @param closeHours 结束营业时间 HH:mm
* @param isToday 是否是今天
* @return 时间槽列表
*/
private List<BookingArgDTO.BookingArgItem> generateTimeSlots(String dateStr, String openingHours, String closeHours, boolean isToday) {
// 参数校验
if (StrUtil.isBlank(dateStr) || StrUtil.isBlank(openingHours) || StrUtil.isBlank(closeHours)) {
logger.warn("[生成时间槽] 参数为空dateStr: {}, openingHours: {}, closeHours: {}", dateStr, openingHours, closeHours);
return Collections.emptyList();
}
try {
List<BookingArgDTO.BookingArgItem> items = new ArrayList<>();
// 添加"立即送出"选项仅限今天
if (isToday) {
BookingArgDTO.BookingArgItem immediateItem = new BookingArgDTO.BookingArgItem();
immediateItem.setTime_title("立即送出");
immediateItem.setBooking_at(0L);
immediateItem.setBooking_state(1);
immediateItem.setBooking_begin_time("");
immediateItem.setBooking_end_time("");
items.add(immediateItem);
}
// 解析营业时间
Date openTime = DateUtil.parse(dateStr + " " + openingHours + ":00", "yyyy-MM-dd HH:mm:ss");
Date closeTime = DateUtil.parse(dateStr + " " + closeHours + ":00", "yyyy-MM-dd HH:mm:ss");
// 验证营业时间有效性
if (openTime.after(closeTime)) {
logger.warn("[生成时间槽] 营业时间无效openTime: {}, closeTime: {}", openTime, closeTime);
return items;
}
// 时间槽间隔分钟
int slotInterval = 30;
// 对于今天需要特殊处理第二个时间槽从当前时间+50分钟开始
Date startTime = openTime;
if (isToday) {
// 当前时间+50分钟作为第二个时间槽的开始时间
Date nowPlusFifty = DateUtil.offsetMinute(new Date(), 50);
// 如果当前时间+50分钟在营业时间范围内则从该时间开始
if (nowPlusFifty.after(openTime) && nowPlusFifty.before(closeTime)) {
startTime = nowPlusFifty;
}
// 如果当前时间+50分钟已经超过营业结束时间则不生成后续时间槽
else if (nowPlusFifty.after(closeTime)) {
logger.debug("[生成时间槽] 当前时间+50分钟已超过营业结束时间不生成后续时间槽");
return items;
}
}
// 生成时间槽
Date currentTimeSlot = startTime;
int slotCount = 0;
final int MAX_SLOTS = 48; // 最多生成48个时间段防止异常循环
while (currentTimeSlot.before(closeTime) && slotCount < MAX_SLOTS) {
Date endTimeSlot = DateUtil.offsetMinute(currentTimeSlot, slotInterval);
// 如果结束时间超过了营业结束时间则使用营业结束时间
if (endTimeSlot.after(closeTime)) {
endTimeSlot = closeTime;
}
// 创建时间段项
BookingArgDTO.BookingArgItem timeItem = new BookingArgDTO.BookingArgItem();
String beginTimeStr = DateUtil.format(currentTimeSlot, "HH:mm");
String endTimeStr = DateUtil.format(endTimeSlot, "HH:mm");
timeItem.setTime_title(beginTimeStr + "-" + endTimeStr);
// 时间戳计算
long bookingAt = currentTimeSlot.getTime() / 1000;
timeItem.setBooking_at(bookingAt);
timeItem.setBooking_state(2);
timeItem.setBooking_begin_time(DateUtil.format(currentTimeSlot, "yyyy-MM-dd HH:mm:ss"));
timeItem.setBooking_end_time(DateUtil.format(endTimeSlot, "yyyy-MM-dd HH:mm:ss"));
items.add(timeItem);
// 移动到下一个时间段
currentTimeSlot = endTimeSlot;
slotCount++;
// 防止时间相同导致的死循环
if (currentTimeSlot.equals(startTime)) {
logger.warn("[生成时间槽] 检测到时间循环,跳出循环");
break;
}
}
if (slotCount >= MAX_SLOTS) {
logger.warn("[生成时间槽] 时间段数量超过最大限制date: {}", dateStr);
}
logger.debug("[生成时间槽] 成功生成时间槽date: {}, 时间段数量: {}", dateStr, items.size());
return items;
} catch (Exception e) {
logger.error("[生成时间槽] 生成时间槽异常date: {}, openingHours: {}, closeHours: {}", dateStr, openingHours, closeHours, e);
return Collections.emptyList();
}
}
}

View File

@ -29,6 +29,7 @@ public interface SFExpressApiService {
/**
* 创建顺丰同店铺-连锁店铺
*
* @param mchId 商家入驻编号
* @param storeId 商家门店ID
* @param shopName 店名
* @param cityName 城市
@ -39,7 +40,7 @@ public interface SFExpressApiService {
* @param latitude 纬度
* @return
*/
Pair<Boolean, String> createSfExpressShop(Integer storeId, String shopName, String cityName, String shopAddress, String contactName, String contactPhone, String longitude, String latitude);
Pair<Boolean, String> createSfExpressShop(Long mchId, Integer storeId, String shopName, String cityName, String shopAddress, String contactName, String contactPhone, String longitude, String latitude);
/**

View File

@ -32,6 +32,7 @@ import com.suisung.mall.common.pojo.req.*;
import com.suisung.mall.common.pojo.res.ThirdApiRes;
import com.suisung.mall.common.pojo.to.AddressParseResultTO;
import com.suisung.mall.common.utils.*;
import com.suisung.mall.shop.esign.service.EsignPlatformInfoService;
import com.suisung.mall.shop.message.service.PushMessageService;
import com.suisung.mall.shop.order.service.ShopOrderBaseService;
import com.suisung.mall.shop.order.service.ShopOrderInfoService;
@ -119,6 +120,10 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
@Autowired
private ShopProductItemService shopProductItemService;
@Lazy
@Autowired
private EsignPlatformInfoService esignPlatformInfoService;
/**
* 创建顺丰同店铺-连锁店铺
*
@ -180,7 +185,6 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
return Pair.of(false, "联系人手机号不能为空");
}
AddressParseResultTO addressParseResultTO = AddressUtil.parseAddress(shopMchEntry.getStore_address());
// 解析城市名称
String cityName = "桂平市"; // 默认城市
@ -212,6 +216,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
// 调用创建店铺方法
Pair<Boolean, String> result = createSfExpressShop(
mchId,
Convert.toInt(shopMchEntry.getStore_id()),
shopStoreName,
cityName,
@ -228,8 +233,9 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
/**
* 创建顺丰同普通型店铺
* 创建顺丰同店铺-连锁店铺
*
* @param mchId 商家入驻编号
* @param storeId 商家门店ID
* @param shopName 店名
* @param cityName 城市
@ -241,19 +247,40 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
* @return Pair<Boolean, String> 第一个元素表示是否成功第二个元素表示结果信息或错误信息
*/
@Override
public Pair<Boolean, String> createSfExpressShop(Integer storeId, String shopName, String cityName,
public Pair<Boolean, String> createSfExpressShop(Long mchId, Integer storeId, String shopName, String cityName,
String shopAddress, String contactName, String contactPhone,
String longitude, String latitude) {
logger.info("开始创建顺丰同城店铺, storeId: {}", storeId);
try {
// 1. 验证必要参数
if (CheckUtil.isEmpty(storeId) || StringUtils.isAnyBlank(shopName, shopAddress, contactName, contactPhone)) {
logger.error("创建顺丰店铺缺少必要参数storeId:{},shopName:{},shopAddress:{},contactName:{},contactPhone:{}", storeId, shopName, shopAddress, contactName, contactPhone);
if ((CheckUtil.isEmpty(mchId) && CheckUtil.isEmpty(storeId)) ||
StringUtils.isAnyBlank(shopName, shopAddress, contactName, contactPhone)) {
logger.error("创建顺丰店铺缺少必要参数mchId:{}, storeId:{},shopName:{},shopAddress:{},contactName:{},contactPhone:{}",
mchId, storeId, shopName, shopAddress, contactName, contactPhone);
return Pair.of(false, "创建顺丰店铺,缺少必要参数!");
}
// 2. 获取或初始化商家配送信息
// 2. 获取商家入驻信息
ShopMchEntry shopMchEntry;
if (CheckUtil.isNotEmpty(mchId)) {
shopMchEntry = shopMchEntryService.shopMerchEntryById(mchId);
if (shopMchEntry == null) {
logger.error("无法找到商家入驻信息mchId: {}", mchId);
return Pair.of(false, "无法找到商家入驻信息");
}
storeId = Convert.toInt(shopMchEntry.getStore_id());
} else {
shopMchEntry = shopMchEntryService.getShopMerchEntryByStoreId(storeId);
if (shopMchEntry == null) {
logger.error("无法找到商家入驻信息storeId: {}", storeId);
return Pair.of(false, "无法找到商家入驻信息");
}
}
// 3. 获取或初始化商家配送信息
ShopStoreSameCityTransportBase transportBase = shopStoreSameCityTransportBaseService
.getShopStoreSameCityTransportBaseById(Long.valueOf(storeId));
@ -264,46 +291,55 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
}
if (transportBase == null) {
logger.error("创建商家配送信息失败!");
logger.error("创建商家配送信息失败!storeId: {}", storeId);
return Pair.of(false, "创建商家配送信息失败");
}
// 3. 如果已存在顺丰店铺ID验证其有效性
// 4. 如果已存在顺丰店铺ID验证其有效性
if (CheckUtil.isNotEmpty(transportBase.getShop_id())) {
logger.debug("如果存在店铺Id从顺丰同城平台查询店铺ID开始验证其有效性");
logger.debug("检测到已存在店铺Id开始验证其有效性shopId: {}", transportBase.getShop_id());
ThirdApiRes shopInfo = getSfShopInfo(transportBase.getShop_id());
if (shopInfo != null && shopInfo.getError_code().equals(0)) {
logger.info("已成功创建顺丰同城店铺!");
logger.info("已成功创建顺丰同城店铺!shopId: {}", transportBase.getShop_id());
return Pair.of(true, transportBase.getShop_id());
}
}
// 4. 构建请求参数
Map<String, Object> params = buildCommonParams();
params.put("supplier_id", supplierId); // 店铺所属商家id
params.put("out_shop_id", storeId); // 外部店铺ID
params.put("shop_name", shopName); // 店铺名称
params.put("city_name", cityName); // 城市名称
// 5. 获取供应商ID
String sfSupplierId = "";
// 获取创建店铺的商家Id由店铺的县级代理商提供
if (CheckUtil.isNotEmpty(shopMchEntry.getDistributor_id())) {
logger.debug("获取创建店铺的县级代理商Id: distributorId={}", shopMchEntry.getDistributor_id());
sfSupplierId = esignPlatformInfoService.getSupplierIdByAgentId(shopMchEntry.getDistributor_id());
}
// RMK 1:快餐 2:药品 3:百货 4:脏衣服收 5:干净衣服派 6:生鲜 8:高端饮品 9:现场勘验 10:快递 12:文件 13:蛋糕 14:鲜花 15:数码 16:服装 17:
//汽配 18:珠宝 20:披萨 21:中餐 22:水产 27:专人直送 32:中端饮品 33:便利店 34:面包糕点 35:火锅 36:证照 40:烧烤小龙虾 41:外部落地配 47:烟酒
// 48:成人用品 99:其他
// 经营类型: 快餐,百货,生鲜,高端饮品,蛋糕,鲜花,数码,服装,披萨,水产,中端饮品,便利店,面包糕点,烟酒,其他
params.put("shop_product_types", "33"); //"1,3,6,8,13,14,15,16,20,22,32,33,34,47,99"
params.put("shop_type", 1); // 店铺类型: 1-普通型 2-平台型
params.put("shop_address", shopAddress); // 店铺地址
params.put("longitude", longitude); // 经度
params.put("latitude", latitude); // 纬度
params.put("shop_contact_name", contactName); // 联系人姓名
params.put("shop_contact_phone", contactPhone); // 联系电话
// 县级代理商如果没有商家Id直接获取默认配置的商家Id
if (StrUtil.isBlank(sfSupplierId)) {
sfSupplierId = supplierId;
}
// 6. 构建请求参数
Map<String, Object> params = buildCommonParams();
params.put("supplier_id", sfSupplierId); // 店铺所属商家id应该由县级代理商提供
params.put("out_shop_id", storeId); // 外部店铺ID
params.put("shop_name", shopName); // 店铺名称
params.put("city_name", cityName); // 城市名称
params.put("shop_product_types", "33"); // 经营类型: 33-便利店
params.put("shop_type", 1); // 店铺类型: 1-普通型 2-平台型
params.put("shop_address", shopAddress); // 店铺地址
params.put("longitude", longitude); // 经度
params.put("latitude", latitude); // 纬度
params.put("shop_contact_name", contactName); // 联系人姓名
params.put("shop_contact_phone", contactPhone); // 联系电话
logger.debug("开始创建顺丰店铺,参数:{}", params);
// 5. 发送请求到顺丰接口
// 7. 发送请求到顺丰接口
String paramJSON = JsonUtil.toJSONString(params);
String sendUrl = buildUrl("createShop", paramJSON);
String responseStr = HttpUtil.post(sendUrl, paramJSON);
logger.debug("创建顺丰店铺结果:{}", responseStr);
logger.debug("创建顺丰店铺结果: {}", responseStr);
if (StrUtil.isBlank(responseStr)) {
logger.error("创建顺丰店铺异常,无返回值!");
return Pair.of(false, "创建顺丰店铺异常,无返回值!");
@ -315,18 +351,24 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
return Pair.of(false, "创建顺丰店铺异常,返回值有误!");
}
// 6. 检查接口调用结果
// 8. 检查接口调用结果
if (!apiRes.getError_code().equals(0) || apiRes.getResult() == null) {
String errMsg = apiRes.getError_code().equals(0) ? "创建顺丰店铺失败!" : "创建顺丰店铺失败: " + apiRes.getError_msg();
String errMsg = StrUtil.isBlank(apiRes.getError_msg()) ?
"创建顺丰店铺失败。" : "创建顺丰店铺失败: " + apiRes.getError_msg();
logger.error("创建顺丰店铺失败: {}", errMsg);
return Pair.of(false, errMsg);
}
// 7. 提取顺丰店铺ID并更新数据库
// 9. 提取顺丰店铺ID并更新数据库
JSONObject result = (JSONObject) apiRes.getResult();
String sfShopId = result.getStr("shop_id");
if (StrUtil.isBlank(sfShopId)) {
logger.error("创建顺丰店铺失败返回的店铺ID为空");
return Pair.of(false, "创建顺丰店铺失败返回的店铺ID为空");
}
transportBase.setShop_id(sfShopId);
transportBase.setShop_state(CommonConstant.Enable);// 顺丰同城快递商品特惠
transportBase.setShop_state(CommonConstant.Enable); // 顺丰同城快递商品特惠
transportBase.setDelivery_brand(CommonConstant.DELIVERY_BRAND_SF);
Pair<Long, String> updateResult = shopStoreSameCityTransportBaseService
@ -346,6 +388,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
}
}
/**
* 创建顺丰同城普通型店铺直调顺丰同城的接口脱离我们的业务
*

View File

@ -4,7 +4,9 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.suisung.mall.common.modules.store.ShopStoreBase;
import com.suisung.mall.common.pojo.dto.StoreBizTimeInfoDTO;
import io.lettuce.core.dynamic.annotation.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@ -31,10 +33,23 @@ public interface ShopStoreBaseMapper extends BaseMapper<ShopStoreBase> {
/**
* 搜索附近店铺排序从近到远 2024-12-26
*
* @param page
* @param params 省份province_id城市city_id县county_id店铺分类store_category_id分店subsite_id店铺名称关键字store_name
* @return
*/
IPage<Map> getNearShop2(Page<Map> page, @Param("params") Map params);
/**
* 获取店铺营业时间信息
*
* @param storeId
* @return
*/
@Select("SELECT ssb.store_id, ssb.store_name, ssb.store_biz_state, ssi.store_opening_hours, ssi.store_close_hours " +
" FROM shop_store_base ssb LEFT JOIN shop_store_info ssi ON ssb.store_id = ssi.store_id " +
" WHERE ssb.store_id = #{storeId} LIMIT 1")
StoreBizTimeInfoDTO getStoreBizTimeInfo(@Param("storeId") Integer storeId);
}

View File

@ -237,6 +237,14 @@ public interface ShopStoreBaseService extends IBaseService<ShopStoreBase> {
*/
Integer getStoreBizState(ShopStoreBase shopStoreBase, ShopStoreInfo shopStoreInfo);
/**
* 根据店铺Id获取店铺营业状态
*
* @param storeId
* @return
*/
Pair<Integer, String> getStoreBizState(Integer storeId);
// Page<ShopStoreBase> getMobileStoreList(Integer page, Integer rows);
}

View File

@ -337,7 +337,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
Pair<String, String> mobileAndLicenseNumber = esignPlatformInfoService.getEsignPlatformMobileAndLicenseNumber();
if (mobileAndLicenseNumber != null) {
Map<String, Object> tmplArgs = new HashMap<>(1);
tmplArgs.put("name", record.getBiz_license_company()); // 商家公司名称
tmplArgs.put("name", record.getStore_name()); // 商家店铺名
shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_486545331", tmplArgs);
}
@ -462,7 +462,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
// 获取平台方的手机号码发送短信通知
Pair<String, String> mobileAndLicenseNumber = esignPlatformInfoService.getEsignPlatformMobileAndLicenseNumber();
if (mobileAndLicenseNumber != null) {
String mchName = StrUtil.isBlank(record.getBiz_license_company()) ? "重新修正" : record.getBiz_license_company();
String mchName = StrUtil.isBlank(record.getStore_name()) ? "重新修正资料" : record.getStore_name();
Map<String, Object> tmplArgs = new HashMap<>(1);
tmplArgs.put("name", mchName); // 商家公司名称
// 尊敬的管理员商家 ${name}提交了入驻我们平台的申请请及时对相关资质材料予以审核以便推进后续流程
@ -928,8 +928,6 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
return CommonResult.failed("商家入驻记录不存在!");
}
// 分账比例最终提交给拉卡拉的分账比例是 20%
BigDecimal splitRatio = getMchEntryRatioOrDefault(shopMchEntry.getBiz_category(), shopMchEntry.getBiz_second_category(), shopMchEntry.getSplit_ratio(), new BigDecimal(94));
// 如果是驳回状态直接返回成功消息
if (approvalStatus.equals(CommonConstant.MCH_APPR_STA_NOPASS)) {
@ -955,7 +953,13 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
shopMchEntry.setApproval_invalid_col(approvalInvalidCol);
shopMchEntry.setUpdated_by(userId);
shopMchEntry.setSettlement_method(1); // 结算类型0-秒到不分账1-次日结算需要分账
shopMchEntry.setSplit_ratio(splitRatio);
// 分账比例最终提交给拉卡拉的分账比例是 20%
BigDecimal splitRatio = shopMchEntry.getSplit_ratio();
if (CheckUtil.isEmpty(splitRatio)) {
splitRatio = getMchEntryRatioOrDefault(shopMchEntry.getBiz_category(), shopMchEntry.getBiz_second_category(), shopMchEntry.getSplit_ratio(), new BigDecimal(94));
shopMchEntry.setSplit_ratio(splitRatio);
}
// 店铺省市区处理
String[] result = handleStoreDistrictInfo(shopMchEntry.getStore_district(), shopMchEntry.getStore_area(), shopMchEntry.getStore_address());
@ -1762,8 +1766,8 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
}
UpdateWrapper<ShopMchEntry> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", mchId).eq("status", CommonConstant.Enable)
.ne("approval_status", CommonConstant.MCH_APPR_STA_PASS);
updateWrapper.eq("id", mchId).eq("status", CommonConstant.Enable);
//.ne("approval_status", CommonConstant.MCH_APPR_STA_PASS);
updateWrapper.set("approval_status", CommonConstant.MCH_APPR_STA_PASS);
updateWrapper.set("approval_remark", "恭喜您,入驻流程已全部完成!");
boolean updateResult = update(updateWrapper); // 更新商户入驻信息
@ -1887,6 +1891,7 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
approvalRemark = "入驻资料正在审核中,请耐心等待";
}
updateWrapper.set("approval_remark", approvalRemark);
// 4. 构建需要更新的字段和值的映射关系

View File

@ -44,6 +44,7 @@ import com.suisung.mall.common.modules.store.*;
import com.suisung.mall.common.modules.user.ShopUserFavoritesStore;
import com.suisung.mall.common.pojo.dto.GpsDTO;
import com.suisung.mall.common.pojo.dto.StandardAddressDTO;
import com.suisung.mall.common.pojo.dto.StoreBizTimeInfoDTO;
import com.suisung.mall.common.service.impl.BaiduMapServiceImpl;
import com.suisung.mall.common.utils.*;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
@ -190,8 +191,6 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
@Lazy
@Autowired
private WxQrCodeService wxQrCodeService;
@Autowired
private I18nUtil i18nUtil;
/**
@ -3207,12 +3206,15 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
CheckUtil.isNotEmpty(shopMchEntry.getBiz_second_category()) ? shopMchEntry.getBiz_second_category() : 0);
}
// 计算分账比例
BigDecimal splitRatio = shopMchEntryService.getMchEntryRatioOrDefault(
shopMchEntry.getBiz_category(),
shopMchEntry.getBiz_second_category(),
shopMchEntry.getSplit_ratio(),
new BigDecimal(94));
BigDecimal splitRatio = shopMchEntry.getSplit_ratio();
if (CheckUtil.isEmpty(splitRatio)) {
// 计算分账比例
splitRatio = shopMchEntryService.getMchEntryRatioOrDefault(
shopMchEntry.getBiz_category(),
shopMchEntry.getBiz_second_category(),
shopMchEntry.getSplit_ratio(),
new BigDecimal(94));
}
if (CheckUtil.isEmpty(shopStoreBase.getSplit_ratio())) {
shopStoreBase.setSplit_ratio(splitRatio);
@ -3288,7 +3290,7 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
shopStoreInfo.setStore_close_hours("21:30");
shopStoreInfo.setStore_discount(BigDecimal.valueOf(10));
shopStoreInfo.setStore_banner(storeFacadeImage);
shopStoreInfo.setStore_tel(contact_mobile);
shopStoreInfo.setContact_mobile(contact_mobile);
shopStoreInfo.setContact_name(shopMchEntry.getContact_name());
@ -3432,7 +3434,8 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
if (storeArea != null) {
String[] areaNames = storeArea.split("/");
String cityName = areaNames.length > 0 ? areaNames[areaNames.length - 1] : storeArea.replace("/", "");
sfExpressApiService.createSfExpressShop(storeId, shopMchEntry.getStore_name(),
sfExpressApiService.createSfExpressShop(mchId, storeId, shopMchEntry.getStore_name(),
cityName, shopMchEntry.getStore_address(), shopMchEntry.getContact_name(),
contact_mobile, shopMchEntry.getStore_longitude(), shopMchEntry.getStore_latitude());
}
@ -4201,38 +4204,95 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
*/
@Override
public Integer getStoreBizState(ShopStoreBase shopStoreBase, ShopStoreInfo shopStoreInfo) {
try {
// 参数校验
if (shopStoreBase == null || shopStoreInfo == null) {
log.warn("店铺基础信息或详细信息为空,无法确定营业状态");
return CommonConstant.Enable;
}
// 参数校验
if (shopStoreBase == null || shopStoreInfo == null) {
log.warn("店铺基础信息或详细信息为空,无法确定营业状态");
return CommonConstant.Disable2;
}
try {
Integer storeBizState = shopStoreBase.getStore_biz_state();
String openingHours = shopStoreInfo.getStore_opening_hours();
String closingHours = shopStoreInfo.getStore_close_hours();
// 检查店铺是否营业中且营业时间已设置
if (CommonConstant.Enable.equals(storeBizState)
&& StrUtil.isNotEmpty(openingHours)
&& StrUtil.isNotEmpty(closingHours)) {
if (CommonConstant.Enable.equals(storeBizState) && !StrUtil.hasBlank(openingHours, closingHours)) {
// 检查当前时间是否在营业时间内
if (!DateTimeUtils.isCurrentTimeInRange(openingHours, closingHours)) {
// 不在营业时间内返回已打烊状态
return CommonConstant.Disable2;
}
return CommonConstant.Enable;
}
// 返回原始营业状态
return storeBizState;
} catch (Exception e) {
// 处理异常避免影响主流程
log.error("检查店铺营业状态时发生异常shopStoreBase: {}, shopStoreInfo: {}",
shopStoreBase, shopStoreInfo, e);
return CommonConstant.Enable;
log.error("检查店铺营业状态时发生异常storeId: {}",
shopStoreBase != null ? shopStoreBase.getStore_id() : "unknown", e);
return CommonConstant.Disable2;
}
}
/**
* 根据店铺ID获取营业状态
*
* @param storeId 店铺ID
* @return 营业状态1-营业中2-已打烊
*/
@Override
public Pair<Integer, String> getStoreBizState(Integer storeId) {
// 参数校验
if (CheckUtil.isEmpty(storeId)) {
log.warn("店铺ID为空无法确定营业状态");
return Pair.of(CommonConstant.Disable2, "店铺营业状态有误");
}
try {
StoreBizTimeInfoDTO storeBizTimeInfo = baseMapper.getStoreBizTimeInfo(storeId);
if (storeBizTimeInfo == null) {
log.warn("未找到店铺营业时间信息storeId: {}", storeId);
return Pair.of(CommonConstant.Disable2, "店铺营业状态有误");
}
Integer storeBizState = storeBizTimeInfo.getStore_biz_state();
String openingHours = storeBizTimeInfo.getStore_opening_hours();
String closingHours = storeBizTimeInfo.getStore_close_hours();
// 检查店铺是否营业中且营业时间已设置
if (CommonConstant.Enable.equals(storeBizState)
&& StrUtil.isNotBlank(openingHours)
&& StrUtil.isNotBlank(closingHours)) {
// 检查当前时间是否在营业时间内
if (!DateTimeUtils.isCurrentTimeInRange(openingHours, closingHours)) {
// 不在营业时间内返回已打烊状态
log.debug("店铺当前不在营业时间内storeId: {}, openingHours: {}, closingHours: {}",
storeId, openingHours, closingHours);
return Pair.of(CommonConstant.Disable2, String.format("%s营业时间段%s-%s", storeBizTimeInfo.getStore_name(),
openingHours, closingHours));
}
return Pair.of(CommonConstant.Enable, "");
}
// 返回原始营业状态处理null情况
Integer resultState = storeBizState != null ? storeBizState : CommonConstant.Disable2;
log.debug("返回店铺营业状态storeId: {}, state: {}", storeId, resultState);
if (resultState == CommonConstant.Disable2) {
return Pair.of(resultState, String.format("%s打烊中", storeBizTimeInfo.getStore_name()));
}
return Pair.of(resultState, "");
} catch (Exception e) {
// 处理异常避免影响主流程
log.error("检查店铺营业状态发生异常storeId: {}", storeId, e);
return Pair.of(CommonConstant.Disable2, "无法获取店铺营业状态");
}
}
/**
* 更新店铺分账比例
*

View File

@ -58,6 +58,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -1049,6 +1050,14 @@ public class ShopUserCartServiceImpl extends BaseServiceImpl<ShopUserCartMapper,
throw new ApiException(I18nUtil._("添加购物车失败!"));
}
// 店铺Id
Integer storeId = Convert.toInt(product_row.get("store_id"));
// 判断店铺是否打烊打烊不能放入购物车
Pair<Integer, String> storeBizState = shopStoreBaseService.getStoreBizState(storeId);
if (storeBizState != null && CommonConstant.Disable2.equals(storeBizState.getFirst())) {
throw new ApiException(I18nUtil._(storeBizState.getSecond() + ",无法加购商品。"));
}
Integer cart_type = Convert.toInt(data.get("cart_type"));
// 判断是新增还是更新
@ -1117,7 +1126,7 @@ public class ShopUserCartServiceImpl extends BaseServiceImpl<ShopUserCartMapper,
}
cart.setUser_id(user_id);
cart.setStore_id((Integer) product_row.get("store_id"));
cart.setStore_id(storeId);
cart.setChain_id(chain_id);
cart.setProduct_id((Long) product_row.get("product_id"));
cart.setItem_id(item_id);

View File

@ -184,8 +184,8 @@ feieyun:
sf-express:
# 顺丰同城 api 接口配置
dev_id: 1715091463
# 桂平顺丰平台商家id 2273453450129
supplier_id: 2269768012593
# 桂平顺丰平台商家id 2273453450129 2269768012593
supplier_id: 2281834525297
appid: 1715091463
appkey: 47466ae69c530f831395e1bc405639fb
# dev_id: 1715091463

View File

@ -592,6 +592,11 @@
<result property="kind_id" column="kind_id"/>
<result property="delivery_type_id" column="delivery_type_id"/>
<result property="distance" column="distance"/>
<!--预约订单相关字段-->
<result property="booking_state" column="booking_state"/>
<result property="booking_begin_time" column="booking_begin_time"/>
<result property="booking_end_time" column="booking_end_time"/>
<result property="booking_at" column="booking_at"/>
<!-- 店铺嵌套对象映射 -->
<association property="store_info" javaType="com.suisung.mall.common.modules.order.dto.MchOrderStoreDTO">
@ -752,6 +757,11 @@
<if test="endTime != null and endTime > 0">
AND oi.order_time <![CDATA[<=]]> #{end_time}
</if>
<!--订单配送预约状态1-立即配送2-预约配送-->
<if test="bookingState != null and bookingState > 0">
AND oi.booking_state = #{bookingState}
</if>
</where>
</sql>
@ -788,6 +798,10 @@
2013, 2014, 2020, 2030, 2040))>1,2,1)
AS is_new_buyer,
oi.payment_time,
oi.booking_state,
oi.booking_begin_time,
oi.booking_end_time,
oi.booking_at,
od.order_shipping_fee,
IFNULL(od.order_shipping_fee_inner, 0) as order_shipping_fee_inner,
IFNULL(od.lkl_fee, 0) as lkl_fee,
@ -843,7 +857,6 @@
osf.feed
</sql>
<select id="selectMchOrderPageList" resultMap="MchOrderResult">
<include refid="mchOrderColumns"/>
@ -859,7 +872,7 @@
<include refid="mchOrderWhereCondition"/>
ORDER BY ob.order_id DESC
ORDER BY ob.order_time DESC
</select>
<select id="countMchOrderByCondition" resultType="java.lang.Long">
@ -869,13 +882,11 @@
JOIN shop_order_data od ON ob.order_id = od.order_id
JOIN shop_store_base sb ON ob.store_id = sb.store_id
JOIN shop_order_delivery_address oda ON ob.order_id = oda.order_id
<include refid="mchOrderWhereCondition"/>
</select>
<select id="getMchOrderDetail" resultMap="MchOrderResult">
<include refid="mchOrderColumns"/>
from shop_order_base ob
join shop_order_info oi on ob.order_id=oi.order_id
join shop_order_data od on ob.order_id=od.order_id

View File

@ -14,14 +14,15 @@
order_item_commission_fee,
order_item_commission_fee_refund, policy_discountrate, item_voucher, order_item_note, order_item_file,
order_item_confirm_file, order_item_confirm_status, design_file_images, order_item_saler_id, item_src_id,
order_item_supplier_sync, src_order_id
order_item_supplier_sync, src_order_id, item_barcode
</sql>
<select id="listItem" resultType="java.util.Map">
SELECT
shop_order_item.store_id,
shop_order_item.product_id,
shop_order_item.item_id,
shop_order_item.item_barcode,
shop_order_item.item_name,
shop_order_item.item_unit_price,
shop_order_item.order_item_image,
@ -86,6 +87,7 @@
ORDER BY
item_total DESC
</select>
<select id="getOrderItemList" resultType="java.util.Map">
select *
from shop_order_item m left join shop_order_info o on m.order_id = o.order_id
@ -157,7 +159,7 @@
a.order_item_unit_price,
a.order_item_quantity,
a.order_item_amount,
"" as product_sn
a.item_barcode as product_sn
FROM shop_order_item a WHERE a.order_id = #{orderId} ORDER BY a.order_item_id asc
</select>
</mapper>