Compare commits
89 Commits
194290bb49
...
48802a666b
| Author | SHA1 | Date | |
|---|---|---|---|
| 48802a666b | |||
| 97ee21b5fb | |||
| 295275b3dc | |||
| f9192c74ff | |||
| a53ccaadc7 | |||
| 7a26bdec49 | |||
| 89a326a05b | |||
| def93e54fa | |||
| 48da403179 | |||
| ca48e78dd1 | |||
| 76b7832908 | |||
| 87f777ca78 | |||
| 9051b0702d | |||
| fc177025a0 | |||
| 28e5b83f6c | |||
| b1f401ff81 | |||
| 950b7b9b32 | |||
| 46b27539b5 | |||
| 7326d0505f | |||
| 1684e43663 | |||
| 6575858004 | |||
| cb0d5e0cc3 | |||
| 2ea022091c | |||
| 2eed30bdf4 | |||
| dcaf638b58 | |||
| e59fa56784 | |||
| d530054e03 | |||
| 81abf15dcd | |||
| 655998c805 | |||
| 24a9def012 | |||
| b4e2b92730 | |||
| d9bb03770a | |||
| 1d328b38f7 | |||
| a73615f350 | |||
| e7d8a126fc | |||
| 62239d4dec | |||
| 30b24dda04 | |||
| e1bd542c12 | |||
| 7e4c2a9ccf | |||
| ed29dcd419 | |||
| 857447ae8b | |||
| c0f11aa224 | |||
| 504f03e5f6 | |||
| 4e2a75520c | |||
| fb10c6e173 | |||
| 45469be52d | |||
| 71cef21472 | |||
| 75795bad0e | |||
| 200f66839b | |||
| 9085dc7681 | |||
| 5c6a4e985a | |||
| d8aadb2d47 | |||
| 3bdb5d73d1 | |||
| 06df245d59 | |||
| d4c3bce80f | |||
| d2c9b6c492 | |||
| da771d42f7 | |||
| f06a166693 | |||
| c14cdb0967 | |||
| b628fffca7 | |||
| 3802044eea | |||
| 32bd2fab91 | |||
| de19921581 | |||
| 2cb58bffa3 | |||
| 9c8f78f3cf | |||
| 9bc2d32c45 | |||
| 8f20e755fb | |||
| db5bd06c35 | |||
| 528c76a912 | |||
| 1022468778 | |||
| 9d59fbcc9c | |||
| 8eeee63f58 | |||
| 3971c5f504 | |||
| 47331a5b2a | |||
| 0b6c87aa31 | |||
| c8699f0bf2 | |||
| ac3b9216d8 | |||
| a3fa5a3fa8 | |||
| 3ca6dcbec9 | |||
| 1b97836bea | |||
| fddd1750a1 | |||
| 4ce40ede17 | |||
| 023bd790df | |||
| 8c9661c77c | |||
| 928b16da60 | |||
| 7dd3822e44 | |||
| 4259a7e454 | |||
| da449a5921 | |||
| a2e0854a7d |
@ -15,9 +15,8 @@ public class StateCode {
|
||||
public static final int DELIVERY_TYPE_AIR_FREIGHT = 4; //货运(空运、水运、铁路运输、公路运输)
|
||||
public static final int DELIVERY_TYPE_SELF_PICK_UP = 5; // 自提(运费 0 元)
|
||||
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 int DELIVERY_TYPE_IN_STORE_SERVICE = 15; // 店铺配送(运费 0 元)
|
||||
public static final int DELIVERY_TYPE_SAME_CITY = 16;//同城配送
|
||||
|
||||
public static final Map<Integer, String> DELIVERY_TYPE_MAP = new HashMap() {
|
||||
{
|
||||
@ -28,7 +27,7 @@ public class StateCode {
|
||||
put(DELIVERY_TYPE_SELF_PICK_UP, "到店自提");
|
||||
put(DELIVERY_TYPE_EXP, "普通快递");
|
||||
put(DELIVERY_TYPE_IN_STORE_SERVICE, "店铺配送");
|
||||
put(DELIVERY_TYPE_SAME_CITY, "顺丰同城");
|
||||
put(DELIVERY_TYPE_SAME_CITY, "顺丰同城配送");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@ public class MqConstant {
|
||||
public static final Integer FAILURE = 2; // 消息消费失败更改状态
|
||||
public static final Integer DELIVERED = 3; // 消息重试消费成功更改状态
|
||||
public static final Integer MAX_COUNT = 3; // 消息重新投递最大重试次数
|
||||
|
||||
public static final String SHOP_EXCHANGE = "shop-event-exchange"; // SHOP服务交换机
|
||||
public static final String ACCOUNT_EXCHANGE = "account-event-exchange"; // ACCOUNT服务交换机
|
||||
public static final String PAY_EXCHANGE = "pay-event-exchange"; // PAY服务交换机
|
||||
|
||||
@ -29,6 +29,9 @@ public class LibraryProduct implements Serializable {
|
||||
@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "商品简称,作为匹配关键字", example = "小米12 Pro")
|
||||
private String sname;
|
||||
|
||||
@ApiModelProperty(value = "商品标题", example = "小米12 Pro")
|
||||
@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
|
||||
private String title;
|
||||
@ -66,7 +69,6 @@ public class LibraryProduct implements Serializable {
|
||||
@ApiModelProperty(value = "商品卖点", example = "绿色有机")
|
||||
private String selling_point;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "商品介绍", example = "商品介绍")
|
||||
private String intro;
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -135,5 +136,9 @@ public class ShopPageBase implements Serializable {
|
||||
@ApiModelProperty(value = "信息发布(BOOL):0-否;1-是")
|
||||
private Integer page_message;
|
||||
|
||||
@ApiModelProperty(value = "创建时间")
|
||||
private Date created_at;
|
||||
|
||||
@ApiModelProperty(value = "最后更新时间")
|
||||
private Date updated_at;
|
||||
}
|
||||
|
||||
@ -43,6 +43,9 @@ public class ShopStoreSameCityTransportBase implements Serializable {
|
||||
@TableId(value = "transport_base_id", type = IdType.AUTO)
|
||||
private Long transport_base_id;
|
||||
|
||||
@ApiModelProperty(value = "平台配送费设置?1-是;2-否")
|
||||
private Integer is_platform;
|
||||
|
||||
@ApiModelProperty(value = "店铺ID")
|
||||
private Long store_id;
|
||||
|
||||
|
||||
@ -34,9 +34,9 @@ import java.math.RoundingMode;
|
||||
public class LklSeparateWithTotalAmountDTO {
|
||||
|
||||
// 商家最低分账比例阈值 20%
|
||||
private static final BigDecimal MCH_RATIO_THRESHOLD = BigDecimal.valueOf(0.2);
|
||||
private static final BigDecimal MIN_MERCHANT_RATIO_THRESHOLD = BigDecimal.valueOf(0.2);
|
||||
// 默认平台比例 1%
|
||||
private static final BigDecimal DEFAULT_PLAT_RATIO = BigDecimal.valueOf(0.01);
|
||||
private static final BigDecimal DEFAULT_PLATFORM_RATIO = BigDecimal.valueOf(0.01);
|
||||
|
||||
// 基础金额属性
|
||||
private Integer totalSeparateAmount; // 分账总金额(分)
|
||||
@ -206,7 +206,16 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
return SeparateResult.failure(errorMsg);
|
||||
}
|
||||
|
||||
// 6. 计算商家实际分账比例
|
||||
// 6. 根据指定规则调整各参与方分账金额
|
||||
Pair<Boolean, String> adjustResult = adjustAmountsWithLklAmount();
|
||||
if (!adjustResult.getFirst()) {
|
||||
String errorMsg = "分账计算参数异常: " + adjustResult.getSecond();
|
||||
log.error(errorMsg);
|
||||
this.errMsg = errorMsg;
|
||||
return SeparateResult.failure(errorMsg);
|
||||
}
|
||||
|
||||
// 7. 计算商家实际分账比例
|
||||
Pair<Boolean, String> mchResult = calculateActualMchRatio();
|
||||
if (!mchResult.getFirst()) {
|
||||
String errorMsg = "分账计算参数异常: " + mchResult.getSecond();
|
||||
@ -322,7 +331,7 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
private Pair<Boolean, String> calculateDefaultRatios() {
|
||||
// 如果平台比例无效,设置默认值0.01
|
||||
if (platRatio == null || platRatio.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
platRatio = DEFAULT_PLAT_RATIO;
|
||||
platRatio = DEFAULT_PLATFORM_RATIO;
|
||||
}
|
||||
|
||||
return Pair.of(true, "");
|
||||
@ -422,6 +431,53 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
return Pair.of(true, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据指定规则调整各参与方分账金额
|
||||
* 如果拉卡拉分账金额lklAmount>0:
|
||||
* 1. 如果agent2ndAmount>0 且大于lklAmount, 则agent2ndAmount=agent2ndAmount-lklAmount,mchAmount=mchAmount+lklAmount
|
||||
* 2. 如果agent2ndAmount<=0 但 agent1stAmount>0 且大于lklAmount, 则agent1stAmount=agent1stAmount-lklAmount,mchAmount=mchAmount+lklAmount
|
||||
* 3. 如果agent2ndAmount<=0 且 agent1stAmount<=0,但 platAmount>0 且大于等于lklAmount, 则 platAmount=platAmount-lklAmount,mchAmount=mchAmount+lklAmount
|
||||
*
|
||||
* @return Pair<Boolean, String> Boolean表示是否成功,String为错误信息
|
||||
*/
|
||||
private Pair<Boolean, String> adjustAmountsWithLklAmount() {
|
||||
try {
|
||||
// 只有当拉卡拉分账金额大于0时才执行调整逻辑
|
||||
if (lklAmount != null && lklAmount > 0) {
|
||||
int adjustment = lklAmount; // 需要调整的金额
|
||||
|
||||
// 情况1: 如果agent2ndAmount>0 且大于lklAmount
|
||||
if (agent2ndAmount != null && agent2ndAmount > 0 && agent2ndAmount > adjustment) {
|
||||
agent2ndAmount -= adjustment;
|
||||
mchAmount += adjustment;
|
||||
log.debug("调整二级代理商分账金额: 减少{},商家分账金额增加{}", adjustment, adjustment);
|
||||
}
|
||||
// 情况2: 如果agent2ndAmount<=0 但 agent1stAmount>0 且大于lklAmount
|
||||
else if ((agent2ndAmount == null || agent2ndAmount <= 0) &&
|
||||
agent1stAmount != null && agent1stAmount > 0 && agent1stAmount > adjustment) {
|
||||
agent1stAmount -= adjustment;
|
||||
mchAmount += adjustment;
|
||||
log.debug("调整一级代理商分账金额: 减少{},商家分账金额增加{}", adjustment, adjustment);
|
||||
}
|
||||
// 情况3: 如果agent2ndAmount<=0 且 agent1stAmount<=0,但 platAmount>0 且大于等于lklAmount
|
||||
else if ((agent2ndAmount == null || agent2ndAmount <= 0) &&
|
||||
(agent1stAmount == null || agent1stAmount <= 0) &&
|
||||
platAmount != null && platAmount > 0 && platAmount >= adjustment) {
|
||||
platAmount -= adjustment;
|
||||
mchAmount += adjustment;
|
||||
log.debug("调整平台分账金额: 减少{},商家分账金额增加{}", adjustment, adjustment);
|
||||
}
|
||||
// 其他情况不作调整
|
||||
else {
|
||||
log.debug("不满足调整条件,无需调整各参与方分账金额");
|
||||
}
|
||||
}
|
||||
|
||||
return Pair.of(true, "");
|
||||
} catch (Exception e) {
|
||||
return Pair.of(false, "调整分账金额时发生异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算商家实际分账比例
|
||||
@ -435,9 +491,9 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
.divide(BigDecimal.valueOf(totalSeparateAmount), 6, RoundingMode.HALF_UP);
|
||||
|
||||
// 如果计算出的实际比例低于阈值,打印日志并返回错误
|
||||
if (mchRatio.compareTo(MCH_RATIO_THRESHOLD) < 0) {
|
||||
if (mchRatio.compareTo(MIN_MERCHANT_RATIO_THRESHOLD) < 0) {
|
||||
String errorMsg = String.format("警告: 商家实际分账比例低于阈值,当前比例: %s,阈值: %s",
|
||||
mchRatio.toPlainString(), MCH_RATIO_THRESHOLD.toPlainString());
|
||||
mchRatio.toPlainString(), MIN_MERCHANT_RATIO_THRESHOLD.toPlainString());
|
||||
log.warn(errorMsg);
|
||||
return Pair.of(false, errorMsg);
|
||||
}
|
||||
@ -611,4 +667,4 @@ public class LklSeparateWithTotalAmountDTO {
|
||||
return new SeparateResult(Boolean.TRUE, data, errMsg != null ? errMsg : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -16,13 +16,16 @@ import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 订单商品详情打印对象
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ApiModel(value = "订单商品打印对象", description = "订单商品打印对象")
|
||||
public class ShopStoreOrderProductPrintVO implements Serializable {
|
||||
@ApiModel(value = "订单商品详情打印对象", description = "订单商品详情打印对象")
|
||||
public class OrderItemPrintVO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
@ApiModelProperty(value = "商品名")
|
||||
private String item_name;
|
||||
@ -47,11 +50,11 @@ public class ShopStoreOrderProductPrintVO implements Serializable {
|
||||
@ApiModelProperty(value = "金额额定字节长度")
|
||||
private Integer amount_blen;
|
||||
|
||||
public ShopStoreOrderProductPrintVO(String itemName, Integer orderItemQuantity, BigDecimal orderItemAmount, String productSn) {
|
||||
new ShopStoreOrderProductPrintVO(itemName, orderItemQuantity, orderItemAmount, productSn, 18, 6, 8);
|
||||
public OrderItemPrintVO(String itemName, Integer orderItemQuantity, BigDecimal orderItemAmount, String productSn) {
|
||||
new OrderItemPrintVO(itemName, orderItemQuantity, orderItemAmount, productSn, 18, 6, 8);
|
||||
}
|
||||
|
||||
public ShopStoreOrderProductPrintVO(String itemName, Integer orderItemQuantity, BigDecimal orderItemAmount, String productSn, int titleBlen, int quantityBlen, int amountBlen) {
|
||||
public OrderItemPrintVO(String itemName, Integer orderItemQuantity, BigDecimal orderItemAmount, String productSn, int titleBlen, int quantityBlen, int amountBlen) {
|
||||
this.item_name = itemName;
|
||||
this.order_item_quantity = orderItemQuantity;
|
||||
this.order_item_amount = orderItemAmount;
|
||||
@ -90,8 +93,8 @@ public class ShopStoreOrderProductPrintVO implements Serializable {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ShopStoreOrderProductPrintVO rebuild() {
|
||||
return new ShopStoreOrderProductPrintVO(this.item_name, this.order_item_quantity, this.order_item_amount, this.product_sn, 18, 6, 8);
|
||||
public OrderItemPrintVO rebuild() {
|
||||
return new OrderItemPrintVO(this.item_name, this.order_item_quantity, this.order_item_amount, this.product_sn, 18, 6, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -0,0 +1,145 @@
|
||||
package com.suisung.mall.common.pojo.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.*;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 退货单打印对象
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@ApiModel(value = "(退款)订单主信息打印对象", description = "(退款)订单主信息打印对象")
|
||||
public class OrderPrintVO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty(value = "订单编号")
|
||||
private String order_id;
|
||||
|
||||
@ApiModelProperty(value = "退单编号")
|
||||
private String return_id;
|
||||
|
||||
@ApiModelProperty(value = "店铺Id")
|
||||
private Integer store_id;
|
||||
|
||||
@ApiModelProperty(value = "店铺名称")
|
||||
private String store_name;
|
||||
|
||||
@ApiModelProperty(value = "店铺电话")
|
||||
private String store_tel;
|
||||
|
||||
@ApiModelProperty(value = "(配送)取单号")
|
||||
@Builder.Default
|
||||
private String order_pickup_num_str = "#0000000";
|
||||
|
||||
@ApiModelProperty(value = "退款订单编号")
|
||||
private String order_message;
|
||||
|
||||
@ApiModelProperty(value = "支付时间")
|
||||
private Date payment_time;
|
||||
|
||||
@ApiModelProperty(value = "商品总件数")
|
||||
private Integer order_items_count;
|
||||
|
||||
@ApiModelProperty(value = "商品总类数")
|
||||
private Integer order_product_amount;
|
||||
|
||||
@ApiModelProperty(value = "订单配送费")
|
||||
private BigDecimal order_shipping_fee;
|
||||
|
||||
@ApiModelProperty(value = "订单来源")
|
||||
@Builder.Default
|
||||
private String order_channel_name = "微信小程序";
|
||||
|
||||
@ApiModelProperty(value = "支付方式")
|
||||
@Builder.Default
|
||||
private String payment_type_name = "微信支付";
|
||||
|
||||
@ApiModelProperty(value = "配送方式ID")
|
||||
@Builder.Default
|
||||
private Integer delivery_type_id = 16;
|
||||
|
||||
@ApiModelProperty(value = "配送方式")
|
||||
@Builder.Default
|
||||
private String delivery_type_name = "顺丰同城";
|
||||
|
||||
@ApiModelProperty(value = "打包费")
|
||||
private BigDecimal packing_fee;
|
||||
|
||||
@ApiModelProperty(value = "会员优惠权益金额")
|
||||
private BigDecimal basic_rights;
|
||||
|
||||
@ApiModelProperty(value = "实付金额")
|
||||
private BigDecimal order_payment_amount;
|
||||
|
||||
@ApiModelProperty(value = "退款金额")
|
||||
private BigDecimal return_refund_amount;
|
||||
|
||||
@ApiModelProperty(value = "订单状态(LIST):2011-待订单审核;2013-待财务审核;2020-待配货/待出库审核;2030-待发货;2040-已发货/待收货确认;2060-已完成/已签收;2070-已取消/已作废;")
|
||||
private String order_state;
|
||||
|
||||
@ApiModelProperty(value = "下单时买家退货留言")
|
||||
private String return_buyer_message;
|
||||
|
||||
@ApiModelProperty(value = "下单时商家留言")
|
||||
private String seller_message;
|
||||
|
||||
@ApiModelProperty(value = "买家退货留言")
|
||||
private String return_store_message;
|
||||
|
||||
@ApiModelProperty(value = "申请退款时间")
|
||||
private Date return_add_time;
|
||||
|
||||
@ApiModelProperty(value = "退款完成时间")
|
||||
private Date return_finish_time;
|
||||
|
||||
@ApiModelProperty(value = "预订单状态")
|
||||
private Integer booking_state;
|
||||
|
||||
@ApiModelProperty(value = "预订单开始时间")
|
||||
private Date booking_begin_time;
|
||||
|
||||
@ApiModelProperty(value = "退货类型(ENUM): 0-不用退货;1-需要退货")
|
||||
@Builder.Default
|
||||
private String return_flag_str = "原路返回";
|
||||
|
||||
@ApiModelProperty(value = "卖家处理状态(ENUM): 3100-【客户】提交退单;3105-退单审核;3110-收货确认;3115-退款确认;3120-【客户】收款确认;3125-完成退款;3130-商家拒绝退货;3135-买家取消退款")
|
||||
private String return_state;
|
||||
|
||||
@ApiModelProperty(value = "买方用户名")
|
||||
private String buyer_user_name;
|
||||
|
||||
@ApiModelProperty(value = "退款人手机号")
|
||||
private String return_tel;
|
||||
|
||||
@ApiModelProperty(value = "收货联系电话")
|
||||
private String da_mobile;
|
||||
|
||||
@ApiModelProperty(value = "收货省份")
|
||||
private String da_province;
|
||||
|
||||
@ApiModelProperty(value = "收货城市")
|
||||
private String da_city;
|
||||
|
||||
@ApiModelProperty(value = "收货详细地址")
|
||||
private String da_address;
|
||||
|
||||
@ApiModelProperty(value = "(店长)收银员")
|
||||
@Builder.Default
|
||||
private String cashier = "收银员";
|
||||
|
||||
@ApiModelProperty(value = "订单商品详情打印对象列表")
|
||||
private List<OrderItemPrintVO> order_items;
|
||||
|
||||
|
||||
}
|
||||
@ -68,7 +68,7 @@ public class ShopStoreOrderPrintVO implements Serializable {
|
||||
@ApiModelProperty(value = "支付方式")
|
||||
private String pay_type;
|
||||
|
||||
@ApiModelProperty(value = "配送来源")
|
||||
@ApiModelProperty(value = "配送方式")
|
||||
private String shipper_type;
|
||||
|
||||
@ApiModelProperty(value = "下单时间")
|
||||
@ -105,9 +105,8 @@ public class ShopStoreOrderPrintVO implements Serializable {
|
||||
@ApiModelProperty(value = "实际应付款")
|
||||
private Long order_payment_amount;
|
||||
|
||||
// 订单商品详情信息
|
||||
@ApiModelProperty(value = "订单商品详情信息")
|
||||
private ShopStoreOrderProductPrintVO order_items;
|
||||
private OrderItemPrintVO order_items;
|
||||
|
||||
@ApiModelProperty(value = "状态:1-有效;2-无效;")
|
||||
private Integer status;
|
||||
|
||||
@ -17,6 +17,7 @@ import com.suisung.mall.common.constant.CommonConstant;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Slf4j
|
||||
@ -76,10 +77,37 @@ public class CommonService {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 普通配送是指除了同城配送、自提和到店服务之外的配送方式
|
||||
return !deliveryTypeId.equals(StateCode.DELIVERY_TYPE_SAME_CITY)
|
||||
&& !deliveryTypeId.equals(StateCode.DELIVERY_TYPE_SELF_PICK_UP)
|
||||
&& !deliveryTypeId.equals(StateCode.DELIVERY_TYPE_IN_STORE_SERVICE);
|
||||
// 普通配送是指除了同城配送、自提和到店服务之外的配送方式(没有物流轨迹的)
|
||||
return !Objects.equals(deliveryTypeId, StateCode.DELIVERY_TYPE_SAME_CITY)
|
||||
&& !Objects.equals(deliveryTypeId, StateCode.DELIVERY_TYPE_SELF_PICK_UP)
|
||||
&& !Objects.equals(deliveryTypeId, StateCode.DELIVERY_TYPE_IN_STORE_SERVICE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配送方式名称
|
||||
*
|
||||
* @param deliveryTypeId 配送方式ID
|
||||
* @return 配送方式名称
|
||||
*/
|
||||
public static String getDeliveryExpressName(Integer deliveryTypeId) {
|
||||
if (deliveryTypeId == null) return "其他配送";
|
||||
String name = StateCode.DELIVERY_TYPE_MAP.get(deliveryTypeId);
|
||||
return name != null ? name : "其他配送";
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断配送方式是否为同城配送
|
||||
*
|
||||
* @param deliveryTypeId 配送方式ID
|
||||
* @return 是否为普通配送
|
||||
*/
|
||||
public static boolean isSameCityExpress(Integer deliveryTypeId) {
|
||||
// 当配送方式ID为空时,返回false
|
||||
if (deliveryTypeId == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(deliveryTypeId, StateCode.DELIVERY_TYPE_SAME_CITY);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -11,7 +11,6 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.ChronoField;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@ -492,7 +491,7 @@ public class DateTimeUtils {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 判断指定时间是否在两个时间点之间(包含边界)
|
||||
*
|
||||
@ -602,6 +601,27 @@ public class DateTimeUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isActivityTimeValid(Date starTime, Date endTime, Date checkTime) {
|
||||
log.debug("检查活动时间有效性 - 开始时间: {}, 结束时间: {}, 检查时间: {}", starTime, endTime, checkTime);
|
||||
|
||||
if (starTime == null || endTime == null) {
|
||||
log.error("活动时间验证失败 - 开始时间或结束时间为null. 开始时间: {}, 结束时间: {}", starTime, endTime);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (checkTime == null) {
|
||||
checkTime = new Date();
|
||||
log.warn("检查时间为空,使用当前时间: {}", checkTime);
|
||||
}
|
||||
|
||||
boolean isValid = !checkTime.before(starTime) && !checkTime.after(endTime);
|
||||
log.debug("活动时间验证结果: {} (检查时间>=开始时间, 检查时间<=结束时间)",
|
||||
isValid);
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
// System.out.println(convertLklDate("2021-02-19")); // 2025-01-02
|
||||
// System.out.println(convertLklDate("2021-2-3")); // 2025-01-02
|
||||
@ -632,29 +652,29 @@ public class DateTimeUtils {
|
||||
|
||||
// System.out.println("当前时间是否在工作时间内:" + isWorkTime);
|
||||
// System.out.println("多个时间段的交集结果:" + isNight);
|
||||
|
||||
System.out.println("=== 测试 findTimeIntersection ===");
|
||||
|
||||
// 测试正常交集情况
|
||||
List<Pair<String, String>> timeList1 = new ArrayList<>();
|
||||
timeList1.add(Pair.of("06:00", "17:00"));
|
||||
timeList1.add(Pair.of("10:00", "18:00"));
|
||||
|
||||
Pair<String, String> intersection1 = findTimeInterSection(timeList1);
|
||||
System.out.println("交集结果1: " + intersection1); // 应该是 10:00 - 17:00
|
||||
|
||||
// 测试无交集情况
|
||||
List<Pair<String, String>> timeList2 = new ArrayList<>();
|
||||
timeList2.add(Pair.of("09:00", "12:00"));
|
||||
timeList2.add(Pair.of("13:00", "17:00"));
|
||||
|
||||
Pair<String, String> intersection2 = findTimeInterSection(timeList2);
|
||||
System.out.println("交集结果2: " + intersection2); // 应该是null
|
||||
|
||||
// 测试空列表
|
||||
Pair<String, String> intersection3 = findTimeInterSection(null);
|
||||
System.out.println("交集结果3 (null输入): " + intersection3); // 应该是null
|
||||
|
||||
//
|
||||
// System.out.println("=== 测试 findTimeIntersection ===");
|
||||
//
|
||||
// // 测试正常交集情况
|
||||
// List<Pair<String, String>> timeList1 = new ArrayList<>();
|
||||
// timeList1.add(Pair.of("06:00", "17:00"));
|
||||
// timeList1.add(Pair.of("10:00", "18:00"));
|
||||
//
|
||||
// Pair<String, String> intersection1 = findTimeInterSection(timeList1);
|
||||
// System.out.println("交集结果1: " + intersection1); // 应该是 10:00 - 17:00
|
||||
//
|
||||
//// 测试无交集情况
|
||||
// List<Pair<String, String>> timeList2 = new ArrayList<>();
|
||||
// timeList2.add(Pair.of("09:00", "12:00"));
|
||||
// timeList2.add(Pair.of("13:00", "17:00"));
|
||||
//
|
||||
// Pair<String, String> intersection2 = findTimeInterSection(timeList2);
|
||||
// System.out.println("交集结果2: " + intersection2); // 应该是null
|
||||
//
|
||||
//// 测试空列表
|
||||
// Pair<String, String> intersection3 = findTimeInterSection(null);
|
||||
// System.out.println("交集结果3 (null输入): " + intersection3); // 应该是null
|
||||
//
|
||||
|
||||
}
|
||||
}
|
||||
@ -39,7 +39,7 @@ public class FreeMakerUtils {
|
||||
* @throws IOException
|
||||
* @throws TemplateException
|
||||
*/
|
||||
public static String processTemplate(Configuration configuration, String templateName, String templateValue, Map<String, Object> binding) {
|
||||
public static String processTemplate(Configuration configuration, String templateName, String templateValue, Object binding) {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
try {
|
||||
Template template = new Template(templateName, templateValue, configuration);
|
||||
@ -63,4 +63,8 @@ public class FreeMakerUtils {
|
||||
public static String processTemplate(String templateName, String templateValue, Map<String, Object> binding) {
|
||||
return processTemplate(stringTempConfiguration(), templateName, templateValue, binding);
|
||||
}
|
||||
|
||||
public static String processTemplate(String templateName, String templateValue, Object binding) {
|
||||
return processTemplate(stringTempConfiguration(), templateName, templateValue, binding);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,349 @@
|
||||
package com.suisung.mall.common.utils;
|
||||
|
||||
import com.suisung.mall.core.web.service.RedisService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* DistributedLockHelper综合测试套件
|
||||
*/
|
||||
public class DistributedLockHelperTest {
|
||||
|
||||
private DistributedLockHelper lockHelper;
|
||||
|
||||
@Mock
|
||||
private RedisService redisService;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
lockHelper = new DistributedLockHelper();
|
||||
ReflectionTestUtils.setField(lockHelper, "redisService", redisService);
|
||||
System.out.println("=== 初始化测试环境 ===");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTryLock_Success() {
|
||||
System.out.println("开始执行: testTryLock_Success");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "test_lock";
|
||||
long expireTimeSec = 30L;
|
||||
String expectedKey = "distributed_lock:" + lockKey;
|
||||
System.out.println("测试参数 - 锁键: " + lockKey + ", 过期时间: " + expireTimeSec + "秒");
|
||||
|
||||
// 当调用时
|
||||
when(redisService.set(anyString(), anyString(), anyLong())).thenReturn(true);
|
||||
boolean result = lockHelper.tryLock(lockKey, expireTimeSec);
|
||||
System.out.println("获取锁结果: " + (result ? "成功" : "失败"));
|
||||
|
||||
// 那么验证
|
||||
assertTrue(result, "锁应该成功获取");
|
||||
verify(redisService).set(eq(expectedKey), anyString(), eq(expireTimeSec));
|
||||
System.out.println("验证通过: Redis set 方法被正确调用");
|
||||
System.out.println("测试完成: testTryLock_Success\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTryLock_Failure() {
|
||||
System.out.println("开始执行: testTryLock_Failure");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "test_lock";
|
||||
long expireTimeSec = 30L;
|
||||
System.out.println("测试参数 - 锁键: " + lockKey + ", 过期时间: " + expireTimeSec + "秒");
|
||||
|
||||
// 当调用时
|
||||
when(redisService.set(anyString(), anyString(), anyLong())).thenThrow(new RuntimeException("Redis错误"));
|
||||
System.out.println("模拟Redis异常: Redis错误");
|
||||
|
||||
// 那么验证
|
||||
assertThrows(RuntimeException.class, () -> {
|
||||
lockHelper.tryLock(lockKey, expireTimeSec);
|
||||
}, "应该抛出RuntimeException");
|
||||
System.out.println("验证通过: 正确捕获了RuntimeException");
|
||||
System.out.println("测试完成: testTryLock_Failure\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReleaseLock_Success() {
|
||||
System.out.println("开始执行: testReleaseLock_Success");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "test_lock";
|
||||
String expectedKey = "distributed_lock:" + lockKey;
|
||||
String lockValue = "uuid:1";
|
||||
System.out.println("测试参数 - 锁键: " + lockKey + ", 锁值: " + lockValue);
|
||||
|
||||
// 设置线程本地变量
|
||||
ReflectionTestUtils.setField(lockHelper, "LOCK_VALUE_HOLDER",
|
||||
new ThreadLocal<String>() {
|
||||
@Override
|
||||
protected String initialValue() {
|
||||
return lockValue;
|
||||
}
|
||||
});
|
||||
|
||||
when(redisService.get(expectedKey)).thenReturn(lockValue);
|
||||
System.out.println("模拟Redis get返回值: " + lockValue);
|
||||
|
||||
// 当调用时
|
||||
lockHelper.releaseLock(lockKey);
|
||||
System.out.println("执行锁释放操作");
|
||||
|
||||
// 那么验证
|
||||
verify(redisService).del(expectedKey);
|
||||
System.out.println("验证通过: Redis del 方法被正确调用");
|
||||
System.out.println("测试完成: testReleaseLock_Success\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReleaseLock_WrongOwner() {
|
||||
System.out.println("开始执行: testReleaseLock_WrongOwner");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "test_lock";
|
||||
String expectedKey = "distributed_lock:" + lockKey;
|
||||
String currentValue = "uuid:1";
|
||||
String threadValue = "uuid:2"; // 不同的值
|
||||
System.out.println("测试参数 - 当前锁值: " + currentValue + ", 线程锁值: " + threadValue);
|
||||
|
||||
// 设置线程本地变量
|
||||
ReflectionTestUtils.setField(lockHelper, "LOCK_VALUE_HOLDER",
|
||||
new ThreadLocal<String>() {
|
||||
@Override
|
||||
protected String initialValue() {
|
||||
return threadValue;
|
||||
}
|
||||
});
|
||||
|
||||
when(redisService.get(expectedKey)).thenReturn(currentValue);
|
||||
System.out.println("模拟Redis中当前锁值: " + currentValue);
|
||||
|
||||
// 当调用时
|
||||
lockHelper.releaseLock(lockKey);
|
||||
System.out.println("执行锁释放操作");
|
||||
|
||||
// 那么验证
|
||||
verify(redisService, never()).del(anyString());
|
||||
System.out.println("验证通过: Redis del 方法未被调用(防止误删)");
|
||||
System.out.println("测试完成: testReleaseLock_WrongOwner\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConcurrentAccess_SingleLockAcquirer() throws InterruptedException {
|
||||
System.out.println("开始执行: testConcurrentAccess_SingleLockAcquirer");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "concurrent_test_lock";
|
||||
int threadCount = 10;
|
||||
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
|
||||
CountDownLatch latch = new CountDownLatch(threadCount);
|
||||
AtomicInteger successCounter = new AtomicInteger(0);
|
||||
System.out.println("测试参数 - 并发线程数: " + threadCount + ", 锁键: " + lockKey);
|
||||
|
||||
// 模拟Redis并发访问行为
|
||||
when(redisService.set(anyString(), anyString(), anyLong()))
|
||||
.thenAnswer(invocation -> {
|
||||
// 只有第一次调用成功,其余都失败
|
||||
boolean result = successCounter.get() == 0;
|
||||
if (result) {
|
||||
System.out.println("线程[" + Thread.currentThread().getName() + "] 成功获取锁");
|
||||
}
|
||||
return result;
|
||||
});
|
||||
System.out.println("模拟Redis行为: 只允许一个线程获取锁");
|
||||
|
||||
// 当执行时
|
||||
for (int i = 0; i < threadCount; i++) {
|
||||
final int threadId = i;
|
||||
executor.submit(() -> {
|
||||
try {
|
||||
System.out.println("启动线程[" + threadId + "]");
|
||||
if (lockHelper.tryLock(lockKey, 30)) {
|
||||
int count = successCounter.incrementAndGet();
|
||||
System.out.println("线程[" + threadId + "] 获取锁成功,当前成功计数: " + count);
|
||||
lockHelper.releaseLock(lockKey);
|
||||
System.out.println("线程[" + threadId + "] 释放锁");
|
||||
} else {
|
||||
System.out.println("线程[" + threadId + "] 获取锁失败");
|
||||
}
|
||||
} finally {
|
||||
latch.countDown();
|
||||
System.out.println("线程[" + threadId + "] 执行完毕,剩余线程数: " + (latch.getCount()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
boolean completed = latch.await(5, TimeUnit.SECONDS);
|
||||
executor.shutdown();
|
||||
System.out.println("所有线程执行完成: " + (completed ? "正常结束" : "超时结束"));
|
||||
|
||||
// 那么验证
|
||||
int successCount = successCounter.get();
|
||||
assertEquals(1, successCount, "应该只有一个线程获得锁");
|
||||
System.out.println("验证通过: 实际成功获取锁的线程数为 " + successCount);
|
||||
System.out.println("测试完成: testConcurrentAccess_SingleLockAcquirer\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutoRenewalFunctionality() throws InterruptedException {
|
||||
System.out.println("开始执行: testAutoRenewalFunctionality");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "auto_renew_test_lock";
|
||||
long expireTimeSec = 5L;
|
||||
long maxHoldTimeSec = 10L;
|
||||
System.out.println("测试参数 - 锁键: " + lockKey + ", 过期时间: " + expireTimeSec + "秒, 最大持有时间: " + maxHoldTimeSec + "秒");
|
||||
|
||||
when(redisService.set(anyString(), anyString(), anyLong())).thenReturn(true);
|
||||
when(redisService.get(anyString())).thenReturn("mock-value");
|
||||
System.out.println("模拟Redis set/get操作成功");
|
||||
|
||||
// 当调用时
|
||||
DistributedLockHelper.LockHolder lockHolder =
|
||||
lockHelper.tryLockWithAutoRenew(lockKey, expireTimeSec, maxHoldTimeSec);
|
||||
System.out.println("获取带自动续期功能的锁");
|
||||
|
||||
assertNotNull(lockHolder, "锁持有者不应为空");
|
||||
System.out.println("锁持有者创建成功");
|
||||
|
||||
// 等待可能的续期操作
|
||||
System.out.println("等待3秒观察自动续期行为...");
|
||||
Thread.sleep(3000);
|
||||
|
||||
// 那么验证
|
||||
verify(redisService, atLeastOnce()).expire(anyString(), anyLong());
|
||||
System.out.println("验证通过: Redis expire 方法至少被调用一次");
|
||||
|
||||
// 清理
|
||||
lockHolder.close();
|
||||
System.out.println("关闭锁持有者,清理资源");
|
||||
System.out.println("测试完成: testAutoRenewalFunctionality\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockHolderAutoClose() {
|
||||
System.out.println("开始执行: testLockHolderAutoClose");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "auto_close_test_lock";
|
||||
System.out.println("测试参数 - 锁键: " + lockKey);
|
||||
|
||||
when(redisService.set(anyString(), anyString(), anyLong())).thenReturn(true);
|
||||
when(redisService.get(anyString())).thenReturn("mock-value");
|
||||
System.out.println("模拟Redis操作成功");
|
||||
|
||||
// 当调用时
|
||||
System.out.println("使用try-with-resources语法获取锁");
|
||||
try (DistributedLockHelper.LockHolder holder =
|
||||
lockHelper.tryLockWithAutoRenew(lockKey, 30, 300)) {
|
||||
assertNotNull(holder, "锁持有者不应为空");
|
||||
System.out.println("锁持有者创建成功");
|
||||
}
|
||||
System.out.println("try-with-resources块结束,自动调用close方法");
|
||||
|
||||
// 那么验证
|
||||
verify(redisService).del(anyString());
|
||||
System.out.println("验证通过: Redis del 方法被正确调用");
|
||||
System.out.println("测试完成: testLockHolderAutoClose\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleLocksIndependence() {
|
||||
System.out.println("开始执行: testMultipleLocksIndependence");
|
||||
|
||||
// 给定条件
|
||||
String lockKey1 = "lock_1";
|
||||
String lockKey2 = "lock_2";
|
||||
System.out.println("测试参数 - 锁键1: " + lockKey1 + ", 锁键2: " + lockKey2);
|
||||
|
||||
when(redisService.set(anyString(), anyString(), anyLong())).thenReturn(true);
|
||||
System.out.println("模拟Redis set操作成功");
|
||||
|
||||
// 当调用时
|
||||
boolean lock1Acquired = lockHelper.tryLock(lockKey1, 30);
|
||||
System.out.println("获取第一个锁: " + (lock1Acquired ? "成功" : "失败"));
|
||||
|
||||
boolean lock2Acquired = lockHelper.tryLock(lockKey2, 30);
|
||||
System.out.println("获取第二个锁: " + (lock2Acquired ? "成功" : "失败"));
|
||||
|
||||
// 那么验证
|
||||
assertTrue(lock1Acquired, "第一个锁应该成功获取");
|
||||
assertTrue(lock2Acquired, "第二个锁应该成功获取");
|
||||
System.out.println("两个锁都成功获取");
|
||||
|
||||
// 验证它们是不同的键
|
||||
verify(redisService).set(eq("distributed_lock:" + lockKey1), anyString(), eq(30L));
|
||||
verify(redisService).set(eq("distributed_lock:" + lockKey2), anyString(), eq(30L));
|
||||
System.out.println("验证通过: 两个独立的锁键都被正确设置");
|
||||
System.out.println("测试完成: testMultipleLocksIndependence\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testThreadIsolation() throws InterruptedException {
|
||||
System.out.println("开始执行: testThreadIsolation");
|
||||
|
||||
// 给定条件
|
||||
String lockKey = "thread_isolation_lock";
|
||||
ExecutorService executor = Executors.newFixedThreadPool(2);
|
||||
CountDownLatch latch = new CountDownLatch(2);
|
||||
AtomicInteger[] results = new AtomicInteger[]{new AtomicInteger(0), new AtomicInteger(0)};
|
||||
System.out.println("测试参数 - 锁键: " + lockKey + ", 线程数: 2");
|
||||
|
||||
when(redisService.set(anyString(), anyString(), anyLong())).thenReturn(true);
|
||||
System.out.println("模拟Redis set操作成功");
|
||||
|
||||
// 当执行时
|
||||
System.out.println("启动两个线程竞争同一个锁");
|
||||
for (int i = 0; i < 2; i++) {
|
||||
final int threadIndex = i;
|
||||
executor.submit(() -> {
|
||||
try {
|
||||
System.out.println("线程[" + threadIndex + "] 尝试获取锁");
|
||||
if (lockHelper.tryLock(lockKey, 30)) {
|
||||
int count = results[threadIndex].incrementAndGet();
|
||||
System.out.println("线程[" + threadIndex + "] 获取锁成功,计数: " + count);
|
||||
// 持有锁一段时间
|
||||
Thread.sleep(100);
|
||||
System.out.println("线程[" + threadIndex + "] 持有锁100ms后释放");
|
||||
lockHelper.releaseLock(lockKey);
|
||||
System.out.println("线程[" + threadIndex + "] 释放锁");
|
||||
} else {
|
||||
System.out.println("线程[" + threadIndex + "] 获取锁失败");
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("线程[" + threadIndex + "] 被中断");
|
||||
Thread.currentThread().interrupt();
|
||||
} finally {
|
||||
latch.countDown();
|
||||
System.out.println("线程[" + threadIndex + "] 执行完毕");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
boolean completed = latch.await(5, TimeUnit.SECONDS);
|
||||
executor.shutdown();
|
||||
System.out.println("所有线程执行完成: " + (completed ? "正常结束" : "超时结束"));
|
||||
|
||||
// 那么验证 - 两个线程都应该能够在不同时间获得锁
|
||||
int result0 = results[0].get();
|
||||
int result1 = results[1].get();
|
||||
assertEquals(1, result0, "线程0应该获得一次锁");
|
||||
assertEquals(1, result1, "线程1应该获得一次锁");
|
||||
System.out.println("验证通过: 线程0获得锁次数=" + result0 + ", 线程1获得锁次数=" + result1);
|
||||
System.out.println("测试完成: testThreadIsolation\n");
|
||||
}
|
||||
}
|
||||
@ -93,6 +93,8 @@ secure:
|
||||
- "/mobile/shop/lakala/sign/ec/**"
|
||||
- "/mobile/**/**/test/case"
|
||||
- "/**/**/testcase"
|
||||
- "/mobile/sns/Story/listComment"
|
||||
- "/mobile/sns/Story/getStory"
|
||||
universal:
|
||||
urls:
|
||||
- "/admin/account/account-user-base/info"
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
lp.id,
|
||||
lp.barcode,
|
||||
lp.name,
|
||||
lp.product_short_name,
|
||||
lp.sname,
|
||||
lp.category,
|
||||
lp.thumb,
|
||||
(
|
||||
@ -37,7 +37,7 @@
|
||||
lp.id,
|
||||
lp.barcode,
|
||||
lp.name,
|
||||
lp.product_short_name,
|
||||
lp.sname,
|
||||
lp.category,
|
||||
lp.thumb,
|
||||
(
|
||||
@ -60,7 +60,7 @@
|
||||
lp.id,
|
||||
lp.barcode,
|
||||
lp.name,
|
||||
lp.product_short_name,
|
||||
lp.sname,
|
||||
lp.category,
|
||||
lp.thumb,
|
||||
(
|
||||
|
||||
@ -33,11 +33,11 @@ public interface ShopActivityCutpriceService extends IBaseService<ShopActivityCu
|
||||
/**
|
||||
* 砍价活动是否可以下单
|
||||
*
|
||||
* @param ac_id 活动 自增Id
|
||||
* @param activity_id 活动 自增Id
|
||||
* @param order_user_id 下单用户
|
||||
* @return
|
||||
*/
|
||||
Pair<Boolean, String> canDoOrderCutPriceActivity(Integer ac_id, Integer order_user_id);
|
||||
Pair<Boolean, String> canDoOrderCutPriceActivity(Integer activity_id, Integer order_user_id);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -25,6 +25,7 @@ import com.suisung.mall.common.modules.activity.ShopActivityGroupbooking;
|
||||
import com.suisung.mall.common.modules.activity.ShopActivityGroupbookingHistory;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreActivityBase;
|
||||
import com.suisung.mall.common.utils.CheckUtil;
|
||||
import com.suisung.mall.common.utils.DateTimeUtils;
|
||||
import com.suisung.mall.common.utils.I18nUtil;
|
||||
import com.suisung.mall.core.web.service.RedisService;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
@ -34,6 +35,7 @@ import com.suisung.mall.shop.activity.service.ShopActivityCutpriceService;
|
||||
import com.suisung.mall.shop.activity.service.ShopActivityGroupbookingHistoryService;
|
||||
import com.suisung.mall.shop.activity.service.ShopActivityGroupbookingService;
|
||||
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
||||
import com.suisung.mall.shop.order.service.ShopOrderInfoService;
|
||||
import com.suisung.mall.shop.store.service.ShopStoreActivityBaseService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -74,6 +76,10 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
@Autowired
|
||||
private ShopStoreActivityBaseService shopStoreActivityBaseService;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ShopOrderInfoService shopOrderInfoService;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private AccountService accountService;
|
||||
@ -275,10 +281,10 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
|
||||
// 参数校验
|
||||
if (activity_id == null || activity_id <= 0) {
|
||||
throw new ApiException(I18nUtil._("活动ID无效!"));
|
||||
throw new ApiException(I18nUtil._("活动编号无效!"));
|
||||
}
|
||||
if (user_id == null || user_id <= 0) {
|
||||
throw new ApiException(I18nUtil._("用户ID无效!"));
|
||||
throw new ApiException(I18nUtil._("用户编号无效!"));
|
||||
}
|
||||
|
||||
// 获取活动基础信息
|
||||
@ -300,14 +306,19 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
queryWrapper.eq("activity_id", activity_id).eq("user_id", user_id);
|
||||
ShopActivityCutprice cutprice_row = findOne(queryWrapper);
|
||||
|
||||
// 需要检查活动有效期和活动商品库存是否足够
|
||||
Pair<Boolean, String> checkStockResult = checkCutPriceExpiredAndStock(activityBase);
|
||||
|
||||
// 立即参与活动?
|
||||
boolean is_join_activity = false;
|
||||
|
||||
// 如果用户未参与该砍价活动,则创建新的砍价记录
|
||||
if (cutprice_row == null) {
|
||||
// 需要检查活动有效期和活动商品库存是否足够
|
||||
Pair<Boolean, String> check_result = checkCutPriceExpiredAndStock(activityBase);
|
||||
if (!check_result.getFirst()) {
|
||||
throw new ApiException(check_result.getSecond());
|
||||
|
||||
if (checkStockResult != null && !checkStockResult.getFirst()) {
|
||||
// 库存不够,立即更改活动状态为已结束
|
||||
shopStoreActivityBaseService.updateActivityState(activity_id, StateCode.ACTIVITY_STATE_FINISHED);
|
||||
throw new ApiException(checkStockResult.getSecond());
|
||||
}
|
||||
|
||||
cutprice_row = new ShopActivityCutprice();
|
||||
@ -330,13 +341,11 @@ 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 * 3600000L);
|
||||
// log.info("砍价失效时间戳:{}", cutprice_row.getExpired_at());
|
||||
|
||||
cutprice_row.setAc_datetime(now);
|
||||
cutprice_row.setOrder_id("");
|
||||
@ -344,7 +353,7 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
|
||||
// 保存砍价记录
|
||||
if (!saveOrUpdate(cutprice_row)) {
|
||||
throw new ApiException(I18nUtil._("创建砍价失败!"));
|
||||
throw new ApiException(I18nUtil._("参加砍价活动失败!"));
|
||||
}
|
||||
|
||||
is_join_activity = true;
|
||||
@ -369,19 +378,26 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
// 设置活动规则信息
|
||||
activity_row.put("activity_rule", JSONUtil.parseObj(activity_row.get("activity_rule")));
|
||||
|
||||
// 判断是否可以立即购买
|
||||
boolean canBuyNow = cutprice_row != null
|
||||
&& CheckUtil.isNotEmpty(cutprice_row.getAc_sale_price())
|
||||
&& CheckUtil.isNotEmpty(cutprice_row.getAc_mix_limit_price())
|
||||
&& NumberUtil.isLessOrEqual(cutprice_row.getAc_sale_price(), cutprice_row.getAc_mix_limit_price());
|
||||
if (checkStockResult != null && !checkStockResult.getFirst()) {
|
||||
// 库存不够,立即更改活动状态为已结束
|
||||
shopStoreActivityBaseService.updateActivityState(activity_id, StateCode.ACTIVITY_STATE_FINISHED);
|
||||
activity_row.put("can_buy_now", CommonConstant.Disable2);
|
||||
activity_row.put("cannot_buy_now_reason", "抱歉,商品已抢完,活动结束。");
|
||||
} else {
|
||||
// 判断是否可以立即购买
|
||||
boolean canBuyNow = cutprice_row != null
|
||||
&& CheckUtil.isNotEmpty(cutprice_row.getAc_sale_price())
|
||||
&& CheckUtil.isNotEmpty(cutprice_row.getAc_mix_limit_price())
|
||||
&& NumberUtil.isLessOrEqual(cutprice_row.getAc_sale_price(), cutprice_row.getAc_mix_limit_price());
|
||||
|
||||
BigDecimal subtractPrice = NumberUtil.sub(cutprice_row.getAc_sale_price(), cutprice_row.getAc_mix_limit_price());
|
||||
BigDecimal subtractPrice = NumberUtil.sub(cutprice_row.getAc_sale_price(), cutprice_row.getAc_mix_limit_price());
|
||||
|
||||
// 设置购买状态和提示信息
|
||||
activity_row.put("can_buy_now", canBuyNow ? CommonConstant.Enable : CommonConstant.Disable2);
|
||||
activity_row.put("cannot_buy_now_reason",
|
||||
canBuyNow ? "恭喜您,商品可以立即出手了。" :
|
||||
String.format("还剩%.2f元到达商品底价,请继续加油!", subtractPrice));
|
||||
// 设置购买状态和提示信息
|
||||
activity_row.put("can_buy_now", canBuyNow ? CommonConstant.Enable : CommonConstant.Disable2);
|
||||
activity_row.put("cannot_buy_now_reason",
|
||||
canBuyNow ? "恭喜您,商品可以立即出手了。" :
|
||||
String.format("还剩%.2f元到达商品底价,继续加油!", subtractPrice));
|
||||
}
|
||||
|
||||
return activity_row;
|
||||
}
|
||||
@ -390,7 +406,7 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
/**
|
||||
* 自己或朋友砍价
|
||||
*
|
||||
* @param ac_id 活动 Id
|
||||
* @param ac_id 活动Id
|
||||
* @param user_id 砍价用户
|
||||
* @return CommonResult 砍价结果
|
||||
*/
|
||||
@ -398,142 +414,177 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
@Transactional
|
||||
public CommonResult doCutPrice(Integer ac_id, Integer user_id) {
|
||||
// 参数校验
|
||||
if (ac_id == null || ac_id <= 0) {
|
||||
return CommonResult.failed(I18nUtil._("活动ID无效!"));
|
||||
}
|
||||
if (user_id == null || user_id <= 0) {
|
||||
return CommonResult.failed(I18nUtil._("用户ID无效!"));
|
||||
if (ac_id == null || ac_id <= 0 || user_id == null || user_id <= 0) {
|
||||
return CommonResult.failed(I18nUtil._("活动或用户编号无效!"));
|
||||
}
|
||||
|
||||
// 获取砍价记录
|
||||
ShopActivityCutprice shopActivityCutprice = get(ac_id);
|
||||
if (shopActivityCutprice == null) {
|
||||
return CommonResult.failed(I18nUtil._("抱歉,砍价记录已失效!"));
|
||||
ShopActivityCutprice cutprice = get(ac_id);
|
||||
if (cutprice == null) {
|
||||
return CommonResult.failed(I18nUtil._("未找到砍价记录!"));
|
||||
}
|
||||
|
||||
// 检查活动状态
|
||||
if (shopStoreActivityBaseService == null) {
|
||||
return CommonResult.failed(I18nUtil._("系统繁忙,请稍后再试!"));
|
||||
}
|
||||
|
||||
ShopStoreActivityBase activityBase = shopStoreActivityBaseService.get(cutprice.getActivity_id());
|
||||
if (activityBase == null) {
|
||||
updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Canceled);
|
||||
return CommonResult.failed(I18nUtil._("抱歉,砍价活动已失效啦!"));
|
||||
}
|
||||
|
||||
Integer activity_id = shopActivityCutprice.getActivity_id();
|
||||
// 检查活动状态是否正常
|
||||
ShopStoreActivityBase shopStoreActivityBase = shopStoreActivityBaseService.get(shopActivityCutprice.getActivity_id());
|
||||
if (shopStoreActivityBase == null) {
|
||||
// 活动不存在,更新砍价订单状态为已取消
|
||||
updateCutPriceState(shopActivityCutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Canceled);
|
||||
return CommonResult.failed(I18nUtil._("抱歉,砍价活动已失效!"));
|
||||
}
|
||||
|
||||
// 活动状态不是正常状态
|
||||
if (!ObjectUtil.equal(shopStoreActivityBase.getActivity_state(), StateCode.ACTIVITY_STATE_NORMAL)) {
|
||||
// 如果活动已结束或已关闭,更新砍价订单状态为已取消
|
||||
if (ObjectUtil.equal(shopStoreActivityBase.getActivity_state(), StateCode.ACTIVITY_STATE_FINISHED)
|
||||
|| ObjectUtil.equal(shopStoreActivityBase.getActivity_state(), StateCode.ACTIVITY_STATE_CLOSED)) {
|
||||
updateCutPriceState(shopActivityCutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Canceled);
|
||||
if (!ObjectUtil.equal(activityBase.getActivity_state(), StateCode.ACTIVITY_STATE_NORMAL)) {
|
||||
if (ObjectUtil.equal(activityBase.getActivity_state(), StateCode.ACTIVITY_STATE_FINISHED)
|
||||
|| ObjectUtil.equal(activityBase.getActivity_state(), StateCode.ACTIVITY_STATE_CLOSED)) {
|
||||
updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Canceled);
|
||||
}
|
||||
return CommonResult.failed(I18nUtil._("抱歉,砍价活动已失效!"));
|
||||
return CommonResult.failed(I18nUtil._("抱歉,砍价活动已结束啦!"));
|
||||
}
|
||||
|
||||
Date now = new Date();
|
||||
Long expired_at = shopActivityCutprice.getExpired_at();
|
||||
Long expiredAt = cutprice.getExpired_at();
|
||||
|
||||
// 检查砍价订单是否过期
|
||||
if (CheckUtil.isNotEmpty(expired_at) && expired_at < now.getTime()) {
|
||||
// 砍价订单已过期,更新状态为已过期
|
||||
updateCutPriceState(shopActivityCutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Expired);
|
||||
return CommonResult.failed(I18nUtil._("砍价已过期,下次早点来!"));
|
||||
// 检查砍价记录是否过期
|
||||
if (CheckUtil.isNotEmpty(expiredAt) && expiredAt < now.getTime()) {
|
||||
updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Expired);
|
||||
return CommonResult.failed(I18nUtil._("抱歉,砍价已过期啦!"));
|
||||
}
|
||||
|
||||
// 检查活动是否已结束(活动时间已过)
|
||||
if (!shopStoreActivityBaseService.isActivityTimeValid(shopStoreActivityBase, now)) {
|
||||
// 活动已结束,更新砍价订单状态为已过期
|
||||
updateCutPriceState(shopActivityCutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Expired);
|
||||
return CommonResult.failed(I18nUtil._("砍价已过期,下次早点来!"));
|
||||
// 检查活动时间是否有效
|
||||
try {
|
||||
if (!shopStoreActivityBaseService.isActivityTimeValid(activityBase, now)) {
|
||||
updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_Expired);
|
||||
return CommonResult.failed(I18nUtil._("活动已结束!"));
|
||||
}
|
||||
|
||||
// 需要检查活动有效期和活动商品库存是否足够
|
||||
Pair<Boolean, String> check_result = checkCutPriceExpiredAndStock(activityBase);
|
||||
if (!check_result.getFirst()) {
|
||||
// 库存不够,立即更改活动状态为已结束
|
||||
shopStoreActivityBaseService.updateActivityState(cutprice.getActivity_id(), StateCode.ACTIVITY_STATE_FINISHED);
|
||||
throw new ApiException(check_result.getSecond());
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
return CommonResult.failed(I18nUtil._("系统繁忙,请稍后再试!"));
|
||||
}
|
||||
|
||||
// 检查是否是帮别人砍价且次数已用完
|
||||
if (!shopActivityCutprice.getUser_id().equals(user_id)) {
|
||||
DateTime today = DateUtil.beginOfDay(new Date());
|
||||
Integer num = accountBaseConfigService.getConfig("user_cutprice_num", 0);
|
||||
Integer cut_num = Convert.toInt(redisService.hGet("cutprice-" + today, user_id.toString()), 0);
|
||||
// 检查帮砍次数限制
|
||||
if (!cutprice.getUser_id().equals(user_id)) {
|
||||
try {
|
||||
if (accountBaseConfigService != null && redisService != null) {
|
||||
DateTime today = DateUtil.beginOfDay(new Date());
|
||||
Integer maxCuts = accountBaseConfigService.getConfig("user_cutprice_num", 0);
|
||||
Integer usedCuts = Convert.toInt(redisService.hGet("cutprice-" + today, user_id.toString()), 0);
|
||||
|
||||
if (num > 0 && cut_num >= num) {
|
||||
return CommonResult.failed(I18nUtil._("今日帮砍次数已用完!"));
|
||||
if (maxCuts > 0 && usedCuts >= maxCuts) {
|
||||
return CommonResult.failed(I18nUtil._("今日帮砍次数已达上限!"));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Redis检查失败时继续执行砍价操作
|
||||
}
|
||||
}
|
||||
|
||||
BigDecimal ac_sale_price = shopActivityCutprice.getAc_sale_price();
|
||||
BigDecimal ac_mix_limit_price = shopActivityCutprice.getAc_mix_limit_price();
|
||||
BigDecimal salePrice = cutprice.getAc_sale_price();
|
||||
BigDecimal minPrice = cutprice.getAc_mix_limit_price();
|
||||
|
||||
// 检查价格数据是否完整
|
||||
if (ac_sale_price == null || ac_mix_limit_price == null) {
|
||||
return CommonResult.failed(I18nUtil._("价格数据异常!"));
|
||||
// 检查价格数据完整性
|
||||
if (salePrice == null || minPrice == null) {
|
||||
return CommonResult.failed(I18nUtil._("商品价格数据异常!"));
|
||||
}
|
||||
|
||||
// 检查是否已达到最低价
|
||||
if (NumberUtil.isLessOrEqual(ac_sale_price, ac_mix_limit_price)) {
|
||||
// 根据上次的状态,立即更改状态:6-砍价助力已完成待下单;
|
||||
updateCutPriceState(shopActivityCutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_CutFinished);
|
||||
|
||||
return CommonResult.failed(I18nUtil._("已达到最低价!"));
|
||||
if (NumberUtil.isLessOrEqual(salePrice, minPrice)) {
|
||||
updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_CutFinished);
|
||||
return CommonResult.failed(I18nUtil._("已砍到最低价啦!"));
|
||||
}
|
||||
|
||||
// 检查是否已经帮过好友砍了价
|
||||
QueryWrapper<ShopActivityCutpriceHistory> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("user_id", user_id).eq("ac_id", ac_id);
|
||||
long ach_num = shopActivityCutpriceHistoryService.count(queryWrapper);
|
||||
if (ach_num > 0) {
|
||||
return CommonResult.failed(I18nUtil._("已经帮好友砍过价!"));
|
||||
// 检查是否已经帮过好友砍价
|
||||
try {
|
||||
if (shopActivityCutpriceHistoryService == null) {
|
||||
return CommonResult.failed(I18nUtil._("系统繁忙,请稍后再试!"));
|
||||
}
|
||||
|
||||
QueryWrapper<ShopActivityCutpriceHistory> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("user_id", user_id).eq("ac_id", ac_id);
|
||||
if (shopActivityCutpriceHistoryService.count(queryWrapper) > 0) {
|
||||
return CommonResult.failed(I18nUtil._("您已帮好友砍过价了!"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return CommonResult.failed(I18nUtil._("系统繁忙,请稍后再试!"));
|
||||
}
|
||||
|
||||
// 计算砍价金额
|
||||
BigDecimal cut_price = shopStoreActivityBaseService.getCutDownPrice(shopStoreActivityBase, shopActivityCutprice);
|
||||
if (cut_price == null || cut_price.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return CommonResult.failed(I18nUtil._("砍价失败!"));
|
||||
BigDecimal cutPrice;
|
||||
try {
|
||||
cutPrice = shopStoreActivityBaseService.getCutDownPrice(activityBase, cutprice);
|
||||
if (cutPrice == null || cutPrice.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return CommonResult.failed(I18nUtil._("砍价失败,请重试!"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return CommonResult.failed(I18nUtil._("砍价失败,请重试!"));
|
||||
}
|
||||
|
||||
// 获取商品ID
|
||||
String str_activity_rule = shopStoreActivityBase.getActivity_rule();
|
||||
if (StrUtil.isBlank(str_activity_rule)) {
|
||||
String ruleStr = activityBase.getActivity_rule();
|
||||
if (StrUtil.isBlank(ruleStr)) {
|
||||
return CommonResult.failed(I18nUtil._("活动规则数据异常!"));
|
||||
}
|
||||
|
||||
JSONObject activity_rule = JSONUtil.parseObj(str_activity_rule);
|
||||
Long item_id = activity_rule.get("item_id", Long.class);
|
||||
if (item_id == null) {
|
||||
return CommonResult.failed(I18nUtil._("未找到商品信息!"));
|
||||
try {
|
||||
JSONObject activityRule = JSONUtil.parseObj(ruleStr);
|
||||
Long itemId = activityRule.get("item_id", Long.class);
|
||||
if (itemId == null) {
|
||||
return CommonResult.failed(I18nUtil._("未找到对应商品!"));
|
||||
}
|
||||
|
||||
// 创建砍价历史记录
|
||||
ShopActivityCutpriceHistory history = new ShopActivityCutpriceHistory();
|
||||
history.setActivity_id(cutprice.getActivity_id());
|
||||
history.setUser_id(user_id);
|
||||
history.setAch_price(cutPrice);
|
||||
history.setItem_id(itemId);
|
||||
history.setAch_datetime(new Date());
|
||||
history.setAc_id(ac_id);
|
||||
|
||||
// 保存历史记录
|
||||
if (!shopActivityCutpriceHistoryService.saveOrUpdate(history)) {
|
||||
throw new ApiException(I18nUtil._("保存砍价记录失败!"));
|
||||
}
|
||||
|
||||
// 更新砍价信息
|
||||
cutprice.setAc_sale_price(NumberUtil.sub(salePrice, cutPrice));
|
||||
cutprice.setAc_num(cutprice.getAc_num() + 1);
|
||||
if (!edit(cutprice)) {
|
||||
throw new ApiException(I18nUtil._("更新砍价信息失败!"));
|
||||
}
|
||||
|
||||
// 更新帮砍次数
|
||||
if (!cutprice.getUser_id().equals(user_id) && redisService != null) {
|
||||
try {
|
||||
DateTime today = DateUtil.beginOfDay(new Date());
|
||||
Integer cutNum = Convert.toInt(redisService.hGet("cutprice-" + today, user_id.toString()), 0);
|
||||
redisService.hSet("cutprice-" + today, user_id.toString(), cutNum + 1, 24 * 60 * 60 * 1000);
|
||||
} catch (Exception e) {
|
||||
// Redis更新失败不影响主流程
|
||||
}
|
||||
}
|
||||
|
||||
// 如果已达到最低价,更新状态
|
||||
if (NumberUtil.isLessOrEqual(cutprice.getAc_sale_price(), minPrice)) {
|
||||
updateCutPriceState(cutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_CutFinished);
|
||||
}
|
||||
|
||||
return CommonResult.success(history);
|
||||
} catch (ApiException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(I18nUtil._("砍价操作失败!"));
|
||||
}
|
||||
|
||||
// 创建砍价历史记录
|
||||
ShopActivityCutpriceHistory ach_data = new ShopActivityCutpriceHistory();
|
||||
ach_data.setActivity_id(activity_id);
|
||||
ach_data.setUser_id(user_id);
|
||||
ach_data.setAch_price(cut_price);
|
||||
ach_data.setItem_id(item_id);
|
||||
ach_data.setAch_datetime(new Date());
|
||||
ach_data.setAc_id(ac_id);
|
||||
|
||||
// 保存砍价历史记录
|
||||
if (!shopActivityCutpriceHistoryService.saveOrUpdate(ach_data)) {
|
||||
throw new ApiException(I18nUtil._("保存砍价历史失败!"));
|
||||
}
|
||||
|
||||
// 更新砍价信息
|
||||
shopActivityCutprice.setAc_sale_price(NumberUtil.sub(ac_sale_price, cut_price));
|
||||
shopActivityCutprice.setAc_num(shopActivityCutprice.getAc_num() + 1);
|
||||
if (!edit(shopActivityCutprice)) {
|
||||
throw new ApiException(I18nUtil._("更新砍价信息失败!"));
|
||||
}
|
||||
|
||||
// 更新帮砍次数(如果不是自己砍自己的话)
|
||||
if (!shopActivityCutprice.getUser_id().equals(user_id)) {
|
||||
DateTime today = DateUtil.beginOfDay(new Date());
|
||||
Integer cut_num = Convert.toInt(redisService.hGet("cutprice-" + today, user_id.toString()), 0);
|
||||
redisService.hSet("cutprice-" + today, user_id.toString(), cut_num + 1, 24 * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
// 根据最新砍价信息(最后一次砍价成功之后,达到最低砍价价格),更新砍价订单状态
|
||||
if (NumberUtil.isGreaterOrEqual(shopActivityCutprice.getAc_sale_price(), ac_mix_limit_price)) {
|
||||
updateCutPriceState(shopActivityCutprice.getAc_id(), null, CommonConstant.CutPrice_Order_State_CutFinished);
|
||||
}
|
||||
|
||||
return CommonResult.success(ach_data);
|
||||
}
|
||||
|
||||
|
||||
@ -566,12 +617,12 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
params.eq("activity_id", activity_id);
|
||||
ShopStoreActivityBase storeActivityBase = shopStoreActivityBaseService.getOne(params);
|
||||
if (storeActivityBase == null) {
|
||||
return Pair.of(false, I18nUtil._("抱歉,系统未找到活动记录。"));
|
||||
return Pair.of(false, I18nUtil._("抱歉,未找到活动记录。"));
|
||||
}
|
||||
|
||||
// 2. 检查活动是否在有效期内
|
||||
if (!shopStoreActivityBaseService.isActivityTimeValid(storeActivityBase.getActivity_starttime(), storeActivityBase.getActivity_endtime(), new Date())) {
|
||||
return Pair.of(false, I18nUtil._("该活动已过期,请检查。"));
|
||||
if (!DateTimeUtils.isActivityTimeValid(storeActivityBase.getActivity_starttime(), storeActivityBase.getActivity_endtime(), new Date())) {
|
||||
return Pair.of(false, I18nUtil._("抱歉,该活动已过期。"));
|
||||
}
|
||||
|
||||
// 3. 检查用户是否有发起的砍价记录
|
||||
@ -581,7 +632,7 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
queryWrapper.orderByDesc("ac_id");
|
||||
ShopActivityCutprice shopActivityCutprice = getOne(queryWrapper);
|
||||
if (shopActivityCutprice == null) {
|
||||
return Pair.of(false, I18nUtil._("系统未找到您发起的砍价记录。"));
|
||||
return Pair.of(false, I18nUtil._("未找到您发起的砍价记录。"));
|
||||
}
|
||||
|
||||
// 4. 检查是否已砍到最低价
|
||||
@ -594,7 +645,7 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
BigDecimal subPrice = NumberUtil.sub(currPrice, mixSalePrice);
|
||||
// 当前价格已经等于或低于底价,可以立即出手下单
|
||||
if (NumberUtil.isGreater(subPrice, BigDecimal.ZERO)) {
|
||||
return Pair.of(false, String.format(I18nUtil._("还剩%.2f元可达活动底价,请继续加油。"), subPrice));
|
||||
return Pair.of(false, String.format(I18nUtil._("还剩%.2f元就到底价,继续加油。"), subPrice));
|
||||
}
|
||||
// 5. 检查是否存在砍价历史记录
|
||||
QueryWrapper<ShopActivityCutpriceHistory> queryWrapperHistory = new QueryWrapper<>();
|
||||
@ -627,35 +678,45 @@ public class ShopActivityCutpriceServiceImpl extends BaseServiceImpl<ShopActivit
|
||||
return Pair.of(false, I18nUtil._("活动信息不能为空"));
|
||||
}
|
||||
|
||||
if (shopStoreActivityBase.getActivity_id() == null || shopStoreActivityBase.getActivity_id() <= 0) {
|
||||
return Pair.of(false, I18nUtil._("活动ID无效"));
|
||||
}
|
||||
|
||||
//activity_state 活动状态(ENUM):0-未开启;1-正常;2-已结束;3-管理员关闭;4-商家关闭
|
||||
if (shopStoreActivityBase.getActivity_state() != null
|
||||
&& !CommonConstant.Enable.equals(shopStoreActivityBase.getActivity_state())) {
|
||||
return Pair.of(false, I18nUtil._("活动已结束,下次再参与!"));
|
||||
}
|
||||
|
||||
// 检查活动是否过期
|
||||
boolean isActivityTimeValid = shopStoreActivityBaseService.isActivityTimeValid(
|
||||
boolean isActivityTimeValid = DateTimeUtils.isActivityTimeValid(
|
||||
shopStoreActivityBase.getActivity_starttime(),
|
||||
shopStoreActivityBase.getActivity_endtime(),
|
||||
new Date()
|
||||
);
|
||||
if (!isActivityTimeValid) {
|
||||
return Pair.of(false, I18nUtil._("该活动已过期,下次早点来!"));
|
||||
return Pair.of(false, I18nUtil._("该活动已过期,下次再参与!"));
|
||||
}
|
||||
|
||||
// 检查活动商品库存
|
||||
Integer productCount = shopStoreActivityBase.getProduct_count();
|
||||
if (CheckUtil.isEmpty(productCount) || productCount <= 0) {
|
||||
return Pair.of(false, I18nUtil._("活动商品库存不足,请稍后再来。"));
|
||||
return Pair.of(false, I18nUtil._("活动商品未给库存,请联系店长!"));
|
||||
}
|
||||
|
||||
// 查询已占用库存的砍价订单数量
|
||||
QueryWrapper<ShopActivityCutprice> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("activity_id", shopStoreActivityBase.getActivity_id())
|
||||
.in("state", Arrays.asList(
|
||||
CommonConstant.CutPrice_Order_State_Finished,
|
||||
CommonConstant.CutPrice_Order_State_CutFinished,
|
||||
CommonConstant.CutPrice_Order_State_ING
|
||||
));
|
||||
long recordCount = count(queryWrapper);
|
||||
// QueryWrapper<ShopActivityCutprice> queryWrapper = new QueryWrapper<>();
|
||||
// queryWrapper.eq("activity_id", shopStoreActivityBase.getActivity_id())
|
||||
// .isNotNull("order_id").likeRight("order_id", "DD_")
|
||||
// .eq("state", CommonConstant.CutPrice_Order_State_Finished);
|
||||
// long recordCount = count(queryWrapper);
|
||||
|
||||
// 实时查询活动的订单数量
|
||||
long recordCount = shopOrderInfoService.fetchActivityOrderSuccessCount(Convert.toStr(shopStoreActivityBase.getActivity_id()), Convert.toStr(StateCode.ACTIVITY_TYPE_CUTPRICE));
|
||||
|
||||
// 判断库存是否充足(当已占用库存大于等于总库存时,表示库存不足)
|
||||
if (recordCount >= productCount) {
|
||||
return Pair.of(false, I18nUtil._("活动商品库存不足,请稍后再来。"));
|
||||
return Pair.of(false, I18nUtil._("活动商品不足,稍后再参与!"));
|
||||
}
|
||||
|
||||
// 所有检查通过
|
||||
|
||||
@ -65,6 +65,9 @@ public class StoreValidTimeJod extends QuartzJobBean {
|
||||
}
|
||||
page++;
|
||||
}
|
||||
|
||||
// 准备筹备中的店铺,到期转正常营业
|
||||
storeBaseService.batchUpdateStoreBizStateToOpening();
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,6 +5,7 @@ import cn.hutool.core.convert.Convert;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.api.StateCode;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreActivityBase;
|
||||
import com.suisung.mall.common.utils.DateTimeUtils;
|
||||
import com.suisung.mall.shop.activity.service.ShopActivityCutpriceService;
|
||||
import com.suisung.mall.shop.config.SpringUtil;
|
||||
import com.suisung.mall.shop.store.service.ShopStoreActivityBaseService;
|
||||
@ -28,33 +29,57 @@ public class UpdateActivityStatusJob extends QuartzJobBean {
|
||||
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
Logger logger = LoggerFactory.getLogger(UpdateActivityStatusJob.class);
|
||||
ShopStoreActivityBaseService shopStoreActivityBaseService = SpringUtil.getBean(ShopStoreActivityBaseService.class);
|
||||
ShopActivityCutpriceService shopActivityCutpriceService = SpringUtil.getBean(ShopActivityCutpriceService.class);
|
||||
TransactionTemplate transactionTemplate = SpringUtil.getBean(TransactionTemplate.class);
|
||||
|
||||
int page = 1;
|
||||
List<ShopStoreActivityBase> activityBaseList;
|
||||
QueryWrapper<ShopStoreActivityBase> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("activity_state", StateCode.ACTIVITY_STATE_WAITING);
|
||||
queryWrapper.le("activity_starttime", new Date());
|
||||
queryWrapper.in("activity_state", StateCode.ACTIVITY_STATE_WAITING, StateCode.ACTIVITY_STATE_NORMAL);
|
||||
// queryWrapper.le("activity_starttime", new Date());
|
||||
|
||||
while (CollUtil.isNotEmpty(activityBaseList = shopStoreActivityBaseService.lists(queryWrapper, page, 20).getRecords())) {
|
||||
for (ShopStoreActivityBase storeActivityBase : activityBaseList) {
|
||||
if (storeActivityBase.getActivity_state() != null
|
||||
&& storeActivityBase.getActivity_state().intValue() == StateCode.ACTIVITY_STATE_WAITING
|
||||
&& DateTimeUtils.isActivityTimeValid(storeActivityBase.getActivity_starttime(), storeActivityBase.getActivity_endtime(), new Date())) {
|
||||
Boolean result = transactionTemplate.execute(status -> {
|
||||
storeActivityBase.setActivity_state(StateCode.ACTIVITY_STATE_NORMAL);
|
||||
Map<String, Object> activityBaseMap = Convert.toMap(String.class, Object.class, storeActivityBase);
|
||||
|
||||
Boolean result = transactionTemplate.execute(status -> {
|
||||
storeActivityBase.setActivity_state(StateCode.ACTIVITY_STATE_NORMAL);
|
||||
Map<String, Object> activityBaseMap = Convert.toMap(String.class, Object.class, storeActivityBase);
|
||||
if (!shopStoreActivityBaseService.editActivityBase(storeActivityBase.getActivity_id(), activityBaseMap)) {
|
||||
status.isRollbackOnly();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!shopStoreActivityBaseService.editActivityBase(storeActivityBase.getActivity_id(), activityBaseMap)) {
|
||||
status.isRollbackOnly();
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
if (Boolean.FALSE.equals(result)) {
|
||||
logger.error(String.format("activity_id : %s 开启出错", storeActivityBase.getActivity_id()));
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (Boolean.FALSE.equals(result)) {
|
||||
logger.error(String.format("activity_id : %s 开启出错", storeActivityBase.getActivity_id()));
|
||||
}
|
||||
|
||||
if (storeActivityBase.getActivity_state() != null
|
||||
&& storeActivityBase.getActivity_state().intValue() == StateCode.ACTIVITY_STATE_NORMAL
|
||||
&& !DateTimeUtils.isActivityTimeValid(storeActivityBase.getActivity_starttime(), storeActivityBase.getActivity_endtime(), new Date())) {
|
||||
|
||||
Boolean result = transactionTemplate.execute(status -> {
|
||||
storeActivityBase.setActivity_state(StateCode.ACTIVITY_STATE_FINISHED);
|
||||
Map<String, Object> activityBaseMap = Convert.toMap(String.class, Object.class, storeActivityBase);
|
||||
|
||||
if (!shopStoreActivityBaseService.editActivityBase(storeActivityBase.getActivity_id(), activityBaseMap)) {
|
||||
status.isRollbackOnly();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (Boolean.FALSE.equals(result)) {
|
||||
logger.error(String.format("activity_id : %s 设置过期出错", storeActivityBase.getActivity_id()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
@ -65,8 +90,18 @@ public class UpdateActivityStatusJob extends QuartzJobBean {
|
||||
page++;
|
||||
}
|
||||
|
||||
// 砍价活动时间到,更新砍价订单的过期状态
|
||||
autoUpdateCutPriceStateJob();
|
||||
}
|
||||
|
||||
/**
|
||||
* 只针对:砍价活动时间到,更新砍价订单的过期状态
|
||||
*/
|
||||
private void autoUpdateCutPriceStateJob() {
|
||||
ShopActivityCutpriceService shopActivityCutpriceService = SpringUtil.getBean(ShopActivityCutpriceService.class);
|
||||
// 活动时间到更新砍价订单的过期状态
|
||||
shopActivityCutpriceService.autoUpdateCutPriceStateJob();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ public class EsignController extends BaseControllerImpl {
|
||||
@ApiOperation(value = "管理员发起签署电子合同流程", notes = "基于文件发起签署电子合同")
|
||||
@RequestMapping(value = "/sign-flow/create-by-file", method = RequestMethod.POST)
|
||||
public CommonResult signFlowCreateByFile(@RequestBody JSONObject paramsJSON) {
|
||||
return esignContractService.signFlowCreateByFile(paramsJSON.getStr("mchMobile"));
|
||||
return esignContractService.signFlowCreateByFile(paramsJSON.getInt("store_id"));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "签署电子合同流程通知接收", notes = "签署电子合同流程通知接收")
|
||||
@ -62,6 +62,6 @@ public class EsignController extends BaseControllerImpl {
|
||||
@ApiOperation(value = "查看已签署的电子合同文件", notes = "管理员查看已签署的电子合同文件")
|
||||
@RequestMapping(value = "/signed/contract/file", method = RequestMethod.POST)
|
||||
public CommonResult getSignedContactFile(@RequestBody JSONObject paramsJSON) {
|
||||
return esignContractService.getSignedContactFile(paramsJSON.getStr("mchMobile"));
|
||||
return esignContractService.getSignedContactFile(paramsJSON.getInt("store_id"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,11 +18,10 @@ public interface EsignContractFillingFileService {
|
||||
/**
|
||||
* 填充合同模版,生成合同文件地址
|
||||
*
|
||||
* @param mchMobile 入驻商家注册手机号
|
||||
* @param platLicenseNumber 平台方(代理商方)营业执照号
|
||||
* @param storeId 入驻成功商家的店铺Id
|
||||
* @return
|
||||
*/
|
||||
Boolean fillDocTemplate(String mchMobile, String platLicenseNumber);
|
||||
Boolean fillDocTemplate(Integer storeId);
|
||||
|
||||
/**
|
||||
* 获取模版的甲方与乙方印章XY位置数据
|
||||
|
||||
@ -21,18 +21,18 @@ public interface EsignContractService {
|
||||
/**
|
||||
* 根据商家注册手机号,发起合同签署流程
|
||||
*
|
||||
* @param mchMobile
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
CommonResult signFlowCreateByFile(String mchMobile);
|
||||
CommonResult signFlowCreateByFile(Integer storeId);
|
||||
|
||||
/**
|
||||
* 内部调用:发起合同签署流程
|
||||
*
|
||||
* @param mchMobile
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
Pair<Boolean, String> innerSignFlowCreateByFile(String mchMobile);
|
||||
Pair<Boolean, String> innerSignFlowCreateByFile(Integer storeId);
|
||||
|
||||
/**
|
||||
* 签署流程结束异步通知(由e签宝通知)
|
||||
@ -44,10 +44,10 @@ public interface EsignContractService {
|
||||
/**
|
||||
* 管理员查看已签署的电子合同文件
|
||||
*
|
||||
* @param mchMobile
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
CommonResult getSignedContactFile(String mchMobile);
|
||||
CommonResult getSignedContactFile(Integer storeId);
|
||||
|
||||
/**
|
||||
* 更新合同流程ID和文件地址和状态
|
||||
@ -131,4 +131,20 @@ public interface EsignContractService {
|
||||
* @return
|
||||
*/
|
||||
Boolean updateContractStoreId(String mchMobile, Integer storeId);
|
||||
|
||||
/**
|
||||
* 根据店铺Id,获取一条合同信息
|
||||
*
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
EsignContract getEsignContractByStoreId(Integer storeId);
|
||||
|
||||
/**
|
||||
* 根据店铺Id,获取合同状态和下载地址
|
||||
*
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
EsignContract getEsignContractStatusUrl(Integer storeId);
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
package com.suisung.mall.shop.esign.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
@ -21,6 +22,8 @@ import com.suisung.mall.common.constant.CommonConstant;
|
||||
import com.suisung.mall.common.modules.esign.EsignContractFillingFile;
|
||||
import com.suisung.mall.common.modules.esign.EsignPlatformInfo;
|
||||
import com.suisung.mall.common.modules.store.ShopMchEntry;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreBase;
|
||||
import com.suisung.mall.common.utils.CheckUtil;
|
||||
import com.suisung.mall.common.utils.StringUtils;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.esign.mapper.EsignContractFillingFileMapper;
|
||||
@ -33,6 +36,7 @@ import com.suisung.mall.shop.esign.utils.enums.EsignRequestType;
|
||||
import com.suisung.mall.shop.esign.utils.exception.EsignDemoException;
|
||||
import com.suisung.mall.shop.page.service.OssService;
|
||||
import com.suisung.mall.shop.store.service.ShopMchEntryService;
|
||||
import com.suisung.mall.shop.store.service.ShopStoreBaseService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
@ -41,6 +45,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -79,6 +84,10 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
|
||||
@Resource
|
||||
private EsignContractService esignContractService;
|
||||
|
||||
@Lazy
|
||||
@Resource
|
||||
private ShopStoreBaseService shopStoreBaseService;
|
||||
|
||||
|
||||
@Resource
|
||||
private OssService ossService;
|
||||
@ -86,112 +95,136 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
|
||||
/**
|
||||
* 根据双方营业执照号码(或个人身份证)填充合同模版,生成合同文件地址
|
||||
* <p>
|
||||
* 后台管理员审核商家通过之后,触发调用这个方法,生成未签署合同文件,预备签署
|
||||
* 拉卡拉审核通过之后,触发调用这个方法,生成未签署合同文件,预备签署
|
||||
*
|
||||
* @param mchMobile 入驻商家(甲方)的注册手机号
|
||||
* @param platLicenseNumber 平台方(代理商方)(乙方)营业执照号
|
||||
* @return
|
||||
* @param storeId 入驻成功商家的店铺Id
|
||||
* @return Boolean 是否成功生成合同文件
|
||||
*/
|
||||
@Override
|
||||
public Boolean fillDocTemplate(String mchMobile, String platLicenseNumber) {
|
||||
if (StrUtil.isEmpty(mchMobile)) {
|
||||
log.error("商家手机号为空");
|
||||
public Boolean fillDocTemplate(Integer storeId) {
|
||||
// 1. 参数校验
|
||||
if (CheckUtil.isEmpty(storeId)) {
|
||||
log.error("[合同生成] 商家店铺ID不能为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取平台方的信息
|
||||
EsignPlatformInfo esignPlatformInfo = esignPlatformInfoService.getEsignPlatformInfo(0, platLicenseNumber);
|
||||
// 2. 获取平台方信息
|
||||
EsignPlatformInfo esignPlatformInfo = esignPlatformInfoService.getEsignPlatformInfo(0, "");
|
||||
if (ObjectUtils.isEmpty(esignPlatformInfo)) {
|
||||
log.error("请添加平台方(代理商方)信息");
|
||||
return null;
|
||||
log.error("[合同生成] 平台方(代理商方)信息缺失,请先配置平台信息");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取入驻商家(审批通过的)的信息
|
||||
ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByCondition(mchMobile, "", CommonConstant.MCH_APPR_STA_PASS);
|
||||
if (StrUtil.isBlank(esignPlatformInfo.getDoc_template())) {
|
||||
log.error("[合同生成] 平台方合同模板信息为空,无法继续生成合同");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 获取入驻商家(审批通过的)的信息
|
||||
ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByStoreId(storeId);
|
||||
if (shopMchEntry == null) {
|
||||
log.error("缺少商家入驻信息");
|
||||
return null;
|
||||
log.error("[合同生成] 找不到商家入驻信息, storeId: {}", storeId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 代理商信息
|
||||
// 4. 检查商家审批状态
|
||||
if (!CommonConstant.MCH_APPR_STA_PASS.equals(shopMchEntry.getApproval_status())) {
|
||||
log.error("[合同生成] 商家入驻审批未通过,当前状态: {}, storeId: {}", shopMchEntry.getApproval_status(), storeId);
|
||||
return false;
|
||||
}
|
||||
|
||||
ShopStoreBase shopStoreBase = shopStoreBaseService.getShopStoreBaseByStoreId(storeId);
|
||||
if (ObjectUtils.isEmpty(shopStoreBase)) {
|
||||
log.error("[合同生成] 缺少商家店铺信息, storeId: {}", storeId);
|
||||
return false;
|
||||
}
|
||||
|
||||
BigDecimal splitRatio = shopStoreBase.getSplit_ratio();
|
||||
if (CheckUtil.isEmpty(splitRatio)) {
|
||||
log.warn("[合同生成] 店铺分账比例为空,将使用入驻申请时设置的比例, storeId: {}", storeId);
|
||||
splitRatio = shopMchEntry.getSplit_ratio();
|
||||
}
|
||||
|
||||
// 5. 获取代理商信息
|
||||
EsignPlatformInfo distributor = esignPlatformInfoService.getDistributorInfoById(shopMchEntry.getDistributor_id());
|
||||
|
||||
String apiaddr = "/v3/files/create-by-doc-template";
|
||||
EsignRequestType requestType = EsignRequestType.POST;
|
||||
|
||||
// 获取平台方(代理商方)合同模版信息
|
||||
// 6. 获取平台方合同模版信息
|
||||
JSONArray templates = JSONUtil.parseArray(esignPlatformInfo.getDoc_template());
|
||||
if (ObjectUtils.isEmpty(templates) || templates.size() <= 0) {
|
||||
log.error("缺少平台方(代理商方)合同模版信息");
|
||||
return null;
|
||||
if (templates == null || templates.isEmpty()) {
|
||||
log.error("[合同生成] 平台方(代理商方)合同模板信息缺失");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 7. 准备基础数据
|
||||
String today = DateUtil.format(new Date(), "yyyy年MM月dd日");
|
||||
// 甲方公司名称,甲方是个人的时候,没有公司名,直接用店铺名(个人实名)
|
||||
String mchCompany = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type()) ? shopMchEntry.getBiz_license_company() : shopMchEntry.getStore_name() + "(" + shopMchEntry.getContact_name() + ")";
|
||||
String mchCompany = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type())
|
||||
? shopMchEntry.getBiz_license_company()
|
||||
: shopMchEntry.getStore_name() + "(" + shopMchEntry.getContact_name() + ")";
|
||||
String platCompany = esignPlatformInfo.getLicense_company();
|
||||
// 甲方法人姓名,甲方是个人的时候,没有法人,直接用个人实名
|
||||
String legalPersonName = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type()) ? shopMchEntry.getLegal_person_name() : shopMchEntry.getContact_name();
|
||||
String LegalPersonMobile = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type()) ? shopMchEntry.getLegal_person_mobile() : shopMchEntry.getLogin_mobile();
|
||||
String legalPersonName = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type())
|
||||
? shopMchEntry.getLegal_person_name()
|
||||
: shopMchEntry.getContact_name();
|
||||
String legalPersonMobile = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type())
|
||||
? shopMchEntry.getLegal_person_mobile()
|
||||
: shopMchEntry.getLogin_mobile();
|
||||
|
||||
// 甲方法人身份证号,甲方是个人的时候,没有法人,直接用个人身份证
|
||||
String legalPersonIdNumber = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type()) ? shopMchEntry.getLegal_person_id_number() : shopMchEntry.getIndividual_id_number();
|
||||
|
||||
String legalPersonIdNumber = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type())
|
||||
? shopMchEntry.getLegal_person_id_number()
|
||||
: shopMchEntry.getIndividual_id_number();
|
||||
|
||||
String contractNumber = StringUtils.genLklOrderNo(4);
|
||||
|
||||
int successCnt = 0;
|
||||
|
||||
// 模版文件里有三份合同,顺序排列的: 1.平台商户入驻服务框架协议 2.小发同城服务费结算 3.结算授权委托书
|
||||
log.info("[合同生成] 开始为商家生成入驻合同文件, storeId: {}, 商家手机号: {}", storeId, shopMchEntry.getLogin_mobile());
|
||||
|
||||
// 8. 遍历模版文件生成合同(模版文件里有三份合同,顺序排列的: 1.平台商户入驻服务框架协议 2.小发同城服务费结算 3.结算授权委托书)
|
||||
for (JSONObject template : templates.jsonIter()) {
|
||||
// 从商家信息里获取模版的信息
|
||||
String templateId = template.getStr("template_id");
|
||||
String fileName = template.getStr("template_name");
|
||||
int seq = template.getInt("seq");
|
||||
try {
|
||||
// 从商家信息里获取模版的信息
|
||||
String templateId = template.getStr("template_id");
|
||||
String fileName = template.getStr("template_name");
|
||||
int seq = template.getInt("seq");
|
||||
|
||||
// 获取填充模版的数据
|
||||
JSONObject fillJson = new JSONObject();
|
||||
fillJson.put("docTemplateId", templateId)
|
||||
.put("fileName", fileName);
|
||||
log.debug("[合同生成] 正在处理合同模板: templateId={}, 文件名={}, 序号={}", templateId, fileName, seq);
|
||||
|
||||
// 9. 构建填充模版的数据
|
||||
JSONObject fillJson = new JSONObject();
|
||||
fillJson.put("docTemplateId", templateId)
|
||||
.put("fileName", fileName);
|
||||
|
||||
JSONArray list = new JSONArray();
|
||||
EsignPlatformInfo finalEsignPlatformInfo = esignPlatformInfo;
|
||||
JSONArray list = new JSONArray();
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_contracts");
|
||||
put("componentValue", "《平台商户入驻服务框架协议》和《小发同城服务费结算》");
|
||||
}});
|
||||
|
||||
// 签署时间
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
int finalI = i;
|
||||
// 10. 填充合同组件数据
|
||||
// 平台合同名称
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_sign_date" + finalI);
|
||||
put("componentValue", today);
|
||||
put("componentKey", "plat_contracts");
|
||||
put("componentValue", "《平台商户入驻服务框架协议》和《小发同城服务费结算》");
|
||||
}});
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
int finalI = i;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_sign_date" + finalI);
|
||||
put("componentValue", today);
|
||||
}});
|
||||
}
|
||||
|
||||
if (CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type())) {
|
||||
// 甲方公司名称,甲方是个人的时候,没有公司名,直接用店铺名
|
||||
for (int i = 1; i <= 17; i++) {
|
||||
// 签署时间(甲方)
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
int finalI = i;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_company" + finalI);
|
||||
put("componentValue", mchCompany);
|
||||
put("componentKey", "mch_sign_date" + finalI);
|
||||
put("componentValue", today);
|
||||
}});
|
||||
}
|
||||
} else {
|
||||
// 甲方公司名称,甲方是个人的时候,没有公司名,直接用店铺名
|
||||
for (int i = 1; i <= 16; i++) {
|
||||
|
||||
// 签署时间(乙方)
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
int finalI = i;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_sign_date" + finalI);
|
||||
put("componentValue", today);
|
||||
}});
|
||||
}
|
||||
|
||||
// 甲方公司名称
|
||||
int mchCompanyCount = CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type()) ? 17 : 16;
|
||||
for (int i = 1; i <= mchCompanyCount; i++) {
|
||||
int finalI = i;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_company" + finalI);
|
||||
@ -199,233 +232,242 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
|
||||
}});
|
||||
}
|
||||
|
||||
//特殊:甲方收款账方,企业是公司名,个人是个人实名
|
||||
// 特殊处理:甲方收款账户方(企业是公司名,个人是个人实名)
|
||||
if (!CommonConstant.MCH_ENTITY_TYPE_QY.equals(shopMchEntry.getEntity_type())) {
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_company17");
|
||||
put("componentValue", shopMchEntry.getContact_name());
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
// 甲方法人姓名,甲方是个人的时候,没有法人,直接用个人实名
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
int finalI = i;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_legal_person_name" + finalI);
|
||||
put("componentValue", legalPersonName);
|
||||
}});
|
||||
}
|
||||
|
||||
// 甲方法人手机号
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
int finalI = i;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_legal_person_mobile" + finalI);
|
||||
put("componentValue", LegalPersonMobile);
|
||||
}});
|
||||
}
|
||||
|
||||
// 甲方身份证号码
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_legal_person_id_number1");
|
||||
put("componentValue", legalPersonIdNumber);
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_store_name1");
|
||||
put("componentValue", shopMchEntry.getStore_name());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "rule_no");
|
||||
put("componentValue", 3);
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_ratio");
|
||||
put("componentValue", shopMchEntry.getSplit_ratio());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "settlement_method");
|
||||
put("componentValue", shopMchEntry.getSettlement_method());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_address1");
|
||||
put("componentValue", shopMchEntry.getStore_address());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_bank1");
|
||||
put("componentValue", shopMchEntry.getBank_name());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_account_number1");
|
||||
put("componentValue", shopMchEntry.getAccount_number());
|
||||
}});
|
||||
|
||||
// 乙方公司名称
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_company1");
|
||||
put("componentValue", platCompany + "和代理商");
|
||||
}});
|
||||
|
||||
for (int i = 2; i <= 5; i++) {
|
||||
int finalI = i;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_company" + finalI);
|
||||
put("componentValue", platCompany);
|
||||
}});
|
||||
}
|
||||
|
||||
for (int i = 1; i <= 2; i++) {
|
||||
int finalI = i;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_mobile" + finalI);
|
||||
put("componentValue", finalEsignPlatformInfo.getLegal_person_mobile());
|
||||
}});
|
||||
}
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_email1");
|
||||
put("componentValue", finalEsignPlatformInfo.getEmail());
|
||||
}});
|
||||
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_email1");
|
||||
put("componentValue", finalEsignPlatformInfo.getEmail());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_email1");
|
||||
put("componentValue", finalEsignPlatformInfo.getEmail());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_email1");
|
||||
put("componentValue", finalEsignPlatformInfo.getEmail());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_email1");
|
||||
put("componentValue", finalEsignPlatformInfo.getEmail());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_email1");
|
||||
put("componentValue", finalEsignPlatformInfo.getEmail());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_bank1");
|
||||
put("componentValue", finalEsignPlatformInfo.getRec_acc_bank_name());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_account_number1");
|
||||
put("componentValue", finalEsignPlatformInfo.getRec_acc_card_no());
|
||||
}});
|
||||
|
||||
// 代理商相关
|
||||
if (distributor != null) {
|
||||
// 有代理商的时候,才填充代理商的信息
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_company1");
|
||||
put("componentValue", distributor.getLicense_company());
|
||||
}});
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_mobile1");
|
||||
put("componentValue", distributor.getLegal_person_mobile());
|
||||
}});
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_company2");
|
||||
put("componentValue", distributor.getLicense_company());
|
||||
}});
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_bank1");
|
||||
put("componentValue", distributor.getRec_acc_bank_name());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_account_number1");
|
||||
put("componentValue", distributor.getRec_acc_card_no());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_sign_date1");
|
||||
put("componentValue", today);
|
||||
}});
|
||||
} else {
|
||||
// 有代理商的时候,才填充代理商的信息
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_company1");
|
||||
put("componentValue", "无");
|
||||
}});
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_mobile1");
|
||||
put("componentValue", "无");
|
||||
}});
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_company2");
|
||||
put("componentValue", "无");
|
||||
}});
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_bank1");
|
||||
put("componentValue", "无");
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_account_number1");
|
||||
put("componentValue", "无");
|
||||
}});
|
||||
|
||||
}
|
||||
|
||||
fillJson.put("components", list);
|
||||
|
||||
String jsonParma = fillJson.toString();
|
||||
|
||||
//生成签名鉴权方式的的header
|
||||
Map<String, String> header = null;
|
||||
try {
|
||||
header = EsignHttpHelper.signAndBuildSignAndJsonHeader(appId, appSecret, jsonParma, requestType.name(), apiaddr, debug);
|
||||
//发起接口请求
|
||||
EsignHttpResponse createByDocTemplate = EsignHttpHelper.doCommHttp(serverUrl, apiaddr, requestType, jsonParma, header, debug);
|
||||
log.info("合同生成数据:{}", createByDocTemplate);
|
||||
if (createByDocTemplate.getStatus() != 200) {
|
||||
return false;
|
||||
// 甲方法人姓名
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
int finalI = i;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_legal_person_name" + finalI);
|
||||
put("componentValue", legalPersonName);
|
||||
}});
|
||||
}
|
||||
|
||||
EsignContractFillingFile esignContractFillingFile = new EsignContractFillingFile();
|
||||
// 甲方法人手机号
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
int finalI = i;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_legal_person_mobile" + finalI);
|
||||
put("componentValue", legalPersonMobile);
|
||||
}});
|
||||
}
|
||||
|
||||
// 甲方身份证号码
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_legal_person_id_number1");
|
||||
put("componentValue", legalPersonIdNumber);
|
||||
}});
|
||||
|
||||
// 甲方店铺名称
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_store_name1");
|
||||
put("componentValue", shopMchEntry.getStore_name());
|
||||
}});
|
||||
|
||||
// 规则编号
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "rule_no");
|
||||
put("componentValue", 3);
|
||||
}});
|
||||
|
||||
// 分账比例
|
||||
BigDecimal finalSplitRatio = splitRatio;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_ratio");
|
||||
put("componentValue", finalSplitRatio);
|
||||
}});
|
||||
|
||||
// 结算方式
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "settlement_method");
|
||||
put("componentValue", shopMchEntry.getSettlement_method());
|
||||
}});
|
||||
|
||||
// 甲方地址
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_address1");
|
||||
put("componentValue", shopMchEntry.getStore_address());
|
||||
}});
|
||||
|
||||
// 甲方银行
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_bank1");
|
||||
put("componentValue", shopMchEntry.getBank_name());
|
||||
}});
|
||||
|
||||
// 甲方账户号
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "mch_account_number1");
|
||||
put("componentValue", shopMchEntry.getAccount_number());
|
||||
}});
|
||||
|
||||
// 乙方公司名称
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_company1");
|
||||
put("componentValue", platCompany + "和代理商");
|
||||
}});
|
||||
|
||||
// 其他乙方公司名称
|
||||
for (int i = 2; i <= 5; i++) {
|
||||
int finalI = i;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_company" + finalI);
|
||||
put("componentValue", platCompany);
|
||||
}});
|
||||
}
|
||||
|
||||
// 乙方手机号
|
||||
for (int i = 1; i <= 2; i++) {
|
||||
int finalI = i;
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_mobile" + finalI);
|
||||
put("componentValue", esignPlatformInfo.getLegal_person_mobile());
|
||||
}});
|
||||
}
|
||||
|
||||
// 乙方邮箱(重复填充,但保持原逻辑)
|
||||
for (int i = 0; i < 6; i++) {
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_email1");
|
||||
put("componentValue", esignPlatformInfo.getEmail());
|
||||
}});
|
||||
}
|
||||
|
||||
// 乙方银行
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_bank1");
|
||||
put("componentValue", esignPlatformInfo.getRec_acc_bank_name());
|
||||
}});
|
||||
|
||||
// 乙方账户号
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "plat_account_number1");
|
||||
put("componentValue", esignPlatformInfo.getRec_acc_card_no());
|
||||
}});
|
||||
|
||||
// 11. 处理代理商相关数据
|
||||
if (distributor != null) {
|
||||
// 有代理商的时候,填充代理商的信息
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_company1");
|
||||
put("componentValue", distributor.getLicense_company());
|
||||
}});
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_mobile1");
|
||||
put("componentValue", distributor.getLegal_person_mobile());
|
||||
}});
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_company2");
|
||||
put("componentValue", distributor.getLicense_company());
|
||||
}});
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_bank1");
|
||||
put("componentValue", distributor.getRec_acc_bank_name());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_account_number1");
|
||||
put("componentValue", distributor.getRec_acc_card_no());
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_sign_date1");
|
||||
put("componentValue", today);
|
||||
}});
|
||||
|
||||
log.debug("[合同生成] 已填充代理商信息: {}", distributor.getLicense_company());
|
||||
} else {
|
||||
// 无代理商时填充默认值
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_company1");
|
||||
put("componentValue", "无");
|
||||
}});
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_mobile1");
|
||||
put("componentValue", "无");
|
||||
}});
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_company2");
|
||||
put("componentValue", "无");
|
||||
}});
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_bank1");
|
||||
put("componentValue", "无");
|
||||
}});
|
||||
|
||||
list.add(new HashMap<String, Object>() {{
|
||||
put("componentKey", "distr_account_number1");
|
||||
put("componentValue", "无");
|
||||
}});
|
||||
|
||||
log.debug("[合同生成] 未配置代理商信息,使用默认值");
|
||||
}
|
||||
|
||||
fillJson.put("components", list);
|
||||
String jsonParam = fillJson.toString();
|
||||
|
||||
String apiAddr = "/v3/files/create-by-doc-template";
|
||||
EsignRequestType requestType = EsignRequestType.POST;
|
||||
|
||||
// 12. 调用e签宝API生成合同文件
|
||||
Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(
|
||||
appId, appSecret, jsonParam, requestType.name(), apiAddr, debug);
|
||||
|
||||
// 发起接口请求
|
||||
EsignHttpResponse createByDocTemplate = EsignHttpHelper.doCommHttp(
|
||||
serverUrl, apiAddr, requestType, jsonParam, header, debug);
|
||||
|
||||
log.info("[合同生成] 调用电子签约服务生成合同文件: status={}, response={}",
|
||||
createByDocTemplate.getStatus(), createByDocTemplate.getBody());
|
||||
|
||||
if (createByDocTemplate.getStatus() != 200) {
|
||||
log.error("[合同生成] 调用电子签约服务生成合同文件失败, HTTP状态码: {}", createByDocTemplate.getStatus());
|
||||
continue; // 继续处理下一个模版
|
||||
}
|
||||
|
||||
// 13. 解析API返回结果
|
||||
JSONObject jsonObject = JSONUtil.parseObj(createByDocTemplate.getBody()).getJSONObject("data");
|
||||
esignContractFillingFile.setUnsigned_contract_url(jsonObject.getStr("fileDownloadUrl"));
|
||||
String fileDownloadUrl = jsonObject.getStr("fileDownloadUrl");
|
||||
String fileId = jsonObject.getStr("fileId");
|
||||
|
||||
// 把合同文件 url 上传到cos服务器
|
||||
// String contractPath = StrUtil.isBlank(shopMchEntry.getBiz_license_number()) ? mchMobile : shopMchEntry.getBiz_license_number();
|
||||
String cosFileName = TENGXUN_DEFAULT_DIR.concat("/").concat("contract")
|
||||
.concat("/").concat(shopMchEntry.getLogin_mobile()).concat("/")
|
||||
.concat(jsonObject.getStr("fileId")).concat(".pdf");
|
||||
// 上传到cos服务器
|
||||
String localFileUrl = ossService.uploadObject4OSS(esignContractFillingFile.getUnsigned_contract_url(), cosFileName);
|
||||
esignContractFillingFile.setUnsigned_contract_local_url(localFileUrl);
|
||||
if (StrUtil.isBlank(fileDownloadUrl) || StrUtil.isBlank(fileId)) {
|
||||
log.error("[合同生成] 电子签约服务返回的合同文件信息不完整, 下载地址: {}, 文件ID: {}", fileDownloadUrl, fileId);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 14. 创建合同填充文件记录
|
||||
EsignContractFillingFile esignContractFillingFile = new EsignContractFillingFile();
|
||||
esignContractFillingFile.setUnsigned_contract_url(fileDownloadUrl);
|
||||
esignContractFillingFile.setFile_id(fileId);
|
||||
|
||||
// 15. 上传合同文件到OSS
|
||||
String cosFileName = TENGXUN_DEFAULT_DIR.concat("/contract/")
|
||||
.concat(shopMchEntry.getLogin_mobile()).concat("/")
|
||||
.concat(fileId).concat(".pdf");
|
||||
|
||||
String localFileUrl = ossService.uploadObject4OSS(fileDownloadUrl, cosFileName);
|
||||
if (StrUtil.isBlank(localFileUrl)) {
|
||||
log.error("[合同生成] 合同文件上传到对象存储失败, fileId: {}", fileId);
|
||||
continue;
|
||||
}
|
||||
|
||||
esignContractFillingFile.setUnsigned_contract_local_url(localFileUrl);
|
||||
esignContractFillingFile.setDoc_template_id(templateId);
|
||||
esignContractFillingFile.setContract_number(contractNumber + seq);
|
||||
esignContractFillingFile.setContract_name("商户入驻小发同城平台合同协议");
|
||||
esignContractFillingFile.setStore_id(contractNumber);
|
||||
esignContractFillingFile.setMobile(mchMobile);
|
||||
esignContractFillingFile.setDoc_template_filling_values(jsonParma);
|
||||
esignContractFillingFile.setStore_id(Convert.toStr(storeId));
|
||||
esignContractFillingFile.setMobile(shopMchEntry.getLogin_mobile());
|
||||
esignContractFillingFile.setDoc_template_filling_values(jsonParam);
|
||||
esignContractFillingFile.setSeq(seq);
|
||||
esignContractFillingFile.setStatus(CommonConstant.Enable);
|
||||
|
||||
// 获取印章的位置信息,写入数据库
|
||||
// 16. 获取印章位置信息
|
||||
Map<String, JSONArray> signPositionMap = getSignPosition(templateId, fileId);
|
||||
if (signPositionMap != null) {
|
||||
if (signPositionMap.get("mch") != null) {
|
||||
@ -441,22 +483,34 @@ public class EsignContractFillingFileServiceImpl extends BaseServiceImpl<EsignCo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 17. 保存合同填充记录并预创建签署流程
|
||||
if (esignContractFillingFileService.trySaveRecord(esignContractFillingFile)) {
|
||||
successCnt += 1;
|
||||
log.debug("[合同生成] 合同记录保存成功, fileId: {}", fileId);
|
||||
|
||||
// 预新增一个签署合同记录(要不要异步执行?)
|
||||
esignContractService.preCreateSignFlow(esignContractFillingFile.getMobile(), esignContractFillingFile.getDoc_template_id());
|
||||
// 预新增一个签署合同记录
|
||||
boolean preCreateResult = esignContractService.preCreateSignFlow(
|
||||
esignContractFillingFile.getMobile(), esignContractFillingFile.getDoc_template_id());
|
||||
log.debug("[合同生成] 预创建签署流程结果: {}, 商家手机号: {}, 模板ID: {}",
|
||||
preCreateResult, esignContractFillingFile.getMobile(), esignContractFillingFile.getDoc_template_id());
|
||||
} else {
|
||||
log.error("[合同生成] 保存合同记录失败, fileId: {}", fileId);
|
||||
}
|
||||
|
||||
} catch (EsignDemoException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (Exception e) {
|
||||
log.error("[合同生成] 处理合同模板时出现异常, templateId: {}", template.getStr("template_id"), e);
|
||||
// 继续处理下一个模版,不中断整个流程
|
||||
}
|
||||
}
|
||||
|
||||
return successCnt > 0;
|
||||
boolean result = successCnt > 0;
|
||||
log.info("[合同生成] 商家合同文件全部生成完毕, storeId: {}, 总模板数: {}, 成功处理数: {}, 最终结果: {}",
|
||||
storeId, templates.size(), successCnt, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取模版的甲方与乙方印章XY位置数据
|
||||
*
|
||||
|
||||
@ -14,6 +14,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.suisung.mall.common.api.CommonResult;
|
||||
@ -22,6 +23,7 @@ import com.suisung.mall.common.modules.esign.EsignContract;
|
||||
import com.suisung.mall.common.modules.esign.EsignContractFillingFile;
|
||||
import com.suisung.mall.common.modules.esign.EsignPlatformInfo;
|
||||
import com.suisung.mall.common.modules.store.ShopMchEntry;
|
||||
import com.suisung.mall.common.utils.CheckUtil;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.components.TaskService;
|
||||
import com.suisung.mall.shop.esign.mapper.EsignContractMapper;
|
||||
@ -32,11 +34,8 @@ import com.suisung.mall.shop.esign.utils.comm.EsignHttpHelper;
|
||||
import com.suisung.mall.shop.esign.utils.comm.EsignHttpResponse;
|
||||
import com.suisung.mall.shop.esign.utils.enums.EsignRequestType;
|
||||
import com.suisung.mall.shop.esign.utils.exception.EsignDemoException;
|
||||
import com.suisung.mall.shop.lakala.service.LakalaApiService;
|
||||
import com.suisung.mall.shop.lakala.service.LklLedgerMemberService;
|
||||
import com.suisung.mall.shop.page.service.OssService;
|
||||
import com.suisung.mall.shop.store.service.ShopMchEntryService;
|
||||
import com.suisung.mall.shop.store.service.ShopStoreBaseService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@ -91,18 +90,6 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
|
||||
@Resource
|
||||
private EsignPlatformInfoService esignPlatformInfoService;
|
||||
|
||||
@Resource
|
||||
private ShopStoreBaseService shopStoreBaseService;
|
||||
|
||||
@Lazy
|
||||
@Resource
|
||||
private LakalaApiService lakalaApiService;
|
||||
|
||||
|
||||
@Lazy
|
||||
@Resource
|
||||
private LklLedgerMemberService lklLedgerMemberService;
|
||||
|
||||
@Resource
|
||||
private OssService ossService;
|
||||
|
||||
@ -169,8 +156,8 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public CommonResult signFlowCreateByFile(String mchMobile) {
|
||||
Pair<Boolean, String> ret = innerSignFlowCreateByFile(mchMobile);
|
||||
public CommonResult signFlowCreateByFile(Integer storeId) {
|
||||
Pair<Boolean, String> ret = innerSignFlowCreateByFile(storeId);
|
||||
if (!ret.getFirst()) {
|
||||
return CommonResult.failed(ret.getSecond());
|
||||
}
|
||||
@ -179,21 +166,25 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<Boolean, String> innerSignFlowCreateByFile(String mchMobile) {
|
||||
//String userId = "0";
|
||||
|
||||
if (StrUtil.isBlank(mchMobile)) {
|
||||
public Pair<Boolean, String> innerSignFlowCreateByFile(Integer storeId) {
|
||||
if (CheckUtil.isEmpty(storeId)) {
|
||||
return Pair.of(false, "缺少必要参数!");
|
||||
}
|
||||
|
||||
EsignContract esignContract = getEsignContractByMchMobile(mchMobile);
|
||||
// 组织和填充商家店铺的模版数据
|
||||
Boolean isFill = esignContractFillingFileService.fillDocTemplate(storeId);
|
||||
if (!isFill) {
|
||||
return Pair.of(false, "合同信息未准备好,请检查商家入驻手续是否已完成!");
|
||||
}
|
||||
|
||||
EsignContract esignContract = getEsignContractByStoreId(storeId);
|
||||
if (esignContract == null) {
|
||||
return Pair.of(false, "未找到商家合同信息");
|
||||
}
|
||||
|
||||
// 检查商户入驻信息是否被审核通过
|
||||
// 检查店铺是否已经申请过入驻
|
||||
Integer apprStatus = shopMchEntryService.getApprovalStatus(mchMobile);
|
||||
Integer apprStatus = shopMchEntryService.getApprovalStatus(esignContract.getMch_mobile());
|
||||
if (!CommonConstant.MCH_APPR_STA_PASS.equals(apprStatus)) {
|
||||
return Pair.of(false, "请先审核商家入驻信息");
|
||||
}
|
||||
@ -211,7 +202,7 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
|
||||
|
||||
//发起接口请求
|
||||
EsignHttpResponse createByDocTemplate = EsignHttpHelper.doCommHttp(serverUrl, apiAddr, requestType, jsonParams, header, debug);
|
||||
log.debug("发起合同签署流程返回消息:{},{}", createByDocTemplate.getStatus(), createByDocTemplate.getBody());
|
||||
log.info("发起合同签署流程返回消息:{},{}", createByDocTemplate.getStatus(), createByDocTemplate.getBody());
|
||||
if (createByDocTemplate.getStatus() != 200) {
|
||||
if (createByDocTemplate.getBody() != null) {
|
||||
JSONObject resBody = JSONUtil.parseObj(createByDocTemplate.getBody());
|
||||
@ -254,108 +245,168 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
|
||||
log.debug("签署流程结束通知:body >>> {}", requestBody);
|
||||
log.debug("签署流程结束通知:header >>> {}", request.getParameterMap());
|
||||
|
||||
//异步通知获取到的header头中的签名值:X-Tsign-Open-App-Id
|
||||
// 1. 验证请求头参数完整性
|
||||
String reqAppId = request.getHeader("X-Tsign-Open-App-Id");
|
||||
//异步通知获取到的header头中的签名值:X-Tsign-Open-SIGNATURE
|
||||
String signture = request.getHeader("X-Tsign-Open-SIGNATURE");
|
||||
//异步通知获取到的header头中的时间戳:X-Tsign-Open-TIMESTAMP
|
||||
String signature = request.getHeader("X-Tsign-Open-SIGNATURE");
|
||||
String timestamp = request.getHeader("X-Tsign-Open-TIMESTAMP");
|
||||
|
||||
if (StrUtil.isBlank(reqAppId) || StrUtil.isBlank(signture) || StrUtil.isBlank(timestamp)) {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new JSONObject().put("code", 400).put("msg", "缺少必要参数").toString());
|
||||
if (StrUtil.isBlank(reqAppId) || StrUtil.isBlank(signature) || StrUtil.isBlank(timestamp)) {
|
||||
log.warn("e签宝异步通知缺少必要参数: reqAppId={}, signature={}, timestamp={}", reqAppId, signature, timestamp);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(new JSONObject().put("code", 400).put("msg", "缺少必要参数").toString());
|
||||
}
|
||||
|
||||
// 2. 验证AppId是否匹配
|
||||
if (!reqAppId.equals(appId)) {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new JSONObject().put("code", 400).put("msg", "appId 有误").toString());
|
||||
log.warn("e签宝异步通知AppId不匹配: 请求AppId={}, 配置AppId={}", reqAppId, appId);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(new JSONObject().put("code", 400).put("msg", "appId 有误").toString());
|
||||
}
|
||||
|
||||
//按照规则进行加密
|
||||
// 3. 验证签名
|
||||
String signData = timestamp + requestBody;
|
||||
String mySignature = getSignature(signData, appSecret, "HmacSHA256", "UTF-8");
|
||||
log.debug("加密出来的签名值:----------->>>>>>" + mySignature);
|
||||
log.debug("header里面的签名值:---------->>>>>>" + signture);
|
||||
if (!mySignature.equals(signture)) {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new JSONObject().put("code", 400).put("msg", "签名校验失败").toString());
|
||||
|
||||
// 签名生成失败处理
|
||||
if (mySignature == null) {
|
||||
log.error("生成签名失败,signData: {}", signData);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(new JSONObject().put("code", 400).put("msg", "签名生成失败").toString());
|
||||
}
|
||||
|
||||
log.debug("加密出来的签名值:----------->>>>>> {}", mySignature);
|
||||
log.debug("header里面的签名值:---------->>>>>> {}", signature);
|
||||
|
||||
if (!mySignature.equals(signature)) {
|
||||
log.warn("e签宝异步通知签名校验失败: 计算签名={}, 请求签名={}", mySignature, signature);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(new JSONObject().put("code", 400).put("msg", "签名校验失败").toString());
|
||||
}
|
||||
|
||||
// 4. 解析请求体数据
|
||||
JSONObject reqBodyJSON;
|
||||
try {
|
||||
reqBodyJSON = JSONUtil.parseObj(requestBody);
|
||||
} catch (Exception e) {
|
||||
log.error("解析e签宝异步通知请求体失败: requestBody={}", requestBody, e);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(new JSONObject().put("code", 400).put("msg", "请求体格式错误").toString());
|
||||
}
|
||||
|
||||
// 处理业务逻辑
|
||||
JSONObject reqBodyJSON = JSONUtil.parseObj(requestBody);
|
||||
String action = reqBodyJSON.getStr("action");
|
||||
String signFlowId = reqBodyJSON.getStr("signFlowId");
|
||||
Integer signResult = reqBodyJSON.getInt("signResult");
|
||||
|
||||
if (StrUtil.isBlank(action) || StrUtil.isBlank(signFlowId)) {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new JSONObject().put("code", 400).put("msg", "返回数据有误").toString());
|
||||
log.warn("e签宝异步通知缺少必要业务参数: action={}, signFlowId={}", action, signFlowId);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(new JSONObject().put("code", 400).put("msg", "返回数据有误").toString());
|
||||
}
|
||||
|
||||
// 获取合同签署记录
|
||||
EsignContract esignContract = baseMapper.selectOne(new QueryWrapper<EsignContract>().eq("sign_flow_id", signFlowId));
|
||||
if (esignContract == null) {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new JSONObject().put("code", 400).put("msg", "获取不到合同记录").toString());
|
||||
// 5. 获取合同签署记录
|
||||
EsignContract esignContract;
|
||||
try {
|
||||
esignContract = baseMapper.selectOne(new QueryWrapper<EsignContract>().eq("sign_flow_id", signFlowId));
|
||||
if (esignContract == null) {
|
||||
log.warn("未找到对应的合同记录: signFlowId={}", signFlowId);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(new JSONObject().put("code", 400).put("msg", "获取不到合同记录").toString());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("查询合同记录异常: signFlowId={}", signFlowId, e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(new JSONObject().put("code", 500).put("msg", "查询合同记录异常").toString());
|
||||
}
|
||||
|
||||
log.debug("签署流程结束通知:action >>> {}", action);
|
||||
if (CommonConstant.CONTRACT_SIGN_STA_FINISH.equals(esignContract.getSign_flow_status()) && StrUtil.isNotEmpty(esignContract.getLocal_contract_url())) {
|
||||
// 已经签署完毕,不用在更改状态
|
||||
|
||||
// 6. 如果合同已经完成且已有本地文件URL,则直接返回成功
|
||||
if (CommonConstant.CONTRACT_SIGN_STA_FINISH.equals(esignContract.getSign_flow_status())
|
||||
&& StrUtil.isNotEmpty(esignContract.getLocal_contract_url())) {
|
||||
log.debug("合同已处理完成,无需重复处理: signFlowId={}", signFlowId);
|
||||
return ResponseEntity.ok(new JSONObject().put("code", 200).put("msg", "success").toString());
|
||||
}
|
||||
|
||||
// 获取正式盖章合同文件,上传到 oss 服务器,更状态,保存数据
|
||||
if (action.equals("SIGN_FLOW_COMPLETE")) {// 签署流程完毕
|
||||
log.debug("签署流程完毕,开始处理业务逻辑");
|
||||
// 获取正式盖章合同文件地址
|
||||
String downloadUrl = getSignedContractFileUrl(signFlowId);
|
||||
// 7. 根据不同动作类型处理业务逻辑
|
||||
try {
|
||||
// 签署流程完毕
|
||||
if ("SIGN_FLOW_COMPLETE".equals(action)) {
|
||||
log.debug("签署流程完毕,开始处理业务逻辑: signFlowId={}", signFlowId);
|
||||
|
||||
// 更新合同流程状态和文件地址
|
||||
boolean success = updateContractFlowStatusAndFileUrlBySignFlowId(signFlowId, CommonConstant.CONTRACT_SIGN_STA_FINISH, downloadUrl);
|
||||
if (success && StrUtil.isNotBlank(downloadUrl)) {
|
||||
|
||||
// 1、(电子合同)给商家申请分账功能使用;务必检查是否申请过?申请过忽略
|
||||
Pair<Boolean, String> retPair = lakalaApiService.innerApplyLedgerMer("", false);
|
||||
if (!retPair.getFirst()) {
|
||||
log.error("商家申请分账业务异常:{}", retPair.getSecond());
|
||||
// 获取正式盖章合同文件地址
|
||||
String downloadUrl = getSignedContractFileUrl(signFlowId);
|
||||
if (StrUtil.isBlank(downloadUrl)) {
|
||||
log.warn("获取签署完成的合同文件URL失败: signFlowId={}", signFlowId);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(new JSONObject().put("code", 500).put("msg", "获取合同文件失败").toString());
|
||||
}
|
||||
|
||||
// TODO mchId 必填字段,更新商家的hasEsigned状态=1
|
||||
shopMchEntryService.updateMulStatus(0L, "", 1, 0, 0, 0, 0, 0, CommonConstant.MCH_APPR_STA_LKL_PADDING);
|
||||
// 更新合同流程状态和文件地址
|
||||
boolean success = updateContractFlowStatusAndFileUrlBySignFlowId(
|
||||
signFlowId,
|
||||
CommonConstant.CONTRACT_SIGN_STA_FINISH,
|
||||
downloadUrl);
|
||||
|
||||
if (success) {
|
||||
log.info("合同签署完成处理成功: signFlowId={}", signFlowId);
|
||||
return ResponseEntity.ok(new JSONObject().put("code", 200).put("msg", "success").toString());
|
||||
} else {
|
||||
log.error("更新合同流程状态失败: signFlowId={}", signFlowId);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(new JSONObject().put("code", 500).put("msg", "更新合同状态失败").toString());
|
||||
}
|
||||
}
|
||||
// 签署方签署结果通知(含拒签)
|
||||
else if ("SIGN_MISSON_COMPLETE".equals(action) && ObjectUtil.isNotEmpty(signResult)) {
|
||||
Integer signFlowStatus = null;
|
||||
|
||||
// 根据签署结果确定合同状态
|
||||
if (Integer.valueOf(2).equals(signResult)) {
|
||||
signFlowStatus = CommonConstant.CONTRACT_SIGN_STA_PARTIALLY;
|
||||
} else if (Integer.valueOf(4).equals(signResult)) {
|
||||
signFlowStatus = CommonConstant.CONTRACT_SIGN_STA_REJECT;
|
||||
}
|
||||
|
||||
if (signFlowStatus == null) {
|
||||
log.warn("未知的签署结果类型: signResult={}", signResult);
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
|
||||
.body(new JSONObject().put("code", 400).put("msg", "未知的签署结果").toString());
|
||||
}
|
||||
|
||||
// 更新合同流程状态
|
||||
boolean success = updateContractFlowStatusAndFileUrlBySignFlowId(signFlowId, signFlowStatus, "");
|
||||
if (success) {
|
||||
log.info("签署任务完成处理成功: signFlowId={}, signResult={}, status={}",
|
||||
signFlowId, signResult, signFlowStatus);
|
||||
return ResponseEntity.ok(new JSONObject().put("code", 200).put("msg", "success").toString());
|
||||
} else {
|
||||
log.error("更新合同流程状态失败: signFlowId={}, signResult={}", signFlowId, signResult);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(new JSONObject().put("code", 500).put("msg", "更新合同状态失败").toString());
|
||||
}
|
||||
}
|
||||
// 其他情况,记录日志但不处理
|
||||
else {
|
||||
log.debug("签署流程未完成或未知动作类型,不做处理: action={}, signFlowId={}", action, signFlowId);
|
||||
return ResponseEntity.ok(new JSONObject().put("code", 200).put("msg", "success").toString());
|
||||
}
|
||||
} else if (action.equals("SIGN_MISSON_COMPLETE") && ObjectUtil.isNotEmpty(signResult)) {// 签署方-签署结果(含拒签)通知
|
||||
Integer signFlowStatus = null;
|
||||
if (signResult.equals(2)) {
|
||||
signFlowStatus = CommonConstant.CONTRACT_SIGN_STA_PARTIALLY;
|
||||
} else if (signResult.equals(4)) {
|
||||
signFlowStatus = CommonConstant.CONTRACT_SIGN_STA_REJECT;
|
||||
}
|
||||
// 更新合同流程状态和文件地址
|
||||
boolean success = updateContractFlowStatusAndFileUrlBySignFlowId(signFlowId, signFlowStatus, "");
|
||||
if (success) {
|
||||
return ResponseEntity.ok(new JSONObject().put("code", 200).put("msg", "success").toString());
|
||||
}
|
||||
} else {
|
||||
log.debug("签署流程未完成,不做处理");
|
||||
} catch (Exception e) {
|
||||
log.error("处理e签宝异步通知异常: action={}, signFlowId={}", action, signFlowId, e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(new JSONObject().put("code", 500).put("msg", "处理通知异常").toString());
|
||||
}
|
||||
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new JSONObject().put("code", 400).put("msg", "未更新数据!").toString());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 管理员查看已签署的电子合同文件
|
||||
*
|
||||
* @param mchMobile
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public CommonResult getSignedContactFile(String mchMobile) {
|
||||
String userId = "0";
|
||||
|
||||
// UserDto user = getCurrentUser();
|
||||
// if (!user.isAdmin()) {
|
||||
// return CommonResult.failed("权限不足!");
|
||||
// }
|
||||
// userId = user.getId().toString();
|
||||
|
||||
EsignContract esignContract = getEsignContractByMchMobile(mchMobile);
|
||||
public CommonResult getSignedContactFile(Integer storeId) {
|
||||
EsignContract esignContract = getEsignContractByStoreId(storeId);
|
||||
if (esignContract == null) {
|
||||
return CommonResult.success(null, "未找到商家合同信息");
|
||||
}
|
||||
@ -583,22 +634,86 @@ public class EsignContractServiceImpl extends BaseServiceImpl<EsignContractMappe
|
||||
/**
|
||||
* 根据商家注册手机号,获取一条合同信息
|
||||
*
|
||||
* @param mchMobile
|
||||
* @return
|
||||
* @param mchMobile 商家注册手机号
|
||||
* @return EsignContract 合同信息对象,若未找到则返回null
|
||||
*/
|
||||
@Override
|
||||
public EsignContract getEsignContractByMchMobile(String mchMobile) {
|
||||
QueryWrapper<EsignContract> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("mch_mobile", mchMobile);
|
||||
queryWrapper.eq("status", CommonConstant.Enable);
|
||||
List<EsignContract> esignContractList = this.list(queryWrapper);
|
||||
if (CollectionUtil.isEmpty(esignContractList)) {
|
||||
// 参数校验
|
||||
if (StrUtil.isBlank(mchMobile)) {
|
||||
log.warn("查询合同信息失败:商家手机号为空");
|
||||
return null;
|
||||
}
|
||||
|
||||
return esignContractList.get(0);
|
||||
try {
|
||||
QueryWrapper<EsignContract> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("mch_mobile", mchMobile);
|
||||
queryWrapper.eq("status", CommonConstant.Enable);
|
||||
|
||||
return findOne(queryWrapper);
|
||||
} catch (Exception e) {
|
||||
log.error("根据商家手机号查询合同信息异常,手机号: {}", mchMobile, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据店铺Id,获取一条合同信息
|
||||
*
|
||||
* @param storeId 店铺ID
|
||||
* @return EsignContract 合同信息对象,若未找到则返回null
|
||||
*/
|
||||
@Override
|
||||
public EsignContract getEsignContractByStoreId(Integer storeId) {
|
||||
// 参数校验
|
||||
if (storeId == null) {
|
||||
log.warn("查询合同信息失败:店铺ID为空");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
QueryWrapper<EsignContract> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("store_id", storeId);
|
||||
queryWrapper.eq("status", CommonConstant.Enable);
|
||||
|
||||
return findOne(queryWrapper);
|
||||
} catch (Exception e) {
|
||||
log.error("根据店铺ID查询合同信息异常,店铺ID: {}", storeId, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据店铺Id,获取合同状态和下载地址
|
||||
*
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public EsignContract getEsignContractStatusUrl(Integer storeId) {
|
||||
// 参数校验
|
||||
if (storeId == null) {
|
||||
log.warn("查询合同状态和URL失败:店铺ID为空");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
LambdaQueryWrapper<EsignContract> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(EsignContract::getStore_id, storeId)
|
||||
.eq(EsignContract::getStatus, CommonConstant.Enable)
|
||||
.eq(EsignContract::getSign_flow_status, CommonConstant.CONTRACT_SIGN_STA_FINISH)
|
||||
.isNotNull(EsignContract::getLocal_contract_url)
|
||||
.ne(EsignContract::getLocal_contract_url, "")
|
||||
.select(EsignContract::getSign_flow_status, EsignContract::getLocal_contract_url);
|
||||
|
||||
return findOne(queryWrapper);
|
||||
} catch (Exception e) {
|
||||
log.error("根据店铺ID查询合同状态和URL异常,店铺ID: {}", storeId, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public EsignContract getEsignContractBySignFlowId(String signFlowId) {
|
||||
QueryWrapper<EsignContract> queryWrapper = new QueryWrapper<>();
|
||||
|
||||
@ -149,12 +149,7 @@ public class EsignPlatformInfoServiceImpl extends BaseServiceImpl<EsignPlatformI
|
||||
queryWrapper.eq("license_number", licenseNumber);
|
||||
}
|
||||
|
||||
List<EsignPlatformInfo> esignPlatformInfos = list(queryWrapper);
|
||||
if (CollectionUtil.isEmpty(esignPlatformInfos)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return esignPlatformInfos.get(0);
|
||||
return findOne(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -14,13 +14,13 @@ import com.suisung.mall.common.api.CommonResult;
|
||||
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
||||
import com.suisung.mall.shop.lakala.service.LakalaApiService;
|
||||
import com.suisung.mall.shop.lakala.service.LklLedgerEcService;
|
||||
import com.suisung.mall.shop.lakala.service.LklLedgerReceiverService;
|
||||
import com.suisung.mall.shop.library.service.LibraryProductService;
|
||||
import com.suisung.mall.shop.message.service.MqMessageService;
|
||||
import com.suisung.mall.shop.message.service.PushMessageService;
|
||||
import com.suisung.mall.shop.order.service.ShopOrderBaseService;
|
||||
import com.suisung.mall.shop.order.service.ShopOrderReturnService;
|
||||
import com.suisung.mall.shop.sfexpress.service.SFExpressApiService;
|
||||
import com.suisung.mall.shop.store.service.ShopStorePrinterService;
|
||||
import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
@ -78,13 +78,11 @@ public class LakalaController extends BaseControllerImpl {
|
||||
|
||||
@Lazy
|
||||
@Resource
|
||||
private LakalaApiService lakalaApiService;
|
||||
private ShopStorePrinterService shopStorePrinterService;
|
||||
|
||||
@Resource
|
||||
private LklLedgerEcService lklLedgerEcService;
|
||||
|
||||
@Resource
|
||||
private LklLedgerReceiverService lklLedgerReceiverService;
|
||||
|
||||
@ApiOperation(value = "测试案例", notes = "测试案例")
|
||||
@RequestMapping(value = "/testcase", method = RequestMethod.POST)
|
||||
@ -94,7 +92,9 @@ public class LakalaController extends BaseControllerImpl {
|
||||
|
||||
// return lakalaApiService.ewalletWithDrawNotify(null, paramsJSON.getStr("a"), paramsJSON.getStr("b"));
|
||||
|
||||
return lakalaApiService.tradeQuery(paramsJSON.getInt("storeId"), paramsJSON.getStr("orderId"));
|
||||
// return lakalaApiService.tradeQuery(paramsJSON.getInt("storeId"), paramsJSON.getStr("orderId"));
|
||||
|
||||
return shopStorePrinterService.printShopStoreReturnOrder(paramsJSON.getStr("returnId"));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "批量发送推送消息 - 测试案例", notes = "批量发送推送消息 - 测试案例")
|
||||
@ -119,8 +119,8 @@ public class LakalaController extends BaseControllerImpl {
|
||||
return lakalaPayService.getBankCardBin(paramsJSON.getStr("bankCardNo"));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "发货类交易确认收货通知", notes = "发货类交易确认收货通知 https://o.lakala.com/#/home/document/detail?id=1003")
|
||||
@RequestMapping(value = "/trans/receive/completeNotify", method = RequestMethod.POST)
|
||||
@ApiOperation(value = "接收拉卡拉发货类交易确认收货通知", notes = "接收拉卡拉发货类交易确认收货通知 https://o.lakala.com/#/home/document/detail?id=1003")
|
||||
@RequestMapping(value = "/trans/receive/completeNotify", method = {RequestMethod.POST, RequestMethod.GET})
|
||||
public ResponseEntity<JSONObject> receiveCompleteNotify(HttpServletRequest request) {
|
||||
// 完整地址: https://mall.gpxscs.cn/api/mobile/shop/lakala/trans/receive/completeNotify
|
||||
JSONObject resp = lakalaPayService.receiveCompleteNotify(request);
|
||||
|
||||
@ -27,6 +27,7 @@ import com.suisung.mall.common.api.CommonResult;
|
||||
import com.suisung.mall.common.constant.CommonConstant;
|
||||
import com.suisung.mall.common.exception.ApiException;
|
||||
import com.suisung.mall.common.feignService.ShopService;
|
||||
import com.suisung.mall.common.modules.esign.EsignPlatformInfo;
|
||||
import com.suisung.mall.common.modules.lakala.*;
|
||||
import com.suisung.mall.common.modules.order.ShopOrderLkl;
|
||||
import com.suisung.mall.common.modules.store.ShopMchEntry;
|
||||
@ -54,6 +55,7 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -470,7 +472,17 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
// 7. 构建合同参数
|
||||
LocalDate today = LocalDate.now();
|
||||
String signDate = DateTimeUtils.formatLocalDate(today, "yyyy-MM-dd");
|
||||
|
||||
// 2. 获取平台方信息
|
||||
String platformName = "桂平发发网络有限公司";
|
||||
String platMobile = "17777525395"; // 平台联系电话
|
||||
EsignPlatformInfo esignPlatformInfo = esignPlatformInfoService.getEsignPlatformInfo(0, "");
|
||||
if (!ObjectUtils.isEmpty(esignPlatformInfo)
|
||||
&& StrUtil.isNotBlank(esignPlatformInfo.getLicense_company())
|
||||
&& StrUtil.isNotBlank(esignPlatformInfo.getTelephone())) {
|
||||
platformName = esignPlatformInfo.getLicense_company();
|
||||
platMobile = esignPlatformInfo.getTelephone();
|
||||
}
|
||||
|
||||
JSONObject ecParams = new JSONObject();
|
||||
ecParams.put("A1", isQy ? shopMchEntry.getBiz_license_company() : shopMchEntry.getAccount_holder_name());
|
||||
@ -511,7 +523,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
ecParams.put("D1", shopMchEntry.getBank_name());
|
||||
ecParams.put("D2", signDate);
|
||||
ecParams.put("D4", platformName);
|
||||
ecParams.put("D5", contractMobile);
|
||||
ecParams.put("D5", platMobile);
|
||||
ecParams.put("D7", signDate);
|
||||
ecParams.put("D9", signDate);
|
||||
ecParams.put("D11", signDate);
|
||||
@ -811,6 +823,14 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
Pair<Boolean, String> checkResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath, false);
|
||||
if (!checkResult.getFirst()) {
|
||||
log.warn("[确认收货通知] 验签失败: {}", checkResult.getSecond());
|
||||
|
||||
try {
|
||||
// 不管成功与否,写入确认收货通知日志,后续补偿遗漏分账的材料
|
||||
lklReceiveNotifyLogService.addOrUpdate(LakalaUtil.getBody(request));
|
||||
} catch (Exception e) {
|
||||
log.error("[确认收货通知] 写入确认收货通知日志失败", e);
|
||||
}
|
||||
|
||||
return JSONUtil.createObj().set("code", "FAIL").set("message", checkResult.getSecond());
|
||||
}
|
||||
|
||||
|
||||
@ -54,27 +54,9 @@ public class MqMessageServiceImpl extends BaseServiceImpl<MqMessageMapper, MqMes
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
String jsonString = null;
|
||||
|
||||
try {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
jsonString = objectMapper.writeValueAsString(data);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
MessageProperties properties = new MessageProperties();
|
||||
properties.setMessageId(uuid);
|
||||
Message message = new Message(jsonString.getBytes(StandardCharsets.UTF_8), properties);
|
||||
|
||||
rabbitTemplate.convertAndSend(exchange, routing_key, message, new CorrelationData(uuid));
|
||||
*/
|
||||
|
||||
// 使用 MessageBuilder 确保设置 messageId
|
||||
Message message = MessageBuilder.withBody(data.toString().getBytes(StandardCharsets.UTF_8))
|
||||
.setHeader("messageId", uuid) // 添加自定义头部存储消息ID
|
||||
// .setContentType("text/plain") // 明确指定内容类型
|
||||
.setMessageId(uuid) // 设置标准 messageId 属性
|
||||
.build();
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ package com.suisung.mall.shop.number.service;
|
||||
|
||||
import com.suisung.mall.common.modules.number.ShopNumberSeq;
|
||||
import com.suisung.mall.core.web.service.IBaseService;
|
||||
import org.springframework.data.util.Pair;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -17,6 +18,14 @@ public interface ShopNumberSeqService extends IBaseService<ShopNumberSeq> {
|
||||
|
||||
String createNextSeq(String prefix);
|
||||
|
||||
/**
|
||||
* 创建下一个编号(键值对)
|
||||
*
|
||||
* @param prefix 前缀
|
||||
* @return 序号和完整编号
|
||||
*/
|
||||
Pair<Long, String> createNextSeqPair(String prefix);
|
||||
|
||||
Long createNextNo(String prefix);
|
||||
|
||||
List<Long> batchCreateNextNo(String seqName, int batchSize);
|
||||
|
||||
@ -27,6 +27,7 @@ import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
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.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -125,6 +126,44 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到下一个编号键值对
|
||||
* 方法走到这里会产生串行化,集群部署这里不能使用单机锁
|
||||
*
|
||||
* @param prefix
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.NOT_SUPPORTED)
|
||||
@DistributedLock(
|
||||
key = "CREATENEXTSEQ_LOCK", // 锁的key
|
||||
waitTime = 3, // 等待3秒
|
||||
leaseTime = 10, // 锁持有10秒
|
||||
errorMsg = "生成ID繁忙,请稍后重试" // 自定义错误消息
|
||||
)
|
||||
public synchronized Pair<Long, String> createNextSeqPair(String prefix) {
|
||||
String ymd = DateUtil.format(new Date(), "yyyyMMdd");
|
||||
String id = String.format("%s_%s_", prefix, ymd);
|
||||
ShopNumberSeq shopNumberSeq = this.baseMapper.selectById(id);
|
||||
if (shopNumberSeq == null) {
|
||||
shopNumberSeq = new ShopNumberSeq();
|
||||
shopNumberSeq.setPrefix(id);
|
||||
shopNumberSeq.setNumber(1L);
|
||||
if (!save(shopNumberSeq)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String order_id = String.format("%s_%s_%s", prefix, ymd, shopNumberSeq.getNumber());
|
||||
shopNumberSeq.setPrefix(id);
|
||||
boolean flag = edit(shopNumberSeq);
|
||||
if (flag) {
|
||||
return Pair.of(shopNumberSeq.getNumber(), order_id);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到下一个Id
|
||||
*
|
||||
@ -280,12 +319,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
boolean isLocked = false;
|
||||
int start = 0;
|
||||
try {
|
||||
isLocked = lock.tryLock(2, 30, TimeUnit.SECONDS);
|
||||
isLocked = lock.tryLock(2, 30, TimeUnit.SECONDS);
|
||||
if (!isLocked) {
|
||||
// 获取锁失败,可以根据业务逻辑进行重试或抛出异常
|
||||
throw new RuntimeException("系统繁忙,请稍后再试");
|
||||
}
|
||||
log.info("成功获得锁:{}",lockKey);
|
||||
log.info("成功获得锁:{}", lockKey);
|
||||
if (null != redisService.get(RedisKey.STOREDATASPECID)) {
|
||||
start = (Integer) redisService.get(RedisKey.STOREDATASPECID);
|
||||
redisService.set(RedisKey.STOREDATASPECID, start + batchSize);
|
||||
@ -305,12 +344,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
return IntStream.rangeClosed(start + 1, start + batchSize).boxed().collect(Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
throw new ApiException(e);
|
||||
}finally {
|
||||
} finally {
|
||||
// 5. 最终检查并释放锁,确保锁一定被释放
|
||||
if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
log.info("成功释放锁:{}",lockKey);
|
||||
log.info("成功释放锁:{}", lockKey);
|
||||
}
|
||||
|
||||
}
|
||||
@ -322,7 +361,7 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<Integer> getBatchSpecItemId(int batchSize) {
|
||||
public List<Integer> getBatchSpecItemId(int batchSize) {
|
||||
// 定义锁的key,这个key在所有服务实例中必须一致
|
||||
String lockKey = "LOCK:" + RedisKey.STOREDATASPECITEMID;
|
||||
// 2. 获取分布式锁对象
|
||||
@ -330,12 +369,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
boolean isLocked = false;
|
||||
int start = 0;
|
||||
try {
|
||||
isLocked=lock.tryLock(2,30,TimeUnit.SECONDS);
|
||||
isLocked = lock.tryLock(2, 30, TimeUnit.SECONDS);
|
||||
if (!isLocked) {
|
||||
// 获取锁失败,可以根据业务逻辑进行重试或抛出异常
|
||||
throw new ApiException("系统繁忙,请稍后再试");
|
||||
}
|
||||
log.info("成功获得锁:{}",lockKey);
|
||||
log.info("成功获得锁:{}", lockKey);
|
||||
if (null != redisService.get(RedisKey.STOREDATASPECITEMID)) {
|
||||
start = (Integer) redisService.get(RedisKey.STOREDATASPECITEMID);
|
||||
redisService.set(RedisKey.STOREDATASPECITEMID, start + batchSize);
|
||||
@ -355,12 +394,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
return IntStream.rangeClosed(start + 1, start + batchSize).boxed().collect(Collectors.toList());
|
||||
} catch (InterruptedException e) {
|
||||
throw new ApiException(e);
|
||||
}finally {
|
||||
} finally {
|
||||
// 5. 最终检查并释放锁,确保锁一定被释放
|
||||
if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
log.info("成功释放锁:{}",lockKey);
|
||||
log.info("成功释放锁:{}", lockKey);
|
||||
}
|
||||
}
|
||||
|
||||
@ -383,7 +422,7 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
// 获取锁失败,可以根据业务逻辑进行重试或抛出异常
|
||||
throw new RuntimeException("系统繁忙,请稍后再试");
|
||||
}
|
||||
log.info("成功获得锁:{}",lockKey);
|
||||
log.info("成功获得锁:{}", lockKey);
|
||||
int start = 0;
|
||||
if (null != redisService.get(RedisKey.STOREDATACCOUNTBASEID)) {
|
||||
start = (Integer) redisService.get(RedisKey.STOREDATACCOUNTBASEID);
|
||||
@ -403,12 +442,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("getBatchUserAccountBaseId获取锁时被中断", e);
|
||||
}finally {
|
||||
} finally {
|
||||
// 5. 最终检查并释放锁,确保锁一定被释放
|
||||
if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
log.info("成功释放锁:{}",lockKey);
|
||||
log.info("成功释放锁:{}", lockKey);
|
||||
}
|
||||
|
||||
}
|
||||
@ -421,7 +460,7 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<Integer> getBatchLibraryProductId(int batchSize) {
|
||||
public List<Integer> getBatchLibraryProductId(int batchSize) {
|
||||
// 定义锁的key,这个key在所有服务实例中必须一致
|
||||
String lockKey = "LOCK:" + RedisKey.STOREDATALIBRARYID;
|
||||
// 2. 获取分布式锁对象
|
||||
@ -434,7 +473,7 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
// 获取锁失败,可以根据业务逻辑进行重试或抛出异常
|
||||
throw new RuntimeException("系统繁忙,请稍后再试");
|
||||
}
|
||||
log.info("成功获得锁:{}",lockKey);
|
||||
log.info("成功获得锁:{}", lockKey);
|
||||
if (null != redisService.get(RedisKey.STOREDATALIBRARYID)) {
|
||||
start = (Integer) redisService.get(RedisKey.STOREDATALIBRARYID);
|
||||
redisService.set(RedisKey.STOREDATALIBRARYID, start + batchSize);
|
||||
@ -454,12 +493,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
return IntStream.rangeClosed(start + 1, start + batchSize).boxed().collect(Collectors.toList());
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}finally {
|
||||
} finally {
|
||||
// 5. 最终检查并释放锁,确保锁一定被释放
|
||||
if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
log.info("成功释放锁:{}",lockKey);
|
||||
log.info("成功释放锁:{}", lockKey);
|
||||
}
|
||||
|
||||
}
|
||||
@ -478,12 +517,12 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
boolean isLocked = false;
|
||||
long start = 0;
|
||||
try {
|
||||
isLocked=lock.tryLock(2,30,TimeUnit.SECONDS);
|
||||
isLocked = lock.tryLock(2, 30, TimeUnit.SECONDS);
|
||||
if (!isLocked) {
|
||||
// 获取锁失败,可以根据业务逻辑进行重试或抛出异常
|
||||
throw new ApiException("系统繁忙,请稍后再试");
|
||||
}
|
||||
log.info("成功获得锁:{}",lockKey);
|
||||
log.info("成功获得锁:{}", lockKey);
|
||||
QueryWrapper<ShopPageBase> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.select("max(page_id) as page_id");
|
||||
ShopPageBase shopPageBase = shopPageBaseService.getOne(queryWrapper);
|
||||
@ -493,41 +532,41 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
return LongStream.rangeClosed(start + 1, start + batchSize).boxed().collect(Collectors.toList());
|
||||
} catch (InterruptedException e) {
|
||||
throw new ApiException(e);
|
||||
}finally {
|
||||
} finally {
|
||||
// 5. 最终检查并释放锁,确保锁一定被释放
|
||||
if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
log.info("成功释放锁:{}",lockKey);
|
||||
log.info("成功释放锁:{}", lockKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化主键
|
||||
*/
|
||||
private void syncPrimaryKey(){
|
||||
List<ShopNumberSeq> shopNumberSeqList=new ArrayList<>();
|
||||
QueryWrapper<ShopProductBase> baseWrapper=new QueryWrapper<>();
|
||||
private void syncPrimaryKey() {
|
||||
List<ShopNumberSeq> shopNumberSeqList = new ArrayList<>();
|
||||
QueryWrapper<ShopProductBase> baseWrapper = new QueryWrapper<>();
|
||||
baseWrapper.select("MAX(product_id) as product_id");
|
||||
ShopProductBase shopProductBase= shopProductBaseService.getOne(baseWrapper);
|
||||
Long productId= shopProductBase.getProduct_id();
|
||||
ShopProductBase shopProductBase = shopProductBaseService.getOne(baseWrapper);
|
||||
Long productId = shopProductBase.getProduct_id();
|
||||
//QueryWrapper<ShopNumberSeq> baseSeWrapper=new QueryWrapper();
|
||||
//baseSeWrapper.eq("prefix", "product_id");
|
||||
ShopNumberSeq shopNumberSeqBase= new ShopNumberSeq();
|
||||
ShopNumberSeq shopNumberSeqBase = new ShopNumberSeq();
|
||||
shopNumberSeqBase.setPrefix("product_id");
|
||||
shopNumberSeqBase.setNumber(productId);
|
||||
//shopNumberSeqServiceImpl.edit(shopNumberSeqBase,baseWrapper);
|
||||
//查询产品item
|
||||
QueryWrapper<ShopProductItem> itemQuery=new QueryWrapper<>();
|
||||
QueryWrapper<ShopProductItem> itemQuery = new QueryWrapper<>();
|
||||
itemQuery.select("MAX(item_id) as item_id");
|
||||
ShopProductItem shopProductItem= shopProductItemService.getOne(itemQuery);
|
||||
Long itemtId=1L;
|
||||
if(null!=shopProductItem){
|
||||
itemtId= shopProductItem.getItem_id();
|
||||
ShopProductItem shopProductItem = shopProductItemService.getOne(itemQuery);
|
||||
Long itemtId = 1L;
|
||||
if (null != shopProductItem) {
|
||||
itemtId = shopProductItem.getItem_id();
|
||||
}
|
||||
// QueryWrapper<ShopNumberSeq> itemWrapper=new QueryWrapper();
|
||||
//itemWrapper.eq("prefix", "item_id");
|
||||
ShopNumberSeq shopNumberSeqItem= new ShopNumberSeq();
|
||||
ShopNumberSeq shopNumberSeqItem = new ShopNumberSeq();
|
||||
shopNumberSeqItem.setNumber(itemtId);
|
||||
shopNumberSeqItem.setPrefix("item_id");
|
||||
shopNumberSeqList.add(shopNumberSeqBase);
|
||||
@ -537,5 +576,4 @@ public class ShopNumberSeqServiceImpl extends BaseServiceImpl<ShopNumberSeqMappe
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -30,7 +30,6 @@ public class MessageListener {
|
||||
listener(dataStr, channel, message);
|
||||
}
|
||||
|
||||
// @RabbitHandler
|
||||
public void listener(String data, Channel channel, Message message) {
|
||||
MsgTO msgTO = JSONUtil.toBean(data, MsgTO.class);
|
||||
String messageId = message.getMessageProperties().getMessageId();
|
||||
|
||||
@ -69,8 +69,7 @@ public class OrderPayedListener {
|
||||
String dataStr = new String(data, StandardCharsets.UTF_8);
|
||||
listener(dataStr, channel, message);
|
||||
}
|
||||
|
||||
// @RabbitHandler
|
||||
|
||||
public void listener(String data, Channel channel, Message message) throws IOException, InterruptedException {
|
||||
// String messageId = message.getMessageProperties().getMessageId();
|
||||
if (StrUtil.isBlank(data)) {
|
||||
@ -115,28 +114,20 @@ public class OrderPayedListener {
|
||||
|
||||
// 检查订单是否已经处理过(幂等性检查)
|
||||
if (isOrderPaid(orderInfoOld)) {
|
||||
logger.info("[订单支付监听] 订单已支付,无需重复处理,订单ID: {}", orderId);
|
||||
logger.debug("[订单支付监听] 订单已支付,无需重复处理,订单ID: {}", orderId);
|
||||
flag = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (order_state_id == StateCode.ORDER_STATE_WAIT_PAY) {
|
||||
// 待支付状态
|
||||
logger.info("[订单支付监听] 处理待支付订单. 订单ID: {}", orderId);
|
||||
flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId));
|
||||
if (StateCode.PAYMENT_TYPE_OFFLINE == orderInfoOld.getPayment_type_id().intValue()) {
|
||||
logger.debug("[订单支付监听] 处理线下支付订单. 订单ID: {}", orderId);
|
||||
ShopOrderInfo orderInfo = new ShopOrderInfo();
|
||||
orderInfo.setOrder_id(orderId);
|
||||
orderInfo.setOrder_is_paid(StateCode.ORDER_PAID_STATE_YES);
|
||||
flag = shopOrderInfoService.edit(orderInfo);
|
||||
} else {
|
||||
//判断是否线下支付
|
||||
if (StateCode.PAYMENT_TYPE_OFFLINE == orderInfoOld.getPayment_type_id().intValue()) {
|
||||
//线下支付,直接处理订单支付状态, 不处理订单状态
|
||||
logger.info("[订单支付监听] 处理线下支付订单. 订单ID: {}", orderId);
|
||||
ShopOrderInfo orderInfo = new ShopOrderInfo();
|
||||
orderInfo.setOrder_id(orderId);
|
||||
orderInfo.setOrder_is_paid(StateCode.ORDER_PAID_STATE_YES);
|
||||
flag = shopOrderInfoService.edit(orderInfo);
|
||||
} else {
|
||||
logger.info("[订单支付监听] 处理其他支付订单. 订单ID: {}", orderId);
|
||||
flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId));
|
||||
}
|
||||
logger.debug("[订单支付监听] 处理支付订单. 订单ID: {}", orderId);
|
||||
flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId));
|
||||
}
|
||||
|
||||
logger.info("[订单支付监听] 订单ID: {},支付异步通知回调处理是否成功: {} ", flag, orderId);
|
||||
|
||||
@ -4,6 +4,7 @@ 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.order.ShopOrderReturn;
|
||||
import com.suisung.mall.common.pojo.vo.OrderPrintVO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@ -30,4 +31,13 @@ public interface ShopOrderReturnMapper extends BaseMapper<ShopOrderReturn> {
|
||||
List<Map<String, Object>> statisticCountSeller(@Param("end") Date end, @Param("days") int days, @Param("store_id") int store_id);
|
||||
|
||||
IPage<Map> getReturnGroupByOrderId(Page<Map> page, @Param("map") Map params);
|
||||
|
||||
/**
|
||||
* 根据退货订单id获取退货订单打印信息
|
||||
*
|
||||
* @param orderId
|
||||
* @param returnId
|
||||
* @return
|
||||
*/
|
||||
OrderPrintVO fetchReturnOrderPrintInfo(@Param("orderId") String orderId, @Param("returnId") String returnId);
|
||||
}
|
||||
|
||||
@ -522,7 +522,7 @@ public interface ShopOrderBaseService extends IBaseService<ShopOrderBase> {
|
||||
* @param payState 支付状态,参考StateCode.ORDER_PAID_STATE_YES
|
||||
* @return
|
||||
*/
|
||||
Map getOrderPrintInfo(Integer storeId, String orderId, Integer payState);
|
||||
Map fetchOrderPrintInfo(Integer storeId, String orderId, Integer payState);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -143,4 +143,13 @@ public interface ShopOrderInfoService extends IBaseService<ShopOrderInfo> {
|
||||
* @return
|
||||
*/
|
||||
List<BookingArgDTO> genBookingOrderArgList(String storeId);
|
||||
|
||||
/**
|
||||
* 获取某个活动订单成功数量
|
||||
*
|
||||
* @param activityId 活动ID
|
||||
* @param activityTypeId 活动类型ID, 可选参数
|
||||
* @return
|
||||
*/
|
||||
long fetchActivityOrderSuccessCount(String activityId, String activityTypeId);
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ package com.suisung.mall.shop.order.service;
|
||||
|
||||
import com.suisung.mall.common.modules.order.ShopOrderItem;
|
||||
import com.suisung.mall.common.modules.pay.dto.ItemActivityInfoDTO;
|
||||
import com.suisung.mall.common.pojo.vo.ShopStoreOrderProductPrintVO;
|
||||
import com.suisung.mall.common.pojo.vo.OrderItemPrintVO;
|
||||
import com.suisung.mall.core.web.service.IBaseService;
|
||||
|
||||
import java.util.List;
|
||||
@ -30,5 +30,5 @@ public interface ShopOrderItemService extends IBaseService<ShopOrderItem> {
|
||||
* @param orderId
|
||||
* @return
|
||||
*/
|
||||
List<ShopStoreOrderProductPrintVO> selectOrderItemPrintInfo(String orderId);
|
||||
List<OrderItemPrintVO> selectOrderItemPrintInfo(String orderId);
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import com.suisung.mall.common.modules.order.ShopOrderItem;
|
||||
import com.suisung.mall.common.modules.order.ShopOrderReturn;
|
||||
import com.suisung.mall.common.modules.order.ShopOrderReturnItem;
|
||||
import com.suisung.mall.common.modules.product.ShopProductIndex;
|
||||
import com.suisung.mall.common.pojo.vo.OrderPrintVO;
|
||||
import com.suisung.mall.core.web.service.IBaseService;
|
||||
import com.suisung.mall.shop.order.vo.OrderReturnInputVo;
|
||||
|
||||
@ -225,4 +226,14 @@ public interface ShopOrderReturnService extends IBaseService<ShopOrderReturn> {
|
||||
CommonResult doRefundForMch(JSONObject params);
|
||||
|
||||
|
||||
/**
|
||||
* 根据退货订单id获取退货订单打印信息
|
||||
*
|
||||
* @param orderId
|
||||
* @param returnId
|
||||
* @return
|
||||
*/
|
||||
OrderPrintVO fetchReturnOrderPrintInfo(String orderId, String returnId);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ import com.suisung.mall.common.pojo.to.MsgTO;
|
||||
import com.suisung.mall.common.pojo.to.PayMoneyTO;
|
||||
import com.suisung.mall.common.pojo.to.PayPointTO;
|
||||
import com.suisung.mall.common.pojo.to.UserLevelTO;
|
||||
import com.suisung.mall.common.pojo.vo.ShopStoreOrderProductPrintVO;
|
||||
import com.suisung.mall.common.pojo.vo.OrderItemPrintVO;
|
||||
import com.suisung.mall.common.service.MessageService;
|
||||
import com.suisung.mall.common.service.impl.CommonService;
|
||||
import com.suisung.mall.common.utils.*;
|
||||
@ -1580,20 +1580,6 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
cartData.put("gb_id", gbId); // 拼团ID, 为0,在创建拼团
|
||||
}
|
||||
|
||||
// 判断是否砍价购买
|
||||
Integer acId = getParameter("ac_id", Integer.class);
|
||||
// 判断是否为砍价活动
|
||||
Boolean isCutPriceActivity = shopStoreActivityBaseService.isCutPriceActivity(activityId);
|
||||
if (CheckUtil.isNotEmpty(acId) && isCutPriceActivity) {
|
||||
cartData.put("ac_id", acId);
|
||||
|
||||
// 校验砍价活动,用户是否可以立即购买了?
|
||||
Pair<Boolean, String> canDoOrderCutPriceActivity = shopActivityCutpriceService.canDoOrderCutPriceActivity(acId, userId);
|
||||
if (!canDoOrderCutPriceActivity.getFirst()) {
|
||||
logger.error(canDoOrderCutPriceActivity.getSecond());
|
||||
throw new ApiException(I18nUtil._("砍价活动未达标,请继续努力,再提交订单。"));
|
||||
}
|
||||
}
|
||||
|
||||
// 注:(重要)邮费检测和计算
|
||||
dealWithCalFee(calFreight, cartData, chainId, isEdu);
|
||||
@ -1621,22 +1607,29 @@ 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");
|
||||
// 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);
|
||||
// }
|
||||
// 判断是否砍价购买
|
||||
Integer acId = getParameter("ac_id", Integer.class);
|
||||
// 判断是否为砍价活动
|
||||
Boolean isCutPriceActivity = shopStoreActivityBaseService.isCutPriceActivity(activityId);
|
||||
if (CheckUtil.isNotEmpty(activityId) && isCutPriceActivity) {
|
||||
// 判断砍价商品库存是否已售罄?
|
||||
if (shopStoreActivityBaseService.isActProdSoldOut(activityId)) {
|
||||
logger.error("检查商品库存:{}", activityId);
|
||||
throw new ApiException(I18nUtil._("砍价商品已售罄,请选择其他商品。"));
|
||||
}
|
||||
|
||||
// 校验砍价活动,用户是否可以立即购买了?
|
||||
Pair<Boolean, String> canDoOrderCutPriceActivity = shopActivityCutpriceService.canDoOrderCutPriceActivity(activityId, userId);
|
||||
if (!canDoOrderCutPriceActivity.getFirst()) {
|
||||
logger.error("检查活动是否达标:{}", canDoOrderCutPriceActivity.getSecond());
|
||||
throw new ApiException(I18nUtil._("活动已过期或未砍到底价,暂无法提交订单。"));
|
||||
}
|
||||
|
||||
cartData.put("ac_id", acId); // shop_activity_cutprice 活动参与记录的自增id
|
||||
cartData.put("activity_id", activityId);
|
||||
cartData.put("activity_type", StateCode.ACTIVITY_TYPE_CUTPRICE);
|
||||
}
|
||||
|
||||
|
||||
// 添加保存订单(关键方法)
|
||||
List<String> orderIdRow = addOrder(cartData, true, false, null);
|
||||
@ -1662,6 +1655,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
// cartData.put("packing_fee", packingFee);
|
||||
// }
|
||||
|
||||
|
||||
// 判断是否拼团购买
|
||||
if (gbId != null) {
|
||||
QueryWrapper<ShopActivityGroupbookingHistory> historyQueryWrapper = new QueryWrapper<>();
|
||||
@ -1673,10 +1667,6 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否砍价购买
|
||||
if (acId != null) {
|
||||
}
|
||||
|
||||
PayUserResource userResRow = payService.getPayUserResource(userId);
|
||||
if (userResRow != null) {
|
||||
cartData.put("user_money", userResRow.getUser_money());
|
||||
@ -5032,7 +5022,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
log.info("[确认收货] 处理订单: orderId={}, currentState={}", order_row.getOrder_id(), order_row.getOrder_state_id());
|
||||
} else {
|
||||
not_eligible_orders.add(order_row.getOrder_id());
|
||||
log.warn("[确认收货] 订单状态不满足收货条件: orderId={}, currentState={}", order_row.getOrder_id(), order_row.getOrder_state_id());
|
||||
log.warn("[确认收货] 订单状态不满足确认收货条件: orderId={}, currentState={}", order_row.getOrder_id(), order_row.getOrder_state_id());
|
||||
}
|
||||
}
|
||||
|
||||
@ -5198,11 +5188,11 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟 消息跳转路径设置接口
|
||||
* 延迟 消息跳转路径设置接口(最好使用消息队列,延迟1秒消费)
|
||||
*
|
||||
* @param orderIds
|
||||
*/
|
||||
private void processOrderJumpPathAsync(List<String> orderIds) {
|
||||
public void processOrderJumpPathAsync(List<String> orderIds) {
|
||||
if (CollectionUtils.isEmpty(orderIds)) {
|
||||
return;
|
||||
}
|
||||
@ -5211,15 +5201,15 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
for (String orderId : orderIds) {
|
||||
try {
|
||||
// 控制API调用频率
|
||||
Thread.sleep(300); // 根据实际API限制调整
|
||||
Thread.sleep(1000); // 根据实际API限制调整
|
||||
wxOrderShippingService.setMsgJumpPath(orderId);
|
||||
log.info("[异步处理] 订单跳转路径设置入口 processOrderJumpPathAsync,订单ID: {}", orderId);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
log.warn("[异步处理] 线程中断,订单ID: {}", orderId);
|
||||
log.error("[异步处理] 线程中断,订单ID: {}", orderId);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
log.warn("[异步处理] 消息跳转路径设置失败,订单ID: {}, 错误: {}", orderId, e.getMessage());
|
||||
// 继续处理下一个订单
|
||||
}
|
||||
}
|
||||
}, executor);
|
||||
@ -5299,17 +5289,17 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
throw new ApiException(I18nUtil._("无符合取消条件的订单!"));
|
||||
}
|
||||
|
||||
ShopOrderBase shopOrderBase = new ShopOrderBase();
|
||||
shopOrderBase.setOrder_id(order_id);
|
||||
shopOrderBase.setOrder_state_id(StateCode.ORDER_STATE_CANCEL);
|
||||
if (!shopOrderBaseService.edit(shopOrderBase)) {
|
||||
ShopOrderBase shopOrderBaseUpd = new ShopOrderBase();
|
||||
shopOrderBaseUpd.setOrder_id(order_id);
|
||||
shopOrderBaseUpd.setOrder_state_id(StateCode.ORDER_STATE_CANCEL);
|
||||
if (!shopOrderBaseService.edit(shopOrderBaseUpd)) {
|
||||
throw new ApiException(ResultCode.FAILED);
|
||||
}
|
||||
|
||||
ShopOrderInfo orderInfo = new ShopOrderInfo();
|
||||
orderInfo.setOrder_id(order_id);
|
||||
orderInfo.setOrder_state_id(StateCode.ORDER_STATE_CANCEL);
|
||||
if (!shopOrderInfoService.edit(orderInfo)) {
|
||||
ShopOrderInfo orderInfoUpd = new ShopOrderInfo();
|
||||
orderInfoUpd.setOrder_id(order_id);
|
||||
orderInfoUpd.setOrder_state_id(StateCode.ORDER_STATE_CANCEL);
|
||||
if (!shopOrderInfoService.edit(orderInfoUpd)) {
|
||||
throw new ApiException(ResultCode.FAILED);
|
||||
}
|
||||
|
||||
@ -5323,6 +5313,26 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
shopOrderDataService.edit(shopOrderData);
|
||||
}
|
||||
|
||||
// 取消顺丰同城配送订单
|
||||
// === 7. 特殊场景:顺丰同城配送、且全单退的时候,才触发顺丰同城订单取消 ===
|
||||
|
||||
if (shopOrderInfo.getDelivery_type_id() != null
|
||||
&& StateCode.DELIVERY_TYPE_SAME_CITY == shopOrderInfo.getDelivery_type_id().intValue()) {
|
||||
try {
|
||||
logger.warn("开始取消顺丰同城配送订单,orderId: {}, delivery_type_id: {}", order_id, shopOrderInfo.getDelivery_type_id());
|
||||
ThirdApiRes sfResult = sfExpressApiService.cancelOrder(order_id, 313, "用户或商家取消订单。");
|
||||
if (sfResult != null && !sfResult.getError_code().equals(0)) {
|
||||
log.error("顺丰同城取消订单返回错误,orderId: {}, errorCode: {}, errorMsg: {}",
|
||||
order_id, sfResult.getError_code(), sfResult.getError_msg());
|
||||
} else {
|
||||
log.info("顺丰同城订单取消成功,orderId: {}", order_id);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("顺丰同城取消订单异常,orderId: {}", order_id, e);
|
||||
// 可以考虑添加补偿机制或异步重试
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 积分退还 order_resource_ext1 默认为积分。
|
||||
ShopOrderData order_data_row = shopOrderDataService.get(order_id);
|
||||
@ -6411,7 +6421,9 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
type_code = StrUtil.isBlank(type_code) ? "DD" : type_code;
|
||||
String xid = RootContext.getXID();
|
||||
RootContext.unbind();
|
||||
String order_id = shopNumberSeqService.createNextSeq(type_code);
|
||||
Pair<Long, String> seqPair = shopNumberSeqService.createNextSeqPair(type_code);// 位数的序号: DD_20251205_1 2025-12-05 1
|
||||
String order_id = seqPair.getSecond();
|
||||
Long seqNo = seqPair.getFirst(); // 序号: DD_20251205_1 得出 1
|
||||
RootContext.bind(xid);
|
||||
|
||||
List<ShopOrderItem> item_rows = new ArrayList();
|
||||
@ -6656,6 +6668,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
}
|
||||
|
||||
info_row.setOrder_id(order_id);
|
||||
info_row.setOrder_pickup_num(seqNo); //重要:配送员的取单号
|
||||
info_row.setOrder_title(product_item_name); // 订单标题
|
||||
if (fixOrderVo != null && fixOrderVo.isFix_price() && StrUtil.isNotEmpty(fixOrderVo.getOrder_title())) {
|
||||
info_row.setOrder_title(fixOrderVo.getOrder_title()); // 订单标题
|
||||
@ -6700,6 +6713,10 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
info_row.setCoupon_type_id(shopProductIndex.getCoupon_type_id());
|
||||
}
|
||||
|
||||
// 保存活动id和类型
|
||||
info_row.setActivity_id(Convert.toStr(cart_data.get("activity_id"), "0"));
|
||||
info_row.setActivity_type_id(Convert.toStr(cart_data.get("activity_type_id"), "0"));
|
||||
|
||||
// 预约订单检测
|
||||
Integer bookingState = Convert.toInt(getParameter("booking_state"));
|
||||
if (CheckUtil.isNotEmpty(bookingState) && CommonConstant.Order_Booking_State_YY.equals(bookingState)) {
|
||||
@ -8777,8 +8794,16 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单打印信息
|
||||
*
|
||||
* @param storeId
|
||||
* @param orderId
|
||||
* @param payState
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Map getOrderPrintInfo(Integer storeId, String orderId, Integer payState) {
|
||||
public Map fetchOrderPrintInfo(Integer storeId, String orderId, Integer payState) {
|
||||
if (StrUtil.isBlank(orderId)) {
|
||||
logger.error("缺少必要参数:orderId:{}");
|
||||
return null;
|
||||
@ -8790,14 +8815,14 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
|
||||
}
|
||||
|
||||
// 订单商品列表
|
||||
List<ShopStoreOrderProductPrintVO> shopStoreOrderProductPrintVOList = shopOrderItemService.selectOrderItemPrintInfo(orderId);
|
||||
if (CollUtil.isEmpty(shopStoreOrderProductPrintVOList)) {
|
||||
List<OrderItemPrintVO> orderItemPrintVOList = shopOrderItemService.selectOrderItemPrintInfo(orderId);
|
||||
if (CollUtil.isEmpty(orderItemPrintVOList)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 重构实体类,处理标题,数量,价格适应长度
|
||||
List<ShopStoreOrderProductPrintVO> orderItems = new ArrayList<>();
|
||||
for (ShopStoreOrderProductPrintVO ent : shopStoreOrderProductPrintVOList) {
|
||||
List<OrderItemPrintVO> orderItems = new ArrayList<>();
|
||||
for (OrderItemPrintVO ent : orderItemPrintVOList) {
|
||||
orderItems.add(ent.rebuild());
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@ import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.suisung.mall.common.api.CommonResult;
|
||||
@ -206,7 +207,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
QueryWrapper<ShopOrderInfo> queryWrapper = new QueryWrapper<>();
|
||||
// 已发货,已签收
|
||||
queryWrapper.in("order_state_id", StateCode.ORDER_STATE_SHIPPED, StateCode.ORDER_STATE_RECEIVED);
|
||||
queryWrapper.eq("order_is_received",CommonConstant.Disable);
|
||||
queryWrapper.eq("order_is_received", CommonConstant.Disable);
|
||||
// 默认7天,自动收货
|
||||
// 配置了发货或已签收的订单,1天自动收货
|
||||
Float order_autofinish_time = accountBaseConfigService.getConfig("order_autofinish_time", 7f);
|
||||
@ -371,8 +372,8 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
/**
|
||||
* 已支付的订单,生成取单号,打票机并打印订单
|
||||
*
|
||||
* @param storeId
|
||||
* @param orderId
|
||||
* @param storeId 商家ID
|
||||
* @param orderId 订单ID
|
||||
* @return 取货单号
|
||||
*/
|
||||
// @Transactional
|
||||
@ -402,11 +403,22 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
}
|
||||
|
||||
try {
|
||||
// 生成取单号
|
||||
Long orderPickupNum = genTodayPickupNum(storeId);
|
||||
if (orderPickupNum == null || orderPickupNum <= 0) {
|
||||
logger.error("生成取单号失败: storeId={}", storeId);
|
||||
return 0L;
|
||||
// 生成取单号(废弃)
|
||||
// Long orderPickupNum = genTodayPickupNum(storeId);
|
||||
// if (orderPickupNum == null || orderPickupNum <= 0) {
|
||||
// logger.error("生成取单号失败: storeId={}", storeId);
|
||||
// return 0L;
|
||||
// }
|
||||
|
||||
Long orderPickupNum = 0L;
|
||||
// 如果订单中尚未设置取单号,则从订单ID中提取
|
||||
if (CheckUtil.isEmpty(orderInfoOld.getOrder_pickup_num())) {
|
||||
// 从订单ID中提取最后的数字部分作为取单号
|
||||
// 例如订单ID为 DD_20250510_11,则提取出 11 作为取单号
|
||||
orderPickupNum = Convert.toLong(StrUtil.subAfter(orderId, "_", true));
|
||||
} else {
|
||||
// 如果已有取单号,则使用现有的
|
||||
orderPickupNum = orderInfoOld.getOrder_pickup_num();
|
||||
}
|
||||
|
||||
// 更新订单信息
|
||||
@ -431,6 +443,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据订单Id、订单状态、配送方式、退款状态 获取订单的数量
|
||||
*
|
||||
@ -1231,6 +1244,49 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
|
||||
return bookingArgList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个活动订单成功数量
|
||||
*
|
||||
* @param activityId 活动ID
|
||||
* @param activityTypeId 活动类型ID, 可选参数
|
||||
* @return 活动订单成功数量
|
||||
*/
|
||||
@Override
|
||||
public long fetchActivityOrderSuccessCount(String activityId, String activityTypeId) {
|
||||
// 参数校验
|
||||
if (StrUtil.isBlank(activityId)) {
|
||||
logger.warn("活动Id无效!");
|
||||
return 0L;
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<ShopOrderInfo> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(ShopOrderInfo::getActivity_id, activityId);
|
||||
|
||||
// 如果activityTypeId不为空,则添加条件
|
||||
if (StrUtil.isNotBlank(activityTypeId)) {
|
||||
queryWrapper.eq(ShopOrderInfo::getActivity_type_id, activityTypeId);
|
||||
}
|
||||
|
||||
// 添加订单状态条件
|
||||
List<Integer> successOrderStates = Arrays.asList(
|
||||
StateCode.ORDER_STATE_WAIT_PAID,
|
||||
StateCode.ORDER_STATE_PICKING,
|
||||
StateCode.ORDER_STATE_WAIT_SHIPPING,
|
||||
StateCode.ORDER_STATE_SHIPPED,
|
||||
StateCode.ORDER_STATE_RECEIVED,
|
||||
StateCode.ORDER_STATE_FINISH);
|
||||
|
||||
queryWrapper.in(ShopOrderInfo::getOrder_state_id, successOrderStates);
|
||||
|
||||
try {
|
||||
return count(queryWrapper);
|
||||
} catch (Exception e) {
|
||||
logger.error("获取活动订单出错, activityId: {}, activityTypeId: {}",
|
||||
activityId, activityTypeId, e);
|
||||
return 0L;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据一个或多个店铺id获取有效店铺的有效营业时间段
|
||||
|
||||
@ -17,7 +17,7 @@ import com.suisung.mall.common.modules.order.ShopOrderDeliveryAddress;
|
||||
import com.suisung.mall.common.modules.order.ShopOrderInfo;
|
||||
import com.suisung.mall.common.modules.order.ShopOrderItem;
|
||||
import com.suisung.mall.common.modules.pay.dto.ItemActivityInfoDTO;
|
||||
import com.suisung.mall.common.pojo.vo.ShopStoreOrderProductPrintVO;
|
||||
import com.suisung.mall.common.pojo.vo.OrderItemPrintVO;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.activity.service.ShopActivityGroupbookingHistoryService;
|
||||
import com.suisung.mall.shop.order.mapper.ShopOrderItemMapper;
|
||||
@ -226,7 +226,7 @@ public class ShopOrderItemServiceImpl extends BaseServiceImpl<ShopOrderItemMappe
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ShopStoreOrderProductPrintVO> selectOrderItemPrintInfo(String orderId) {
|
||||
public List<OrderItemPrintVO> selectOrderItemPrintInfo(String orderId) {
|
||||
// 输入验证
|
||||
if (StrUtil.isBlank(orderId)) {
|
||||
return Collections.emptyList();
|
||||
@ -238,7 +238,7 @@ public class ShopOrderItemServiceImpl extends BaseServiceImpl<ShopOrderItemMappe
|
||||
}
|
||||
|
||||
return mList.stream().map(map -> {
|
||||
ShopStoreOrderProductPrintVO vo = new ShopStoreOrderProductPrintVO();
|
||||
OrderItemPrintVO vo = new OrderItemPrintVO();
|
||||
vo.setProduct_sn(Convert.toStr(map.get("product_sn")));
|
||||
vo.setItem_name(Convert.toStr(map.get("item_name")));
|
||||
vo.setOrder_item_amount(Convert.toBigDecimal(map.get("order_item_amount")));
|
||||
|
||||
@ -268,7 +268,9 @@ public class ShopOrderLogisticsServiceImpl extends BaseServiceImpl<ShopOrderLogi
|
||||
logisticsType = 3;
|
||||
}
|
||||
|
||||
if (deliveryType != null && deliveryType.equals(StateCode.DELIVERY_TYPE_SELF_PICK_UP)) {
|
||||
// 门店自提、商家送货上门
|
||||
if (deliveryType != null &&
|
||||
(deliveryType.equals(StateCode.DELIVERY_TYPE_SELF_PICK_UP) || deliveryType.equals(StateCode.DELIVERY_TYPE_IN_STORE_SERVICE))) {
|
||||
logisticsType = 4;
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,9 @@ import com.suisung.mall.common.modules.product.ShopProductInfo;
|
||||
import com.suisung.mall.common.modules.product.ShopProductItem;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreBase;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreShippingAddress;
|
||||
import com.suisung.mall.common.pojo.vo.OrderPrintVO;
|
||||
import com.suisung.mall.common.service.MessageService;
|
||||
import com.suisung.mall.common.service.impl.CommonService;
|
||||
import com.suisung.mall.common.utils.*;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductUnitService;
|
||||
@ -55,9 +57,9 @@ import com.suisung.mall.shop.product.service.ShopProductBaseService;
|
||||
import com.suisung.mall.shop.product.service.ShopProductIndexService;
|
||||
import com.suisung.mall.shop.product.service.ShopProductInfoService;
|
||||
import com.suisung.mall.shop.product.service.ShopProductItemService;
|
||||
import com.suisung.mall.shop.sfexpress.service.SFExpressApiService;
|
||||
import com.suisung.mall.shop.store.service.ShopStoreBaseService;
|
||||
import com.suisung.mall.shop.store.service.ShopStoreConfigService;
|
||||
import com.suisung.mall.shop.store.service.ShopStorePrinterService;
|
||||
import com.suisung.mall.shop.store.service.ShopStoreShippingAddressService;
|
||||
import com.suisung.mall.shop.sync.service.SyncThirdDataService;
|
||||
import io.seata.spring.annotation.GlobalTransactional;
|
||||
@ -195,13 +197,17 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
@Autowired
|
||||
private LklOrderSeparateService lklOrderSeparateService;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ShopStorePrinterService shopStorePrinterService;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private LklOrderDrawService lklOrderDrawService;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private SFExpressApiService sfExpressApiService;
|
||||
private CommonService commonService;
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@ -617,6 +623,9 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
data.put("return", orderReturn);
|
||||
data.put("items", shopOrderReturnItems);
|
||||
|
||||
// 打票机打印退款订单到店(异步执行)
|
||||
shopStorePrinterService.printShopStoreReturnOrder(return_id);
|
||||
|
||||
// 发送消息通知
|
||||
if (needSendMsg != null && needSendMsg) {
|
||||
// 退款提醒商家
|
||||
@ -981,20 +990,25 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
try {
|
||||
String remark = "同城配送异常自动退款!";
|
||||
|
||||
QueryWrapper<ShopOrderReturn> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("order_id", shopOrderId);
|
||||
ShopOrderReturn shopOrderReturn = findOne(queryWrapper);
|
||||
if (shopOrderReturn == null) {
|
||||
logger.error("[顺丰超时自动退款] 订单信息异常,未找到退货单: shopOrderId={}", shopOrderId);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ObjectUtil.equal(shopOrderReturn.getReturn_state_id(), StateCode.RETURN_PROCESS_FINISH)
|
||||
|| ObjectUtil.equal(shopOrderReturn.getReturn_is_paid(), CommonConstant.Enable)) {
|
||||
logger.warn("[顺丰超时自动退款] 订单之前已处理完成,请勿重复处理: shopOrderId={}", shopOrderId);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 对已存在部分退款的订单,进行剩余商品的全部退款
|
||||
CommonResult commonResult = addRemainingItems(shopOrderId, true, remark);
|
||||
commonResult.checkFenResult();
|
||||
logger.debug("[顺丰超时自动退款] 整单退货申请创建成功: shopOrderId={}", shopOrderId);
|
||||
|
||||
QueryWrapper<ShopOrderReturn> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("order_id", shopOrderId);
|
||||
ShopOrderReturn shopOrderReturn = findOne(queryWrapper);
|
||||
|
||||
if (shopOrderReturn == null) {
|
||||
logger.error("[顺丰超时自动退款] 订单信息异常,未找到退货单: shopOrderId={}", shopOrderId);
|
||||
throw new ApiException(I18nUtil._("订单信息异常!"));
|
||||
}
|
||||
|
||||
shopOrderReturn.setReturn_flag(0); // 0-不用退货;1-需要退货
|
||||
shopOrderReturn.setReturn_buyer_message(remark);
|
||||
shopOrderReturn.setReturn_store_message(remark);
|
||||
@ -1377,7 +1391,9 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
Integer store_id = Optional.ofNullable(shopOrderReturn.getStore_id())
|
||||
.orElseGet(() -> Convert.toInt(getCurrentUser().getStore_id()));
|
||||
|
||||
List<String> return_ids = Convert.toList(String.class, shopOrderReturn.getReturn_id());
|
||||
String returnId = shopOrderReturn.getReturn_id();
|
||||
|
||||
List<String> return_ids = Convert.toList(String.class, returnId);
|
||||
List<ShopOrderReturn> orderReturns = gets(return_ids);
|
||||
|
||||
if (!CheckUtil.checkDataRights(store_id, orderReturns, ShopOrderReturn::getStore_id)) {
|
||||
@ -1415,6 +1431,9 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
}
|
||||
}
|
||||
|
||||
// 打票机打印退款订单到店(异步执行)
|
||||
shopStorePrinterService.printShopStoreReturnOrder(returnId);
|
||||
|
||||
// 3. 通知买家
|
||||
messageService.sendNoticeMsg(
|
||||
shopOrderReturn.getBuyer_user_id(),
|
||||
@ -1580,12 +1599,12 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
QueryWrapper<ShopOrderReturnItem> returnItemQueryWrapper = new QueryWrapper<>();
|
||||
returnItemQueryWrapper.in("return_id", return_ids);
|
||||
List<ShopOrderReturnItem> returnItems = orderReturnItemService.find(returnItemQueryWrapper);
|
||||
QueryWrapper<ShopOrderReturn> shopOrderReturnQueryWrapper= new QueryWrapper<>();
|
||||
QueryWrapper<ShopOrderReturn> shopOrderReturnQueryWrapper = new QueryWrapper<>();
|
||||
shopOrderReturnQueryWrapper.in("return_id", return_ids);
|
||||
List<ShopOrderReturn> shopOrderReturnList= shopOrderReturnService.find(shopOrderReturnQueryWrapper);
|
||||
Map<String,Long> shopOrderReturnMap=new HashMap<>();
|
||||
if(!shopOrderReturnList.isEmpty()){
|
||||
shopOrderReturnMap=shopOrderReturnList.stream().collect(Collectors.toMap(ShopOrderReturn::getReturn_id, s->s.getUpdated_at().getTime()));
|
||||
List<ShopOrderReturn> shopOrderReturnList = shopOrderReturnService.find(shopOrderReturnQueryWrapper);
|
||||
Map<String, Long> shopOrderReturnMap = new HashMap<>();
|
||||
if (!shopOrderReturnList.isEmpty()) {
|
||||
shopOrderReturnMap = shopOrderReturnList.stream().collect(Collectors.toMap(ShopOrderReturn::getReturn_id, s -> s.getUpdated_at().getTime()));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(returnItems)) {
|
||||
for (ShopOrderReturnItem returnItem : returnItems) {
|
||||
@ -1637,17 +1656,17 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
// RMK 第三方数据同步相关:redis 新增返还思迅库存
|
||||
Map<String, Integer> stockDeltaMap = new HashMap<>();
|
||||
String item_src_id = productItem.getItem_src_id();
|
||||
String mapKey=item_src_id + "-" + shopOrderItem.getOrder_id() + "-" + shopOrderItem.getOrder_item_unit_price();
|
||||
if(null!=shopOrderReturnMap.get(returnItem.getReturn_id())){
|
||||
mapKey=mapKey+"-" + shopOrderReturnMap.get(returnItem.getReturn_id());//时间
|
||||
String mapKey = item_src_id + "-" + shopOrderItem.getOrder_id() + "-" + shopOrderItem.getOrder_item_unit_price();
|
||||
if (null != shopOrderReturnMap.get(returnItem.getReturn_id())) {
|
||||
mapKey = mapKey + "-" + shopOrderReturnMap.get(returnItem.getReturn_id());//时间
|
||||
}
|
||||
stockDeltaMap.put(mapKey, returnNum);
|
||||
syncThirdDataService.incrProductStockToRedis(stockDeltaMap, returnItem.getReturn_item_subtotal());
|
||||
logger.info("退货返回给思迅,存入redis成功,item_src_id:{},订单号:{},数量:{},mapKey:{}", item_src_id, shopOrderItem.getOrder_id(), returnNum,mapKey);
|
||||
logger.info("退货返回给思迅,存入redis成功,item_src_id:{},订单号:{},数量:{},mapKey:{}", item_src_id, shopOrderItem.getOrder_id(), returnNum, mapKey);
|
||||
} else {
|
||||
logger.warn("退货数量为空,无法增加库存,订单项ID: {}", orderItemId);
|
||||
}
|
||||
}else {//没有出库也要做思迅出库,在客户端计算支付流水,防止部分数据有出无进
|
||||
} else {//没有出库也要做思迅出库,在客户端计算支付流水,防止部分数据有出无进
|
||||
Long orderItemId = returnItem.getOrder_item_id();
|
||||
ShopOrderItem shopOrderItem = shopOrderItemService.get(orderItemId);
|
||||
if (shopOrderItem == null) {
|
||||
@ -1669,13 +1688,13 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
// RMK 第三方数据同步相关:redis 新增返还思迅库存
|
||||
Map<String, Integer> stockDeltaMap = new HashMap<>();
|
||||
String item_src_id = productItem.getItem_src_id();
|
||||
String mapKey=item_src_id + "-" + shopOrderItem.getOrder_id() + "-" + shopOrderItem.getOrder_item_unit_price();
|
||||
if(null!=shopOrderReturnMap.get(returnItem.getReturn_id())){
|
||||
mapKey=mapKey+"-" + shopOrderReturnMap.get(returnItem.getReturn_id());//时间
|
||||
String mapKey = item_src_id + "-" + shopOrderItem.getOrder_id() + "-" + shopOrderItem.getOrder_item_unit_price();
|
||||
if (null != shopOrderReturnMap.get(returnItem.getReturn_id())) {
|
||||
mapKey = mapKey + "-" + shopOrderReturnMap.get(returnItem.getReturn_id());//时间
|
||||
}
|
||||
stockDeltaMap.put(mapKey, returnNum);
|
||||
syncThirdDataService.incrProductStockToRedis(stockDeltaMap, returnItem.getReturn_item_subtotal());
|
||||
logger.info("未出库退货返回给思迅,存入redis成功,item_src_id:{},订单号:{},数量:{},mapKey:{}", item_src_id, shopOrderItem.getOrder_id(), returnNum,mapKey);
|
||||
logger.info("未出库退货返回给思迅,存入redis成功,item_src_id:{},订单号:{},数量:{},mapKey:{}", item_src_id, shopOrderItem.getOrder_id(), returnNum, mapKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1872,7 +1891,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
// shopOrderReturn.setReturn_finish_time(now);
|
||||
//
|
||||
ShopOrderReturn updateRefundStatus = new ShopOrderReturn();
|
||||
updateRefundStatus.setReturn_is_paid(1); // 0-退货未完成;1-退货完成
|
||||
updateRefundStatus.setReturn_is_paid(CommonConstant.Enable); // 0-退货未完成;1-退货完成
|
||||
updateRefundStatus.setReturn_finish_time(now);
|
||||
|
||||
QueryWrapper<ShopOrderReturn> updateWrapper = new QueryWrapper<>();
|
||||
@ -2564,7 +2583,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
}
|
||||
|
||||
/**
|
||||
* 对已存在部分退款的订单,进行剩余商品的全部退款(前提是未发货之前)
|
||||
* 对已存在部分退款的订单,进行剩余商品的全部退款,也适合全部退款(前提是未发货之前)
|
||||
* 该方法用于处理订单中部分商品已经申请退款后,对剩余商品进行整单退款的场景
|
||||
*
|
||||
* @param orderId 订单ID
|
||||
@ -2612,7 +2631,6 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
QueryWrapper<ShopOrderItem> itemQueryWrapper = new QueryWrapper<>();
|
||||
itemQueryWrapper.eq("order_id", orderId);
|
||||
List<ShopOrderItem> allOrderItems = shopOrderItemService.find(itemQueryWrapper);
|
||||
|
||||
if (CollectionUtil.isEmpty(allOrderItems)) {
|
||||
logger.warn("订单剩余商品退款申请失败:订单商品表为空,订单ID: {}", orderId);
|
||||
throw new ApiException(I18nUtil._("订单商品表为空!"));
|
||||
@ -2875,7 +2893,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
|
||||
if (lklOrderSeparateService.isOrderSeparated(orderId)) {
|
||||
// TODO 后期如果已经分账的订单,一定强硬退款,可能需要拉卡拉撤销分账,再退款,已提现的,真的没有办法退款了
|
||||
return CommonResult.failed("订单已三方结清,无法退款");
|
||||
return CommonResult.failed("订单已三方结清,暂无法退款");
|
||||
}
|
||||
|
||||
List<ShopOrderItem> orderItems = shopOrderItemService.find(new QueryWrapper<ShopOrderItem>().eq("order_id", orderId));
|
||||
@ -2983,16 +3001,16 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
throw new ApiException("退款审核失败!");
|
||||
}
|
||||
|
||||
// === 7. 特殊场景:同城配送订单取消 ===
|
||||
if (orderInfo.getDelivery_type_id() != null
|
||||
&& StateCode.DELIVERY_TYPE_SAME_CITY == orderInfo.getDelivery_type_id().intValue()
|
||||
&& !isPartialRefund) {
|
||||
try {
|
||||
sfExpressApiService.cancelOrder(orderId, 313, refundOrder.getReturn_store_message());
|
||||
} catch (Exception e) {
|
||||
log.error("顺丰同城取消订单失败", e);
|
||||
}
|
||||
}
|
||||
// // === 7. 特殊场景:顺丰同城配送、且全单退的时候,才触发顺丰同城订单取消 === RMK 在ShopOrderBaseServiceImpl.cancel取消订单方法里执行了
|
||||
// if (orderInfo.getDelivery_type_id() != null
|
||||
// && StateCode.DELIVERY_TYPE_SAME_CITY == orderInfo.getDelivery_type_id().intValue()
|
||||
// && !isPartialRefund) {
|
||||
// try {
|
||||
// sfExpressApiService.cancelOrder(orderId, 313, refundOrder.getReturn_store_message());
|
||||
// } catch (Exception e) {
|
||||
// log.error("顺丰同城取消订单失败", e);
|
||||
// }
|
||||
// }
|
||||
|
||||
return CommonResult.success();
|
||||
} catch (Exception e) {
|
||||
@ -3008,6 +3026,37 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据退货订单id获取退货订单打印信息
|
||||
*
|
||||
* @param orderId 订单ID 可选参数
|
||||
* @param returnId 退货单ID 必填参数
|
||||
* @return 退货订单打印信息对象
|
||||
*/
|
||||
@Override
|
||||
public OrderPrintVO fetchReturnOrderPrintInfo(String orderId, String returnId) {
|
||||
// 参数校验
|
||||
if (StrUtil.isBlank(returnId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 调用Mapper方法获取退货订单打印信息 ShopStoreOrderPrintVO
|
||||
OrderPrintVO shopOrderPrintVO = shopOrderReturnMapper.fetchReturnOrderPrintInfo(orderId, returnId);
|
||||
if (shopOrderPrintVO == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 设置配送方式名称
|
||||
shopOrderPrintVO.setDelivery_type_name(CommonService.getDeliveryExpressName(shopOrderPrintVO.getDelivery_type_id()));
|
||||
|
||||
return shopOrderPrintVO;
|
||||
} catch (Exception e) {
|
||||
logger.error("获取退货订单打印信息失败, orderId: {}, returnId: {}", orderId, returnId, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取拒绝退货的详细原因
|
||||
|
||||
@ -131,7 +131,7 @@ public class ShopPageAppServiceImpl extends BaseServiceImpl<ShopPageAppMapper, S
|
||||
* @param subsite_id
|
||||
* @param store_id
|
||||
* @param tpl_id
|
||||
* @param app_type
|
||||
* @param app_type 69 107 3
|
||||
*/
|
||||
@Override
|
||||
public void getModel(ModelAndView view, Integer subsite_id, Integer store_id, Integer tpl_id, Integer app_type) {
|
||||
@ -152,7 +152,6 @@ public class ShopPageAppServiceImpl extends BaseServiceImpl<ShopPageAppMapper, S
|
||||
String page_nav = pageBase.get("PageNav").toString();
|
||||
String page_config = pageBase.get("PageConfig").toString();
|
||||
|
||||
//用户中心菜单
|
||||
//用户中心菜单
|
||||
Map menu = new HashMap();
|
||||
String app_member_center = accountBaseConfigService.getConfig("app_member_center");
|
||||
|
||||
@ -164,6 +164,14 @@ public interface SFExpressApiService {
|
||||
*/
|
||||
ThirdApiRes notifyProductReady(Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 订单实时信息查询
|
||||
* https://openic.sf-express.com/open/api/external/getorderstatus?sign=$sign
|
||||
*
|
||||
* @param sfOrderId
|
||||
* @return
|
||||
*/
|
||||
ThirdApiRes getOrderStatus(String sfOrderId);
|
||||
|
||||
// *********** 顺丰同城回调相关业务 ****************
|
||||
|
||||
@ -194,18 +202,6 @@ public interface SFExpressApiService {
|
||||
*/
|
||||
ThirdApiRes receiveOrderCompleteNotify(String jsonData, String sign);
|
||||
|
||||
//
|
||||
// /**
|
||||
// * 个推推送消息到员工
|
||||
// *
|
||||
// * @param storeId
|
||||
// * @param orderId
|
||||
// * @param message
|
||||
// * @param payloadJson
|
||||
// * @return
|
||||
// */
|
||||
// void pushMessageToStoreEmployee(Integer storeId, String orderId, String message, String payloadJson);
|
||||
|
||||
/**
|
||||
* 商家自行配送发货
|
||||
*
|
||||
|
||||
@ -185,42 +185,10 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
|
||||
return Pair.of(false, "联系人手机号不能为空");
|
||||
}
|
||||
|
||||
// AddressParseResultTO addressParseResultTO = AddressUtil.parseAddress(shopMchEntry.getStore_address());
|
||||
// // 解析城市名称
|
||||
// String cityName = "桂平市"; // 默认城市
|
||||
//
|
||||
// // 去掉省市区的详细地址
|
||||
// String storeAddress = addressParseResultTO.getDetailAddress();
|
||||
//
|
||||
// if (StrUtil.isNotBlank(shopMchEntry.getStore_area())) {
|
||||
// String[] areaNames = shopMchEntry.getStore_area().split("/");
|
||||
// if (areaNames.length >= 3) {
|
||||
// cityName = areaNames[areaNames.length - 1];
|
||||
// } else {
|
||||
// cityName = shopMchEntry.getStore_area().replace("/", "");
|
||||
// }
|
||||
// } else {
|
||||
// cityName = addressParseResultTO.getCity();
|
||||
// }
|
||||
//
|
||||
// // 如果解析后城市名为空,使用默认值
|
||||
// if (StrUtil.isBlank(cityName)) {
|
||||
// cityName = "桂平市";
|
||||
// logger.warn("[顺丰] 城市名为空,使用默认城市: {}", cityName);
|
||||
// } else {
|
||||
// logger.debug("[顺丰] 解析得到城市名: {}", cityName);
|
||||
// }
|
||||
//
|
||||
// // 为了其他顺丰店同名,店铺名称加上[门店ID]; 如:xxxx[xxxx] 聚万家生鲜超市[69]
|
||||
// String shopStoreName = String.format("%s[%s]", shopMchEntry.getStore_name(), shopMchEntry.getStore_id());
|
||||
|
||||
// 调用创建店铺方法
|
||||
Pair<Boolean, String> result = createSfExpressShop(
|
||||
mchId,
|
||||
Convert.toInt(shopMchEntry.getStore_id()),
|
||||
// shopStoreName,
|
||||
// cityName,
|
||||
// storeAddress,
|
||||
shopMchEntry.getContact_name(),
|
||||
contactMobile,
|
||||
shopMchEntry.getStore_longitude(),
|
||||
@ -707,9 +675,10 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
|
||||
public ThirdApiRes cancelOrder(String orderId, Integer cancelCode, String cancelReason) {
|
||||
Map<String, Object> params = buildCommonParams();
|
||||
params.put("order_id", shopStoreSfOrderService.getSfOrderIdByShopOrderId(orderId)); // 商家 orderId 转 顺丰的订单号
|
||||
params.put("cancel_type", 1); //1、顺丰订单号 2、商家订单号
|
||||
if (StrUtil.isNotBlank(cancelReason) && cancelCode != null) {
|
||||
params.put("cancel_code", orderId);
|
||||
params.put("cancel_reason", orderId);
|
||||
params.put("cancel_code", cancelCode);
|
||||
params.put("cancel_reason", cancelReason);
|
||||
}
|
||||
return cancelOrder(params);
|
||||
}
|
||||
@ -718,77 +687,107 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
|
||||
* 取消订单
|
||||
*
|
||||
* @param params 综合参数,请参考:https://openic.sf-express.com/open/api/docs/index/#/apidoc
|
||||
* @return
|
||||
* @return ThirdApiRes 取消订单结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public ThirdApiRes cancelOrder(Map<String, Object> params) {
|
||||
// TODO 检验用户权限
|
||||
logger.info("[取消顺丰订单] 开始取消顺丰订单流程");
|
||||
|
||||
// 1. 参数校验
|
||||
if (params == null || ObjectUtil.isEmpty(params.get("order_id"))) {
|
||||
logger.warn("[取消顺丰订单] 取消订单参数校验失败: 参数为空或缺少order_id");
|
||||
return new ThirdApiRes().fail(1003, "请求参数有误!");
|
||||
}
|
||||
|
||||
// 转换 json 字符串参数
|
||||
String sfOrderId = params.get("order_id").toString(); // 这是顺丰的订单号,不是商城的订单号
|
||||
params.putAll(buildCommonParams());
|
||||
try {
|
||||
// 2. 获取顺丰订单号
|
||||
String sfOrderId = params.get("order_id").toString();
|
||||
logger.debug("[取消顺丰订单] 准备取消订单: sfOrderId={}", sfOrderId);
|
||||
|
||||
String paramJSON = JsonUtil.toJSONString(params);
|
||||
// 先实时查询顺丰订单状态
|
||||
ThirdApiRes thirdApiRes = getOrderStatus(sfOrderId);
|
||||
if (thirdApiRes != null && ObjectUtil.equal(thirdApiRes.getError_code(), 0)) {
|
||||
Object resultObj = thirdApiRes.getResult();
|
||||
if (resultObj != null) {
|
||||
JSONObject result = JSONUtil.parseObj(resultObj);
|
||||
Integer orderStatus = result.getInt("order_status");
|
||||
if (orderStatus != null &&
|
||||
(ObjectUtil.equal(orderStatus, SFExpressConstant.Cons_CanceledOrder) ||
|
||||
ObjectUtil.equal(orderStatus, SFExpressConstant.Cons_CancelingOrder))) {
|
||||
return new ThirdApiRes().success("订单已取消过!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据参数生成请求签名
|
||||
String send_url = buildUrl("cancelorder", paramJSON);
|
||||
String retRespStr = HttpUtil.post(send_url, paramJSON);
|
||||
if (StrUtil.isBlank(retRespStr)) {
|
||||
logger.error("顺丰同城:取消订单异常,无返回值!");
|
||||
return new ThirdApiRes().fail(2, "顺丰同城:无返回值!");
|
||||
// 3. 添加公共参数
|
||||
params.putAll(buildCommonParams());
|
||||
String paramJSON = JsonUtil.toJSONString(params);
|
||||
|
||||
// 4. 调用顺丰取消订单接口
|
||||
String sendUrl = buildUrl("cancelorder", paramJSON);
|
||||
logger.debug("[取消顺丰订单] 调用取消订单接口: url={}, params={}", sendUrl, paramJSON);
|
||||
|
||||
String responseStr = HttpUtil.post(sendUrl, paramJSON);
|
||||
if (StrUtil.isBlank(responseStr)) {
|
||||
logger.error("[取消顺丰订单] 取消订单接口调用失败: 无返回值, sfOrderId={}", sfOrderId);
|
||||
return new ThirdApiRes().fail(2, "顺丰同城:无返回值!");
|
||||
}
|
||||
|
||||
// 5. 解析接口响应
|
||||
ThirdApiRes sfExpressApiRes = JsonUtil.json2object(responseStr, ThirdApiRes.class);
|
||||
if (sfExpressApiRes == null) {
|
||||
logger.error("[取消顺丰订单] 取消订单接口响应解析失败: {}, sfOrderId={}", responseStr, sfOrderId);
|
||||
return new ThirdApiRes().fail(2, "顺丰同城:响应解析失败!");
|
||||
}
|
||||
|
||||
// 6. 检查接口调用结果
|
||||
if (!sfExpressApiRes.getError_code().equals(0)) {
|
||||
logger.error("[取消顺丰订单] 取消订单接口调用失败: errorCode={}, errorMsg={}, sfOrderId={}",
|
||||
sfExpressApiRes.getError_code(), sfExpressApiRes.getError_msg(), sfOrderId);
|
||||
return new ThirdApiRes().fail(2, sfExpressApiRes.getError_msg());
|
||||
}
|
||||
|
||||
logger.info("[取消顺丰订单] 顺丰接口取消订单成功: sfOrderId={}", sfOrderId);
|
||||
|
||||
// 7. 检查本地订单状态
|
||||
ShopStoreSfOrder existingOrder = shopStoreSfOrderService.getBySfOrderId(sfOrderId);
|
||||
if (existingOrder == null) {
|
||||
logger.error("[取消顺丰订单] 本地订单不存在: sfOrderId={}", sfOrderId);
|
||||
return new ThirdApiRes().fail(2, "订单不存在!");
|
||||
}
|
||||
|
||||
// 8. 检查订单是否已经取消
|
||||
if (existingOrder.getOrder_status() != null &&
|
||||
(existingOrder.getOrder_status().equals(StateCode.SF_ORDER_STATUS_CANCELED) ||
|
||||
existingOrder.getOrder_status().equals(StateCode.SF_ORDER_STATUS_CANCELING))) {
|
||||
logger.info("[取消顺丰订单] 订单已处于取消状态,无需重复操作: sfOrderId={}, status={}",
|
||||
sfOrderId, existingOrder.getOrder_status());
|
||||
return new ThirdApiRes().success("订单已取消过!");
|
||||
}
|
||||
|
||||
// 9. 更新顺丰订单状态为已取消
|
||||
ShopStoreSfOrder updateOrder = new ShopStoreSfOrder();
|
||||
updateOrder.setSf_order_id(existingOrder.getSf_order_id());
|
||||
updateOrder.setOrder_status(StateCode.SF_ORDER_STATUS_CANCELED);
|
||||
updateOrder.setStatus_desc("线上商城发起取消订单");
|
||||
|
||||
Boolean updateSuccess = shopStoreSfOrderService.updateShopStoreSfOrderStatus(updateOrder);
|
||||
if (!updateSuccess) {
|
||||
logger.error("[取消顺丰订单] 更新本地订单状态失败: sfOrderId={}", sfOrderId);
|
||||
throw new ApiException(_("取消顺丰订单失败!"));
|
||||
}
|
||||
|
||||
logger.info("[取消顺丰订单] 本地订单状态更新成功: sfOrderId={}", sfOrderId);
|
||||
return sfExpressApiRes;
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("[取消顺丰订单] 取消订单过程中发生异常: ", e);
|
||||
return new ThirdApiRes().fail(-1, "系统异常: " + e.getMessage());
|
||||
}
|
||||
|
||||
ThirdApiRes sfExpressApiRes = JsonUtil.json2object(retRespStr, ThirdApiRes.class);
|
||||
if (sfExpressApiRes == null) {
|
||||
logger.error("顺丰同城:取消订单,返回值异常!{}", retRespStr);
|
||||
return new ThirdApiRes().fail(2, "顺丰同城:无返回值!");
|
||||
}
|
||||
|
||||
if (!sfExpressApiRes.getError_code().equals(0)) {
|
||||
logger.error("顺丰同城:取消订单失败!{}", retRespStr);
|
||||
return new ThirdApiRes().fail(2, sfExpressApiRes.getError_msg());
|
||||
}
|
||||
|
||||
// 判断订单的状态,是否已经取消了?已取消,不再执行
|
||||
ShopStoreSfOrder shopStoreSfOrderExist = shopStoreSfOrderService.getByShopOrderId(sfOrderId);
|
||||
if (shopStoreSfOrderExist == null) {
|
||||
return new ThirdApiRes().fail(2, "订单有误!");
|
||||
}
|
||||
|
||||
if (shopStoreSfOrderExist.getOrder_status() != null
|
||||
&& (shopStoreSfOrderExist.getOrder_status().equals(StateCode.SF_ORDER_STATUS_CANCELED) ||
|
||||
(shopStoreSfOrderExist.getOrder_status().equals(StateCode.SF_ORDER_STATUS_CANCELING)))) {
|
||||
return new ThirdApiRes().success("订单已取消过!");
|
||||
}
|
||||
|
||||
// // 更改商城订单状态为:已取消,注意事务问题
|
||||
// List<String> orderList = new ArrayList<>();
|
||||
// orderList.add(shopStoreSfOrderExist.getShop_order_id());
|
||||
// 取消订单, 流程:订单状态;积分、众宝、库存、礼包、优惠券 有就统统退还
|
||||
// Boolean success = shopOrderReturnService.sfExpressExpiredForceRefund(shopStoreSfOrderExist.getShop_order_id()); // 不检查订单付款状态
|
||||
// if (!success) {
|
||||
// throw new ApiException(I18nUtil._("取消商家订单失败!"));
|
||||
// }
|
||||
|
||||
// 更改顺丰的订单状态
|
||||
ShopStoreSfOrder shopStoreSfOrder = new ShopStoreSfOrder();
|
||||
shopStoreSfOrder.setSf_order_id(shopStoreSfOrderExist.getSf_order_id());
|
||||
shopStoreSfOrder.setOrder_status(StateCode.SF_ORDER_STATUS_CANCELED);
|
||||
shopStoreSfOrder.setStatus_desc("线上商城发起取消订单");
|
||||
Boolean success = shopStoreSfOrderService.updateShopStoreSfOrderStatus(shopStoreSfOrder);
|
||||
if (!success) {
|
||||
throw new ApiException(_("取消顺丰订单失败!"));
|
||||
}
|
||||
|
||||
|
||||
return sfExpressApiRes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 订单加小费,订单创建后,骑士未接单的情况下通过该接口对订单进行加小费,促进订单接单,截止订单完成前,都可以对订单加小费
|
||||
*
|
||||
@ -991,6 +990,39 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
|
||||
return JsonUtil.json2object(retRespStr, ThirdApiRes.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单实时信息查询
|
||||
* https://openic.sf-express.com/open/api/external/getorderstatus?sign=$sign
|
||||
*
|
||||
* @param sfOrderId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ThirdApiRes getOrderStatus(String sfOrderId) {
|
||||
if (StrUtil.isBlank(sfOrderId)) {
|
||||
return new ThirdApiRes().fail(1003, "缺少必要参数!");
|
||||
}
|
||||
|
||||
Map<String, Object> params = buildCommonParams();
|
||||
params.put("order_id", sfOrderId);
|
||||
params.put("order_type", 1);//查询订单ID类型:1、顺丰订单号 2、商家订单号
|
||||
|
||||
|
||||
// 转换 json 字符串参数
|
||||
String paramJSON = JsonUtil.toJSONString(params);
|
||||
logger.debug("订单实时信息查询:" + paramJSON);
|
||||
|
||||
// 根据参数生成请求签名
|
||||
String send_url = buildUrl("getorderstatus", paramJSON);
|
||||
String retRespStr = HttpUtil.post(send_url, paramJSON);
|
||||
if (StrUtil.isBlank(retRespStr)) {
|
||||
logger.error("顺丰同城:订单实时信息查询,无返回值!");
|
||||
return new ThirdApiRes().fail(-1, "顺丰同城:无返回值!");
|
||||
}
|
||||
|
||||
return JsonUtil.json2object(retRespStr, ThirdApiRes.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 接收顺丰原因订单取消回调
|
||||
@ -1170,10 +1202,10 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
|
||||
String order_id = shopStoreSfOrder.getShop_order_id();
|
||||
itemQueryWrapper.eq("order_id", order_id);
|
||||
List<ShopOrderItem> order_item_rows = shopOrderItemService.find(itemQueryWrapper);
|
||||
ShopOrderBase shopOrderBase=shopOrderBaseService.get(order_id);
|
||||
String saleTimeStr=null;
|
||||
if(null!=shopOrderBase){
|
||||
saleTimeStr= String.valueOf(shopOrderBase.getOrder_time().getTime());
|
||||
ShopOrderBase shopOrderBase = shopOrderBaseService.get(order_id);
|
||||
String saleTimeStr = null;
|
||||
if (null != shopOrderBase) {
|
||||
saleTimeStr = String.valueOf(shopOrderBase.getOrder_time().getTime());
|
||||
}
|
||||
if (picking(order_item_rows)) {
|
||||
logger.info("顺丰发货商品扣减库存成功");
|
||||
@ -1183,12 +1215,12 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
|
||||
Map<String, Integer> stockDeltaMap = new HashMap<>();
|
||||
String item_src_id = shopOrderItem.getItem_src_id();
|
||||
Integer order_item_quantity = shopOrderItem.getOrder_item_quantity();
|
||||
String mapKey=item_src_id + "-" + shopStoreSfOrder.getShop_order_id()+"-"+shopOrderItem.getOrder_item_unit_price();
|
||||
if(StringUtils.isNotEmpty(saleTimeStr)){
|
||||
mapKey=mapKey+"-"+saleTimeStr;
|
||||
String mapKey = item_src_id + "-" + shopStoreSfOrder.getShop_order_id() + "-" + shopOrderItem.getOrder_item_unit_price();
|
||||
if (StringUtils.isNotEmpty(saleTimeStr)) {
|
||||
mapKey = mapKey + "-" + saleTimeStr;
|
||||
}
|
||||
stockDeltaMap.put(mapKey, -order_item_quantity);
|
||||
syncThirdDataService.incrProductStockToRedis(stockDeltaMap,null);
|
||||
syncThirdDataService.incrProductStockToRedis(stockDeltaMap, null);
|
||||
}
|
||||
}
|
||||
//出库扣减思迅库存end
|
||||
@ -1356,9 +1388,9 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
|
||||
Map<String, Integer> stockDeltaMap = new HashMap<>();
|
||||
String item_src_id = shopOrderItem.getItem_src_id();
|
||||
Integer order_item_quantity = shopOrderItem.getOrder_item_quantity();
|
||||
String mapKey=item_src_id + "-" + shopOrderItem.getOrder_id()+"-"+shopOrderItem.getOrder_item_unit_price()+"-"+shopOrderBase.getOrder_time().getTime();
|
||||
String mapKey = item_src_id + "-" + shopOrderItem.getOrder_id() + "-" + shopOrderItem.getOrder_item_unit_price() + "-" + shopOrderBase.getOrder_time().getTime();
|
||||
stockDeltaMap.put(mapKey, -order_item_quantity);
|
||||
syncThirdDataService.incrProductStockToRedis(stockDeltaMap,null);
|
||||
syncThirdDataService.incrProductStockToRedis(stockDeltaMap, null);
|
||||
}
|
||||
}
|
||||
return CommonResult.success("操作成功");
|
||||
|
||||
@ -44,7 +44,7 @@ public class ShopMchEntryController extends BaseControllerImpl {
|
||||
@ApiOperation(value = "测试", notes = "测试")
|
||||
@RequestMapping(value = "/gencon", method = RequestMethod.POST)
|
||||
public Object fillDocTemplate() {
|
||||
return esignContractFillingFileService.fillDocTemplate("13128997057", "91450881MADEQ92533");
|
||||
return esignContractFillingFileService.fillDocTemplate(57);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "店铺主营分类(类目)", notes = "店铺主营分类(类目)")
|
||||
|
||||
@ -367,4 +367,12 @@ public interface ShopMchEntryService {
|
||||
* @return 包含ID路径和名称路径的字符串数组,格式为 [ID路径, 名称路径]
|
||||
*/
|
||||
String[] handleStoreDistrictInfo(String storeDistrict, String storeArea, String refStoreAddress);
|
||||
|
||||
/**
|
||||
* 根据店铺Id,获取拉卡拉的审核状态和下载地址
|
||||
*
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
ShopMchEntry getLklContractStatusUrl(Integer storeId);
|
||||
}
|
||||
@ -69,15 +69,15 @@ public interface ShopStoreActivityBaseService extends IBaseService<ShopStoreActi
|
||||
*/
|
||||
boolean isActivityTimeValid(ShopStoreActivityBase shopStoreActivityBase, Date checkTime);
|
||||
|
||||
/**
|
||||
* 验证活动时间是否有效
|
||||
*
|
||||
* @param starTime 活动开始时间
|
||||
* @param endTime 活动结束时间
|
||||
* @param checkTime 待验证时间
|
||||
* @return 时间是否有效
|
||||
*/
|
||||
boolean isActivityTimeValid(Date starTime, Date endTime, Date checkTime);
|
||||
// /**
|
||||
// * 验证活动时间是否有效
|
||||
// *
|
||||
// * @param starTime 活动开始时间
|
||||
// * @param endTime 活动结束时间
|
||||
// * @param checkTime 待验证时间
|
||||
// * @return 时间是否有效
|
||||
// */
|
||||
// boolean isActivityTimeValid(Date starTime, Date endTime, Date checkTime);
|
||||
|
||||
Map listsMarketing();
|
||||
|
||||
@ -199,4 +199,21 @@ public interface ShopStoreActivityBaseService extends IBaseService<ShopStoreActi
|
||||
Boolean isCutPriceActivity(Integer activity_id);
|
||||
|
||||
|
||||
/**
|
||||
* 修改活动状态
|
||||
*
|
||||
* @param activity_id
|
||||
* @param activity_state
|
||||
* @return
|
||||
*/
|
||||
boolean updateActivityState(Integer activity_id, Integer activity_state);
|
||||
|
||||
|
||||
/**
|
||||
* 判断活动商品是否售完
|
||||
*
|
||||
* @param activity_id
|
||||
* @return
|
||||
*/
|
||||
boolean isActProdSoldOut(Integer activity_id);
|
||||
}
|
||||
|
||||
@ -255,6 +255,15 @@ public interface ShopStoreBaseService extends IBaseService<ShopStoreBase> {
|
||||
*/
|
||||
Date getLatestBizOpeningDate(String storeIds);
|
||||
|
||||
|
||||
/**
|
||||
* 批量更新店铺营业状态为营业中
|
||||
* 将符合条件的"筹备中"状态店铺更新为"营业中"状态
|
||||
*
|
||||
* @return Boolean 更新是否成功
|
||||
*/
|
||||
Boolean batchUpdateStoreBizStateToOpening();
|
||||
|
||||
// Page<ShopStoreBase> getMobileStoreList(Integer page, Integer rows);
|
||||
|
||||
}
|
||||
|
||||
@ -80,6 +80,14 @@ public interface ShopStorePrinterService extends IBaseService<ShopStorePrinter>
|
||||
*/
|
||||
Boolean printShopStoreOrder(Integer storeId, String orderId);
|
||||
|
||||
/**
|
||||
* 退货成功后,立即打印门店的退货信息
|
||||
*
|
||||
* @param returnId
|
||||
* @return
|
||||
*/
|
||||
Boolean printShopStoreReturnOrder(String returnId);
|
||||
|
||||
/**
|
||||
* 获取店铺所有有效打印机
|
||||
*
|
||||
|
||||
@ -17,6 +17,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
@ -339,9 +340,10 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
Map<String, Object> tmplArgs = new HashMap<>(1);
|
||||
tmplArgs.put("name", record.getStore_name()); // 商家店铺名
|
||||
|
||||
// 【桂平发发网络】通知管理员有商家申请入驻
|
||||
if (!shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_498535058", tmplArgs)) {
|
||||
shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_486545331", tmplArgs); // 【小发同城】通知管理员有商家申请入驻
|
||||
// 【小发同城】通知管理员有商家申请入驻
|
||||
if (!shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_486545331", tmplArgs)) {
|
||||
// 【桂平发发网络】通知管理员有商家申请入驻
|
||||
shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_498535058", tmplArgs);
|
||||
}
|
||||
|
||||
}
|
||||
@ -471,10 +473,10 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
Map<String, Object> tmplArgs = new HashMap<>(1);
|
||||
tmplArgs.put("name", mchName); // 商家公司名称
|
||||
|
||||
// 【桂平发发网络】通知管理员有商家申请入驻
|
||||
if (!shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_498535058", tmplArgs)) {
|
||||
// 尊敬的管理员,商家 ${name},提交了入驻我们平台的申请,请及时对相关资质材料予以审核,以便推进后续流程。
|
||||
shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_486545331", tmplArgs); // 【小发同城】通知管理员有商家申请入驻
|
||||
// 【小发同城】通知管理员有商家申请入驻:尊敬的管理员,商家 ${name},提交了入驻我们平台的申请,请及时对相关资质材料予以审核,以便推进后续流程。
|
||||
if (!shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_486545331", tmplArgs)) {
|
||||
// 【桂平发发网络】通知管理员有商家申请入驻
|
||||
shopMessageTemplateService.aliyunSmsSend(mobileAndLicenseNumber.getFirst(), "SMS_498535058", tmplArgs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2510,6 +2512,36 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据店铺Id,获取拉卡拉的审核状态和下载地址
|
||||
*
|
||||
* @param storeId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public ShopMchEntry getLklContractStatusUrl(Integer storeId) {
|
||||
// 参数校验
|
||||
if (storeId == null) {
|
||||
log.warn("查询合同状态和URL失败:店铺ID为空");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
LambdaQueryWrapper<ShopMchEntry> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(ShopMchEntry::getStore_id, storeId)
|
||||
.eq(ShopMchEntry::getStatus, CommonConstant.Enable)
|
||||
.eq(ShopMchEntry::getApproval_status, CommonConstant.MCH_APPR_STA_PASS)
|
||||
.isNotNull(ShopMchEntry::getContract_download_url)
|
||||
.ne(ShopMchEntry::getContract_download_url, "")
|
||||
.select(ShopMchEntry::getApproval_status, ShopMchEntry::getContract_download_url);
|
||||
|
||||
return findOne(queryWrapper);
|
||||
} catch (Exception e) {
|
||||
log.error("根据店铺ID查询合同状态和URL异常,店铺ID: {}", storeId, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@ import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.suisung.mall.common.api.CommonResult;
|
||||
import com.suisung.mall.common.api.ResultCode;
|
||||
@ -36,10 +37,7 @@ import com.suisung.mall.common.modules.product.ShopProductItem;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreActivityBase;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreActivityItem;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreBase;
|
||||
import com.suisung.mall.common.utils.CheckUtil;
|
||||
import com.suisung.mall.common.utils.I18nUtil;
|
||||
import com.suisung.mall.common.utils.StringUtils;
|
||||
import com.suisung.mall.common.utils.UserInfoService;
|
||||
import com.suisung.mall.common.utils.*;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.activity.service.*;
|
||||
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
||||
@ -48,6 +46,7 @@ import com.suisung.mall.shop.base.service.ShopBaseCurrencyService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseStateCodeService;
|
||||
import com.suisung.mall.shop.order.service.ShopOrderBaseService;
|
||||
import com.suisung.mall.shop.order.service.ShopOrderDataService;
|
||||
import com.suisung.mall.shop.order.service.ShopOrderInfoService;
|
||||
import com.suisung.mall.shop.product.pojo.vo.ProductVo;
|
||||
import com.suisung.mall.shop.product.service.ShopProductBaseService;
|
||||
import com.suisung.mall.shop.product.service.ShopProductImageService;
|
||||
@ -92,6 +91,9 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl<ShopStoreA
|
||||
ShopOrderBaseService shopOrderBaseService;
|
||||
@Autowired
|
||||
ShopUserVoucherService shopUserVoucherService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
ShopOrderInfoService shopOrderInfoService;
|
||||
@Autowired
|
||||
private ShopStoreActivityBaseMapper shopStoreActivityBaseMapper;
|
||||
@Lazy
|
||||
@ -134,6 +136,7 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl<ShopStoreA
|
||||
private ShopActivityGroupbookingService shopActivityGroupbookingService;
|
||||
@Autowired
|
||||
private ShopStoreActivityCodeService shopStoreActivityCodeService;
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ShopOrderDataService shopOrderDataService;
|
||||
@Autowired
|
||||
@ -2090,29 +2093,38 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl<ShopStoreA
|
||||
Date starTime = shopStoreActivityBase.getActivity_starttime();
|
||||
Date endTime = shopStoreActivityBase.getActivity_endtime();
|
||||
|
||||
return isActivityTimeValid(starTime, endTime, checkTime);
|
||||
return DateTimeUtils.isActivityTimeValid(starTime, endTime, checkTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证活动时间是否有效
|
||||
*
|
||||
* @param starTime 活动开始时间
|
||||
* @param endTime 活动结束时间
|
||||
* @param checkTime 待验证时间
|
||||
* @return 时间是否有效
|
||||
*/
|
||||
@Override
|
||||
public boolean isActivityTimeValid(Date starTime, Date endTime, Date checkTime) {
|
||||
if (starTime == null || endTime == null) {
|
||||
return false;
|
||||
}
|
||||
// /**
|
||||
// * 验证活动时间是否有效
|
||||
// *
|
||||
// * @param starTime 活动开始时间
|
||||
// * @param endTime 活动结束时间
|
||||
// * @param checkTime 待验证时间
|
||||
// * @return 时间是否有效
|
||||
// */
|
||||
// @Override
|
||||
// public boolean isActivityTimeValid(Date starTime, Date endTime, Date checkTime) {
|
||||
// logger.debug("检查活动时间有效性 - 开始时间: {}, 结束时间: {}, 检查时间: {}", starTime, endTime, checkTime);
|
||||
//
|
||||
// if (starTime == null || endTime == null) {
|
||||
// logger.error("活动时间验证失败 - 开始时间或结束时间为null. 开始时间: {}, 结束时间: {}", starTime, endTime);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// if (checkTime == null) {
|
||||
// checkTime = new Date();
|
||||
// logger.warn("检查时间为空,使用当前时间: {}", checkTime);
|
||||
// }
|
||||
//
|
||||
// boolean isValid = !checkTime.before(starTime) && !checkTime.after(endTime);
|
||||
// logger.debug("活动时间验证结果: {} (检查时间>=开始时间, 检查时间<=结束时间)",
|
||||
// isValid);
|
||||
//
|
||||
// return isValid;
|
||||
// }
|
||||
|
||||
if (checkTime == null) {
|
||||
checkTime = new Date();
|
||||
}
|
||||
|
||||
return !checkTime.before(starTime) && !checkTime.after(endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map listsMarketing() {
|
||||
@ -4433,6 +4445,100 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl<ShopStoreA
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改活动状态
|
||||
*
|
||||
* @param activity_id 活动ID
|
||||
* @param activity_state 活动状态
|
||||
* @return boolean 是否更新成功
|
||||
*/
|
||||
@Override
|
||||
public boolean updateActivityState(Integer activity_id, Integer activity_state) {
|
||||
// 参数校验
|
||||
if (activity_id == null || activity_id <= 0) {
|
||||
logger.warn("活动ID无效: {}", activity_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (activity_state == null) {
|
||||
logger.warn("活动状态不能为空: activity_id={}", activity_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 直接使用LambdaUpdateWrapper提高性能,避免创建额外实体对象
|
||||
boolean result = update(new UpdateWrapper<ShopStoreActivityBase>()
|
||||
.eq("activity_id", activity_id)
|
||||
.set("activity_state", activity_state));
|
||||
|
||||
if (result) {
|
||||
logger.info("活动状态更新成功,活动ID: {},新状态: {}", activity_id, activity_state);
|
||||
} else {
|
||||
logger.warn("活动状态更新失败,活动ID: {},状态: {}", activity_id, activity_state);
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
logger.error("活动状态更新异常,活动ID: {},状态: {}", activity_id, activity_state, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断活动商品是否售完
|
||||
*
|
||||
* @param activity_id 活动ID
|
||||
* @return boolean 是否已售完
|
||||
*/
|
||||
@Override
|
||||
public boolean isActProdSoldOut(Integer activity_id) {
|
||||
// 参数校验:检查活动ID是否有效
|
||||
if (activity_id == null || activity_id <= 0) {
|
||||
logger.info("活动商品售完检查失败:无效的活动ID - {}", activity_id);
|
||||
return true; // 将无效输入视为"已售完"
|
||||
}
|
||||
|
||||
try {
|
||||
// 直接从数据库查询活动记录,只获取需要的字段以提高性能
|
||||
ShopStoreActivityBase activity = get(activity_id);
|
||||
// 如果活动不存在,视为已售完
|
||||
if (activity == null) {
|
||||
logger.info("活动商品售完检查:未找到活动记录,activity_id={}", activity_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取商品库存数量
|
||||
Integer productCount = activity.getProduct_count();
|
||||
logger.info("活动商品库存检查:activity_id={}, 库存数量={}", activity_id, productCount);
|
||||
|
||||
// 如果库存为null或小于等于0,视为已售完
|
||||
if (productCount == null || productCount <= 0) {
|
||||
logger.info("活动商品售完检查:库存为0或空,activity_id={}", activity_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 获取该活动已成功的订单数量
|
||||
long soldCount = shopOrderInfoService.fetchActivityOrderSuccessCount(
|
||||
Convert.toStr(activity_id),
|
||||
""); //Convert.toStr(StateCode.ACTIVITY_TYPE_CUTPRICE)
|
||||
|
||||
logger.info("活动商品售完检查:activity_id={}, 已售数量={}, 库存数量={}",
|
||||
activity_id, soldCount, productCount);
|
||||
|
||||
// 如果已售数量大于等于库存数量,则已售完
|
||||
boolean isSoldOut = soldCount >= productCount;
|
||||
if (isSoldOut) {
|
||||
logger.info("活动商品已售完:activity_id={}, 已售数量={}, 库存数量={}",
|
||||
activity_id, soldCount, productCount);
|
||||
}
|
||||
|
||||
return isSoldOut;
|
||||
} catch (Exception e) {
|
||||
logger.error("活动商品售完检查异常:activity_id={}", activity_id, e);
|
||||
return true; // 出现异常时保守地返回已售完
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public boolean removeActivityBase(Integer activity_id, ShopStoreActivityBase activity_row) {
|
||||
@ -5105,7 +5211,7 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl<ShopStoreA
|
||||
.ge("activity_item_endtime", activity.get("activity_starttime"));
|
||||
List<ShopStoreActivityItem> item_row = shopStoreActivityItemService.find(itemQueryWrapper);
|
||||
|
||||
List<Long> item_id_row = item_row.stream().filter(s->s.getActivity_item_state().equals(StateCode.ACTIVITY_STATE_NORMAL)).map(s -> s.getItem_id()).distinct().collect(Collectors.toList());
|
||||
List<Long> item_id_row = item_row.stream().filter(s -> s.getActivity_item_state().equals(StateCode.ACTIVITY_STATE_NORMAL)).map(s -> s.getItem_id()).distinct().collect(Collectors.toList());
|
||||
List<Integer> activity_id_row = item_row.stream().map(s -> s.getActivity_id()).distinct().collect(Collectors.toList());
|
||||
|
||||
List<Long> used_id_row = new ArrayList<>();
|
||||
@ -5553,13 +5659,14 @@ public class ShopStoreActivityBaseServiceImpl extends BaseServiceImpl<ShopStoreA
|
||||
activity_rule.put("product_image", product_row.getProduct_image());
|
||||
activity_rule.put("item_unit_price", item_row.getItem_unit_price());
|
||||
|
||||
// cut_hour - 砍价有效期(小时)
|
||||
Integer cut_hour = getParameter("cut_hour", 72);
|
||||
// product_count - 参与活动商品总数(个)
|
||||
Integer product_count = getParameter("product_count", 3);
|
||||
|
||||
Integer cut_hour = getParameter("cut_hour", 72);// cut_hour - 砍价有效期(小时)
|
||||
Integer product_count = getParameter("product_count", 3);// product_count - 参与活动商品总数(个)
|
||||
activity_rule.put("product_count", product_count); // 参与活动的商品总数(个)
|
||||
activity_rule.put("cut_hour", cut_hour); // 砍价的有效期(小时)
|
||||
|
||||
data.put("product_count", product_count);
|
||||
data.put("cut_hour", cut_hour);
|
||||
} else if (ObjectUtil.equal(activity_type_id, StateCode.ACTIVITY_TYPE_GIFTBAG)) {
|
||||
//a+b组合套餐
|
||||
String activity_bag_category = getParameter("activity_bag_category");//礼包分类
|
||||
|
||||
@ -33,6 +33,7 @@ import com.suisung.mall.common.modules.account.AccountUserInfo;
|
||||
import com.suisung.mall.common.modules.account.AccountUserSns;
|
||||
import com.suisung.mall.common.modules.base.*;
|
||||
import com.suisung.mall.common.modules.distribution.ShopDistributionPlantformUser;
|
||||
import com.suisung.mall.common.modules.esign.EsignContract;
|
||||
import com.suisung.mall.common.modules.invoicing.InvoicingCustomerLevel;
|
||||
import com.suisung.mall.common.modules.invoicing.InvoicingWarehouseBase;
|
||||
import com.suisung.mall.common.modules.page.ShopPageBase;
|
||||
@ -48,6 +49,7 @@ 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;
|
||||
import com.suisung.mall.shop.activity.service.ShopActivityCutpriceService;
|
||||
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseProductTagService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseStoreCategoryService;
|
||||
@ -55,6 +57,7 @@ import com.suisung.mall.shop.base.service.ShopBaseStoreGradeService;
|
||||
import com.suisung.mall.shop.config.BaiduUtil;
|
||||
import com.suisung.mall.shop.distribution.service.ShopDistributionPlantformUserService;
|
||||
import com.suisung.mall.shop.entity.LocationBean;
|
||||
import com.suisung.mall.shop.esign.service.EsignContractService;
|
||||
import com.suisung.mall.shop.invoicing.service.InvoicingCustomerLevelService;
|
||||
import com.suisung.mall.shop.invoicing.service.InvoicingWarehouseBaseService;
|
||||
import com.suisung.mall.shop.page.service.ShopPageBaseService;
|
||||
@ -139,6 +142,11 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ShopStoreAnalyticsService shopStoreAnalyticsService;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ShopActivityCutpriceService shopActivityCutpriceService;
|
||||
|
||||
@Autowired
|
||||
private AccountBaseConfigService accountBaseConfigService;
|
||||
@Autowired
|
||||
@ -178,6 +186,11 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
@Lazy
|
||||
@Autowired
|
||||
private ShopMchEntryService shopMchEntryService;
|
||||
|
||||
@Lazy
|
||||
@Autowired
|
||||
private EsignContractService esignContractService;
|
||||
|
||||
@Autowired
|
||||
private ThreadPoolExecutor executor;
|
||||
|
||||
@ -1104,18 +1117,44 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
if (CheckUtil.isNotEmpty(activity_type_id)) {
|
||||
queryWrapper.eq("activity_type_id", activity_type_id);
|
||||
} else {
|
||||
queryWrapper.in("activity_type_id", StateCode.ACTIVITY_TYPE_BARGAIN,
|
||||
queryWrapper.in("activity_type_id",
|
||||
StateCode.ACTIVITY_TYPE_BARGAIN,
|
||||
StateCode.ACTIVITY_TYPE_GIFT,
|
||||
StateCode.ACTIVITY_TYPE_LIMITED_DISCOUNT,
|
||||
StateCode.ACTIVITY_TYPE_DISCOUNT_PACKAGE,
|
||||
StateCode.ACTIVITY_TYPE_DIY_PACKAGE,
|
||||
StateCode.ACTIVITY_TYPE_REDUCTION);
|
||||
StateCode.ACTIVITY_TYPE_REDUCTION,
|
||||
StateCode.ACTIVITY_TYPE_CUTPRICE);
|
||||
}
|
||||
|
||||
// 为执行排序设置默认排序
|
||||
queryWrapper.orderByDesc("activity_id");
|
||||
|
||||
Page<ShopStoreActivityBase> lists = shopStoreActivityBaseService.lists(queryWrapper, 1, 500);
|
||||
Page<ShopStoreActivityBase> lists = shopStoreActivityBaseService.lists(queryWrapper, 1, 200);
|
||||
|
||||
// Optimized version with improved code quality and readability
|
||||
List<ShopStoreActivityBase> filteredActivities = new ArrayList<>();
|
||||
for (ShopStoreActivityBase activity : lists.getRecords()) {
|
||||
// Check if it's a cut-price activity that needs validation
|
||||
if (activity.getActivity_type_id() != null
|
||||
&& activity.getActivity_type_id() == StateCode.ACTIVITY_TYPE_CUTPRICE) {
|
||||
|
||||
// Validate cut-price activity stock and expiration
|
||||
Pair<Boolean, String> checkStockResult = shopActivityCutpriceService.checkCutPriceExpiredAndStock(activity);
|
||||
if (checkStockResult != null && !checkStockResult.getFirst()) {
|
||||
// Insufficient stock or expired - update activity state to finished
|
||||
shopStoreActivityBaseService.updateActivityState(activity.getActivity_id(), StateCode.ACTIVITY_STATE_FINISHED);
|
||||
continue; // Skip adding this activity to results
|
||||
}
|
||||
}
|
||||
|
||||
// Add valid activities to filtered list
|
||||
filteredActivities.add(activity);
|
||||
}
|
||||
|
||||
// Update the page records with filtered results
|
||||
lists.setRecords(filteredActivities);
|
||||
|
||||
|
||||
Map data = toMobileResult(lists);
|
||||
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
@ -1442,6 +1481,7 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
List<Map> items = (List<Map>) data.get("items");
|
||||
|
||||
//经营期限
|
||||
|
||||
List<Integer> store_ids = items.stream().map(s -> Convert.toInt(s.get("store_id"))).collect(Collectors.toList());
|
||||
List<ShopStoreInfo> store_info_rows = shopStoreInfoService.gets(store_ids);
|
||||
List<Integer> subsite_ids = items.stream().map(s -> Convert.toInt(s.get("subsite_id"))).distinct().collect(Collectors.toList());
|
||||
@ -1449,6 +1489,7 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
if (CollUtil.isNotEmpty(subsite_ids)) {
|
||||
subsite_rows = shopPlantformSubsiteService.gets(subsite_ids);
|
||||
}
|
||||
|
||||
//店铺统计
|
||||
List<ShopStoreAnalytics> store_analytics_rows = shopStoreAnalyticsService.gets(store_ids);
|
||||
List<ShopPlantformSubsite> finalSubsite_rows = subsite_rows;
|
||||
@ -1493,6 +1534,25 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
} else {
|
||||
s.put("subsite_name", I18nUtil._("全国站"));
|
||||
}
|
||||
|
||||
// E签宝和拉卡拉的合同文件下载地址
|
||||
String lkl_contract_file_url = "";
|
||||
String esign_contract_file_url = "";
|
||||
Integer esign_contract_flow_status = -1;//合同签署状态:-1:预备数据阶段;0-等待签署;1-已部分签署;2-已完成(所有签署方完成签署);3-已撤销(发起方撤销签署任务;5-已过期(签署截止日到期后触发);7-已拒签(签署方拒绝签署)
|
||||
ShopMchEntry entry = shopMchEntryService.getLklContractStatusUrl(_store_id);
|
||||
if (ObjectUtil.isNotEmpty(entry)) {
|
||||
lkl_contract_file_url = entry.getContract_download_url();
|
||||
}
|
||||
|
||||
EsignContract esignContract = esignContractService.getEsignContractStatusUrl(_store_id);
|
||||
if (ObjectUtil.isNotEmpty(esignContract)) {
|
||||
esign_contract_file_url = esignContract.getSigned_contract_url();
|
||||
esign_contract_flow_status = esignContract.getSign_flow_status();
|
||||
}
|
||||
|
||||
s.put("lkl_contract_file_url", lkl_contract_file_url);
|
||||
s.put("esign_contract_file_url", esign_contract_file_url);
|
||||
s.put("esign_contract_flow_status", esign_contract_flow_status);
|
||||
});
|
||||
|
||||
data.put("items", accountService.fixUserAvatar((List<Map>) data.get("items"), true));
|
||||
@ -1526,6 +1586,24 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
}
|
||||
}
|
||||
|
||||
// E签宝和拉卡拉的合同文件下载地址
|
||||
String lkl_contract_file_url = "";
|
||||
String esign_contract_file_url = "";
|
||||
Integer esign_contract_flow_status = -1; //合同签署状态:-1:预备数据阶段;0-等待签署;1-已部分签署;2-已完成(所有签署方完成签署);3-已撤销(发起方撤销签署任务;5-已过期(签署截止日到期后触发);7-已拒签(签署方拒绝签署)
|
||||
ShopMchEntry entry = shopMchEntryService.getLklContractStatusUrl(store_id);
|
||||
if (ObjectUtil.isNotEmpty(entry)) {
|
||||
lkl_contract_file_url = entry.getContract_download_url();
|
||||
}
|
||||
|
||||
EsignContract esignContract = esignContractService.getEsignContractStatusUrl(store_id);
|
||||
if (ObjectUtil.isNotEmpty(esignContract)) {
|
||||
esign_contract_file_url = esignContract.getSigned_contract_url();
|
||||
esign_contract_flow_status = esignContract.getSign_flow_status();
|
||||
}
|
||||
row.put("lkl_contract_file_url", lkl_contract_file_url);
|
||||
row.put("esign_contract_file_url", esign_contract_file_url);
|
||||
row.put("esign_contract_flow_status", esign_contract_flow_status);
|
||||
|
||||
// 火星坐标系GCJ02经纬度 转出 百度坐标系BD09经纬度(因为数据库保存的经纬度统一是GCJ02经纬度,所以需要转换 )
|
||||
gcj02ToBd09Gps(row);
|
||||
|
||||
@ -4404,6 +4482,29 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新店铺营业状态为营业中
|
||||
* 将符合条件的"筹备中"状态店铺更新为"营业中"状态
|
||||
*
|
||||
* @return Boolean 更新是否成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean batchUpdateStoreBizStateToOpening() {
|
||||
try {
|
||||
UpdateWrapper<ShopStoreBase> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("store_biz_state", CommonConstant.Store_Biz_State_PreActivity) // 筹备中状态
|
||||
.eq("store_is_open", CommonConstant.Enable) // 店铺已开启
|
||||
.le("store_biz_opening_date", new Date()) // 开业日期小于等于当前日期
|
||||
.set("store_biz_state", CommonConstant.Store_Biz_State_Opening); // 更新为营业中状态
|
||||
|
||||
return update(updateWrapper);
|
||||
} catch (Exception e) {
|
||||
log.error("批量更新店铺营业状态失败", e);
|
||||
// 发生异常时返回true,避免影响主流程执行
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @Override
|
||||
// public Page<ShopStoreBase> getMobileStoreList(Integer page, Integer rows) {
|
||||
|
||||
@ -5,11 +5,9 @@ import cn.hutool.core.util.StrUtil;
|
||||
import com.suisung.mall.common.modules.store.ShopStorePrinterLog;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.store.mapper.ShopStorePrinterLogMapper;
|
||||
import com.suisung.mall.shop.store.mapper.ShopStorePrinterMapper;
|
||||
import com.suisung.mall.shop.store.service.ShopStorePrinterLogService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
@ -19,41 +17,70 @@ import java.util.List;
|
||||
public class ShopStorePrinterLogServiceImpl extends BaseServiceImpl<ShopStorePrinterLogMapper, ShopStorePrinterLog> implements ShopStorePrinterLogService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ShopStorePrinterLogServiceImpl.class);
|
||||
@Autowired
|
||||
private ShopStorePrinterMapper shopStorePrinterMapper;
|
||||
|
||||
@Override
|
||||
public Boolean insertShopStorePrinterLog(ShopStorePrinterLog record) {
|
||||
// 参数校验
|
||||
if (record == null) {
|
||||
logger.warn("插入打印日志失败:记录为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 必要字段校验
|
||||
if (record.getStore_id() == null ||
|
||||
StrUtil.isBlank(record.getOrder_id()) ||
|
||||
StrUtil.isBlank(record.getTemplate_value()) ||
|
||||
StrUtil.isBlank(record.getPrint_content())) {
|
||||
logger.warn("插入打印日志失败:必要字段缺失,storeId={}, orderId={}",
|
||||
record.getStore_id(), record.getOrder_id());
|
||||
return false;
|
||||
}
|
||||
|
||||
return add(record);
|
||||
try {
|
||||
// 执行插入操作
|
||||
return add(record);
|
||||
} catch (Exception e) {
|
||||
logger.error("插入打印日志时发生异常,storeId={}, orderId={}",
|
||||
record.getStore_id(), record.getOrder_id(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void insertShopStorePrinterLogBatch(List<ShopStorePrinterLog> records) {
|
||||
// 参数校验
|
||||
if (CollUtil.isEmpty(records)) {
|
||||
logger.debug("批量插入打印日志失败:记录列表为空");
|
||||
return;
|
||||
}
|
||||
|
||||
for (ShopStorePrinterLog record : records) {
|
||||
if (record.getStore_id() == null ||
|
||||
StrUtil.isBlank(record.getOrder_id()) ||
|
||||
StrUtil.isBlank(record.getTemplate_value()) ||
|
||||
StrUtil.isBlank(record.getPrint_content())) {
|
||||
continue;
|
||||
try {
|
||||
for (ShopStorePrinterLog record : records) {
|
||||
// 单条记录校验
|
||||
if (record == null) {
|
||||
logger.warn("批量插入打印日志跳过:记录为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (record.getStore_id() == null ||
|
||||
StrUtil.isBlank(record.getOrder_id()) ||
|
||||
StrUtil.isBlank(record.getTemplate_value()) ||
|
||||
StrUtil.isBlank(record.getPrint_content())) {
|
||||
logger.warn("批量插入打印日志跳过:必要字段缺失,storeId={}, orderId={}",
|
||||
record.getStore_id(), record.getOrder_id());
|
||||
continue;
|
||||
}
|
||||
|
||||
// 执行插入操作
|
||||
add(record);
|
||||
}
|
||||
|
||||
add(record);
|
||||
logger.debug("批量插入打印日志完成,共处理 {} 条记录", records.size());
|
||||
} catch (Exception e) {
|
||||
logger.error("批量插入打印日志时发生异常,记录数: {}", records.size(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -14,13 +14,15 @@ import com.suisung.mall.common.domain.UserDto;
|
||||
import com.suisung.mall.common.modules.store.ShopStorePrinter;
|
||||
import com.suisung.mall.common.modules.store.ShopStorePrinterLog;
|
||||
import com.suisung.mall.common.modules.store.ShopStorePrinterTemplate;
|
||||
import com.suisung.mall.common.pojo.vo.OrderItemPrintVO;
|
||||
import com.suisung.mall.common.pojo.vo.OrderPrintVO;
|
||||
import com.suisung.mall.common.pojo.vo.ShopStorePrinterVO;
|
||||
import com.suisung.mall.common.utils.CheckUtil;
|
||||
import com.suisung.mall.common.utils.FreeMakerUtils;
|
||||
import com.suisung.mall.common.utils.JsonUtil;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.order.service.ShopOrderBaseService;
|
||||
import com.suisung.mall.shop.order.service.impl.ShopOrderInfoServiceImpl;
|
||||
import com.suisung.mall.shop.order.service.ShopOrderReturnService;
|
||||
import com.suisung.mall.shop.store.mapper.ShopStorePrinterMapper;
|
||||
import com.suisung.mall.shop.store.service.ShopStorePrinterLogService;
|
||||
import com.suisung.mall.shop.store.service.ShopStorePrinterService;
|
||||
@ -30,6 +32,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -49,15 +52,13 @@ public class ShopStorePrinterServiceImpl extends BaseServiceImpl<ShopStorePrinte
|
||||
@Autowired
|
||||
private FeieUtil feieUtil;
|
||||
@Autowired
|
||||
private FreeMakerUtils freeMakerUtils;
|
||||
@Autowired
|
||||
private ShopStorePrinterTemplateService shopStorePrinterTemplateService;
|
||||
@Autowired
|
||||
private ShopOrderBaseService shopOrderBaseService;
|
||||
@Autowired
|
||||
private ShopStorePrinterLogService shopStorePrinterLogService;
|
||||
@Autowired
|
||||
private ShopOrderInfoServiceImpl shopOrderInfoServiceImpl;
|
||||
private ShopOrderReturnService shopOrderReturnService;
|
||||
|
||||
@Override
|
||||
public CommonResult shopStorePrinterPageList(String keyword, Integer pageNum, Integer pageSize) {
|
||||
@ -341,7 +342,7 @@ public class ShopStorePrinterServiceImpl extends BaseServiceImpl<ShopStorePrinte
|
||||
public Boolean printShopStoreOrder(Integer storeId, String orderId) {
|
||||
logger.debug("#### 调用飞鹅打票机的打印操作开始 ####");
|
||||
logger.debug("#### 店铺:{},打印订单:{} ####", storeId, orderId);
|
||||
// 获取订单,包含所有所需的字段,参考实体类:ShopStoreOrderPrintVO 和 ShopStoreOrderProductPrintVO
|
||||
// 获取订单,包含所有所需的字段,参考实体类:ShopStoreOrderPrintVO 和 OrderItemPrintVO
|
||||
|
||||
if (StrUtil.isBlank(orderId)) {
|
||||
logger.error("订单为空,无法打印小票。");
|
||||
@ -349,7 +350,7 @@ public class ShopStorePrinterServiceImpl extends BaseServiceImpl<ShopStorePrinte
|
||||
}
|
||||
|
||||
// 获取打印的订单信息,判断订单支付状态:已支付
|
||||
Map<String, Object> binding = shopOrderBaseService.getOrderPrintInfo(storeId, orderId, StateCode.ORDER_PAID_STATE_YES);
|
||||
Map<String, Object> binding = shopOrderBaseService.fetchOrderPrintInfo(storeId, orderId, StateCode.ORDER_PAID_STATE_YES);
|
||||
if (binding == null) {
|
||||
logger.error("订单{}信息无法获取,无法打印小票。", orderId);
|
||||
return false;
|
||||
@ -406,6 +407,139 @@ public class ShopStorePrinterServiceImpl extends BaseServiceImpl<ShopStorePrinte
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步打印店铺退货订单的小票信息。
|
||||
* <p>
|
||||
* 该方法通过调用飞鹅打票机接口,完成指定订单的退货小票打印功能。主要流程包括:
|
||||
* 1. 校验订单号是否合法;
|
||||
* 2. 获取订单及店铺相关信息;
|
||||
* 3. 查询对应店铺绑定的打印机列表与打印模板;
|
||||
* 4. 渲染打印内容并发送至所有绑定的打印机;
|
||||
* 5. 记录打印日志。
|
||||
* </p>
|
||||
*
|
||||
* @param returnId 退货单编号,用于标识具体的退货记录
|
||||
* @return 打印操作是否成功,成功返回 true,否则返回 false
|
||||
*/
|
||||
@Async
|
||||
@Override
|
||||
public Boolean printShopStoreReturnOrder(String returnId) {
|
||||
logger.debug("#### 调用飞鹅打票机的打印退款订单操作开始 ####");
|
||||
|
||||
// 参数校验
|
||||
if (StrUtil.isBlank(returnId)) {
|
||||
logger.error("退款订单为空,无法打印小票。");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 获取打印的订单信息,并检查订单是否存在且已支付
|
||||
OrderPrintVO orderPrintVO = shopOrderReturnService.fetchReturnOrderPrintInfo("", returnId);
|
||||
if (orderPrintVO == null) {
|
||||
logger.error("退款订单Id{}信息无法获取,无法打印小票。", returnId);
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.debug("退款订单信息:{}", orderPrintVO);
|
||||
|
||||
String orderId = orderPrintVO.getOrder_id();
|
||||
Integer storeId = orderPrintVO.getStore_id();
|
||||
if (CheckUtil.isEmpty(storeId) || CheckUtil.isEmpty(orderId)) {
|
||||
logger.error("订单Id:{},店铺ID:{}为空,无法打印小票。", orderId, storeId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 查询店铺配置的打印机列表
|
||||
List<ShopStorePrinter> printerList = selectPrinterList(storeId);
|
||||
if (CollUtil.isEmpty(printerList)) {
|
||||
// 店铺没有打印机,不再继续执行打印逻辑
|
||||
logger.error("店铺{}未添加打票机,无法打印小票。", storeId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取适用于退货场景的打印模板
|
||||
ShopStorePrinterTemplate template = shopStorePrinterTemplateService.getShopStorePrinterTemplateInner(storeId, StateCode.PRINTER_TEMP_CATE_REFUND);
|
||||
if (template == null
|
||||
|| StrUtil.isBlank(template.getTemplate_name())
|
||||
|| StrUtil.isBlank(template.getTemplate_value())) {
|
||||
// 模板缺失或无效,终止打印流程
|
||||
logger.error("店铺{}未添加打票机打印模版,无法打印小票。", storeId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 重要:重构实体类,处理标题,数量,价格适应长度
|
||||
List<OrderItemPrintVO> orderItems = orderPrintVO.getOrder_items();
|
||||
if (CollUtil.isEmpty(orderItems)) {
|
||||
logger.error("订单{}商品信息为空,无法打印小票。", orderId);
|
||||
return false;
|
||||
}
|
||||
|
||||
List<OrderItemPrintVO> rebuiltItems = new ArrayList<>(orderItems.size());
|
||||
for (OrderItemPrintVO item : orderItems) {
|
||||
if (item != null) {
|
||||
rebuiltItems.add(item.rebuild());
|
||||
}
|
||||
}
|
||||
orderPrintVO.setOrder_items(rebuiltItems);
|
||||
|
||||
// 使用 FreeMarker 模板引擎渲染实际要打印的内容
|
||||
String printContent = FreeMakerUtils.processTemplate(template.getTemplate_name(), template.getTemplate_value(), orderPrintVO);
|
||||
if (StrUtil.isBlank(printContent)) {
|
||||
logger.error("订单{}信息模版渲染异常,无法打印小票。", orderId);
|
||||
return false;
|
||||
}
|
||||
logger.debug("打印内容长度:{}", printContent.length());
|
||||
|
||||
// 提取所有打印机设备序列号,准备批量打印
|
||||
List<String> printerSnList = new ArrayList<>(printerList.size());
|
||||
for (ShopStorePrinter printer : printerList) {
|
||||
if (printer != null && StrUtil.isNotBlank(printer.getPrinter_sn())) {
|
||||
printerSnList.add(printer.getPrinter_sn());
|
||||
}
|
||||
}
|
||||
|
||||
if (CollUtil.isEmpty(printerSnList)) {
|
||||
logger.error("订单{}没有有效的打印机设备,无法打印小票。", orderId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 向飞鹅打票机发送打印任务
|
||||
List<Pair<String, String>> respList = feieUtil.printContentByList(printerSnList, printContent);
|
||||
if (CollUtil.isEmpty(respList)) {
|
||||
// 所有打印机均未能响应,视为失败
|
||||
logger.error("订单{}信息打印,调用飞鹅打印机打印失败。", orderId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 遍历每台打印机的响应结果,记录打印日志
|
||||
for (Pair<String, String> respSn : respList) {
|
||||
if (respSn != null) {
|
||||
// 构造并保存本次打印的日志记录
|
||||
ShopStorePrinterLog shopStorePrinterLog = new ShopStorePrinterLog(
|
||||
template.getCategory(),
|
||||
storeId,
|
||||
orderId,
|
||||
template.getTemplate_id(),
|
||||
template.getTemplate_value(),
|
||||
JsonUtil.object2json(orderPrintVO),
|
||||
printContent,
|
||||
respSn.getSecond(),
|
||||
respSn.getFirst()
|
||||
);
|
||||
shopStorePrinterLogService.insertShopStorePrinterLog(shopStorePrinterLog);
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("#### 调用飞鹅打票机的打印退款订单操作结束 ####");
|
||||
return true;
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("打印退货订单小票时发生异常, 退货单ID: {}", returnId, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<ShopStorePrinter> selectPrinterList(Integer storeId) {
|
||||
if (storeId == null) {
|
||||
|
||||
@ -2,6 +2,7 @@ package com.suisung.mall.shop.store.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.api.CommonResult;
|
||||
import com.suisung.mall.common.constant.CommonConstant;
|
||||
import com.suisung.mall.common.modules.store.ShopStorePrinterTemplate;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.store.mapper.ShopStorePrinterTemplateMapper;
|
||||
@ -37,6 +38,7 @@ public class ShopStorePrinterTemplateServiceImpl extends BaseServiceImpl<ShopSto
|
||||
QueryWrapper<ShopStorePrinterTemplate> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("store_id", storeId != null ? storeId : 0)
|
||||
.eq("category", category)
|
||||
.eq("status", CommonConstant.Enable)
|
||||
.orderByAsc("template_id");
|
||||
|
||||
ShopStorePrinterTemplate shopStorePrinterTemplate = findOne(queryWrapper);
|
||||
@ -46,6 +48,7 @@ public class ShopStorePrinterTemplateServiceImpl extends BaseServiceImpl<ShopSto
|
||||
queryWrapper.clear();
|
||||
queryWrapper.eq("store_id", 0)
|
||||
.eq("category", category)
|
||||
.eq("status", CommonConstant.Enable)
|
||||
.orderByAsc("template_id");
|
||||
|
||||
shopStorePrinterTemplate = findOne(queryWrapper);
|
||||
|
||||
@ -48,9 +48,14 @@ public class ShopStoreSfOrderServiceImpl extends BaseServiceImpl<ShopStoreSfOrde
|
||||
if (StrUtil.isBlank(shopOrderId)) {
|
||||
return null;
|
||||
}
|
||||
QueryWrapper<ShopStoreSfOrder> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("shop_order_id", shopOrderId);
|
||||
return getOne(wrapper);
|
||||
|
||||
if (StrUtil.startWith(shopOrderId, "JS")) { // 顺丰同城的订单号标志
|
||||
return getBySfOrderId(shopOrderId);
|
||||
} else {
|
||||
QueryWrapper<ShopStoreSfOrder> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("shop_order_id", shopOrderId);
|
||||
return getOne(wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -6,7 +6,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.suisung.mall.common.pojo.res.FeiePrinterApiRes;
|
||||
import com.suisung.mall.common.pojo.vo.ShopStoreOrderProductPrintVO;
|
||||
import com.suisung.mall.common.pojo.vo.OrderItemPrintVO;
|
||||
import com.suisung.mall.common.utils.JsonUtil;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
@ -330,7 +330,7 @@ public class FeieUtil {
|
||||
* @param amountLen 金额字节数,最大8个字节
|
||||
* @return
|
||||
*/
|
||||
public String genProductStr(List<ShopStoreOrderProductPrintVO> productList, int titleLen, int numLen, int amountLen) {
|
||||
public String genProductStr(List<OrderItemPrintVO> productList, int titleLen, int numLen, int amountLen) {
|
||||
String resultStr = "";
|
||||
resultStr += "<L>商品名称 数量 金额</L><BR>";
|
||||
resultStr += "--------------------------------<BR>";
|
||||
|
||||
@ -819,8 +819,8 @@
|
||||
<!--总计优惠金额 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)
|
||||
<!--预计收入:订单原价金额-总计优惠金额-配送费-平台费+打包费-->
|
||||
(ob.order_product_amount-od.order_discount_amount-od.voucher_price-od.order_points_fee-od.order_adjust_fee-od.platform_fee-order_shipping_fee_inner+od.packing_fee)
|
||||
as order_income_amount,
|
||||
(od.platform_fee+lkl_fee) as platform_fee,
|
||||
od.packing_fee,
|
||||
@ -1027,9 +1027,9 @@
|
||||
</choose>
|
||||
</if>
|
||||
|
||||
<!-- 2-物流配送订单 -->
|
||||
<!-- 2-非同城配送 物流配送订单 -->
|
||||
<if test="delivery != null and delivery == 2">
|
||||
AND oi.delivery_type_id IN (1,2,3,4,10)
|
||||
AND oi.delivery_type_id IN (1,2,3,4,5,10,15)
|
||||
|
||||
<!-- 订单状态筛选 -->
|
||||
<choose>
|
||||
|
||||
@ -86,4 +86,97 @@
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
|
||||
<resultMap id="ReturnOrderPrintInfoResult" type="com.suisung.mall.common.pojo.vo.OrderPrintVO">
|
||||
<!--订单对象映射-->
|
||||
<result property="order_id" column="order_id"/>
|
||||
<result property="return_id" column="return_id"/>
|
||||
<result property="store_id" column="store_id"/>
|
||||
<result property="store_name" column="store_name"/>
|
||||
<result property="store_tel" column="store_tel"/>
|
||||
<result property="order_pickup_num_str" column="order_pickup_num_str"/>
|
||||
<result property="order_message" column="order_message"/>
|
||||
<result property="seller_message" column="seller_message"/>
|
||||
<result property="payment_time" column="payment_time"/>
|
||||
<result property="order_items_count" column="order_items_count"/>
|
||||
<result property="order_product_amount" column="order_product_amount"/>
|
||||
<result property="order_shipping_fee" column="order_shipping_fee"/>
|
||||
<result property="order_channel_name" column="order_channel_name"/>
|
||||
<result property="payment_type_name" column="payment_type_name"/>
|
||||
<result property="delivery_type_id" column="delivery_type_id"/>
|
||||
<result property="delivery_type_name" column="delivery_type_name"/>
|
||||
<result property="packing_fee" column="packing_fee"/>
|
||||
<result property="basic_rights" column="basic_rights"/>
|
||||
<result property="order_payment_amount" column="order_payment_amount"/>
|
||||
<result property="return_refund_amount" column="return_refund_amount"/>
|
||||
<result property="order_state" column="order_state"/>
|
||||
<result property="return_buyer_message" column="return_buyer_message"/>
|
||||
<result property="return_store_message" column="return_store_message"/>
|
||||
<result property="return_add_time" column="return_add_time"/>
|
||||
<result property="return_finish_time" column="return_finish_time"/>
|
||||
<result property="return_flag_str" column="return_flag_str"/>
|
||||
<result property="return_state" column="return_state"/>
|
||||
<result property="buyer_user_name" column="buyer_user_name"/>
|
||||
<result property="return_tel" column="return_tel"/>
|
||||
<result property="da_mobile" column="da_mobile"/>
|
||||
<result property="da_province" column="da_province"/>
|
||||
<result property="da_city" column="da_city"/>
|
||||
<result property="da_address" column="da_address"/>
|
||||
<result property="cashier" column="cashier"/>
|
||||
<!-- 集合类型映射 -->
|
||||
<collection property="order_items" ofType="com.suisung.mall.common.pojo.vo.OrderItemPrintVO">
|
||||
<result property="item_name" column="item_name"/>
|
||||
<result property="order_item_quantity" column="order_item_quantity"/>
|
||||
<result property="order_item_amount" column="order_item_amount"/>
|
||||
<result property="s_name" column="s_name"/>
|
||||
<result property="s_quantity" column="s_quantity"/>
|
||||
<result property="s_amount" column="s_amount"/>
|
||||
<result property="product_sn" column="product_sn"/>
|
||||
</collection>
|
||||
</resultMap>
|
||||
|
||||
|
||||
<select id="fetchReturnOrderPrintInfo" resultMap="ReturnOrderPrintInfoResult">
|
||||
select
|
||||
sob.order_id,sob.store_id,sob.store_name,sob.buyer_user_id,
|
||||
sob.buyer_user_name,sob.order_time,sob.order_payment_amount,sob.order_product_amount,
|
||||
soi.order_title, soi.delivery_type_id, soi.payment_type_id, soi.payment_time,
|
||||
LPAD(soi.order_pickup_num, 7, '0') as order_pickup_num_str,
|
||||
CASE WHEN soi.booking_state = 2 THEN 2 ELSE 1 END AS booking_state, soi.booking_begin_time,
|
||||
sod.order_message, sod.order_shipping_fee, sod.order_shipping_fee_amount, sod.delivery_time, sod.delivery_type_id,
|
||||
(sod.order_discount_amount + sod.voucher_price + sod.order_points_fee + sod.order_adjust_fee) as total_discount_amount,
|
||||
sod.packing_fee,
|
||||
ssi.store_tel,
|
||||
soda.da_province,soda.da_city,soda.da_address,soda.da_mobile, soda.order_id,
|
||||
sor.return_id, sor.return_buyer_message, sor.return_store_message, sor.return_add_time, sor.return_finish_time,
|
||||
CASE WHEN sor.return_flag != 1 THEN '仅退款' ELSE '退款退货' END AS return_flag_str,
|
||||
sor.return_state_id, sor.return_refund_amount,
|
||||
sor.return_tel,
|
||||
soi_item.item_barcode as product_sn, soi_item.item_name,
|
||||
sor_item.return_item_subtotal as order_item_amount, sor_item.return_item_num as order_item_quantity
|
||||
from shop_order_base sob
|
||||
INNER JOIN shop_order_info soi on sob.order_id=soi.order_id
|
||||
INNER JOIN shop_order_data sod on sob.order_id=sod.order_id
|
||||
INNER JOIN shop_store_base ssb on sob.store_id=ssb.store_id
|
||||
INNER JOIN shop_store_info ssi on sob.store_id=ssi.store_id
|
||||
INNER JOIN shop_order_delivery_address soda on sob.order_id=soda.order_id
|
||||
INNER JOIN shop_order_item soi_item on soi_item.order_id=sob.order_id
|
||||
INNER JOIN shop_order_return sor on sob.order_id=sor.order_id
|
||||
INNER JOIN shop_order_return_item sor_item on sor_item.order_id=sob.order_id AND sor_item.return_id=sor.return_id
|
||||
AND sor_item.order_item_id=soi_item.order_item_id
|
||||
|
||||
<where>
|
||||
<if test="orderId!=null and orderId != ''">
|
||||
and sob.order_id=#{orderId}
|
||||
</if>
|
||||
|
||||
<if test="returnId!=null and returnId != ''">
|
||||
and sor.return_id=#{returnId}
|
||||
</if>
|
||||
|
||||
</where>
|
||||
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
@ -161,7 +161,7 @@
|
||||
shop_product_image spi
|
||||
INNER JOIN
|
||||
library_product lp ON
|
||||
spi.product_short_name = lp.product_short_name
|
||||
spi.product_short_name = lp.sname
|
||||
LEFT JOIN
|
||||
(
|
||||
SELECT
|
||||
@ -178,7 +178,7 @@
|
||||
WHERE
|
||||
spi.product_from = '1005'
|
||||
AND spi.item_image_default = '1'
|
||||
<![CDATA[ AND lp.product_short_name <> '' ]]>
|
||||
<![CDATA[ AND lp.sname <> '' ]]>
|
||||
)t
|
||||
)temp
|
||||
where
|
||||
@ -213,7 +213,7 @@
|
||||
shop_product_image spi
|
||||
INNER JOIN
|
||||
library_product lp ON
|
||||
spi.product_short_name = lp.product_short_name
|
||||
spi.product_short_name = lp.sname
|
||||
LEFT JOIN
|
||||
(
|
||||
SELECT
|
||||
@ -230,7 +230,7 @@
|
||||
WHERE
|
||||
spi.product_from = '1005'
|
||||
AND spi.item_image_default = '1'
|
||||
<![CDATA[ AND lp.product_short_name <> '' ]]>
|
||||
<![CDATA[ AND lp.sname <> '' ]]>
|
||||
)t
|
||||
)temp
|
||||
where
|
||||
|
||||
@ -51,6 +51,48 @@
|
||||
收银员:李小璐<BR>
|
||||
|
||||
|
||||
格式化带变量模版:
|
||||
<#if is_booking_order><CB><B>【预约订单】<BR></B></CB>
|
||||
</#if><CB>${store_name}</CB><BR>
|
||||
--------------------------------<BR>
|
||||
<CB>#${order_pickup_num_str}</CB><BR>
|
||||
<L>买家备注:${order_message!'-'}</L><BR>
|
||||
<BOLD>配送时间:${payment_time?string('MM-dd HH:mm')}~${delivery_time?string('HH:mm')}</BOLD><BR>
|
||||
--------------------------------<BR>
|
||||
订单编号:${order_id}<BR>
|
||||
订单来源:微信小程序<BR>
|
||||
支付方式:微信支付<BR>
|
||||
配送来源:顺丰同城<BR>
|
||||
付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}<BR>
|
||||
--------------------------------<BR>
|
||||
<L>商品名称 数量 金额</L><BR>
|
||||
--------------------------------<BR>
|
||||
<#list order_items as item><L>${item.s_name}</L><L><BOLD>${item.s_quantity}</BOLD></L><L>${item.s_amount}</L><BR>
|
||||
<#if item.s_name_segs??><#list item.s_name_segs as seg><L>${seg}</L><BR>
|
||||
</#list></#if><BOLD><#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}</BOLD><BR>
|
||||
</#if><BR>
|
||||
|
||||
</#list>--------------------------------<BR>
|
||||
商品总件数:<BOLD>${order_items_count!0}</BOLD><BR>
|
||||
商品总额:<BOLD>¥${order_product_amount?string('0.00')}</BOLD><BR>
|
||||
运费:<BOLD>¥${order_shipping_fee?string('0.00')}</BOLD><BR>
|
||||
<#if packing_fee?? && (packing_fee > 0)>打包费:<BOLD>¥${packing_fee?string('0.00')}</BOLD><BR>
|
||||
</#if>优惠金额:<BOLD>-¥${(quanyi!0)?string('0.00')}</BOLD><BR>
|
||||
实付金额:<BOLD>¥${order_payment_amount?string('0.00')}</BOLD><BR>
|
||||
<#if seller_message?default("")?trim?length gt 1>
|
||||
--------------------------------<BR>
|
||||
<BOLD>商家备注:${seller_message!'-'}</BOLD><BR>
|
||||
</#if>
|
||||
--------------------------------<BR>
|
||||
<BOLD>收货人:${buyer_user_name!''}</BOLD><BR>
|
||||
<BOLD>收货人手机:${da_mobile!'-'}</BOLD><BR>
|
||||
<BOLD>收货地址:${da_province!'-'}${da_city!'-'}${da_address!'-'}</BOLD><BR>
|
||||
--------------------------------<BR>
|
||||
门店:${store_name}<BR>
|
||||
门店电话:<BOLD>${store_tel!'-'}</BOLD><BR>
|
||||
收银员:${cashier!'店长'}<BR>
|
||||
|
||||
|
||||
格式化的示例:
|
||||
<CB>小发同城</CB><BR>--------------------------------<BR><CB>#00019232</CB><BR><L>买家备注:不用敲门,放在门口旁边的外卖箱,打个电话告知送达就行,谢谢!!!</L><BR><BOLD>配送时间:2024-10-25 14:00-14:30</BOLD><BR>--------------------------------<BR>订单编号:ES20231026111444527685<BR>订单来源:微信小程序<BR>支付方式:微信支付<BR>配送来源:顺丰同城<BR>付款时间:2024-10-25 14:00:23<BR>--------------------------------<BR><L>商品名称 数量 金额</L><BR>--------------------------------<BR><L>可口可乐CocaC</L> <L><BOLD> x110 </BOLD></L><L> 8100.45</L><BR><L>ola经典美味汽水1.2</L><BR><L>5L/瓶</L><BR><BOLD>6970448170051</BOLD><BR><L>排骨约350g(默 </L><L><BOLD> 1 </BOLD></L><L> 150.13 </L><BR><L>认砍小块)</L><BR><BOLD>6970448170053</BOLD><BR><L>新鲜虫草花1包约2 </L><L><BOLD> x11 </BOLD></L><L> 4.01 </L><BR><L>00g 韭菜1000g 鸡蛋</L><BR><L>2003克</L><BR><BOLD>6970448170054</BOLD><BR><L>冰红茶风味饮料 <L><BOLD> 1 </BOLD></L><L> 13.24 </L></L><BR><BOLD>6970448170055</BOLD><BR>--------------------------------<BR>商品总件数:<BOLD>3</BOLD><BR>商品总额:<BOLD>¥18.7</BOLD><BR>押金:<BOLD>¥500</BOLD><BR>运费:<BOLD>¥5.54</BOLD><BR>会员权益:<BOLD>-¥50</BOLD><BR>秒杀:<BOLD>-¥100</BOLD><BR>实付金额:<BOLD>¥428.9元</BOLD><BR>--------------------------------<BR><BOLD>商家备注:老顾客赠送一箱牛奶;玻璃瓶包装轻拿轻放!</BOLD><BR>--------------------------------<BR><BOLD>收货人:张三</BOLD><BR><BOLD>收货人手机:13128778765</BOLD><BR><BOLD>收货地址:北京市朝阳区朝阳路朝阳人民小区1号楼1栋1101</BOLD><BR>--------------------------------<BR>门店:岛内价生活超市<BR>门店电话:<BOLD>13665822542</BOLD><BR>收银员:李小璐<BR>
|
||||
|
||||
|
||||
@ -37,8 +37,45 @@
|
||||
--------------------------------<BR>
|
||||
操作员:李小明<BR>
|
||||
|
||||
格式化模版:
|
||||
############################################
|
||||
|
||||
修改后的模版
|
||||
|
||||
|
||||
<CB><B>用户退款订单</B></CB><BR>
|
||||
<CB>${store_name}</CB><BR>
|
||||
--------------------------------<BR>
|
||||
<CB>#${order_pickup_num_str}</CB><BR>
|
||||
<L>退款原因:${return_buyer_message!'-'}</L><BR>
|
||||
<BOLD>配送时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}(20-30分钟)</BOLD><BR>
|
||||
--------------------------------<BR>
|
||||
订单编号:${order_id}<BR>
|
||||
退单编号:${return_id}<BR>
|
||||
订单来源:${order_channel_name!'微信小程序'}<BR>
|
||||
支付方式:${payment_type_name!'微信支付'}<BR>
|
||||
配送来源:${deliver_type_name!'顺丰同城'}<BR>
|
||||
付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}<BR>
|
||||
申请退款:${return_add_time?string('yyyy-MM-dd HH:mm:ss')}<BR>
|
||||
确认退款:${return_finish_time?string('yyyy-MM-dd HH:mm:ss')}<BR>
|
||||
--------------------------------<BR>
|
||||
<C>******* 退款商品 ******</C><BR>
|
||||
--------------------------------<BR>
|
||||
<#list order_items as item><L>${item.s_name}</L><L><BOLD>${item.s_quantity}</BOLD></L><L>${item.s_amount}</L><BR><#if item.s_name_segs??><#list item.s_name_segs as seg><L>${seg}</L><BR></#list></#if><BOLD><#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}</BOLD><BR></#if></#list>
|
||||
--------------------------------<BR>
|
||||
实付金额:<BOLD>¥${order_payment_amount?string('0.00')}元</BOLD><BR>
|
||||
配送费:<BOLD>¥${order_shipping_fee?string('0.00')}元</BOLD><BR>
|
||||
申请退款:<BOLD>¥${return_refund_amount?string('0.00')}</BOLD><BR>
|
||||
退款方式:<BOLD>${return_flag_str}</BOLD><BR>
|
||||
商家审批备注:<BOLD>${return_store_message!'-'}</BOLD><BR>
|
||||
--------------------------------<BR>
|
||||
<BOLD>会员名称:${buyer_user_name!'微信用户'}</BOLD><BR>
|
||||
<BOLD>会员手机:${return_tel!'-'}</BOLD><BR>
|
||||
--------------------------------<BR>
|
||||
操作员:${cashier!'-'}<BR>
|
||||
|
||||
|
||||
原模版:
|
||||
<CB>${store_name}</CB><BR>--------------------------------<BR><CB>#${order_pickup_num_str}</CB><BR><L>买家备注:${order_message!'-'}</L><BR><BOLD>配送时间:${delivery_time}</BOLD><BR>--------------------------------<BR>订单编号:${order_id}<BR>订单来源:微信小程序<BR>支付方式:微信支付<BR>配送来源:顺丰同城<BR>付款时间:${payment_time}<BR>--------------------------------<BR><L>商品名称 数量 金额</L><BR>--------------------------------<BR><#list order_items as item><L>${item.s_name}</L><L><BOLD>${item.s_quantity}</BOLD></L><L>${item.s_amount}</L><BR><#if item.s_name_segs??><#list item.s_name_segs as seg><L>${seg}</L><BR></#list></#if><BOLD><#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}</BOLD><BR></#if></#list>--------------------------------<BR>商品总件数:<BOLD>${order_items_count!0}</BOLD><BR>商品总额:<BOLD>¥${order_product_amount?string('0.00')}</BOLD><BR>押金:<BOLD>¥${(yajin!0)?string('0.00')}</BOLD><BR>运费:<BOLD>¥${order_shipping_fee?string('0.00')}</BOLD><BR>会员权益:<BOLD>-¥${(quanyi!0)?string('0.00')}</BOLD><BR>秒杀:<BOLD>-¥${(miaosha!0)?string('0.00')}</BOLD><BR>实付金额:<BOLD>¥${order_payment_amount?string('0.00')}</BOLD><BR><#if seller_message?default("")?trim?length gt 1>--------------------------------<BR><BOLD>商家备注:${seller_message!'---'}</BOLD><BR></#if>--------------------------------<BR><BOLD>收货人:${buyer_user_name!''}</BOLD><BR><BOLD>收货人手机:${store_tel!''}</BOLD><BR><BOLD>收货地址:${da_province!'-'}${da_city!'-'}${da_address!'-'}</BOLD><BR>--------------------------------<BR>门店:${store_name}<BR>门店电话:<BOLD>${store_tel!'-'}</BOLD><BR>收银员:${cashier!'-'}<BR>
|
||||
|
||||
带参模版:
|
||||
<CB><B>用户退款订单</B></CB><BR><CB>${store_name}</CB><BR>--------------------------------<BR><CB>#${order_pickup_num_str}</CB><BR><L>退款原因:${return_buyer_message!'-'}</L><BR><BOLD>配送时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}(20-30分钟)</BOLD><BR>--------------------------------<BR>订单编号:${order_id}<BR>退单编号:${return_id}<BR>订单来源:${order_channel_name!'微信小程序'}<BR>支付方式:${payment_type_name!'微信支付'}<BR>配送来源:${deliver_type_name!'顺丰同城'}<BR>付款时间:${payment_time?string('yyyy-MM-dd HH:mm:ss')}<BR>申请退款:${return_add_time?string('yyyy-MM-dd HH:mm:ss')}<BR>确认退款:${return_finish_time?string('yyyy-MM-dd HH:mm:ss')}<BR>--------------------------------<BR><C>******* 退款商品 ******</C><BR>--------------------------------<BR><#list order_items as item><L>${item.s_name}</L><L><BOLD>${item.s_quantity}</BOLD></L><L>${item.s_amount}</L><BR><#if item.s_name_segs??><#list item.s_name_segs as seg><L>${seg}</L><BR></#list></#if><BOLD><#if item.product_sn?default("")?trim?length gt 1>${item.product_sn}</BOLD><BR></#if></#list>--------------------------------<BR>实付金额:<BOLD>¥${order_payment_amount?string('0.00')}元</BOLD><BR>配送费:<BOLD>¥${order_shipping_fee?string('0.00')}元</BOLD><BR>申请退款:<BOLD>¥${return_refund_amount?string('0.00')}</BOLD><BR>退款方式:<BOLD>${return_flag_str}</BOLD><BR>商家审批备注:<BOLD>${return_store_message!'-'}</BOLD><BR>--------------------------------<BR><BOLD>会员名称:${buyer_user_name}</BOLD><BR><BOLD>会员手机:${return_tel}</BOLD><BR>--------------------------------<BR>操作员:${cashier!'-'}<BR>
|
||||
|
||||
@ -185,7 +185,7 @@ public class SnsStoryBaseServiceImpl extends BaseServiceImpl<SnsStoryBaseMapper,
|
||||
}
|
||||
|
||||
if (snsStoryBase.getStory_enable() != null) {
|
||||
queryWrapper.eq("story_enable", snsStoryBase.getStory_enable() );
|
||||
queryWrapper.eq("story_enable", snsStoryBase.getStory_enable());
|
||||
}
|
||||
|
||||
if (CheckUtil.isNotEmpty(snsStoryBase.getStory_index())) {
|
||||
@ -201,7 +201,7 @@ public class SnsStoryBaseServiceImpl extends BaseServiceImpl<SnsStoryBaseMapper,
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map getStoryList(StorySearchDTO storySearchDTO) {
|
||||
public Map getStoryList(StorySearchDTO storySearchDTO) {
|
||||
QueryWrapper<SnsStoryBase> column_row = new QueryWrapper<>(); //查询获得相关的SnsStoryBase列表集合
|
||||
|
||||
if (storySearchDTO.getStory_type() != null) {
|
||||
@ -266,44 +266,44 @@ public class SnsStoryBaseServiceImpl extends BaseServiceImpl<SnsStoryBaseMapper,
|
||||
}
|
||||
|
||||
UserDto user = ContextUtil.getCurrentUser();
|
||||
if(user!=null){
|
||||
if (user != null) {
|
||||
//用户是否点赞
|
||||
QueryWrapper<SnsStoryLike> queryWrapper=new QueryWrapper<>();
|
||||
queryWrapper.eq("user_id",user.getId());
|
||||
QueryWrapper<SnsStoryLike> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("user_id", user.getId());
|
||||
List<SnsStoryLike> snsStoryLikes = snsStoryLikeService.find(queryWrapper);
|
||||
List<Integer> collect = snsStoryLikes.stream().map(s -> s.getStory_id()).distinct().collect(Collectors.toList());
|
||||
for(Map item :items){
|
||||
for (Map item : items) {
|
||||
Integer story_id = Convert.toInt(item.get("story_id"));
|
||||
if(collect.contains(story_id)){
|
||||
item.put("IsFabulous",1);
|
||||
}else{
|
||||
item.put("IsFabulous",0);
|
||||
if (collect.contains(story_id)) {
|
||||
item.put("IsFabulous", 1);
|
||||
} else {
|
||||
item.put("IsFabulous", 0);
|
||||
}
|
||||
}
|
||||
|
||||
//用户是否收藏
|
||||
QueryWrapper<SnsStoryCollection> snsStoryCollectionQueryWrapper=new QueryWrapper<>();
|
||||
snsStoryCollectionQueryWrapper.eq("user_id",user.getId());
|
||||
QueryWrapper<SnsStoryCollection> snsStoryCollectionQueryWrapper = new QueryWrapper<>();
|
||||
snsStoryCollectionQueryWrapper.eq("user_id", user.getId());
|
||||
List<SnsStoryCollection> snsStoryCollections = snsStoryCollectionService.find(snsStoryCollectionQueryWrapper);
|
||||
List<Integer> collectionList = snsStoryCollections.stream().map(s -> s.getStory_id()).distinct().collect(Collectors.toList());
|
||||
for(Map item :items){
|
||||
for (Map item : items) {
|
||||
Integer story_id = Convert.toInt(item.get("story_id"));
|
||||
if(collectionList.contains(story_id)){
|
||||
item.put("IsCollection",1);
|
||||
}else{
|
||||
item.put("IsCollection",0);
|
||||
if (collectionList.contains(story_id)) {
|
||||
item.put("IsCollection", 1);
|
||||
} else {
|
||||
item.put("IsCollection", 0);
|
||||
}
|
||||
}
|
||||
|
||||
//用户是否关注
|
||||
for(Map item:items){
|
||||
QueryWrapper<SnsUserFriend> friendQueryWrapper=new QueryWrapper<>();
|
||||
friendQueryWrapper.eq("user_id",user.getId()).eq("friend_id",Convert.toInt(item.get("user_id")));
|
||||
for (Map item : items) {
|
||||
QueryWrapper<SnsUserFriend> friendQueryWrapper = new QueryWrapper<>();
|
||||
friendQueryWrapper.eq("user_id", user.getId()).eq("friend_id", Convert.toInt(item.get("user_id")));
|
||||
SnsUserFriend one = snsUserFriendService.findOne(friendQueryWrapper);
|
||||
if(one!=null){
|
||||
item.put("IsFollow",true);
|
||||
}else{
|
||||
item.put("IsFollow",false);
|
||||
if (one != null) {
|
||||
item.put("IsFollow", true);
|
||||
} else {
|
||||
item.put("IsFollow", false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -382,7 +382,7 @@ public class SnsStoryBaseServiceImpl extends BaseServiceImpl<SnsStoryBaseMapper,
|
||||
if (story_id == null) {
|
||||
accountUserSns.setUser_story(accountUserSns.getUser_story() + 1);
|
||||
if (!accountService.saveOrUpdateAccountUserSns(accountUserSns)) {
|
||||
log.error(I18nUtil._("更新用户发帖数量失败!bean[{}]"), accountUserSns.toString());
|
||||
log.error(I18nUtil._("更新用户发帖数量失败!bean[{}]"), accountUserSns);
|
||||
throw new ApiException(I18nUtil._("更新用户发帖数量失败!"));
|
||||
}
|
||||
}
|
||||
@ -406,28 +406,44 @@ public class SnsStoryBaseServiceImpl extends BaseServiceImpl<SnsStoryBaseMapper,
|
||||
|
||||
//帖子类型不是视频类型
|
||||
@Override
|
||||
public Map getStory(Integer story_id) {
|
||||
public Map getStory(Integer story_id) {
|
||||
UserDto user = ContextUtil.getCurrentUser();
|
||||
Integer user_id = 0;
|
||||
Integer user_id = null;
|
||||
|
||||
if (user == null) {
|
||||
throw new ApiException(ResultCode.NEED_LOGIN);
|
||||
} else {
|
||||
// 允许未登录用户访问
|
||||
if (user != null) {
|
||||
user_id = user.getId();
|
||||
}
|
||||
|
||||
// 参数校验
|
||||
if (story_id == null || story_id <= 0) {
|
||||
throw new ApiException("无效的故事ID");
|
||||
}
|
||||
|
||||
SnsStoryBase storyBase = get(story_id);
|
||||
|
||||
// 检查故事是否存在
|
||||
if (storyBase == null) {
|
||||
throw new ApiException("故事不存在");
|
||||
}
|
||||
|
||||
Map row = Convert.toMap(String.class, Object.class, storyBase);
|
||||
row = accountService.fixUserAvatar(row, true);
|
||||
|
||||
// 检查是否包含富文本
|
||||
String story_content = Convert.toStr(row.get("story_content"));
|
||||
if (StrUtil.isNotBlank(story_content)) {
|
||||
Document document = Jsoup.parse(story_content);
|
||||
String text = document.text();
|
||||
// 如果不相等就是富文本
|
||||
row.put("has_rich", story_content.length() != text.length());
|
||||
try {
|
||||
Document document = Jsoup.parse(story_content);
|
||||
String text = document.text();
|
||||
// 如果不相等就是富文本
|
||||
row.put("has_rich", story_content.length() != text.length());
|
||||
} catch (Exception e) {
|
||||
// 解析失败时默认不是富文本
|
||||
row.put("has_rich", false);
|
||||
}
|
||||
} else {
|
||||
row.put("has_rich", false);
|
||||
}
|
||||
|
||||
row.put("product_item_name", "");
|
||||
@ -437,54 +453,108 @@ public class SnsStoryBaseServiceImpl extends BaseServiceImpl<SnsStoryBaseMapper,
|
||||
|
||||
String str_item_id = storyBase.getItem_id(); //获得帖子商品的item_id值
|
||||
if (StrUtil.isNotBlank(str_item_id)) {
|
||||
List<Long> item_ids = Convert.toList(Long.class, str_item_id);
|
||||
Map product_row = shopService.getProductItemOne(item_ids.get(0));
|
||||
try {
|
||||
List<Long> item_ids = Convert.toList(Long.class, str_item_id);
|
||||
// 检查列表是否为空以及索引是否有效
|
||||
if (CollUtil.isNotEmpty(item_ids) && item_ids.get(0) != null) {
|
||||
Map product_row = shopService.getProductItemOne(item_ids.get(0));
|
||||
|
||||
if (CollUtil.isNotEmpty(product_row)) {
|
||||
String product_name = Convert.toStr(product_row.get("product_name"), "");
|
||||
String item_name = Convert.toStr(product_row.get("item_name"), "");
|
||||
row.put("product_item_name", product_name + " " + item_name);
|
||||
row.put("item_unit_price", product_row.get("item_unit_price"));
|
||||
row.put("item_market_price", product_row.get("item_market_price"));
|
||||
row.put("product_image", product_row.get("product_image"));
|
||||
if (CollUtil.isNotEmpty(product_row)) {
|
||||
String product_name = Convert.toStr(product_row.get("product_name"), "");
|
||||
String item_name = Convert.toStr(product_row.get("item_name"), "");
|
||||
row.put("product_item_name", product_name + " " + item_name);
|
||||
row.put("item_unit_price", product_row.get("item_unit_price"));
|
||||
row.put("item_market_price", product_row.get("item_market_price"));
|
||||
row.put("product_image", product_row.get("product_image"));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("获取商品信息失败, story_id: {}, item_id: {}", story_id, str_item_id, e);
|
||||
// 发生异常时保持默认值
|
||||
}
|
||||
}
|
||||
|
||||
// 是否点赞
|
||||
QueryWrapper<SnsStoryLike> likeQueryWrapper = new QueryWrapper<>();
|
||||
likeQueryWrapper.eq("story_id", story_id).eq("user_id", user_id);
|
||||
SnsStoryLike story_like_row = snsStoryLikeService.findOne(likeQueryWrapper);
|
||||
row.put("IsFabulous", story_like_row != null ? 1 : 0);
|
||||
// 是否点赞 - 只有登录用户才能查看点赞状态
|
||||
if (user_id != null) {
|
||||
try {
|
||||
QueryWrapper<SnsStoryLike> likeQueryWrapper = new QueryWrapper<>();
|
||||
likeQueryWrapper.eq("story_id", story_id).eq("user_id", user_id);
|
||||
SnsStoryLike story_like_row = snsStoryLikeService.findOne(likeQueryWrapper);
|
||||
row.put("IsFabulous", story_like_row != null ? 1 : 0);
|
||||
} catch (Exception e) {
|
||||
log.warn("查询点赞状态失败, story_id: {}, user_id: {}", story_id, user_id, e);
|
||||
row.put("IsFabulous", 0);
|
||||
}
|
||||
} else {
|
||||
row.put("IsFabulous", 0); // 未登录用户默认未点赞
|
||||
}
|
||||
|
||||
// 下面两个查询用不到
|
||||
/*QueryWrapper<SnsStoryAdvertisement> advertisementQueryWrapper = new QueryWrapper<>();
|
||||
advertisementQueryWrapper.eq("adv_enable", 1).eq("adv_is_top", 1);
|
||||
row.put("adv_top", snsStoryAdvertisementService.findOne(advertisementQueryWrapper));
|
||||
/*QueryWrapper<SnsStoryAdvertisement> advertisementQueryWrapper = new QueryWrapper<>();
|
||||
advertisementQueryWrapper.eq("adv_enable", 1).eq("adv_is_top", 1);
|
||||
row.put("adv_top", snsStoryAdvertisementService.findOne(advertisementQueryWrapper));
|
||||
|
||||
QueryWrapper<SnsStoryAdvertisement> advListQueryWrapper = new QueryWrapper<>();
|
||||
advListQueryWrapper.eq("adv_enable", 1).eq("adv_is_top", 0);
|
||||
row.put("adv_lists", snsStoryAdvertisementService.find(advListQueryWrapper));*/
|
||||
QueryWrapper<SnsStoryAdvertisement> advListQueryWrapper = new QueryWrapper<>();
|
||||
advListQueryWrapper.eq("adv_enable", 1).eq("adv_is_top", 0);
|
||||
row.put("adv_lists", snsStoryAdvertisementService.find(advListQueryWrapper));*/
|
||||
|
||||
// 移动端不需要分类
|
||||
if (!isMobile()) {
|
||||
row.put("category_row", snsStoryCategoryService.find(new QueryWrapper<>()));
|
||||
QueryWrapper<SnsStoryBase> baseQueryWrapper = new QueryWrapper<>();
|
||||
baseQueryWrapper.eq("user_id", row.get("user_id")).eq("story_status", 1).eq("story_enable", 1).eq("story_privacy", 0).orderByDesc("story_time");
|
||||
row.put("story_user_items", snsStoryBaseService.lists(baseQueryWrapper, 1, 5).getRecords());
|
||||
try {
|
||||
row.put("category_row", snsStoryCategoryService.find(new QueryWrapper<>()));
|
||||
QueryWrapper<SnsStoryBase> baseQueryWrapper = new QueryWrapper<>();
|
||||
baseQueryWrapper.eq("user_id", row.get("user_id"))
|
||||
.eq("story_status", 1)
|
||||
.eq("story_enable", 1)
|
||||
.eq("story_privacy", 0)
|
||||
.orderByDesc("story_time");
|
||||
|
||||
Object userId = row.get("user_id");
|
||||
if (userId != null) {
|
||||
Page<SnsStoryBase> storyPage = snsStoryBaseService.lists(baseQueryWrapper, 1, 5);
|
||||
row.put("story_user_items", storyPage.getRecords());
|
||||
} else {
|
||||
row.put("story_user_items", new ArrayList<>());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("获取用户故事列表失败, user_id: {}", row.get("user_id"), e);
|
||||
row.put("story_user_items", new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
QueryWrapper<SnsUserFriend> friendQueryWrapper = new QueryWrapper<>();
|
||||
friendQueryWrapper.eq("friend_id", row.get("user_id")).eq("user_id", user_id);
|
||||
SnsUserFriend friend_row = snsUserFriendService.findOne(friendQueryWrapper);
|
||||
// 关注状态 - 只有登录用户才能查看关注状态
|
||||
if (user_id != null && row.get("user_id") != null) {
|
||||
try {
|
||||
QueryWrapper<SnsUserFriend> friendQueryWrapper = new QueryWrapper<>();
|
||||
friendQueryWrapper.eq("friend_id", row.get("user_id")).eq("user_id", user_id);
|
||||
SnsUserFriend friend_row = snsUserFriendService.findOne(friendQueryWrapper);
|
||||
|
||||
if (friend_row != null) {
|
||||
row.put("IsFollow", 1);
|
||||
if (friend_row != null) {
|
||||
row.put("IsFollow", 1);
|
||||
} else {
|
||||
row.put("IsFollow", 0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("查询关注状态失败, friend_id: {}, user_id: {}", row.get("user_id"), user_id, e);
|
||||
row.put("IsFollow", 0);
|
||||
}
|
||||
} else {
|
||||
row.put("IsFollow", 0);
|
||||
row.put("IsFollow", 0); // 未登录用户默认未关注
|
||||
}
|
||||
|
||||
//row.put("story_file", StrUtil.split(row.get("story_file").toString(), ","));
|
||||
row.put("story_file", Convert.toList(String.class, row.get("story_file")));
|
||||
// 处理故事文件
|
||||
try {
|
||||
//row.put("story_file", StrUtil.split(row.get("story_file").toString(), ","));
|
||||
Object storyFileObj = row.get("story_file");
|
||||
if (storyFileObj != null) {
|
||||
row.put("story_file", Convert.toList(String.class, storyFileObj));
|
||||
} else {
|
||||
row.put("story_file", new ArrayList<>());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("处理故事文件失败, story_id: {}", story_id, e);
|
||||
row.put("story_file", new ArrayList<>());
|
||||
}
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
@ -189,99 +189,170 @@ public class SnsStoryCategoryServiceImpl extends BaseServiceImpl<SnsStoryCategor
|
||||
|
||||
@Override
|
||||
public Map listComment() {
|
||||
|
||||
Integer user_id = null;
|
||||
UserDto user = ContextUtil.getCurrentUser();
|
||||
if (user == null) {
|
||||
throw new ApiUserException(I18nUtil._("用户信息异常!"));
|
||||
if (user != null) {
|
||||
user_id = user.getId();
|
||||
}
|
||||
Integer user_id = user.getId();
|
||||
|
||||
Integer page = getParameter("page", 1); //当前页码
|
||||
Integer rows = getParameter("rows", 20);//每页记录条数
|
||||
|
||||
QueryWrapper<SnsStoryComment> wrapper = new QueryWrapper<>();
|
||||
Integer story_id = Convert.toInt(getParameter("story_id"));
|
||||
|
||||
// 参数校验
|
||||
if (story_id == null || story_id <= 0) {
|
||||
return new HashMap();
|
||||
}
|
||||
|
||||
wrapper.eq("story_id", story_id);
|
||||
wrapper.orderByDesc("comment_time");
|
||||
Map data = snsStoryCommentService.getLists(wrapper, page, rows);
|
||||
|
||||
Map data = new HashMap();
|
||||
try {
|
||||
data = snsStoryCommentService.getLists(wrapper, page, rows);
|
||||
} catch (Exception e) {
|
||||
// 处理查询异常
|
||||
data.put("items", new ArrayList<>());
|
||||
data.put("total", 0);
|
||||
}
|
||||
|
||||
// 确保 items 字段存在
|
||||
if (data.get("items") == null) {
|
||||
data.put("items", new ArrayList<>());
|
||||
}
|
||||
|
||||
data.put("items", accountService.fixUserAvatar((List<Map>) data.get("items"), false));
|
||||
|
||||
//读取评论回复
|
||||
List<Map> items = (List<Map>) data.get("items");
|
||||
if (CollUtil.isEmpty(items)) {
|
||||
return new HashMap();
|
||||
return data;
|
||||
}
|
||||
|
||||
List<Integer> comment_id_row = items.stream().map(s -> Convert.toInt(s.get("comment_id"))).collect(Collectors.toList());
|
||||
// 避免转换中的空值问题
|
||||
List<Integer> comment_id_row = items.stream()
|
||||
.map(s -> Convert.toInt(s.get("comment_id")))
|
||||
.filter(id -> id != null)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollUtil.isEmpty(comment_id_row)) {
|
||||
return data;
|
||||
}
|
||||
|
||||
QueryWrapper<SnsStoryCommentHelpful> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.in("comment_id", comment_id_row);
|
||||
queryWrapper.eq("user_id", user_id);
|
||||
//
|
||||
if (user_id != null) {
|
||||
queryWrapper.eq("user_id", user_id);
|
||||
}
|
||||
|
||||
//判断评论是否IsFabulous
|
||||
List<SnsStoryCommentHelpful> snsStoryCommentHelpfuls = snsStoryCommentHelpfulService.find(queryWrapper);
|
||||
List<SnsStoryCommentHelpful> snsStoryCommentHelpfuls = new ArrayList<>();
|
||||
try {
|
||||
snsStoryCommentHelpfuls = snsStoryCommentHelpfulService.find(queryWrapper);
|
||||
} catch (Exception e) {
|
||||
// 忽略查询异常
|
||||
}
|
||||
|
||||
List<Map> comment_helpful_rows = Convert.toList(Map.class, snsStoryCommentHelpfuls);
|
||||
if (comment_helpful_rows == null) {
|
||||
comment_helpful_rows = new ArrayList<>();
|
||||
}
|
||||
|
||||
QueryWrapper<SnsStoryCommentReply> snsStoryCommentReplyQueryWrapper = new QueryWrapper<>();
|
||||
snsStoryCommentReplyQueryWrapper.in("comment_id", comment_id_row);
|
||||
snsStoryCommentReplyQueryWrapper.eq("comment_reply_show_flag", 1);
|
||||
snsStoryCommentReplyQueryWrapper.orderByDesc("comment_reply_time");
|
||||
|
||||
List<SnsStoryCommentReply> snsStoryCommentReplies = snsStoryCommentReplyService.find(snsStoryCommentReplyQueryWrapper);
|
||||
List<Map> comment_reply_rows = Convert.toList(Map.class, snsStoryCommentReplies);
|
||||
List<SnsStoryCommentReply> snsStoryCommentReplies = new ArrayList<>();
|
||||
try {
|
||||
snsStoryCommentReplies = snsStoryCommentReplyService.find(snsStoryCommentReplyQueryWrapper);
|
||||
} catch (Exception e) {
|
||||
// 忽略查询异常
|
||||
}
|
||||
|
||||
List<Map> comment_reply_rows = Convert.toList(Map.class, snsStoryCommentReplies);
|
||||
if (comment_reply_rows == null) {
|
||||
comment_reply_rows = new ArrayList<>();
|
||||
}
|
||||
|
||||
try {
|
||||
accountService.fixUserAvatar(comment_reply_rows, false);
|
||||
} catch (Exception e) {
|
||||
// 忽略头像修复异常
|
||||
}
|
||||
|
||||
accountService.fixUserAvatar(comment_reply_rows, false);
|
||||
Map comment_reply_tmp_rows = new HashMap();
|
||||
for (Map comment_reply_row : comment_reply_rows) {
|
||||
Integer comment_id = Convert.toInt(comment_reply_row.get("comment_id"));
|
||||
if (comment_id == null) continue; // 避免空值
|
||||
|
||||
List comment_rows = (List) ObjectUtil.defaultIfNull(comment_reply_tmp_rows.get(comment_id), new ArrayList());
|
||||
|
||||
if (CollUtil.isEmpty(comment_rows)) comment_reply_tmp_rows.put(comment_id, comment_rows);
|
||||
if (CollUtil.isEmpty(comment_rows)) {
|
||||
comment_reply_tmp_rows.put(comment_id, new ArrayList<>()); // 使用新实例
|
||||
comment_rows = (List) comment_reply_tmp_rows.get(comment_id);
|
||||
}
|
||||
comment_rows.add(comment_reply_row);
|
||||
}
|
||||
|
||||
//判断子评论是否IsFabulous
|
||||
List<Integer> comment_reply_id_row = comment_reply_rows.stream().map(s -> Convert
|
||||
.toInt(s.get("comment_reply_id"))).collect(Collectors.toList());
|
||||
List<Integer> comment_reply_id_row = comment_reply_rows.stream()
|
||||
.map(s -> Convert.toInt(s.get("comment_reply_id")))
|
||||
.filter(id -> id != null)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
QueryWrapper<SnsStoryCommentReplyHelpful> helpfulQueryWrapper = new QueryWrapper<>();
|
||||
if (CollUtil.isNotEmpty(comment_reply_id_row)) helpfulQueryWrapper.in("comment_reply_id", comment_reply_id_row);
|
||||
Map comment_reply_helpful_tmp_rows = new HashMap(); // 提前定义变量
|
||||
if (CollUtil.isNotEmpty(comment_reply_id_row)) {
|
||||
QueryWrapper<SnsStoryCommentReplyHelpful> helpfulQueryWrapper = new QueryWrapper<>();
|
||||
helpfulQueryWrapper.in("comment_reply_id", comment_reply_id_row);
|
||||
if (user_id != null) {
|
||||
helpfulQueryWrapper.eq("user_id", user_id);
|
||||
}
|
||||
|
||||
helpfulQueryWrapper.eq("user_id", user_id);
|
||||
List<SnsStoryCommentReplyHelpful> storyCommentHelpfuls = new ArrayList<>();
|
||||
try {
|
||||
storyCommentHelpfuls = snsStoryCommentReplyHelpfulService.find(helpfulQueryWrapper);
|
||||
} catch (Exception e) {
|
||||
// 忽略查询异常
|
||||
}
|
||||
|
||||
List<SnsStoryCommentReplyHelpful> storyCommentHelpfuls = snsStoryCommentReplyHelpfulService.find(helpfulQueryWrapper);
|
||||
List<Map> comment_reply_helpful_rows = Convert.toList(Map.class, storyCommentHelpfuls);
|
||||
List<Map> comment_reply_helpful_rows = Convert.toList(Map.class, storyCommentHelpfuls);
|
||||
if (comment_reply_helpful_rows == null) {
|
||||
comment_reply_helpful_rows = new ArrayList<>();
|
||||
}
|
||||
|
||||
Map comment_reply_helpful_tmp_rows = new HashMap();
|
||||
for (Map comment_reply_helpful_row : comment_reply_helpful_rows) {
|
||||
Integer comment_reply_id = Convert.toInt(comment_reply_helpful_row.get("comment_reply_id"));
|
||||
List comment_rows = (List) ObjectUtil.defaultIfNull(comment_reply_helpful_tmp_rows.get(comment_reply_id), new ArrayList());
|
||||
if (CollUtil.isEmpty(comment_rows)) comment_reply_helpful_tmp_rows.put(comment_reply_id, comment_rows);
|
||||
comment_rows.add(comment_reply_helpful_row);
|
||||
for (Map comment_reply_helpful_row : comment_reply_helpful_rows) {
|
||||
Integer comment_reply_id = Convert.toInt(comment_reply_helpful_row.get("comment_reply_id"));
|
||||
if (comment_reply_id == null) continue; // 避免空值
|
||||
|
||||
List comment_rows = (List) ObjectUtil.defaultIfNull(comment_reply_helpful_tmp_rows.get(comment_reply_id), new ArrayList());
|
||||
if (CollUtil.isEmpty(comment_rows)) {
|
||||
comment_reply_helpful_tmp_rows.put(comment_reply_id, new ArrayList<>()); // 使用新实例
|
||||
comment_rows = (List) comment_reply_helpful_tmp_rows.get(comment_reply_id);
|
||||
}
|
||||
comment_rows.add(comment_reply_helpful_row);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
QueryWrapper<SnsStoryCommentReply> wrapper1 = new QueryWrapper<>();
|
||||
wrapper1.in("comment_id", comment_id_row);
|
||||
wrapper1.eq("user_id", user_id);
|
||||
List<SnsStoryCommentReply> storyCommentReplies = snsStoryCommentReplyService.find(wrapper1);
|
||||
|
||||
*/
|
||||
|
||||
comment_helpful_rows = Convert.toList(Map.class, snsStoryCommentHelpfuls);
|
||||
|
||||
Map comment_helpful_tmp_rows = new HashMap();
|
||||
for (Map comment_helpful_row : comment_helpful_rows) {
|
||||
|
||||
Integer comment_id = Convert.toInt(comment_helpful_row.get("comment_id"));
|
||||
List comment_rows = (List) ObjectUtil.defaultIfNull(comment_helpful_tmp_rows.get(comment_id), new ArrayList());
|
||||
if (CollUtil.isEmpty(comment_rows)) comment_reply_helpful_tmp_rows.put(comment_id, comment_rows);
|
||||
if (comment_id == null) continue; // 避免空值
|
||||
|
||||
List comment_rows = (List) ObjectUtil.defaultIfNull(comment_helpful_tmp_rows.get(comment_id), new ArrayList());
|
||||
if (CollUtil.isEmpty(comment_rows)) {
|
||||
comment_helpful_tmp_rows.put(comment_id, new ArrayList<>()); // 使用新实例
|
||||
comment_rows = (List) comment_helpful_tmp_rows.get(comment_id);
|
||||
}
|
||||
comment_rows.add(comment_helpful_row);
|
||||
comment_helpful_tmp_rows.put(comment_helpful_row.get("comment_id"), comment_helpful_row);
|
||||
}
|
||||
|
||||
for (Map item : items) {
|
||||
Integer comment_id = Convert.toInt(item.get("comment_id"));
|
||||
if (comment_id == null) continue; // 避免空值
|
||||
|
||||
if (ObjectUtil.isNotNull(comment_reply_tmp_rows.get(comment_id))) {
|
||||
item.put("commentList", comment_reply_tmp_rows.get(comment_id));
|
||||
} else {
|
||||
@ -292,22 +363,22 @@ public class SnsStoryCategoryServiceImpl extends BaseServiceImpl<SnsStoryCategor
|
||||
|
||||
//评论回复是否点赞
|
||||
for (Map comment_reply_row : commentLists) {
|
||||
if (ObjectUtil.isNotNull(comment_reply_helpful_tmp_rows.get(comment_reply_row.get("comment_reply_id")))) {
|
||||
comment_reply_row.put("IsFabulous", 1);
|
||||
Integer reply_id = Convert.toInt(comment_reply_row.get("comment_reply_id"));
|
||||
if (reply_id != null && ObjectUtil.isNotNull(comment_reply_helpful_tmp_rows.get(reply_id))) {
|
||||
// 检查具体的点赞记录而不仅仅是容器
|
||||
List helpfulList = (List) comment_reply_helpful_tmp_rows.get(reply_id);
|
||||
if (CollUtil.isNotEmpty(helpfulList)) {
|
||||
comment_reply_row.put("IsFabulous", 1);
|
||||
} else {
|
||||
comment_reply_row.put("IsFabulous", 0);
|
||||
}
|
||||
} else {
|
||||
comment_reply_row.put("IsFabulous", 0);
|
||||
}
|
||||
}
|
||||
|
||||
//是否点赞
|
||||
if (ObjectUtil.isNotNull(comment_reply_tmp_rows.get(item.get("comment_id")))) {
|
||||
item.put("IsFabulous", 1);
|
||||
} else {
|
||||
item.put("IsFabulous", 0);
|
||||
}
|
||||
|
||||
//是否点赞
|
||||
if (ObjectUtil.isNotNull(comment_helpful_tmp_rows.get(item.get("comment_id")))) {
|
||||
//是否点赞 - 修正重复判断逻辑
|
||||
if (ObjectUtil.isNotNull(comment_helpful_tmp_rows.get(comment_id))) {
|
||||
item.put("IsFabulous", 1);
|
||||
} else {
|
||||
item.put("IsFabulous", 0);
|
||||
@ -317,6 +388,7 @@ public class SnsStoryCategoryServiceImpl extends BaseServiceImpl<SnsStoryCategor
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map story() {
|
||||
Integer user_id = Convert.toInt(getParameter("user_id"));
|
||||
@ -401,7 +473,7 @@ public class SnsStoryCategoryServiceImpl extends BaseServiceImpl<SnsStoryCategor
|
||||
AccountUserInfo user_info = accountService.getUserInfo(user_id);
|
||||
Integer user_certification = user_info.getUser_certification();
|
||||
|
||||
if (true || user_certification == 1) {
|
||||
if (true) {
|
||||
|
||||
/*
|
||||
AccountUserType accountUserType = accountService.getAccountUserType(user_info.getUser_type_id());
|
||||
|
||||
6
pom.xml
6
pom.xml
@ -581,7 +581,6 @@
|
||||
<pushImage>true</pushImage>
|
||||
<!--推送镜像仓库校验安全证书,无安全证书无法推送-->
|
||||
<dockerCertPath>${docker.ca}</dockerCertPath>
|
||||
|
||||
<!--定义基础镜像-->
|
||||
<!-- <baseImage>java:8</baseImage>-->
|
||||
<baseImage>openjdk:8-jre</baseImage>
|
||||
@ -600,11 +599,6 @@
|
||||
<entryPoint>["sh", "-c", "mkdir -p /tmp /app/temp /root/nacos/naming/public && chmod -R 777 /tmp /app/temp /root/nacos && java -Djava.io.tmpdir=/app/temp -Dnacos.naming.cache.dir=/root/nacos/naming -jar -Xms256m -Xmx512m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:+UseContainerSupport -XX:MaxRAMPercentage=60.0 -XX:+UseSerialGC -XX:MinHeapFreeRatio=40 -XX:MaxHeapFreeRatio=60 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:./gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M -Dspring.profiles.active=${spring.profile} -Duser.timezone=Asia/Shanghai /${project.build.finalName}.jar"]
|
||||
</entryPoint>
|
||||
|
||||
<!-- 添加额外的Dockerfile指令来清理不必要的文件 -->
|
||||
<!-- <runs>-->
|
||||
<!-- <run>rm -rf /root/.m2 && rm -rf /tmp/* && rm -rf /var/cache/*</run>-->
|
||||
<!-- </runs>-->
|
||||
|
||||
<resources>
|
||||
<resource>
|
||||
<targetPath>/</targetPath>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user