Merge branch 'main' into dev
This commit is contained in:
commit
1a9375086c
@ -30,6 +30,7 @@ import com.suisung.mall.common.pojo.dto.OssCallbackResultDTO;
|
||||
import com.suisung.mall.common.pojo.dto.OssPolicyResultDTO;
|
||||
import com.suisung.mall.common.utils.I18nUtil;
|
||||
import com.suisung.mall.common.utils.LogUtil;
|
||||
import com.suisung.mall.common.utils.UploadUtil;
|
||||
import com.suisung.mall.common.utils.VideoUtil;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
@ -169,6 +170,9 @@ public class OssServiceImpl implements OssService {
|
||||
* @return
|
||||
*/
|
||||
public Map upload(MultipartFile file, UserDto user, String dir, String uploadPath, String uploadName, String fileName) {
|
||||
// 如果是图片,先压缩图片,再上传到 cos 对象存储
|
||||
file = UploadUtil.compressImageIfNeeded(file, 2048);
|
||||
|
||||
// 创建临时文件
|
||||
creTempFile(file, dir, uploadName);
|
||||
String url = null;
|
||||
@ -248,7 +252,7 @@ public class OssServiceImpl implements OssService {
|
||||
tempFile.delete();
|
||||
logger.info("临时文件已删除: {}", uploadPath);
|
||||
}
|
||||
|
||||
|
||||
// 同时删除可能创建的封面文件
|
||||
String coverPath = uploadPath.replace("." + VideoUtil.getVideoFormat(uploadPath), ".jpg");
|
||||
File coverFile = new File(coverPath);
|
||||
|
||||
@ -17,6 +17,7 @@ public class StateCode {
|
||||
public static final int DELIVERY_TYPE_EXP = 10; // 普通快递
|
||||
public static final int DELIVERY_TYPE_IN_STORE_SERVICE = 15; // 店铺配送
|
||||
public static final int DELIVERY_TYPE_SAME_CITY = 16;//顺丰同城配送
|
||||
public static final int DELIVERY_TYPE_STORE_BY_SELF = 17; // 商家(线下)自己配送
|
||||
|
||||
public static final Map<Integer, String> DELIVERY_TYPE_MAP = new HashMap() {
|
||||
{
|
||||
@ -450,6 +451,11 @@ public class StateCode {
|
||||
public static final int SF_ORDER_STATUS_EXCEPTION = 91;
|
||||
public static final int SF_ORDER_STATUS_CANCELING = 31;
|
||||
|
||||
// 退款状态:0-是无退款;1-是部分退款;2-是全部退款
|
||||
public static final int ORDER_REFUND_STATUS_NO = 0;
|
||||
public static final int ORDER_REFUND_STATUS_PART = 1;
|
||||
public static final int ORDER_REFUND_STATUS_ALL = 2;
|
||||
|
||||
static {
|
||||
DELIVERY_TIME_NOT_TIMER.put(1, I18nUtil._("不限时段"));
|
||||
DELIVERY_TIME_NOT_TIMER.put(15, I18nUtil._("上午"));
|
||||
|
||||
@ -42,6 +42,9 @@ public class MchOrderInfoDTO implements Serializable {
|
||||
// 物流轨迹信息(物流,已发货的才有数据)
|
||||
@ApiModelProperty(value = "物流轨迹信息")
|
||||
Map<String, Object> logistics_traces;
|
||||
|
||||
// 退款订单详情
|
||||
MchReturnOrderDetailDTO return_order_detail;
|
||||
|
||||
// 订单信息
|
||||
@ApiModelProperty(value = "订单编号")
|
||||
@ -95,16 +98,12 @@ 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;
|
||||
}
|
||||
|
||||
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2025. 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.modules.order.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@ApiModel(value = "退款单详情主表实体类 对象", description = "商家版退款单详情主表实体类")
|
||||
public class MchReturnOrderDetailDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty(value = "退货单编号")
|
||||
private String return_id;
|
||||
|
||||
@ApiModelProperty(value = "订单编号")
|
||||
private String order_id;
|
||||
|
||||
@ApiModelProperty(value = "买家用户ID")
|
||||
private Integer buyer_user_id;
|
||||
|
||||
@ApiModelProperty(value = "买家店铺ID")
|
||||
private Integer buyer_store_id;
|
||||
|
||||
@ApiModelProperty(value = "退货原因ID")
|
||||
private Integer return_reason_id;
|
||||
|
||||
@ApiModelProperty(value = "退货原因名称")
|
||||
private String return_reason_name;
|
||||
|
||||
@ApiModelProperty(value = "买家退货留言")
|
||||
private String return_buyer_message;
|
||||
|
||||
@ApiModelProperty(value = "店铺ID")
|
||||
private Integer store_id;
|
||||
|
||||
@ApiModelProperty(value = "退货退款金额")
|
||||
private BigDecimal return_refund_amount;
|
||||
|
||||
@ApiModelProperty(value = "退货佣金费用")
|
||||
private BigDecimal return_commision_fee;
|
||||
|
||||
@ApiModelProperty(value = "退货状态ID")
|
||||
private Integer return_state_id;
|
||||
|
||||
@ApiModelProperty(value = "退货状态名称")
|
||||
private String return_state_name;
|
||||
|
||||
@ApiModelProperty(value = "退货联系电话")
|
||||
private String return_tel;
|
||||
|
||||
@ApiModelProperty(value = "退货年份")
|
||||
private Integer return_year;
|
||||
|
||||
@ApiModelProperty(value = "退货月份")
|
||||
private Integer return_month;
|
||||
|
||||
@ApiModelProperty(value = "退货日期")
|
||||
private Integer return_day;
|
||||
|
||||
@ApiModelProperty(value = "退货地址")
|
||||
private String return_addr;
|
||||
|
||||
@ApiModelProperty(value = "退货联系手机")
|
||||
private Long return_mobile;
|
||||
|
||||
@ApiModelProperty(value = "退货联系电话")
|
||||
private String return_telephone;
|
||||
|
||||
@ApiModelProperty(value = "退货联系人姓名")
|
||||
private String return_contact_name;
|
||||
|
||||
@ApiModelProperty(value = "分站ID")
|
||||
private Integer subsite_id;
|
||||
|
||||
@ApiModelProperty(value = "退货申请时间")
|
||||
private Date return_add_time;
|
||||
|
||||
@ApiModelProperty(value = "退货完成时间")
|
||||
private Date return_finish_time;
|
||||
|
||||
@ApiModelProperty(value = "是否已退款(ENUM): 0-未退款; 1-已退款")
|
||||
private Integer return_is_paid;
|
||||
|
||||
@ApiModelProperty(value = "退款渠道代码")
|
||||
private String return_channel_code;
|
||||
|
||||
@ApiModelProperty(value = "退款渠道交易ID")
|
||||
private String return_channel_trans_id;
|
||||
|
||||
@ApiModelProperty(value = "退款渠道处理时间")
|
||||
private Date return_channel_time;
|
||||
|
||||
@ApiModelProperty(value = "退款渠道状态(ENUM): 0-待退; 1-已退; 2-异常")
|
||||
private Integer return_channel_flag;
|
||||
|
||||
@ApiModelProperty(value = "支付交易号")
|
||||
private String deposit_trade_no;
|
||||
|
||||
@ApiModelProperty(value = "支付渠道ID")
|
||||
private Integer payment_channel_id;
|
||||
|
||||
@ApiModelProperty(value = "商家处理留言")
|
||||
private String return_store_message;
|
||||
|
||||
@ApiModelProperty(value = "平台退货状态ID")
|
||||
private Integer plantform_return_state_id;
|
||||
|
||||
@ApiModelProperty(value = "平台退货状态名称")
|
||||
private String plantform_return_state_name;
|
||||
|
||||
@ApiModelProperty(value = "退货类型(ENUM): 0-不用退货; 1-需要退货")
|
||||
private Integer return_flag;
|
||||
|
||||
@ApiModelProperty(value = "申请类型(ENUM): 1-退款申请; 2-退货申请; 3-虚拟退款")
|
||||
private Integer return_type;
|
||||
|
||||
@ApiModelProperty(value = "提交的退货退款金额")
|
||||
private BigDecimal submit_return_refund_amount;
|
||||
|
||||
@ApiModelProperty(value = "订单商品ID列表")
|
||||
private List<Long> order_item_ids;
|
||||
|
||||
@ApiModelProperty(value = "买家用户名")
|
||||
private String buyer_user_name;
|
||||
|
||||
@ApiModelProperty(value = "是否有合同类型")
|
||||
private Boolean contract_type_ids;
|
||||
|
||||
@ApiModelProperty(value = "尝试退款次数")
|
||||
private Integer try_return_count;
|
||||
|
||||
// 收货地址相关信息
|
||||
@ApiModelProperty(value = "收货省份")
|
||||
private String da_province;
|
||||
|
||||
@ApiModelProperty(value = "收货城市")
|
||||
private String da_city;
|
||||
|
||||
@ApiModelProperty(value = "收货区县")
|
||||
private String da_county;
|
||||
|
||||
@ApiModelProperty(value = "收货详细地址")
|
||||
private String da_address;
|
||||
|
||||
@ApiModelProperty(value = "收货人姓名")
|
||||
private String da_name;
|
||||
|
||||
@ApiModelProperty(value = "收货人手机号")
|
||||
private String da_mobile;
|
||||
|
||||
@ApiModelProperty(value = "收货人电话")
|
||||
private String da_telephone;
|
||||
|
||||
@ApiModelProperty(value = "收货省份ID")
|
||||
private Integer da_province_id;
|
||||
|
||||
@ApiModelProperty(value = "收货城市ID")
|
||||
private Integer da_city_id;
|
||||
|
||||
@ApiModelProperty(value = "收货区县ID")
|
||||
private Integer da_county_id;
|
||||
|
||||
@ApiModelProperty(value = "纬度")
|
||||
private String da_latitude;
|
||||
|
||||
@ApiModelProperty(value = "经度")
|
||||
private String da_longitude;
|
||||
|
||||
// 退款商品列表
|
||||
@ApiModelProperty(value = "退货商品详情列表")
|
||||
private List<MchReturnOrderItemDetailDTO> items;
|
||||
}
|
||||
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2025. 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.modules.order.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@ApiModel(value = "退款单商品详情实体对象", description = "退款单商品详情实体类")
|
||||
public class MchReturnOrderItemDetailDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty(value = "退货商品项ID")
|
||||
private Long order_return_item_id;
|
||||
|
||||
@ApiModelProperty(value = "退货单编号")
|
||||
private String return_id;
|
||||
|
||||
@ApiModelProperty(value = "订单商品项ID")
|
||||
private Long order_item_id;
|
||||
|
||||
@ApiModelProperty(value = "订单编号")
|
||||
private String order_id;
|
||||
|
||||
@ApiModelProperty(value = "退货商品数量")
|
||||
private Integer return_item_num;
|
||||
|
||||
@ApiModelProperty(value = "退货商品小计金额")
|
||||
private BigDecimal return_item_subtotal;
|
||||
|
||||
@ApiModelProperty(value = "退货原因ID")
|
||||
private Integer return_reason_id;
|
||||
|
||||
@ApiModelProperty(value = "退货商品备注")
|
||||
private String return_item_note;
|
||||
|
||||
@ApiModelProperty(value = "退货商品图片")
|
||||
private String return_item_image;
|
||||
|
||||
@ApiModelProperty(value = "退货商品状态ID")
|
||||
private Integer return_state_id;
|
||||
|
||||
@ApiModelProperty(value = "退货商品佣金费用")
|
||||
private BigDecimal return_item_commision_fee;
|
||||
|
||||
@ApiModelProperty(value = "退货商品商家备注")
|
||||
private String return_item_store_remark;
|
||||
|
||||
// 关联的订单商品信息
|
||||
@ApiModelProperty(value = "商品名称")
|
||||
private String item_name;
|
||||
|
||||
@ApiModelProperty(value = "产品名称")
|
||||
private String product_name;
|
||||
|
||||
@ApiModelProperty(value = "货品ID")
|
||||
private Long item_id;
|
||||
|
||||
@ApiModelProperty(value = "订单商品图片")
|
||||
private String order_item_image;
|
||||
|
||||
@ApiModelProperty(value = "单位ID")
|
||||
private Integer unit_id;
|
||||
|
||||
@ApiModelProperty(value = "单位名称")
|
||||
private String unit_name;
|
||||
|
||||
@ApiModelProperty(value = "订单商品单价")
|
||||
private BigDecimal order_item_unit_price;
|
||||
|
||||
@ApiModelProperty(value = "订单商品数量")
|
||||
private Integer order_item_quantity;
|
||||
|
||||
@ApiModelProperty(value = "订单商品总金额")
|
||||
private BigDecimal order_item_amount;
|
||||
|
||||
@ApiModelProperty(value = "订单商品总重量")
|
||||
private BigDecimal order_item_weight_total;
|
||||
|
||||
@ApiModelProperty(value = "订单商品备注")
|
||||
private String order_item_note;
|
||||
|
||||
@ApiModelProperty(value = "商品编号")
|
||||
private String item_number;
|
||||
|
||||
@ApiModelProperty(value = "产品编号")
|
||||
private String product_number;
|
||||
}
|
||||
@ -33,8 +33,10 @@ import java.math.RoundingMode;
|
||||
@Slf4j
|
||||
public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
// 常量定义
|
||||
// 商家最低分账比例阈值 20%
|
||||
private static final BigDecimal MCH_RATIO_THRESHOLD = BigDecimal.valueOf(0.2);
|
||||
// 默认平台比例 1%
|
||||
private static final BigDecimal DEFAULT_PLAT_RATIO = BigDecimal.valueOf(0.01);
|
||||
|
||||
// 基础金额属性
|
||||
private Integer totalSeparateAmount; // 分账总金额(分)
|
||||
@ -237,25 +239,21 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
private Pair<Boolean, String> validateInputs() {
|
||||
// 校验totalSeparateAmount必须为有效值且大于0
|
||||
if (totalSeparateAmount == null || totalSeparateAmount <= 0) {
|
||||
log.error("分账计算:总分账金额小于等于0");
|
||||
return Pair.of(false, "分账计算:总分账金额小于等于0");
|
||||
return Pair.of(false, "分账计算:总分账金额必须大于0");
|
||||
}
|
||||
|
||||
// 校验必要参数
|
||||
if (lklRatio == null || lklRatio.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
log.error("分账计算:拉卡拉分账比例小于等于0");
|
||||
return Pair.of(false, "分账计算:拉卡拉分账比例小于等于0");
|
||||
return Pair.of(false, "分账计算:拉卡拉分账比例必须大于0");
|
||||
}
|
||||
|
||||
if (mchRatio == null || mchRatio.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
log.error("分账计算:商户分账比例小于等于0");
|
||||
return Pair.of(false, "分账计算:商户分账比例小于等于0");
|
||||
return Pair.of(false, "分账计算:商户分账比例必须大于0");
|
||||
}
|
||||
|
||||
// 校验shippingFee不能大于等于totalSeparateAmount
|
||||
if (shippingFee != null && shippingFee >= totalSeparateAmount) {
|
||||
log.error("分账计算:分账总金额低于平台内部运费");
|
||||
return Pair.of(false, "分账计算:分账总金额低于平台内部运费");
|
||||
if (shippingFee != null && shippingFee > 0 && shippingFee >= totalSeparateAmount) {
|
||||
return Pair.of(false, "分账计算:配送费用不能大于等于总金额");
|
||||
}
|
||||
|
||||
return Pair.of(true, "");
|
||||
@ -276,9 +274,6 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
// 校验拉卡拉分账金额不能为负数
|
||||
if (lklAmount < 0) {
|
||||
// 记录详细日志
|
||||
String errorMsg = "拉卡拉分账金额计算结果为负数: " + lklAmount;
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, "拉卡拉分账金额计算异常");
|
||||
}
|
||||
|
||||
@ -287,9 +282,6 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
// 校验可分账金额不能为负数
|
||||
if (canSeparateAmount < 0) {
|
||||
// 记录详细日志
|
||||
String errorMsg = "可分账金额计算结果为负数: " + canSeparateAmount;
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, "可分账金额计算异常");
|
||||
}
|
||||
|
||||
@ -316,9 +308,6 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
// 校验实际可分账金额不能为负数
|
||||
if (actualCanSeparateAmountB < 0) {
|
||||
// 记录详细日志
|
||||
String errorMsg = "实际可分账金额计算结果为负数: " + actualCanSeparateAmountB;
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, "实际可分账金额计算异常");
|
||||
}
|
||||
|
||||
@ -333,7 +322,7 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
private Pair<Boolean, String> calculateDefaultRatios() {
|
||||
// 如果平台比例无效,设置默认值0.01
|
||||
if (platRatio == null || platRatio.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
platRatio = new BigDecimal("0.01");
|
||||
platRatio = DEFAULT_PLAT_RATIO;
|
||||
}
|
||||
|
||||
return Pair.of(true, "");
|
||||
@ -356,9 +345,7 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
// 2. 校验实际可分账金额不能小于0
|
||||
if (actualCanSeparateAmount < 0) {
|
||||
String errorMsg = "实际可分账金额不能为负数";
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
return Pair.of(false, "实际可分账金额不能小于0");
|
||||
}
|
||||
|
||||
// 3. 初始化剩余金额为实际可分账金额
|
||||
@ -371,9 +358,7 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
// 校验平台分账金额不能为负数
|
||||
if (platAmount < 0) {
|
||||
String errorMsg = "平台分账金额计算异常";
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
return Pair.of(false, "平台分账金额不能小于0");
|
||||
}
|
||||
|
||||
// 确保不超过剩余金额
|
||||
@ -398,9 +383,7 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
// 校验二级代理商分账金额不能为负数
|
||||
if (agent2ndAmount < 0) {
|
||||
String errorMsg = "二级代理商分账金额计算异常";
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
return Pair.of(false, "二级代理商分账金额不能小于0");
|
||||
}
|
||||
|
||||
// 确保不超过剩余金额
|
||||
@ -418,9 +401,7 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
// 校验一级代理商分账金额不能为负数
|
||||
if (agent1stAmount < 0) {
|
||||
String errorMsg = "一级代理商分账金额计算异常";
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
return Pair.of(false, "一级代理商分账金额不能小于0");
|
||||
}
|
||||
|
||||
// 确保不超过剩余金额
|
||||
@ -435,9 +416,7 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
// 校验商家分账金额不能为负数
|
||||
if (mchAmount < 0) {
|
||||
String errorMsg = "商家分账金额计算异常";
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
return Pair.of(false, "商家分账金额不能小于0");
|
||||
}
|
||||
|
||||
return Pair.of(true, "");
|
||||
@ -450,16 +429,17 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
* @return Pair<Boolean, String> Boolean表示是否成功,String为错误信息
|
||||
*/
|
||||
private Pair<Boolean, String> calculateActualMchRatio() {
|
||||
if (totalSeparateAmount != null && totalSeparateAmount > 0 && mchAmount != null) {
|
||||
if (totalSeparateAmount != null && totalSeparateAmount > 0 && mchAmount != null && mchAmount >= 0) {
|
||||
// 计算实际比例,保留6位小数
|
||||
mchRatio = BigDecimal.valueOf(mchAmount)
|
||||
.divide(BigDecimal.valueOf(totalSeparateAmount), 6, RoundingMode.HALF_UP);
|
||||
|
||||
// 如果计算出的实际比例低于阈值,打印日志并返回错误
|
||||
if (mchRatio.compareTo(MCH_RATIO_THRESHOLD) < 0) {
|
||||
String errorMsg = "警告: 商家实际分账比例低于阈值,当前比例: " + mchRatio + ",阈值: " + MCH_RATIO_THRESHOLD;
|
||||
String errorMsg = String.format("警告: 商家实际分账比例低于阈值,当前比例: %s,阈值: %s",
|
||||
mchRatio.toPlainString(), MCH_RATIO_THRESHOLD.toPlainString());
|
||||
log.warn(errorMsg);
|
||||
return Pair.of(false, "商家分账低于阈值");
|
||||
return Pair.of(false, errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -472,23 +452,28 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
* @return Pair<Boolean, String> Boolean表示是否成功,String为错误信息
|
||||
*/
|
||||
private Pair<Boolean, String> validateSeparateAmountTotal() {
|
||||
long totalAmount = 0;
|
||||
totalAmount += (lklAmount != null ? lklAmount : 0);
|
||||
totalAmount += (platAmount != null ? platAmount : 0);
|
||||
totalAmount += (agent2ndAmount != null ? agent2ndAmount : 0);
|
||||
totalAmount += (agent1stAmount != null ? agent1stAmount : 0);
|
||||
totalAmount += (mchAmount != null ? mchAmount : 0);
|
||||
long totalAmount = getValueOrZero(lklAmount) +
|
||||
getValueOrZero(platAmount) +
|
||||
getValueOrZero(agent2ndAmount) +
|
||||
getValueOrZero(agent1stAmount) +
|
||||
getValueOrZero(mchAmount);
|
||||
|
||||
if (totalAmount > totalSeparateAmount) {
|
||||
// 记录详细日志
|
||||
String errorMsg = "分账金额总和超过总金额,分账金额总和: " + totalAmount + ",总金额: " + totalSeparateAmount;
|
||||
log.error(errorMsg);
|
||||
return Pair.of(false, "分账金额总和超过总金额");
|
||||
if (totalAmount > getValueOrZero(totalSeparateAmount)) {
|
||||
String errorMsg = String.format("分账金额总和(%d)超过总金额(%d)",
|
||||
totalAmount, getValueOrZero(totalSeparateAmount));
|
||||
return Pair.of(false, errorMsg);
|
||||
}
|
||||
|
||||
return Pair.of(true, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全获取Integer值,避免空指针
|
||||
*/
|
||||
private int getValueOrZero(Integer value) {
|
||||
return value != null ? value : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成对象的字符串表示
|
||||
*
|
||||
@ -520,22 +505,42 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
* @return JSON格式字符串
|
||||
*/
|
||||
public String toJSON() {
|
||||
String sb = "{" + "\"totalSeparateAmount\":" + totalSeparateAmount + "," +
|
||||
"\"canSeparateAmount\":" + canSeparateAmount + "," +
|
||||
"\"refCanSeparateAmount\":" + refCanSeparateAmount + "," +
|
||||
"\"shippingFee\":" + shippingFee + "," +
|
||||
"\"lklRatio\":" + (lklRatio != null ? "\"" + lklRatio + "\"" : "null") + "," +
|
||||
"\"mchRatio\":" + (mchRatio != null ? "\"" + mchRatio + "\"" : "null") + "," +
|
||||
"\"platRatio\":" + (platRatio != null ? "\"" + platRatio + "\"" : "null") + "," +
|
||||
"\"agent1stRatio\":" + (agent1stRatio != null ? "\"" + agent1stRatio + "\"" : "null") + "," +
|
||||
"\"agent2ndRatio\":" + (agent2ndRatio != null ? "\"" + agent2ndRatio + "\"" : "null") + "," +
|
||||
"\"lklAmount\":" + lklAmount + "," +
|
||||
"\"mchAmount\":" + mchAmount + "," +
|
||||
"\"platAmount\":" + platAmount + "," +
|
||||
"\"agent1stAmount\":" + agent1stAmount + "," +
|
||||
"\"agent2ndAmount\":" + agent2ndAmount +
|
||||
"}";
|
||||
return sb;
|
||||
StringBuilder sb = new StringBuilder("{");
|
||||
appendJsonField(sb, "totalSeparateAmount", totalSeparateAmount);
|
||||
appendJsonField(sb, "canSeparateAmount", canSeparateAmount);
|
||||
appendJsonField(sb, "refCanSeparateAmount", refCanSeparateAmount);
|
||||
appendJsonField(sb, "shippingFee", shippingFee);
|
||||
appendJsonField(sb, "lklRatio", lklRatio);
|
||||
appendJsonField(sb, "mchRatio", mchRatio);
|
||||
appendJsonField(sb, "platRatio", platRatio);
|
||||
appendJsonField(sb, "agent1stRatio", agent1stRatio);
|
||||
appendJsonField(sb, "agent2ndRatio", agent2ndRatio);
|
||||
appendJsonField(sb, "lklAmount", lklAmount);
|
||||
appendJsonField(sb, "mchAmount", mchAmount);
|
||||
appendJsonField(sb, "platAmount", platAmount);
|
||||
appendJsonField(sb, "agent1stAmount", agent1stAmount);
|
||||
appendJsonField(sb, "agent2ndAmount", agent2ndAmount);
|
||||
// 移除最后的逗号并添加结束括号
|
||||
if (sb.charAt(sb.length() - 1) == ',') {
|
||||
sb.setLength(sb.length() - 1);
|
||||
}
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加JSON字段的辅助方法
|
||||
*/
|
||||
private void appendJsonField(StringBuilder sb, String fieldName, Object fieldValue) {
|
||||
sb.append("\"").append(fieldName).append("\":");
|
||||
if (fieldValue instanceof BigDecimal) {
|
||||
sb.append("\"").append(fieldValue).append("\"");
|
||||
} else if (fieldValue == null) {
|
||||
sb.append("null");
|
||||
} else {
|
||||
sb.append(fieldValue);
|
||||
}
|
||||
sb.append(",");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -544,11 +549,7 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
* @return SeparateResult 包含成功状态、分账结果和错误信息的包装类
|
||||
*/
|
||||
public SeparateResult getSeparateResult() {
|
||||
SeparateResult result = new SeparateResult();
|
||||
result.setIsSuccess(true);
|
||||
result.setData(this);
|
||||
result.setErrMsg(this.errMsg);
|
||||
return result;
|
||||
return new SeparateResult(Boolean.TRUE, this, this.errMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -610,5 +611,4 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
return new SeparateResult(Boolean.TRUE, data, errMsg != null ? errMsg : "");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,8 +6,11 @@ import org.apache.tika.Tika;
|
||||
import org.springframework.util.Base64Utils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.file.Files;
|
||||
@ -437,4 +440,250 @@ public class UploadUtil {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 压缩图片文件以提高质量。
|
||||
* 如果文件大小超过500KB,则在保持宽高比的同时调整大小
|
||||
* 以提高清晰度并减小文件大小。
|
||||
*
|
||||
* @param file 原始图片文件
|
||||
* @param pixelLimit 像素限制
|
||||
* @return 压缩后的图片文件,如果不需要压缩则返回原始文件
|
||||
*/
|
||||
public static MultipartFile compressImageIfNeeded(MultipartFile file, Integer pixelLimit) {
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 检查文件是否为图片格式
|
||||
String contentType = file.getContentType();
|
||||
if (contentType == null || !contentType.startsWith("image/")) {
|
||||
log.debug("文件不是图片格式,跳过压缩: {}", contentType);
|
||||
return file;
|
||||
}
|
||||
|
||||
if (pixelLimit == null) {
|
||||
pixelLimit = 2048;
|
||||
}
|
||||
|
||||
// 小文件直接返回
|
||||
if (file.getSize() <= 512000) { // 500KB
|
||||
log.debug("文件大小在限制范围内 ({} 字节),无需压缩", file.getSize());
|
||||
return file;
|
||||
}
|
||||
|
||||
// 将MultipartFile转换为BufferedImage
|
||||
BufferedImage originalImage = ImageIO.read(file.getInputStream());
|
||||
if (originalImage == null) {
|
||||
log.warn("读取图片文件失败,跳过压缩");
|
||||
return file;
|
||||
}
|
||||
|
||||
int originalWidth = originalImage.getWidth();
|
||||
int originalHeight = originalImage.getHeight();
|
||||
|
||||
// 小图片直接返回
|
||||
if (originalWidth <= pixelLimit && originalHeight <= pixelLimit) {
|
||||
log.debug("图片尺寸在限制范围内 ({}x{}),无需调整大小", originalWidth, originalHeight);
|
||||
return file;
|
||||
}
|
||||
|
||||
// 计算保持宽高比的新尺寸
|
||||
double aspectRatio = (double) originalWidth / originalHeight;
|
||||
int newWidth, newHeight;
|
||||
|
||||
// 目标尺寸:最长边最大为pixelLimit像素
|
||||
if (originalWidth > originalHeight) {
|
||||
newWidth = Math.min(pixelLimit, originalWidth);
|
||||
newHeight = (int) (newWidth / aspectRatio);
|
||||
} else {
|
||||
newHeight = Math.min(pixelLimit, originalHeight);
|
||||
newWidth = (int) (newHeight * aspectRatio);
|
||||
}
|
||||
|
||||
// 确保最小尺寸
|
||||
newWidth = Math.max(newWidth, 1);
|
||||
newHeight = Math.max(newHeight, 1);
|
||||
|
||||
log.debug("调整图片尺寸从 {}x{} 到 {}x{}", originalWidth, originalHeight, newWidth, newHeight);
|
||||
|
||||
// 获取图片格式并执行高质量渐进式缩放
|
||||
String format = getImageFormat(file.getOriginalFilename());
|
||||
BufferedImage resizedImage = progressiveResize(originalImage, newWidth, newHeight, format);
|
||||
|
||||
// 转换回MultipartFile
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ImageIO.write(resizedImage, format, baos);
|
||||
byte[] compressedBytes = baos.toByteArray();
|
||||
|
||||
log.info("图片从 {} 字节压缩到 {} 字节", file.getSize(), compressedBytes.length);
|
||||
|
||||
return new InMemoryMultipartFile(
|
||||
file.getName(),
|
||||
file.getOriginalFilename(),
|
||||
file.getContentType(),
|
||||
compressedBytes
|
||||
);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("压缩图片时出错,使用原始文件: {}", e.getMessage(), e);
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 渐进式调整图片大小以提高质量
|
||||
*
|
||||
* @param originalImage 原始图片
|
||||
* @param targetWidth 目标宽度
|
||||
* @param targetHeight 目标高度
|
||||
* @param format 图片格式
|
||||
* @return 调整大小后的图片,质量更好
|
||||
*/
|
||||
private static BufferedImage progressiveResize(BufferedImage originalImage, int targetWidth, int targetHeight, String format) {
|
||||
int currentWidth = originalImage.getWidth();
|
||||
int currentHeight = originalImage.getHeight();
|
||||
|
||||
// 多步缩小以提高质量
|
||||
BufferedImage resizedImage = originalImage;
|
||||
|
||||
while (currentWidth > targetWidth * 2 || currentHeight > targetHeight * 2) {
|
||||
currentWidth = Math.max(targetWidth, currentWidth / 2);
|
||||
currentHeight = Math.max(targetHeight, currentHeight / 2);
|
||||
|
||||
resizedImage = scaleImage(resizedImage, currentWidth, currentHeight, format);
|
||||
}
|
||||
|
||||
// 最终调整到目标尺寸
|
||||
return scaleImage(resizedImage, targetWidth, targetHeight, format);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用高质量渲染提示缩放图片
|
||||
*
|
||||
* @param originalImage 原始图片
|
||||
* @param targetWidth 目标宽度
|
||||
* @param targetHeight 目标高度
|
||||
* @param format 图片格式
|
||||
* @return 缩放后的图片
|
||||
*/
|
||||
private static BufferedImage scaleImage(BufferedImage originalImage, int targetWidth, int targetHeight, String format) {
|
||||
int imageType = getImageTypeForFormat(format);
|
||||
BufferedImage scaledImage = new BufferedImage(targetWidth, targetHeight, imageType);
|
||||
Graphics2D g2d = scaledImage.createGraphics();
|
||||
|
||||
// 高质量渲染设置
|
||||
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
|
||||
|
||||
g2d.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);
|
||||
g2d.dispose();
|
||||
|
||||
return scaledImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文件扩展名获取图片格式,支持更多格式
|
||||
*
|
||||
* @param filename 原始文件名
|
||||
* @return 图片格式 (jpg, png, gif 等)
|
||||
*/
|
||||
private static String getImageFormat(String filename) {
|
||||
if (StrUtil.isBlank(filename)) {
|
||||
return "jpg";
|
||||
}
|
||||
|
||||
String extension = filename.substring(filename.lastIndexOf('.') + 1).toLowerCase();
|
||||
switch (extension) {
|
||||
case "png":
|
||||
return "png";
|
||||
case "gif":
|
||||
return "gif";
|
||||
case "bmp":
|
||||
return "bmp";
|
||||
case "wbmp":
|
||||
return "wbmp";
|
||||
case "jpeg":
|
||||
case "jpg":
|
||||
return "jpeg";
|
||||
default:
|
||||
return "jpeg";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据格式确定适当的图片类型以保留透明度
|
||||
*
|
||||
* @param format 图片格式
|
||||
* @return BufferedImage类型
|
||||
*/
|
||||
private static int getImageTypeForFormat(String format) {
|
||||
if ("png".equalsIgnoreCase(format) || "gif".equalsIgnoreCase(format)) {
|
||||
return BufferedImage.TYPE_INT_ARGB; // 保留透明度
|
||||
}
|
||||
return BufferedImage.TYPE_INT_RGB; // JPEG等格式的默认值
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple MultipartFile implementation for in-memory data
|
||||
*/
|
||||
private static class InMemoryMultipartFile implements MultipartFile {
|
||||
private final String name;
|
||||
private final String originalFilename;
|
||||
private final String contentType;
|
||||
private final byte[] content;
|
||||
|
||||
public InMemoryMultipartFile(String name, String originalFilename, String contentType, byte[] content) {
|
||||
this.name = name;
|
||||
this.originalFilename = originalFilename;
|
||||
this.contentType = contentType;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return originalFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return content == null || content.length == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return content.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() throws IOException {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferTo(File dest) throws IOException, IllegalStateException {
|
||||
new FileOutputStream(dest).write(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,13 +330,17 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
|
||||
// 该砍价记录过期时间戳
|
||||
Integer cut_hour = activityBase.getCut_hour();
|
||||
// log.info("砍价失效(小时)cut_hour:{}", cut_hour);
|
||||
if (CheckUtil.isEmpty(cut_hour)) {
|
||||
cut_hour = 48;
|
||||
}
|
||||
cutprice_row.setExpired_at(now.getTime() + cut_hour * 60000L);
|
||||
|
||||
cutprice_row.setExpired_at(now.getTime() + cut_hour * 3600000L);
|
||||
// log.info("砍价失效时间戳:{}", cutprice_row.getExpired_at());
|
||||
|
||||
cutprice_row.setAc_datetime(now);
|
||||
cutprice_row.setOrder_id("");
|
||||
cutprice_row.setUpdated_at(now);
|
||||
|
||||
// 保存砍价记录
|
||||
if (!saveOrUpdate(cutprice_row)) {
|
||||
|
||||
@ -65,7 +65,7 @@ public class UpdateActivityStatusJob extends QuartzJobBean {
|
||||
page++;
|
||||
}
|
||||
|
||||
// 更新砍价订单的过期状态
|
||||
// 活动时间到更新砍价订单的过期状态
|
||||
shopActivityCutpriceService.autoUpdateCutPriceStateJob();
|
||||
|
||||
}
|
||||
|
||||
@ -86,7 +86,6 @@ public class LklReceiveNotifyLogServiceImpl extends BaseServiceImpl<LklReceiveNo
|
||||
try {
|
||||
log.debug("[LklReceiveNotifyLog] 开始查询拉卡拉确认收货通知记录,订单号={}", orderId);
|
||||
|
||||
|
||||
QueryWrapper<LklReceiveNotifyLog> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("order_id", orderId);
|
||||
|
||||
|
||||
@ -136,85 +136,124 @@ public class LklTkServiceImpl {
|
||||
* 身份证反面:ID_CARD_BEHIND;
|
||||
* 营业执照:BUSINESS_LICENCE;
|
||||
* 银行卡:BANK_CARD
|
||||
* @return
|
||||
* @return 上传结果及OCR识别信息
|
||||
*/
|
||||
public CommonResult uploadOcrImg(MultipartFile file, String imgType) {
|
||||
UserDto currentUser = getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
currentUser = new UserDto();
|
||||
}
|
||||
|
||||
// 参数校验
|
||||
if (file == null || StrUtil.isBlank(imgType)) {
|
||||
logger.warn("上传文件参数缺失: imgType={}", imgType);
|
||||
return CommonResult.failed("上传文件或图片类型不能为空");
|
||||
}
|
||||
|
||||
CommonResult ossImgInfo = ossService.uploadFile(file, currentUser);
|
||||
if (ossImgInfo == null) {
|
||||
return CommonResult.failed("上传文件失败");
|
||||
}
|
||||
|
||||
if (ossImgInfo.getStatus() != ResultCode.SUCCESS.getStatus() || ossImgInfo.getData() == null) {
|
||||
return CommonResult.failed(ossImgInfo.getMsg());
|
||||
}
|
||||
|
||||
String imgURL = JSONUtil.parseObj(ossImgInfo.getData()).getStr("url");
|
||||
|
||||
String authorization = getLklTkAuthorization();
|
||||
if (StrUtil.isBlank(authorization)) {
|
||||
return CommonResult.failed("获取拉卡拉token失败");
|
||||
}
|
||||
|
||||
JSONObject header = new JSONObject();
|
||||
header.put("Authorization", authorization);
|
||||
|
||||
|
||||
String fileBase64 = UploadUtil.multipartFileToBase64(file);
|
||||
if (StrUtil.isBlank(fileBase64)) {
|
||||
return CommonResult.failed("解析文件转换失败");
|
||||
}
|
||||
// Base64Utils.encodeToString(file.getBytes());
|
||||
|
||||
JSONObject requestBody = new JSONObject();
|
||||
requestBody.put("fileBase64", fileBase64);
|
||||
requestBody.put("imgType", imgType);
|
||||
requestBody.put("sourcechnl", "0"); // 来源: 0:PC,1:安卓,2:IOS
|
||||
requestBody.put("isOcr", "true");
|
||||
|
||||
String urlPath = "/sit/htkregistration/file/base/upload";
|
||||
if (isLklProd) {
|
||||
// 生产环境启用
|
||||
urlPath = "/registration/file/base/upload";
|
||||
}
|
||||
|
||||
try {
|
||||
ResponseEntity<JSONObject> updResponse = RestTemplateHttpUtil.sendPostBodyBackEntity(buildLklTkUrl(urlPath), header, requestBody, JSONObject.class);
|
||||
if (ObjectUtil.isEmpty(updResponse)
|
||||
|| updResponse.getStatusCode() != HttpStatus.OK
|
||||
|| ObjectUtil.isEmpty(updResponse.getBody())) {
|
||||
UserDto currentUser = getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
currentUser = new UserDto();
|
||||
}
|
||||
|
||||
// Compress image if needed before processing
|
||||
MultipartFile processedFile = UploadUtil.compressImageIfNeeded(file, 2048);
|
||||
if (processedFile == null) {
|
||||
logger.warn("上传文件压缩失败: filename={}, imgType={}",
|
||||
file.getOriginalFilename(), imgType);
|
||||
return CommonResult.failed("服务繁忙,请重试!");
|
||||
}
|
||||
|
||||
// 上传文件到OSS
|
||||
CommonResult ossImgInfo = ossService.uploadFile(processedFile, currentUser);
|
||||
if (ossImgInfo == null) {
|
||||
logger.error("上传文件到OSS失败,filename={}, imgType={}",
|
||||
processedFile.getOriginalFilename(), imgType);
|
||||
return CommonResult.failed("上传文件失败");
|
||||
}
|
||||
|
||||
if (ossImgInfo.getStatus() != ResultCode.SUCCESS.getStatus() || ossImgInfo.getData() == null) {
|
||||
logger.error("OSS上传响应异常,filename={}, imgType={}, status={}",
|
||||
processedFile.getOriginalFilename(), imgType, ossImgInfo.getStatus());
|
||||
return CommonResult.failed(ossImgInfo.getMsg());
|
||||
}
|
||||
|
||||
String imgURL = JSONUtil.parseObj(ossImgInfo.getData()).getStr("url");
|
||||
logger.debug("文件上传OSS成功,filename={}", processedFile.getOriginalFilename());
|
||||
|
||||
// 获取拉卡拉认证信息
|
||||
String authorization = getLklTkAuthorization();
|
||||
if (StrUtil.isBlank(authorization)) {
|
||||
logger.error("获取拉卡拉token失败,filename={}, imgType={}",
|
||||
processedFile.getOriginalFilename(), imgType);
|
||||
return CommonResult.failed("获取拉卡拉token失败");
|
||||
}
|
||||
|
||||
// 构造请求头
|
||||
JSONObject header = new JSONObject();
|
||||
header.put("Authorization", authorization);
|
||||
|
||||
// 文件转Base64
|
||||
String fileBase64 = UploadUtil.multipartFileToBase64(processedFile);
|
||||
if (StrUtil.isBlank(fileBase64)) {
|
||||
logger.error("文件转换Base64失败,filename={}, imgType={}",
|
||||
processedFile.getOriginalFilename(), imgType);
|
||||
return CommonResult.failed("解析文件转换失败");
|
||||
}
|
||||
|
||||
// 构造请求体
|
||||
JSONObject requestBody = new JSONObject();
|
||||
requestBody.put("fileBase64", fileBase64);
|
||||
requestBody.put("imgType", imgType);
|
||||
requestBody.put("sourcechnl", "0"); // 来源: 0:PC,1:安卓,2:IOS
|
||||
requestBody.put("isOcr", "true");
|
||||
|
||||
// 构造请求路径
|
||||
String urlPath = "/sit/htkregistration/file/base/upload";
|
||||
if (isLklProd) {
|
||||
urlPath = "/registration/file/base/upload";
|
||||
}
|
||||
|
||||
// 发送请求并获取响应
|
||||
ResponseEntity<JSONObject> updResponse = RestTemplateHttpUtil.sendPostBodyBackEntity(
|
||||
buildLklTkUrl(urlPath), header, requestBody, JSONObject.class);
|
||||
|
||||
logger.info("调用拉卡拉文件上传接口,filename={}, imgType={}",
|
||||
processedFile.getOriginalFilename(), imgType);
|
||||
|
||||
// 检查响应有效性
|
||||
if (ObjectUtil.isEmpty(updResponse) ||
|
||||
updResponse.getStatusCode() != HttpStatus.OK ||
|
||||
ObjectUtil.isEmpty(updResponse.getBody())) {
|
||||
logger.error("拉卡拉文件上传响应数据异常,filename={}, imgType={}",
|
||||
processedFile.getOriginalFilename(), imgType);
|
||||
return CommonResult.failed("上传文件返回值有误");
|
||||
}
|
||||
|
||||
// {batchNo,status,url,showUrl,result{} }
|
||||
// 提取上传结果
|
||||
JSONObject updObj = updResponse.getBody();
|
||||
String batchNo = updObj.getStr("batchNo");
|
||||
if (StrUtil.isBlank(batchNo)) {
|
||||
logger.error("拉卡拉文件上传返回批次号为空,filename={}, imgType={}",
|
||||
processedFile.getOriginalFilename(), imgType);
|
||||
return CommonResult.failed("上传文件返回值有误");
|
||||
}
|
||||
|
||||
updObj.put("cosURL", imgURL);
|
||||
logger.info("拉卡拉文件上传成功,filename={}, imgType={}, batchNo={}",
|
||||
processedFile.getOriginalFilename(), imgType, batchNo);
|
||||
|
||||
return CommonResult.success(updObj);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("上传文件失败: ", e.getMessage());
|
||||
logger.error("上传文件过程发生异常,filename={}, imgType={}",
|
||||
file != null ? file.getOriginalFilename() : "unknown", imgType, e);
|
||||
return CommonResult.failed("上传文件失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据上传的图片的批次号,获取 OCR 识别结果
|
||||
*
|
||||
* @param batchNo
|
||||
* @param imgType * ID_CARD_FRONT 身份证正⾯
|
||||
* @param batchNo 批次号
|
||||
* @param imgType 图片类型
|
||||
* * ID_CARD_FRONT 身份证正⾯
|
||||
* * ID_CARD_BEHIND 身份证反⾯
|
||||
* * BUSINESS_LICENCE 营业执照照⽚
|
||||
* * BANK_CARD 银行卡(企业对公不需要传)
|
||||
@ -227,55 +266,70 @@ public class LklTkServiceImpl {
|
||||
* * SETTLE_ID_CARD_FRONT 结算人身份证人像面
|
||||
* * SETTLE_ID_CARD_BEHIND 结算人身份证国徽面
|
||||
* * LETTER_OF_AUTHORIZATION 法人授权涵
|
||||
* @return
|
||||
* @return OCR识别结果
|
||||
*/
|
||||
public CommonResult imgOcrResult(String batchNo, String imgType) {
|
||||
// 参数校验
|
||||
if (StrUtil.isBlank(batchNo) || StrUtil.isBlank(imgType)) {
|
||||
logger.warn("OCR识别参数缺失: batchNo={}, imgType={}", batchNo, imgType);
|
||||
return CommonResult.failed("批次号或图片类型不能为空");
|
||||
}
|
||||
|
||||
// 调用 OCR 识别接口
|
||||
String authorization = getLklTkAuthorization();
|
||||
if (StrUtil.isBlank(authorization)) {
|
||||
return CommonResult.failed("获取拉卡拉token失败");
|
||||
}
|
||||
|
||||
JSONObject header = new JSONObject();
|
||||
header.put("Authorization", authorization);
|
||||
|
||||
|
||||
JSONObject ocrRequestBody = new JSONObject();
|
||||
ocrRequestBody.put("batchNo", batchNo);
|
||||
ocrRequestBody.put("imgType", imgType);
|
||||
logger.info("ocr请求参数:{}", ocrRequestBody);
|
||||
|
||||
String urlPath = "/sit/htkregistration/ocr/result";
|
||||
if (isLklProd) {
|
||||
// 生产环境启用
|
||||
urlPath = "/registration/ocr/result";
|
||||
}
|
||||
|
||||
try {
|
||||
ResponseEntity<JSONObject> ocrResponse = RestTemplateHttpUtil.sendPostBodyBackEntity(buildLklTkUrl(urlPath), header, ocrRequestBody, JSONObject.class);
|
||||
if (ObjectUtil.isEmpty(ocrResponse)
|
||||
|| ocrResponse.getStatusCode() != HttpStatus.OK
|
||||
|| ObjectUtil.isEmpty(ocrResponse.getBody())) {
|
||||
// 获取认证信息
|
||||
String authorization = getLklTkAuthorization();
|
||||
if (StrUtil.isBlank(authorization)) {
|
||||
logger.error("获取拉卡拉token失败,batchNo={}, imgType={}", batchNo, imgType);
|
||||
return CommonResult.failed("获取拉卡拉token失败");
|
||||
}
|
||||
|
||||
// 构造请求头
|
||||
JSONObject header = new JSONObject();
|
||||
header.put("Authorization", authorization);
|
||||
|
||||
// 构造请求体
|
||||
JSONObject ocrRequestBody = new JSONObject();
|
||||
ocrRequestBody.put("batchNo", batchNo);
|
||||
ocrRequestBody.put("imgType", imgType);
|
||||
logger.info("调用OCR识别接口,batchNo={}, imgType={}", batchNo, imgType);
|
||||
|
||||
// 构造请求路径
|
||||
String urlPath = "/sit/htkregistration/ocr/result";
|
||||
if (isLklProd) {
|
||||
urlPath = "/registration/ocr/result";
|
||||
}
|
||||
|
||||
// 发送请求并获取响应
|
||||
ResponseEntity<JSONObject> ocrResponse = RestTemplateHttpUtil.sendPostBodyBackEntity(
|
||||
buildLklTkUrl(urlPath), header, ocrRequestBody, JSONObject.class);
|
||||
|
||||
// 检查响应有效性
|
||||
if (ObjectUtil.isEmpty(ocrResponse) ||
|
||||
ocrResponse.getStatusCode() != HttpStatus.OK ||
|
||||
ObjectUtil.isEmpty(ocrResponse.getBody())) {
|
||||
logger.error("OCR识别响应数据异常,batchNo={}, imgType={}", batchNo, imgType);
|
||||
return CommonResult.failed("OCR响应数据有误");
|
||||
}
|
||||
|
||||
JSONObject ocrObj = ocrResponse.getBody().get("result", JSONObject.class);
|
||||
logger.info("ocr返回结果:{}", ocrResponse);
|
||||
// 提取OCR结果
|
||||
JSONObject result = ocrResponse.getBody();
|
||||
JSONObject ocrObj = result.get("result", JSONObject.class);
|
||||
logger.info("OCR识别成功,batchNo={}, imgType={}", batchNo, imgType);
|
||||
|
||||
if (ObjectUtil.isEmpty(ocrObj)) {
|
||||
logger.warn("OCR识别返回结果为空,batchNo={}, imgType={}", batchNo, imgType);
|
||||
return CommonResult.failed("OCR返回结果有误");
|
||||
}
|
||||
|
||||
return CommonResult.success(ocrObj);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("OCR识别失败: ", e.getMessage());
|
||||
logger.error("OCR识别过程发生异常,batchNo={}, imgType={}", batchNo, imgType, e);
|
||||
return CommonResult.failed("OCR识别失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* (商户进件前)请求获取token
|
||||
*
|
||||
|
||||
@ -385,8 +385,10 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
|
||||
@Autowired
|
||||
private ThreadPoolExecutor executor;
|
||||
|
||||
@Autowired
|
||||
private DataSourceTransactionManager transactionManager;
|
||||
|
||||
@Autowired
|
||||
private TransactionDefinition transactionDefinition;
|
||||
|
||||
@ -5053,6 +5055,8 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
|
||||
log.info("[确认收货] 符合条件的订单数量: eligibleCount={}, totalChecked={}", receive_id_row.size(), order_rows.size());
|
||||
|
||||
// 收集需要处理跳转路径的订单ID
|
||||
List<String> jumpPathOrderIds = new ArrayList<>();
|
||||
// 处理符合条件的订单
|
||||
for (ShopOrderBase order_row : order_rows) {
|
||||
// 只处理符合条件的订单
|
||||
@ -5076,7 +5080,8 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
}
|
||||
|
||||
/// 服务号确认收货通知跳转链接设置
|
||||
wxOrderShippingService.setMsgJumpPath(order_id);
|
||||
jumpPathOrderIds.add(order_row.getOrder_id());
|
||||
// wxOrderShippingService.setMsgJumpPath(order_id);
|
||||
|
||||
BigDecimal order_points_add = order_data_row.getOrder_points_add();
|
||||
BigDecimal order_double_points_add = order_data_row.getOrder_double_points_add();
|
||||
@ -5126,6 +5131,11 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
}
|
||||
}
|
||||
|
||||
// 异步批量处理延迟跳转路径设置
|
||||
if (!jumpPathOrderIds.isEmpty()) {
|
||||
processOrderJumpPathAsync(jumpPathOrderIds);
|
||||
}
|
||||
|
||||
// 修改订单状态, 随机去一个订单获取店铺编号
|
||||
ShopOrderBase shopOrderBase = order_rows.stream()
|
||||
.filter(order -> receive_id_row.contains(order.getOrder_id()))
|
||||
@ -5176,10 +5186,39 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
log.info("[确认收货] 处理完成: processedOrders={}", receive_id_row.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟 消息跳转路径设置接口
|
||||
*
|
||||
* @param orderIds
|
||||
*/
|
||||
private void processOrderJumpPathAsync(List<String> orderIds) {
|
||||
if (CollectionUtils.isEmpty(orderIds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CompletableFuture.runAsync(() -> {
|
||||
for (String orderId : orderIds) {
|
||||
try {
|
||||
// 控制API调用频率
|
||||
Thread.sleep(300); // 根据实际API限制调整
|
||||
wxOrderShippingService.setMsgJumpPath(orderId);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
log.warn("[异步处理] 线程中断,订单ID: {}", orderId);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
log.warn("[异步处理] 消息跳转路径设置失败,订单ID: {}, 错误: {}", orderId, e.getMessage());
|
||||
// 继续处理下一个订单
|
||||
}
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 订单确认收货(定时任务用途)
|
||||
@ -7834,8 +7873,8 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
data_row.setOrder_redpacket_price(BigDecimal.ZERO); // 红包抵扣订单金额
|
||||
data_row.setOrder_resource_ext1(order_resource_ext1_use_current);
|
||||
data_row.setOrder_resource_ext2(order_resource_ext2_use);
|
||||
data_row.setOrder_refund_status(0); // 退款状态:0-是无退款;1-是部分退款;2-是全部退款
|
||||
data_row.setOrder_return_status(0); // 退货状态(ENUM):0-是无退货;1-是部分退货;2-是全部退货
|
||||
data_row.setOrder_refund_status(StateCode.ORDER_REFUND_STATUS_NO); // 退款状态:0-是无退款;1-是部分退款;2-是全部退款
|
||||
data_row.setOrder_return_status(StateCode.ORDER_REFUND_STATUS_NO); // 退货状态(ENUM):0-是无退货;1-是部分退货;2-是全部退货
|
||||
data_row.setOrder_return_num(0); // 退货数量
|
||||
|
||||
BigDecimal order_item_commission_fee = item_rows.stream().map(s -> s.getOrder_item_commission_fee()).reduce(BigDecimal::add).get();
|
||||
|
||||
@ -1063,6 +1063,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
if (shopOrderData == null) {
|
||||
throw new ApiException(I18nUtil._("订单详细信息为空!"));
|
||||
}
|
||||
|
||||
for (ShopOrderReturnItem orderReturnItem : orderReturnItems) {
|
||||
ShopOrderItem order_item_row = order_item_rows.stream().filter(s -> s.getOrder_item_id().equals(orderReturnItem.getOrder_item_id())).findFirst().orElse(null);
|
||||
|
||||
@ -1150,45 +1151,91 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取退款详情数据
|
||||
*
|
||||
* @param return_id 退货单ID
|
||||
* @return 退货单详情信息
|
||||
*/
|
||||
@Override
|
||||
public Map getReturnDetail(String return_id) {
|
||||
// 1. 获取退货单基础信息
|
||||
ShopOrderReturn shopOrderReturn = get(return_id);
|
||||
if (shopOrderReturn == null) {
|
||||
logger.warn("退货单不存在: return_id={}", return_id);
|
||||
return new HashMap<>();
|
||||
}
|
||||
Map return_row = Convert.toMap(String.class, Object.class, shopOrderReturn);
|
||||
|
||||
// 2. 获取退货单商品明细
|
||||
QueryWrapper<ShopOrderReturnItem> itemQueryWrapper = new QueryWrapper<>();
|
||||
itemQueryWrapper.eq("return_id", return_id);
|
||||
List<ShopOrderReturnItem> shopOrderReturnItems = orderReturnItemService.find(itemQueryWrapper);
|
||||
List<Map> return_item_rows = Convert.toList(Map.class, shopOrderReturnItems);
|
||||
List<Long> order_item_ids = shopOrderReturnItems.stream().map(s -> s.getOrder_item_id()).distinct().collect(Collectors.toList());
|
||||
List<Long> order_item_ids = shopOrderReturnItems.stream()
|
||||
.map(ShopOrderReturnItem::getOrder_item_id)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 3. 获取原订单详情
|
||||
String order_id = shopOrderReturn.getOrder_id();
|
||||
Map order_row = shopOrderBaseService.getOrderDetail(order_id, null);
|
||||
if (order_row == null) {
|
||||
logger.warn("原订单详情不存在: order_id={}", order_id);
|
||||
return return_row;
|
||||
}
|
||||
|
||||
// 4. 获取退货原因列表
|
||||
List<ShopOrderReturnReason> return_reason_rows = orderReturnReasonService.find(new QueryWrapper<>());
|
||||
|
||||
// 5. 获取订单收货地址信息
|
||||
ShopOrderDeliveryAddress deliveryAddress = orderDeliveryAddressService.get(order_id);
|
||||
Map order_delivery = Convert.toMap(String.class, Object.class, deliveryAddress);
|
||||
return_row.putAll(order_delivery);
|
||||
if (deliveryAddress != null) {
|
||||
Map order_delivery = Convert.toMap(String.class, Object.class, deliveryAddress);
|
||||
return_row.putAll(order_delivery);
|
||||
}
|
||||
|
||||
// 6. 获取订单商品相关信息
|
||||
List<Map> order_row_items = (List<Map>) order_row.get("items");
|
||||
if (CollUtil.isEmpty(order_row_items)) {
|
||||
logger.warn("订单商品列表为空: order_id={}", order_id);
|
||||
return_row.put("items", new ArrayList<>());
|
||||
return return_row;
|
||||
}
|
||||
|
||||
List<Long> item_ids = order_row_items.stream().map(s -> Convert.toLong(s.get("item_id"))).distinct().collect(Collectors.toList());
|
||||
List<Map> product_items = shopProductItemService.gets(item_ids);
|
||||
List<Long> item_ids = order_row_items.stream()
|
||||
.map(s -> Convert.toLong(s.get("item_id")))
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<Integer> product_ids = order_row_items.stream().map(s -> Convert.toInt(s.get("product_id"))).distinct().collect(Collectors.toList());
|
||||
List<ShopProductInfo> product_infos = shopProductInfoService.gets(product_ids);
|
||||
List<Map> product_items = CollUtil.isEmpty(item_ids) ? new ArrayList<>() :
|
||||
shopProductItemService.gets(item_ids);
|
||||
|
||||
List<ShopProductIndex> product_indexs = shopProductIndexService.gets(product_ids);
|
||||
List<Integer> product_ids = order_row_items.stream()
|
||||
.map(s -> Convert.toInt(s.get("product_id")))
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 退货商品数据
|
||||
Map return_item_temp_rows = new HashMap();
|
||||
List<ShopProductInfo> product_infos = CollUtil.isEmpty(product_ids) ? new ArrayList<>() :
|
||||
shopProductInfoService.gets(product_ids);
|
||||
|
||||
List<ShopProductIndex> product_indexs = CollUtil.isEmpty(product_ids) ? new ArrayList<>() :
|
||||
shopProductIndexService.gets(product_ids);
|
||||
|
||||
// 7. 构建退货商品临时数据映射
|
||||
Map<Long, Map> return_item_temp_rows = new HashMap<>();
|
||||
for (Map item : order_row_items) {
|
||||
Long order_item_id = Convert.toLong(item.get("order_item_id"));
|
||||
|
||||
// 只处理当前退货单相关的订单商品
|
||||
if (order_item_ids.contains(order_item_id)) {
|
||||
Map order_item = new HashMap();
|
||||
Long item_id = Convert.toLong(item.get("item_id"));
|
||||
Integer product_id = Convert.toInt(item.get("product_id"));
|
||||
|
||||
// 复制订单商品基本信息
|
||||
order_item.put("item_name", item.get("item_name"));
|
||||
order_item.put("product_name", item.get("product_name"));
|
||||
order_item.put("item_id", item_id);
|
||||
@ -1201,55 +1248,113 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
order_item.put("order_item_amount", item.get("order_item_amount"));
|
||||
order_item.put("order_item_note", item.get("order_item_note"));
|
||||
|
||||
Optional<Map> productItemOpl = product_items.stream().filter(s -> ObjectUtil.equal(item_id, Convert.toInt(s.get("item_id")))).findFirst();
|
||||
Map productItem = productItemOpl.orElseGet(HashMap::new);
|
||||
order_item.put("item_number", productItem.get("item_number"));
|
||||
// 关联SKU信息
|
||||
if (CollUtil.isNotEmpty(product_items)) {
|
||||
Optional<Map> productItemOpl = product_items.stream()
|
||||
.filter(s -> ObjectUtil.equal(item_id, Convert.toLong(s.get("item_id"))))
|
||||
.findFirst();
|
||||
Map productItem = productItemOpl.orElse(new HashMap<>());
|
||||
order_item.put("item_number", productItem.get("item_number"));
|
||||
}
|
||||
|
||||
Optional<ShopProductInfo> productInfoOpl = product_infos.stream().filter(s -> ObjectUtil.equal(product_id, s.getProduct_id())).findFirst();
|
||||
ShopProductInfo productInfo = productInfoOpl.orElseGet(ShopProductInfo::new);
|
||||
order_item.put("product_number", productInfo.getProduct_number());
|
||||
// 关联商品信息
|
||||
if (CollUtil.isNotEmpty(product_infos)) {
|
||||
Optional<ShopProductInfo> productInfoOpl = product_infos.stream()
|
||||
.filter(s -> ObjectUtil.equal(product_id, s.getProduct_id()))
|
||||
.findFirst();
|
||||
ShopProductInfo productInfo = productInfoOpl.orElse(new ShopProductInfo());
|
||||
order_item.put("product_number", productInfo.getProduct_number());
|
||||
}
|
||||
|
||||
return_item_temp_rows.put(order_item_id, order_item);
|
||||
}
|
||||
}
|
||||
|
||||
// 8. 合并退货商品详细信息
|
||||
for (Map return_item_row : return_item_rows) {
|
||||
Long order_item_id = Convert.toLong(return_item_row.get("order_item_id"));
|
||||
Map return_item_temp_row = (Map) return_item_temp_rows.get(order_item_id);
|
||||
return_item_row.putAll(ObjectUtil.defaultIfNull(return_item_temp_row, new HashMap()));
|
||||
Map return_item_temp_row = return_item_temp_rows.get(order_item_id);
|
||||
|
||||
// 合并订单商品信息到退货商品中
|
||||
if (return_item_temp_row != null) {
|
||||
return_item_row.putAll(return_item_temp_row);
|
||||
}
|
||||
|
||||
// 处理退货图片信息
|
||||
String return_item_image = (String) return_item_row.get("return_item_image");
|
||||
if (StrUtil.isNotBlank(return_item_image)) {
|
||||
return_item_row.put("return_item_image", Convert.toList(String.class, return_item_image));
|
||||
// 如果是逗号分隔的图片字符串,转换为列表
|
||||
if (return_item_image.contains(",")) {
|
||||
return_item_row.put("return_item_image",
|
||||
Arrays.asList(return_item_image.split(",")));
|
||||
} else {
|
||||
return_item_row.put("return_item_image",
|
||||
Collections.singletonList(return_item_image));
|
||||
}
|
||||
} else {
|
||||
return_item_row.put("return_item_image", new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
// 9. 处理合同类型信息
|
||||
if (CollUtil.isNotEmpty(product_indexs)) {
|
||||
return_row.put("contract_type_ids", StrUtil.isNotEmpty(product_indexs.get(0).getContract_type_ids()));
|
||||
ShopProductIndex firstIndex = product_indexs.get(0);
|
||||
if (firstIndex != null && StrUtil.isNotEmpty(firstIndex.getContract_type_ids())) {
|
||||
return_row.put("contract_type_ids", true);
|
||||
} else {
|
||||
return_row.put("contract_type_ids", false);
|
||||
}
|
||||
} else {
|
||||
return_row.put("contract_type_ids", false);
|
||||
}
|
||||
|
||||
// 10. 添加买家信息
|
||||
return_row.put("buyer_user_name", order_row.get("buyer_user_name"));
|
||||
|
||||
BigDecimal return_item_subtotal = shopOrderReturnItems.stream().map(s -> s.getReturn_item_subtotal()).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
// 11. 计算退货总金额
|
||||
BigDecimal return_item_subtotal = shopOrderReturnItems.stream()
|
||||
.map(ShopOrderReturnItem::getReturn_item_subtotal)
|
||||
.filter(Objects::nonNull)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
return_row.put("submit_return_refund_amount", return_item_subtotal);
|
||||
return_row.put("order_item_ids", order_item_ids);
|
||||
|
||||
// 12. 处理退货原因名称
|
||||
Integer return_reason_id = Convert.toInt(return_row.get("return_reason_id"));
|
||||
Optional<ShopOrderReturnReason> reasonOpl = return_reason_rows.stream().filter(s -> ObjectUtil.equal(return_reason_id, s.getReturn_reason_id())).findFirst();
|
||||
ShopOrderReturnReason returnReason = reasonOpl.orElseGet(ShopOrderReturnReason::new);
|
||||
return_row.put("return_reason_name", returnReason.getReturn_reason_name());
|
||||
if (return_reason_id != null && CollUtil.isNotEmpty(return_reason_rows)) {
|
||||
Optional<ShopOrderReturnReason> reasonOpl = return_reason_rows.stream()
|
||||
.filter(s -> ObjectUtil.equal(return_reason_id, s.getReturn_reason_id()))
|
||||
.findFirst();
|
||||
ShopOrderReturnReason returnReason = reasonOpl.orElse(new ShopOrderReturnReason());
|
||||
return_row.put("return_reason_name", returnReason.getReturn_reason_name());
|
||||
} else {
|
||||
return_row.put("return_reason_name", "");
|
||||
}
|
||||
|
||||
// 13. 设置退货商品列表和状态名称
|
||||
return_row.put("items", return_item_rows);
|
||||
return_row.put("return_state_name", stateCodeService.getText(Convert.toInt(return_row.get("return_state_id")), "1"));
|
||||
|
||||
Integer return_state_id = Convert.toInt(return_row.get("return_state_id"));
|
||||
if (return_state_id != null) {
|
||||
return_row.put("return_state_name",
|
||||
stateCodeService.getText(return_state_id, "1"));
|
||||
} else {
|
||||
return_row.put("return_state_name", "");
|
||||
}
|
||||
|
||||
// 14. 处理平台退货状态名称
|
||||
Integer plantform_return_state_id = Convert.toInt(return_row.get("plantform_return_state_id"));
|
||||
return_row.put("plantform_return_state_name", getPlantformReturnStateName(plantform_return_state_id));
|
||||
|
||||
if (plantform_return_state_id != null) {
|
||||
return_row.put("plantform_return_state_name",
|
||||
getPlantformReturnStateName(plantform_return_state_id));
|
||||
} else {
|
||||
return_row.put("plantform_return_state_name", "");
|
||||
}
|
||||
|
||||
return return_row;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退货单审核(商家同意退款退库)
|
||||
* 处理逻辑:
|
||||
@ -1503,7 +1608,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
if (productItem == null) {
|
||||
logger.error("该订单商品表-SKU表信息不存在!商品项ID: {}", itemId);//说明这个itemid已经不存在了,不对库存操作
|
||||
continue;
|
||||
// throw new ApiException(I18nUtil._("该订单商品表-SKU表信息不存在!"));
|
||||
// throw new ApiException(I18nUtil._("该订单商品表-SKU表信息不存在!"));
|
||||
}
|
||||
|
||||
// 增加库存
|
||||
@ -1526,8 +1631,8 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
// RMK 第三方数据同步相关:redis 新增返还思迅库存
|
||||
Map<String, Integer> stockDeltaMap = new HashMap<>();
|
||||
String item_src_id = productItem.getItem_src_id();
|
||||
stockDeltaMap.put(item_src_id + "-" + shopOrderItem.getOrder_id()+"-"+shopOrderItem.getItem_unit_price(), returnNum);
|
||||
syncThirdDataService.incrProductStockToRedis(stockDeltaMap,returnItem.getReturn_item_subtotal());
|
||||
stockDeltaMap.put(item_src_id + "-" + shopOrderItem.getOrder_id() + "-" + shopOrderItem.getItem_unit_price(), returnNum);
|
||||
syncThirdDataService.incrProductStockToRedis(stockDeltaMap, returnItem.getReturn_item_subtotal());
|
||||
logger.info("退货返回给思迅,存入redis成功,item_src_id:{},订单号:{},数量:{}", item_src_id, shopOrderReturn.getOrder_id(), returnNum);
|
||||
} else {
|
||||
logger.warn("退货数量为空,无法增加库存,订单项ID: {}", orderItemId);
|
||||
@ -1594,7 +1699,8 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
|
||||
ShopOrderData shopOrderData = new ShopOrderData();
|
||||
shopOrderData.setOrder_id(order_id);
|
||||
shopOrderData.setOrder_refund_status(2); //退款状态:0-是无退款;1-是部分退款;2-是全部退款
|
||||
shopOrderData.setOrder_refund_status(StateCode.ORDER_REFUND_STATUS_ALL); //退款状态:0-是无退款;1-是部分退款;2-是全部退款
|
||||
shopOrderData.setOrder_return_status(StateCode.ORDER_REFUND_STATUS_ALL);
|
||||
if (!shopOrderDataService.edit(shopOrderData)) {
|
||||
logger.error("修改订单退款状态失败!订单ID: {}", order_id);
|
||||
throw new ApiException(ResultCode.FAILED);
|
||||
@ -1671,7 +1777,9 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
logger.debug("订单部分商品退款,订单ID: {}", order_id);
|
||||
ShopOrderData orderData = new ShopOrderData();
|
||||
orderData.setOrder_id(order_id);
|
||||
orderData.setOrder_refund_status(CommonConstant.Enable);
|
||||
// 退款状态:0-是无退款;1-是部分退款;2-是全部退款
|
||||
orderData.setOrder_refund_status(StateCode.ORDER_REFUND_STATUS_PART);
|
||||
orderData.setOrder_return_status(StateCode.ORDER_REFUND_STATUS_PART);
|
||||
if (!shopOrderDataService.edit(orderData)) {
|
||||
logger.error("部分退款失败!订单ID: {}", order_id);
|
||||
throw new ApiException(I18nUtil._("部分退款失败!"));
|
||||
|
||||
@ -27,6 +27,7 @@ import com.suisung.mall.common.pojo.dto.OssPolicyResultDTO;
|
||||
import com.suisung.mall.common.utils.CheckUtil;
|
||||
import com.suisung.mall.common.utils.I18nUtil;
|
||||
import com.suisung.mall.common.utils.LogUtil;
|
||||
import com.suisung.mall.common.utils.UploadUtil;
|
||||
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
||||
import com.suisung.mall.shop.page.service.OssService;
|
||||
import com.suisung.mall.shop.page.utis.VideoUtil;
|
||||
@ -144,7 +145,7 @@ public class OssServiceImpl implements OssService {
|
||||
throw new ApiException(String.format(I18nUtil._("允许上传格式为:【%s】"), StringUtils.join(allowExtList, ",")));
|
||||
}
|
||||
|
||||
Map result = upload(file, user, dir, uploadPath, uploadName, fileName);
|
||||
Map result = upload(file, user, dir, uploadPath, uploadName);
|
||||
String url = (String) result.get("media_url");
|
||||
String thumb = (String) result.get("thumb");
|
||||
|
||||
@ -173,7 +174,10 @@ public class OssServiceImpl implements OssService {
|
||||
* @param user 用户信息
|
||||
* @return
|
||||
*/
|
||||
public Map upload(MultipartFile file, UserDto user, String dir, String uploadPath, String uploadName, String fileName) {
|
||||
public Map upload(MultipartFile file, UserDto user, String dir, String uploadPath, String uploadName) {
|
||||
// 如果是图片,先压缩图片,再上传到 cos 对象存储
|
||||
file = UploadUtil.compressImageIfNeeded(file, 2048);
|
||||
|
||||
// 创建临时文件
|
||||
creTempFile(file, dir, uploadName);
|
||||
// String localUrl = IP + "/admin/shop/static/image/" + dir + uploadName; // 文件本地路径
|
||||
@ -294,7 +298,7 @@ public class OssServiceImpl implements OssService {
|
||||
throw new ApiException(String.format(I18nUtil._("允许上传格式为:【%s】"), StringUtils.join(allowExtList, ",")));
|
||||
}
|
||||
|
||||
return upload(file, user, dir, uploadPath, uploadName, fileName);
|
||||
return upload(file, user, dir, uploadPath, uploadName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -2078,11 +2078,11 @@ public class ShopProductBaseServiceImpl extends BaseServiceImpl<ShopProductBaseM
|
||||
|
||||
Integer product_sale_num = Convert.toInt(product_index_row.get("product_sale_num"));
|
||||
|
||||
if (product_base_row != null) {
|
||||
// 获取店铺营业状态:1-开业营业中(且在营业时间内);12-开业打烊中(但在营业时间外) ;2-停业中;3-开业(或活动)筹备中;
|
||||
Pair<Integer, String> store_biz_state = shopStoreBaseService.getStoreBizState(Convert.toInt(product_base_row.get("store_id")));
|
||||
product_base_row.put("store_biz_state", store_biz_state.getFirst());
|
||||
}
|
||||
// if (product_base_row != null) {
|
||||
// // 获取店铺营业状态:1-开业营业中(且在营业时间内);12-开业打烊中(但在营业时间外) ;2-停业中;3-开业(或活动)筹备中;
|
||||
// Pair<Integer, String> store_biz_state = shopStoreBaseService.getStoreBizState(Convert.toInt(product_base_row.get("store_id")));
|
||||
// product_base_row.put("store_biz_state", store_biz_state.getFirst());
|
||||
// }
|
||||
|
||||
//虚拟销量
|
||||
// todo 是否为商家后台访问
|
||||
|
||||
@ -338,7 +338,12 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
if (mobileAndLicenseNumber != null) {
|
||||
Map<String, Object> tmplArgs = new HashMap<>(1);
|
||||
tmplArgs.put("name", record.getStore_name()); // 商家店铺名
|
||||
shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_486545331", tmplArgs);
|
||||
|
||||
// 【桂平发发网络】通知管理员有商家申请入驻
|
||||
if (!shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_498535058", tmplArgs)) {
|
||||
shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_486545331", tmplArgs); // 【小发同城】通知管理员有商家申请入驻
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
log.info("商家入驻申请提交成功,recordId: {},手机号: {}", record.getId(), loginMobile);
|
||||
@ -465,8 +470,12 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
String mchName = StrUtil.isBlank(record.getStore_name()) ? "重新修正资料" : record.getStore_name();
|
||||
Map<String, Object> tmplArgs = new HashMap<>(1);
|
||||
tmplArgs.put("name", mchName); // 商家公司名称
|
||||
// 尊敬的管理员,商家 ${name},提交了入驻我们平台的申请,请及时对相关资质材料予以审核,以便推进后续流程。
|
||||
shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_486545331", tmplArgs);
|
||||
|
||||
// 【桂平发发网络】通知管理员有商家申请入驻
|
||||
if (!shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_498535058", tmplArgs)) {
|
||||
// 尊敬的管理员,商家 ${name},提交了入驻我们平台的申请,请及时对相关资质材料予以审核,以便推进后续流程。
|
||||
shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_486545331", tmplArgs); // 【小发同城】通知管理员有商家申请入驻
|
||||
}
|
||||
}
|
||||
|
||||
return CommonResult.success();
|
||||
|
||||
@ -184,7 +184,7 @@ feieyun:
|
||||
sf-express:
|
||||
# 顺丰同城 api 接口配置
|
||||
dev_id: 1715091463
|
||||
# 桂平顺丰平台商家id 2273453450129 2269768012593
|
||||
# 桂平顺丰平台商家id 2273453450129 2269768012593 2281834525297
|
||||
supplier_id: 2281834525297
|
||||
appid: 1715091463
|
||||
appkey: 47466ae69c530f831395e1bc405639fb
|
||||
|
||||
@ -592,6 +592,7 @@
|
||||
<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"/>
|
||||
@ -656,10 +657,320 @@
|
||||
<result property="order_item_return_num" column="order_item_return_num"/>
|
||||
<result property="order_item_return_agree_amount" column="order_item_return_agree_amount"/>
|
||||
</collection>
|
||||
|
||||
<!-- 退款订单集合映射 -->
|
||||
<collection property="return_order_detail" ofType="com.suisung.mall.common.modules.order.dto.MchReturnOrderDetailDTO">
|
||||
<id property="return_id" column="return_id"/>
|
||||
<result property="order_id" column="return_order_id"/>
|
||||
<result property="buyer_user_id" column="return_buyer_user_id"/>
|
||||
<result property="buyer_store_id" column="return_buyer_store_id"/>
|
||||
<result property="return_reason_id" column="return_reason_id"/>
|
||||
<result property="return_reason_name" column="return_reason_name"/>
|
||||
<result property="return_buyer_message" column="return_buyer_message"/>
|
||||
<result property="store_id" column="return_store_id"/>
|
||||
<result property="return_refund_amount" column="return_refund_amount"/>
|
||||
<result property="return_commision_fee" column="return_commision_fee"/>
|
||||
<result property="return_state_id" column="return_state_id"/>
|
||||
<result property="return_state_name" column="return_state_name"/>
|
||||
<result property="return_tel" column="return_tel"/>
|
||||
<result property="return_year" column="return_year"/>
|
||||
<result property="return_month" column="return_month"/>
|
||||
<result property="return_day" column="return_day"/>
|
||||
<result property="return_addr" column="return_addr"/>
|
||||
<result property="return_mobile" column="return_mobile"/>
|
||||
<result property="return_telephone" column="return_telephone"/>
|
||||
<result property="return_contact_name" column="return_contact_name"/>
|
||||
<result property="subsite_id" column="return_subsite_id"/>
|
||||
<result property="return_add_time" column="return_add_time"/>
|
||||
<result property="return_finish_time" column="return_finish_time"/>
|
||||
<result property="return_is_paid" column="return_is_paid"/>
|
||||
<result property="return_channel_code" column="return_channel_code"/>
|
||||
<result property="return_channel_trans_id" column="return_channel_trans_id"/>
|
||||
<result property="return_channel_time" column="return_channel_time"/>
|
||||
<result property="return_channel_flag" column="return_channel_flag"/>
|
||||
<result property="deposit_trade_no" column="return_deposit_trade_no"/>
|
||||
<result property="payment_channel_id" column="return_payment_channel_id"/>
|
||||
<result property="return_store_message" column="return_store_message"/>
|
||||
<result property="plantform_return_state_id" column="plantform_return_state_id"/>
|
||||
<result property="plantform_return_state_name" column="plantform_return_state_name"/>
|
||||
<result property="return_flag" column="return_flag"/>
|
||||
<result property="return_type" column="return_type"/>
|
||||
<result property="submit_return_refund_amount" column="submit_return_refund_amount"/>
|
||||
<result property="buyer_user_name" column="return_buyer_user_name"/>
|
||||
<result property="contract_type_ids" column="contract_type_ids"/>
|
||||
<result property="try_return_count" column="try_return_count"/>
|
||||
|
||||
<!-- 收货地址相关信息 -->
|
||||
<result property="da_province" column="return_da_province"/>
|
||||
<result property="da_city" column="return_da_city"/>
|
||||
<result property="da_county" column="return_da_county"/>
|
||||
<result property="da_address" column="return_da_address"/>
|
||||
<result property="da_name" column="return_da_name"/>
|
||||
<result property="da_mobile" column="return_da_mobile"/>
|
||||
<result property="da_telephone" column="return_da_telephone"/>
|
||||
<result property="da_province_id" column="return_da_province_id"/>
|
||||
<result property="da_city_id" column="return_da_city_id"/>
|
||||
<result property="da_county_id" column="return_da_county_id"/>
|
||||
<result property="da_latitude" column="return_da_latitude"/>
|
||||
<result property="da_longitude" column="return_da_longitude"/>
|
||||
|
||||
<!-- 退款商品列表映射 -->
|
||||
<collection property="items" ofType="com.suisung.mall.common.modules.order.dto.MchReturnOrderItemDetailDTO">
|
||||
<id property="order_return_item_id" column="order_return_item_id"/>
|
||||
<result property="return_id" column="item_return_id"/>
|
||||
<result property="order_item_id" column="return_order_item_id"/>
|
||||
<result property="order_id" column="item_order_id"/>
|
||||
<result property="return_item_num" column="return_item_num"/>
|
||||
<result property="return_item_subtotal" column="return_item_subtotal"/>
|
||||
<result property="return_reason_id" column="item_return_reason_id"/>
|
||||
<result property="return_item_note" column="return_item_note"/>
|
||||
<result property="return_item_image" column="return_item_image"/>
|
||||
<result property="return_state_id" column="item_return_state_id"/>
|
||||
<result property="return_item_commision_fee" column="return_item_commision_fee"/>
|
||||
<result property="return_item_store_remark" column="return_item_store_remark"/>
|
||||
|
||||
<!-- 关联的订单商品信息 -->
|
||||
<result property="item_name" column="return_item_name"/>
|
||||
<result property="product_name" column="return_product_name"/>
|
||||
<result property="item_id" column="return_item_id"/>
|
||||
<result property="order_item_image" column="return_order_item_image"/>
|
||||
<result property="unit_id" column="return_unit_id"/>
|
||||
<result property="unit_name" column="return_unit_name"/>
|
||||
<result property="order_item_unit_price" column="return_order_item_unit_price"/>
|
||||
<result property="order_item_quantity" column="return_order_item_quantity"/>
|
||||
<result property="order_item_amount" column="return_order_item_amount"/>
|
||||
<result property="order_item_weight_total" column="return_order_item_weight_total"/>
|
||||
<result property="order_item_note" column="return_order_item_note"/>
|
||||
<result property="item_number" column="return_item_number"/>
|
||||
<result property="product_number" column="return_product_number"/>
|
||||
</collection>
|
||||
</collection>
|
||||
|
||||
</resultMap>
|
||||
|
||||
|
||||
<!--refundstatus 退款状态:0-是无退款;1-是部分退款;2-是全部退款
|
||||
<select id="selectMchOrderPageList" resultMap="MchOrderResult">
|
||||
<include refid="mchOrderColumns"/>
|
||||
<include refid="mchOrderFromAndJoins"/>
|
||||
<include refid="mchOrderWhereCondition"/>
|
||||
ORDER BY ob.order_time DESC
|
||||
</select>
|
||||
|
||||
<select id="countMchOrderByCondition" resultType="java.lang.Long">
|
||||
SELECT COUNT(DISTINCT ob.order_id)
|
||||
|
||||
<include refid="mchOrderFromAndJoins"/>
|
||||
|
||||
<include refid="mchOrderWhereCondition"/>
|
||||
</select>
|
||||
|
||||
<select id="getMchOrderDetail" resultMap="MchOrderResult">
|
||||
<include refid="mchOrderColumns"/>
|
||||
<include refid="mchOrderFromAndJoins"/>
|
||||
<where>
|
||||
ob.order_id=#{orderId}
|
||||
</where>
|
||||
|
||||
ORDER BY ob.order_id DESC
|
||||
</select>
|
||||
|
||||
<!--应付金额/应支付金额:order_goods_amount - order_discount_amount + order_shipping_fee - order_voucher_price - order_points_fee - order_adjust_fee-->
|
||||
<sql id="mchOrderColumns">
|
||||
SELECT
|
||||
ob.order_id,
|
||||
ob.order_time,
|
||||
|
||||
<!--送达时间戳-->
|
||||
CASE
|
||||
WHEN oi.delivery_type_id IS NOT NULL AND oi.delivery_type_id = 16 AND #{expireSeconds} IS NOT NULL AND
|
||||
#{expireSeconds} > 0
|
||||
THEN oi.order_time + #{expireSeconds}*1000
|
||||
ELSE oi.order_time + 864000000 <!-- 10天 = 10*24*60*60*1000 = 864000000毫秒 -->
|
||||
END as arrival_time,
|
||||
|
||||
ob.order_product_amount,
|
||||
ob.order_payment_amount,
|
||||
ob.currency_id,
|
||||
ob.order_state_id,
|
||||
ob.operate_flag,
|
||||
ST_Distance_Sphere(
|
||||
POINT(sb.store_longitude, sb.store_latitude),
|
||||
POINT(oda.da_longitude, oda.da_latitude)
|
||||
) as distance,
|
||||
oi.order_title,
|
||||
oi.order_pickup_num,
|
||||
oi.delivery_type_id,
|
||||
oi.buyer_user_id,
|
||||
oi.order_picked_time,
|
||||
oi.order_is_received,
|
||||
oi.kind_id,
|
||||
IF((SELECT count(*) FROM shop_order_base WHERE buyer_user_id = oi.buyer_user_id AND order_state_id IN
|
||||
(2011,2012,
|
||||
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,
|
||||
<!--总计优惠金额 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-lkl_fee+od.packing_fee)
|
||||
as order_income_amount,
|
||||
(od.platform_fee+lkl_fee) as platform_fee,
|
||||
od.packing_fee,
|
||||
od.order_message,
|
||||
sb.store_id,
|
||||
sb.store_name,
|
||||
sb.store_logo,
|
||||
sb.store_latitude,
|
||||
sb.store_longitude,
|
||||
sb.store_area,
|
||||
sb.store_address,
|
||||
sb.store_grade_id,
|
||||
sbsg.store_grade_name,
|
||||
oit.item_id,
|
||||
oit.product_id,
|
||||
oit.item_name,
|
||||
oit.order_item_quantity,
|
||||
oit.item_unit_price,
|
||||
oit.order_item_amount,
|
||||
IF(oit.order_item_return_num > 0, oit.order_item_return_num, 0) AS order_item_return_num,
|
||||
IF(oit.order_item_return_agree_amount > 0, oit.order_item_return_agree_amount, 0.00) AS
|
||||
order_item_return_agree_amount,
|
||||
spi.item_barcode,
|
||||
oit.order_item_image,
|
||||
oit.spec_info,
|
||||
oda.da_name,
|
||||
oda.da_mobile,
|
||||
oda.da_latitude,
|
||||
oda.da_longitude,
|
||||
oda.da_province,
|
||||
oda.da_city,
|
||||
oda.da_county,
|
||||
oda.da_address,
|
||||
osf.sf_order_id,
|
||||
osf.operator_name,
|
||||
osf.operator_phone,
|
||||
osf.rider_lng,
|
||||
osf.rider_lat,
|
||||
osf.order_status,
|
||||
osf.status_desc,
|
||||
osf.cancel_code,
|
||||
osf.cancel_reason,
|
||||
osf.push_time,
|
||||
osf.h5_url,
|
||||
osf.feed,
|
||||
|
||||
<!-- 退款信息字段 -->
|
||||
sor.return_id,
|
||||
sor.order_id as return_order_id,
|
||||
sor.buyer_user_id as return_buyer_user_id,
|
||||
sor.buyer_store_id as return_buyer_store_id,
|
||||
sor.return_reason_id,
|
||||
sorr.return_reason_name,
|
||||
sor.return_buyer_message,
|
||||
sor.store_id as return_store_id,
|
||||
sor.return_refund_amount,
|
||||
sor.return_commision_fee,
|
||||
sor.return_state_id,
|
||||
sc1.state_code_name as return_state_name,
|
||||
sor.return_tel,
|
||||
sor.return_year,
|
||||
sor.return_month,
|
||||
sor.return_day,
|
||||
sor.return_addr,
|
||||
sor.return_mobile,
|
||||
sor.return_telephone,
|
||||
sor.return_contact_name,
|
||||
sor.subsite_id as return_subsite_id,
|
||||
sor.return_add_time,
|
||||
sor.return_finish_time,
|
||||
sor.return_is_paid,
|
||||
sor.return_channel_code,
|
||||
sor.return_channel_trans_id,
|
||||
sor.return_channel_time,
|
||||
sor.return_channel_flag,
|
||||
sor.deposit_trade_no as return_deposit_trade_no,
|
||||
sor.payment_channel_id as return_payment_channel_id,
|
||||
sor.return_store_message,
|
||||
sor.plantform_return_state_id,
|
||||
sc2.state_code_name as plantform_return_state_name,
|
||||
sor.return_flag,
|
||||
sor.return_type,
|
||||
sor.return_refund_amount as submit_return_refund_amount,
|
||||
ob.buyer_user_name as return_buyer_user_name,
|
||||
sor.try_return_count,
|
||||
|
||||
<!-- 退款收货地址信息 -->
|
||||
sorda.da_province as return_da_province,
|
||||
sorda.da_city as return_da_city,
|
||||
sorda.da_county as return_da_county,
|
||||
sorda.da_address as return_da_address,
|
||||
sorda.da_name as return_da_name,
|
||||
sorda.da_mobile as return_da_mobile,
|
||||
sorda.da_telephone as return_da_telephone,
|
||||
sorda.da_province_id as return_da_province_id,
|
||||
sorda.da_city_id as return_da_city_id,
|
||||
sorda.da_county_id as return_da_county_id,
|
||||
sorda.da_latitude as return_da_latitude,
|
||||
sorda.da_longitude as return_da_longitude,
|
||||
|
||||
<!-- 退款商品信息 -->
|
||||
sori.order_return_item_id,
|
||||
sori.return_id as item_return_id,
|
||||
sori.order_item_id as return_order_item_id,
|
||||
sori.order_id as item_order_id,
|
||||
sori.return_item_num,
|
||||
sori.return_item_subtotal,
|
||||
sori.return_reason_id as item_return_reason_id,
|
||||
sori.return_item_note,
|
||||
sori.return_item_image,
|
||||
sori.return_state_id as item_return_state_id,
|
||||
sori.return_item_commision_fee,
|
||||
sori.return_item_store_remark,
|
||||
soi.item_name as return_item_name,
|
||||
spb.product_name as return_product_name,
|
||||
soi.item_id as return_item_id,
|
||||
soi.order_item_image as return_order_item_image,
|
||||
spb.unit_id as return_unit_id,
|
||||
sbpu.unit_name as return_unit_name,
|
||||
soi.order_item_unit_price as return_order_item_unit_price,
|
||||
soi.order_item_quantity as return_order_item_quantity,
|
||||
soi.order_item_amount as return_order_item_amount,
|
||||
soi.order_item_note as return_order_item_note,
|
||||
spi.item_number as return_item_number,
|
||||
spb.product_number as return_product_number
|
||||
</sql>
|
||||
|
||||
<!-- 公共的FROM和JOIN子句 -->
|
||||
<sql id="mchOrderFromAndJoins">
|
||||
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
|
||||
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
|
||||
JOIN shop_order_item oit ON ob.order_id = oit.order_id
|
||||
LEFT JOIN shop_store_sf_order osf ON ob.order_id = osf.shop_order_id
|
||||
LEFT JOIN shop_product_item spi ON oit.item_id = spi.item_id
|
||||
LEFT JOIN shop_base_store_grade sbsg ON sb.store_grade_id = sbsg.store_grade_id
|
||||
LEFT JOIN shop_order_return sor ON ob.order_id = sor.order_id
|
||||
LEFT JOIN shop_order_return_reason sorr ON sor.return_reason_id = sorr.return_reason_id
|
||||
LEFT JOIN shop_base_state_code sc1 ON sor.return_state_id = sc1.state_code_id
|
||||
LEFT JOIN shop_base_state_code sc2 ON sor.plantform_return_state_id = sc2.state_code_id
|
||||
LEFT JOIN shop_order_delivery_address sorda ON sor.order_id = sorda.order_id
|
||||
LEFT JOIN shop_order_return_item sori ON sor.return_id = sori.return_id
|
||||
LEFT JOIN shop_order_item soi ON sori.order_item_id = soi.order_item_id
|
||||
LEFT JOIN shop_product_base spb ON soi.product_id = spb.product_id
|
||||
LEFT JOIN shop_base_product_unit sbpu ON spb.unit_id = sbpu.unit_id
|
||||
</sql>
|
||||
|
||||
<!--refundstatus 退款状态:0-是无退款;1-是部分退款;2-是全部退款
|
||||
orderstatus 订单状态:2010-待付款;2011-待订单审核;2012-待发货;2013-待财务审核;2014-待配货/待出库审核;2020-待发货;
|
||||
2030-待发货/待收货确认;2040-已发货/待收货确认;2050-已签收;2060-已完成/已签收;2070-已取消/已作废;2080-自提-->
|
||||
<!-- status: 同城配送订单状态(delivery=1时才生效):无值 or 0-全部订单;1-进行中订单;2-异常(超时)订单;3-退款订单;9-已完成订单-->
|
||||
@ -693,17 +1004,17 @@
|
||||
<!-- 1-进行中订单 -->
|
||||
<when test="status != null and status == 1 and expireSeconds != null and expireSeconds > 0">
|
||||
AND ob.order_state_id IN (2011,2012,2013,2014,2020,2030,2040)
|
||||
AND (oi.order_time + #{expireSeconds}*1000) <![CDATA[>=]]> UNIX_TIMESTAMP() * 1000
|
||||
AND (oi.order_time + #{expireSeconds}*1000) <![CDATA[>]]> UNIX_TIMESTAMP() * 1000
|
||||
</when>
|
||||
<!-- 2-异常(超时)订单 -->
|
||||
<when test="status != null and status == 2 and expireSeconds != null and expireSeconds > 0">
|
||||
AND ob.order_state_id IN (2011,2012,2013,2014,2020,2030,2040)
|
||||
AND (oi.order_time + #{expireSeconds}*1000) <![CDATA[<]]> UNIX_TIMESTAMP() * 1000
|
||||
AND ob.order_state_id IN (2011,2012,2013,2014,2020,2030)
|
||||
AND (oi.order_time + #{expireSeconds}*1000) <![CDATA[<=]]> UNIX_TIMESTAMP() * 1000
|
||||
</when>
|
||||
<!-- 3-退款订单 -->
|
||||
<when test="status != null and status == 3">
|
||||
AND od.order_refund_status IN (1, 2)
|
||||
AND ob.order_state_id = 2070
|
||||
<!-- AND ob.order_state_id = 2070-->
|
||||
</when>
|
||||
<!-- 9-已完成订单 -->
|
||||
<when test="status != null and status == 9">
|
||||
@ -765,145 +1076,6 @@
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<!--应付金额/应支付金额:order_goods_amount - order_discount_amount + order_shipping_fee - order_voucher_price - order_points_fee - order_adjust_fee-->
|
||||
<sql id="mchOrderColumns">
|
||||
SELECT
|
||||
ob.order_id,
|
||||
ob.order_time,
|
||||
<!--送达时间戳-->
|
||||
CASE
|
||||
WHEN oi.delivery_type_id IS NOT NULL AND oi.delivery_type_id = 16 AND #{expireSeconds} IS NOT NULL AND
|
||||
#{expireSeconds} > 0
|
||||
THEN oi.order_time + #{expireSeconds}*1000
|
||||
ELSE oi.order_time + 864000000 <!-- 10天 = 10*24*60*60*1000 = 864000000毫秒 -->
|
||||
END as arrival_time,
|
||||
ob.order_product_amount,
|
||||
ob.order_payment_amount,
|
||||
ob.currency_id,
|
||||
ob.order_state_id,
|
||||
ob.operate_flag,
|
||||
ST_Distance_Sphere(
|
||||
POINT(sb.store_longitude, sb.store_latitude),
|
||||
POINT(oda.da_longitude, oda.da_latitude)
|
||||
) as distance,
|
||||
oi.order_title,
|
||||
oi.order_pickup_num,
|
||||
oi.delivery_type_id,
|
||||
oi.buyer_user_id,
|
||||
oi.order_picked_time,
|
||||
oi.order_is_received,
|
||||
oi.kind_id,
|
||||
IF((SELECT count(*) FROM shop_order_base WHERE buyer_user_id = oi.buyer_user_id AND order_state_id IN
|
||||
(2011,2012,
|
||||
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,
|
||||
<!--总计优惠金额 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-lkl_fee+od.packing_fee)
|
||||
as order_income_amount,
|
||||
(od.platform_fee+lkl_fee) as platform_fee,
|
||||
od.packing_fee,
|
||||
od.order_message,
|
||||
sb.store_id,
|
||||
sb.store_name,
|
||||
sb.store_logo,
|
||||
sb.store_latitude,
|
||||
sb.store_longitude,
|
||||
sb.store_area,
|
||||
sb.store_address,
|
||||
sb.store_grade_id,
|
||||
sbsg.store_grade_name,
|
||||
oit.item_id,
|
||||
oit.product_id,
|
||||
oit.item_name,
|
||||
oit.order_item_quantity,
|
||||
oit.item_unit_price,
|
||||
oit.order_item_amount,
|
||||
IF(oit.order_item_return_num > 0, oit.order_item_return_num, 0) AS order_item_return_num,
|
||||
IF(oit.order_item_return_agree_amount > 0, oit.order_item_return_agree_amount, 0.00) AS
|
||||
order_item_return_agree_amount,
|
||||
spi.item_barcode,
|
||||
oit.order_item_image,
|
||||
oit.spec_info,
|
||||
oda.da_name,
|
||||
oda.da_mobile,
|
||||
oda.da_latitude,
|
||||
oda.da_longitude,
|
||||
oda.da_province,
|
||||
oda.da_city,
|
||||
oda.da_county,
|
||||
oda.da_address,
|
||||
osf.sf_order_id,
|
||||
osf.operator_name,
|
||||
osf.operator_phone,
|
||||
osf.rider_lng,
|
||||
osf.rider_lat,
|
||||
osf.order_status,
|
||||
osf.status_desc,
|
||||
osf.cancel_code,
|
||||
osf.cancel_reason,
|
||||
osf.push_time,
|
||||
osf.h5_url,
|
||||
osf.feed
|
||||
</sql>
|
||||
|
||||
<select id="selectMchOrderPageList" 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
|
||||
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
|
||||
join shop_order_item oit on ob.order_id=oit.order_id
|
||||
left join shop_store_sf_order osf on ob.order_id=osf.shop_order_id
|
||||
left join shop_product_item spi on oit.product_id=spi.product_id
|
||||
left join shop_base_store_grade sbsg on sb.store_grade_id=sbsg.store_grade_id
|
||||
|
||||
<include refid="mchOrderWhereCondition"/>
|
||||
|
||||
ORDER BY ob.order_time DESC
|
||||
</select>
|
||||
|
||||
<select id="countMchOrderByCondition" resultType="java.lang.Long">
|
||||
SELECT COUNT(DISTINCT ob.order_id)
|
||||
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
|
||||
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
|
||||
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
|
||||
join shop_order_item oit on ob.order_id=oit.order_id
|
||||
left join shop_store_sf_order osf on ob.order_id=osf.shop_order_id
|
||||
left join shop_product_item spi on oit.product_id=spi.product_id
|
||||
left join shop_base_store_grade sbsg on sb.store_grade_id=sbsg.store_grade_id
|
||||
|
||||
<where>
|
||||
ob.order_id=#{orderId}
|
||||
</where>
|
||||
|
||||
ORDER BY ob.order_id DESC
|
||||
</select>
|
||||
|
||||
|
||||
<select id="getWxOrderBaseInfo" resultMap="WxOrderBaseInfoResult">
|
||||
SELECT a.store_id,
|
||||
|
||||
File diff suppressed because one or more lines are too long
21605
mall-shop/src/main/resources/static/diy/js/diy.js.bak1114
Normal file
21605
mall-shop/src/main/resources/static/diy/js/diy.js.bak1114
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
5589
mall-shop/src/main/resources/templates/diy.html.bak1114
Normal file
5589
mall-shop/src/main/resources/templates/diy.html.bak1114
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user