Authored by chenchao

Merge branch 'dev_order' into test6.8.2

# Conflicts:
#	order/src/main/java/com/yohoufo/order/service/impl/SellerOrderService.java
Showing 44 changed files with 1463 additions and 233 deletions
... ... @@ -56,5 +56,9 @@ public class AddressUtil {
String hidden = "i4cTBWa4QCq4x97BWgcuvw==";
int result = AddressUtil.getDecryptStr(hidden);
System.out.println(hidden + "-->" + result);
String addressId = "2394872";
System.out.println(addressId + " --> " + AddressUtil.getEncryptStr(addressId));
}
}
... ...
package com.yohoufo.common.utils;
/**
* Created by chao.chen on 2018/11/20.
*/
public class PageHelper {
private PageHelper() {
}
public static int getPageTotal(int total, int pageSize) {
return total % pageSize == 0 ? total/pageSize: total/pageSize + 1;
}
}
... ...
... ... @@ -23,4 +23,11 @@ public interface EntrySellerRechargeOrderMapper {
//根据用户uid ,获取流水(分页)
List<EntrySellerRechargeOrder> selectWithPageByUid(@Param("uid") Integer uid, @Param("start") Integer start, @Param("limit") Integer limit);
void updateByOrderCode(EntrySellerRechargeOrder order);
EntrySellerRechargeOrder selectByOrderCodeUid(long orderCode, int uid);
EntrySellerRechargeOrder selectByOrderCode(long orderCode);
}
\ No newline at end of file
... ...
... ... @@ -54,4 +54,6 @@ public interface OrdersPayMapper {
* @mbggenerated
*/
int updateByPrimaryKey(OrdersPay record);
int addMoney(OrdersPay record);
}
\ No newline at end of file
... ...
... ... @@ -15,6 +15,7 @@ public interface SellerOrderGoodsMapper {
SellerOrderGoods selectByPrimaryKey(Integer id);
List<SellerOrderGoods> selectByBatchNo(SellerOrderGoods record);
List<SellerOrderGoods> selectBySkups(@Param("list") List<Integer> skup);
... ... @@ -33,6 +34,6 @@ public interface SellerOrderGoodsMapper {
int updateStatusBySkpu(SellerOrderGoods record);
int insertBatch(@Param("records") Collection<SellerOrderGoods> records);
}
\ No newline at end of file
... ...
... ... @@ -11,6 +11,8 @@ public interface SellerOrderMapper {
int insert(SellerOrder record);
int insertBatch(@Param("records") Collection<SellerOrder> records);
int insertSelective(SellerOrder record);
SellerOrder selectByPrimaryKey(Integer id);
... ...
... ... @@ -3,6 +3,7 @@ package com.yohoufo.dal.order;
import com.yohoufo.dal.order.model.SellerOrderMeta;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
import java.util.List;
public interface SellerOrderMetaMapper {
... ... @@ -12,6 +13,8 @@ public interface SellerOrderMetaMapper {
int insertSelective(SellerOrderMeta record);
int insertBatch(@Param("records") Collection<SellerOrderMeta> records);
SellerOrderMeta selectByPrimaryKey(Integer id);
int updateByPrimaryKeySelective(SellerOrderMeta record);
... ...
package com.yohoufo.dal.order;
import org.apache.ibatis.annotations.Param;
import com.yohoufo.dal.order.model.SellerWallet;
public interface SellerWalletMapper {
... ... @@ -14,5 +16,11 @@ public interface SellerWalletMapper {
int updateByPrimaryKey(SellerWallet record);
SellerWallet selectByUidAndType(@Param("uid") Integer uid, @Param("type") int type);
int addMoney(SellerWallet sw);
int returnMoney(SellerWallet sw);
SellerWallet selectByUidNType(SellerWallet condition);
}
\ No newline at end of file
... ...
... ... @@ -302,4 +302,12 @@ public class OrdersPay {
public void setAttach(String attach) {
this.attach = attach;
}
@Override
public String toString() {
return "OrdersPay [id=" + id + ", orderCode=" + orderCode + ", uid=" + uid + ", payment=" + payment
+ ", amount=" + amount + ", payOrderCode=" + payOrderCode + ", payLevel=" + payLevel + ", serialNo="
+ serialNo + ", createTime=" + createTime + ", attach=" + attach + "]";
}
}
\ No newline at end of file
... ...
... ... @@ -258,4 +258,12 @@ public class OrdersPayRefund {
public void setOrderType(int orderType) {
this.orderType = orderType;
}
@Override
public String toString() {
return "OrdersPayRefund [orderType=" + orderType + ", id=" + id + ", orderCode=" + orderCode + ", serialNo="
+ serialNo + ", amount=" + amount + ", status=" + status + ", createTime=" + createTime
+ ", updateTime=" + updateTime + ", refundCode=" + refundCode + "]";
}
}
\ No newline at end of file
... ...
... ... @@ -32,6 +32,9 @@ public class SellerOrderGoods {
private String imageUrl;
private Integer isDel;
private Long batchNo;
public String getImageUrl() {
return imageUrl;
}
... ... @@ -153,4 +156,12 @@ public class SellerOrderGoods {
public void setIsDel(Integer isDel) {
this.isDel = isDel;
}
public Long getBatchNo() {
return batchNo;
}
public void setBatchNo(Long batchNo) {
this.batchNo = batchNo;
}
}
\ No newline at end of file
... ...
... ... @@ -9,9 +9,9 @@ public class SellerWallet {
private BigDecimal amount;
private Byte status;
private Integer status;
private Byte type;
private Integer type;
private Integer createTime;
... ... @@ -41,19 +41,19 @@ public class SellerWallet {
this.amount = amount;
}
public Byte getStatus() {
public Integer getStatus() {
return status;
}
public void setStatus(Byte status) {
public void setStatus(Integer status) {
this.status = status;
}
public Byte getType() {
public Integer getType() {
return type;
}
public void setType(Byte type) {
public void setType(Integer type) {
this.type = type;
}
... ... @@ -72,4 +72,11 @@ public class SellerWallet {
public void setUpdateTime(Integer updateTime) {
this.updateTime = updateTime;
}
@Override
public String toString() {
return "SellerWallet [id=" + id + ", uid=" + uid + ", amount=" + amount + ", status=" + status + ", type="
+ type + ", createTime=" + createTime + ", updateTime=" + updateTime + "]";
}
}
\ No newline at end of file
... ...
... ... @@ -2,6 +2,11 @@ package com.yohoufo.dal.order.model;
import java.math.BigDecimal;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class SellerWalletDetail {
private Integer id;
... ... @@ -13,73 +18,13 @@ public class SellerWalletDetail {
private BigDecimal amount;
private Byte type;
private Integer type;
private Integer createTime;
private Integer updateTime;
private Integer isBatch;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getWalletId() {
return walletId;
}
public void setWalletId(Integer walletId) {
this.walletId = walletId;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Long getOrderCode() {
return orderCode;
}
public void setOrderCode(Long orderCode) {
this.orderCode = orderCode;
}
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public Byte getType() {
return type;
}
public void setType(Byte type) {
this.type = type;
}
public Integer getCreateTime() {
return createTime;
}
public void setCreateTime(Integer createTime) {
this.createTime = createTime;
}
public Integer getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Integer updateTime) {
this.updateTime = updateTime;
}
}
\ No newline at end of file
... ...
... ... @@ -139,6 +139,36 @@
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByOrderCode" parameterType="com.yohoufo.dal.order.model.BuyerOrder">
update entry_seller_recharge_order
set
<if test="status != null">
status = #{status,jdbcType=INTEGER},
</if>
<if test="payment != null">
payment = #{payment,jdbcType=INTEGER},
</if>
update_time = #{updateTime,jdbcType=INTEGER}
where order_code = #{orderCode,jdbcType=BIGINT}
</update>
<select id="selectByOrderCodeUid" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from entry_seller_recharge_order
where order_code = #{orderCode,jdbcType=BIGINT}
and uid = #{uid,jdbcType=INTEGER}
limit 1
</select>
<select id="selectByOrderCode" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from entry_seller_recharge_order
where order_code = #{orderCode,jdbcType=BIGINT}
limit 1
</select>
<sql id="Query_Condition_Sql" >
uid = #{uid,jdbcType=INTEGER}
</sql>
... ...
... ... @@ -188,4 +188,9 @@
create_time = #{createTime,jdbcType=INTEGER}
where id = #{id,jdbcType=INTEGER}
</update>
<update id="addMoney" parameterType="com.yohoufo.dal.order.model.OrdersPay" >
update orders_pay set amount = amount + #{amount,jdbcType=DECIMAL},update_time = #{updateTime,jdbcType=INTEGER} where order_code = #{orderCode,jdbcType=BIGINT}
and uid = #{uid,jdbcType=INTEGER} and amount + #{amount,jdbcType=DECIMAL} &gt;= 0
</update>
</mapper>
\ No newline at end of file
... ...
... ... @@ -16,10 +16,12 @@
<result column="status" jdbcType="TINYINT" property="status" />
<result column="image_url" jdbcType="VARCHAR" property="imageUrl" />
<result column="is_del" jdbcType="TINYINT" property="isDel" />
<result column="batch_no" jdbcType="BIGINT" property="batchNo" />
</resultMap>
<sql id="Base_Column_List">
id, uid, product_id, product_name, storage_id, depot_no, size_id, size_name,
color_id, color_name, goods_price, status, image_url, is_del
color_id, color_name, goods_price, status, image_url, is_del, batch_no
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap">
select
... ... @@ -42,6 +44,13 @@
</if>
</select>
<select id="selectByBatchNo" parameterType="com.yohoufo.dal.order.model.SellerOrderGoods" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from seller_order_goods
where batch_no = #{batchNo,jdbcType=BIGINT} and status = #{status,jdbcType=TINYINT}
</select>
<select id="selectBySkup" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
... ... @@ -97,6 +106,24 @@
#{colorId,jdbcType=SMALLINT}, #{colorName,jdbcType=VARCHAR},
#{goodsPrice,jdbcType=DECIMAL}, #{status,jdbcType=TINYINT})
</insert>
<insert id="insertBatch" keyColumn="id" keyProperty="id" useGeneratedKeys="true">
insert into seller_order_goods (product_id, product_name, storage_id,
depot_no, size_id, size_name,
color_id, color_name,
goods_price, status, batch_no)
values
<foreach collection="records" item="sog" separator=",">
(#{sog.productId,jdbcType=INTEGER}, #{sog.productName,jdbcType=VARCHAR}, #{sog.storageId,jdbcType=INTEGER},
#{sog.depotNo,jdbcType=INTEGER}, #{sog.sizeId,jdbcType=INTEGER}, #{sog.sizeName,jdbcType=VARCHAR},
#{sog.colorId,jdbcType=SMALLINT}, #{sog.colorName,jdbcType=VARCHAR},
#{sog.goodsPrice,jdbcType=DECIMAL}, #{sog.status,jdbcType=TINYINT}, #{sog.batchNo,jdbcType=BIGINT})
</foreach>
</insert>
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.yohoufo.dal.order.model.SellerOrderGoods" useGeneratedKeys="true">
insert into seller_order_goods
<trim prefix="(" suffix=")" suffixOverrides=",">
... ... @@ -136,6 +163,9 @@
<if test="status != null">
status,
</if>
<if test="batchNo != null">
batch_no,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="productId != null">
... ... @@ -174,6 +204,9 @@
<if test="status != null">
#{status,jdbcType=TINYINT},
</if>
<if test="batchNo != null">
#{batchNo,jdbcType=BIGINT},
</if>
</trim>
</insert>
... ...
... ... @@ -77,6 +77,22 @@
#{createTime,jdbcType=INTEGER}, #{updateTime,jdbcType=INTEGER})
</insert>
<insert id="insertBatch" >
insert into seller_order (order_code, skup, uid,
payment, income,
earnest_money, is_del, status,
create_time)
values
<foreach collection="records" item="record" separator=",">
(#{record.orderCode,jdbcType=BIGINT}, #{record.skup,jdbcType=INTEGER}, #{record.uid,jdbcType=INTEGER},
#{record.payment,jdbcType=TINYINT}, #{record.income,jdbcType=DECIMAL},
#{record.earnestMoney,jdbcType=DECIMAL}, #{record.isDel,jdbcType=TINYINT}, #{record.status,jdbcType=TINYINT},
#{record.createTime,jdbcType=INTEGER})
</foreach>
</insert>
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.yohoufo.dal.order.model.SellerOrder" useGeneratedKeys="true">
insert into seller_order
<trim prefix="(" suffix=")" suffixOverrides=",">
... ...
... ... @@ -40,6 +40,17 @@
</select>
<insert id="insertBatch">
insert into seller_order_meta (skup, uid, meta_key,
meta_value)
values
<foreach collection="records" item="record" separator=",">
(#{record.skup,jdbcType=INTEGER}, #{record.uid,jdbcType=INTEGER}, #{record.metaKey,jdbcType=VARCHAR},
#{record.metaValue,jdbcType=VARCHAR})
</foreach>
</insert>
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.yohoufo.dal.order.model.SellerOrderMeta" useGeneratedKeys="true">
insert into seller_order_meta
<trim prefix="(" suffix=")" suffixOverrides=",">
... ...
... ... @@ -10,9 +10,10 @@
<result column="type" property="type" jdbcType="TINYINT" />
<result column="create_time" property="createTime" jdbcType="INTEGER" />
<result column="update_time" property="updateTime" jdbcType="INTEGER" />
<result column="is_batch" property="isBatch" jdbcType="INTEGER" />
</resultMap>
<sql id="Base_Column_List" >
id, wallet_id, uid, order_code, amount, type, create_time, update_time
id, wallet_id, uid, order_code, amount, type, create_time, update_time,is_batch
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
... ... @@ -24,15 +25,15 @@
delete from seller_wallet_detail
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.yohoufo.dal.order.model.SellerWalletDetail" >
<insert id="insert" parameterType="com.yohoufo.dal.order.model.SellerWalletDetail" keyColumn="id" keyProperty="id" useGeneratedKeys="true">
insert into seller_wallet_detail (id, wallet_id, uid,
order_code, amount, type,
create_time, update_time)
create_time, update_time,is_batch)
values (#{id,jdbcType=INTEGER}, #{walletId,jdbcType=INTEGER}, #{uid,jdbcType=INTEGER},
#{orderCode,jdbcType=BIGINT}, #{amount,jdbcType=DECIMAL}, #{type,jdbcType=TINYINT},
#{createTime,jdbcType=INTEGER}, #{updateTime,jdbcType=INTEGER})
#{createTime,jdbcType=INTEGER}, #{updateTime,jdbcType=INTEGER}, #{isBatch,jdbcType=INTEGER})
</insert>
<insert id="insertSelective" parameterType="com.yohoufo.dal.order.model.SellerWalletDetail" >
<insert id="insertSelective" parameterType="com.yohoufo.dal.order.model.SellerWalletDetail" keyColumn="id" keyProperty="id" useGeneratedKeys="true">
insert into seller_wallet_detail
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
... ... @@ -59,6 +60,9 @@
<if test="updateTime != null" >
update_time,
</if>
<if test="isBatch != null" >
is_batch,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
... ... @@ -85,6 +89,9 @@
<if test="updateTime != null" >
#{updateTime,jdbcType=INTEGER},
</if>
<if test="isBatch != null" >
#{isBatch,jdbcType=INTEGER},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.yohoufo.dal.order.model.SellerWalletDetail" >
... ...
... ... @@ -5,8 +5,8 @@
<id column="id" property="id" jdbcType="INTEGER" />
<result column="uid" property="uid" jdbcType="INTEGER" />
<result column="amount" property="amount" jdbcType="DECIMAL" />
<result column="status" property="status" jdbcType="TINYINT" />
<result column="type" property="type" jdbcType="TINYINT" />
<result column="status" property="status" jdbcType="INTEGER" />
<result column="type" property="type" jdbcType="INTEGER" />
<result column="create_time" property="createTime" jdbcType="INTEGER" />
<result column="update_time" property="updateTime" jdbcType="INTEGER" />
</resultMap>
... ... @@ -19,6 +19,10 @@
from seller_wallet
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from seller_wallet
where id = #{id,jdbcType=INTEGER}
</delete>
<select id="selectByUidNType" resultMap="BaseResultMap" parameterType="com.yohoufo.dal.order.model.SellerWallet" >
select
... ... @@ -32,10 +36,10 @@
status, type, create_time,
update_time)
values (#{id,jdbcType=INTEGER}, #{uid,jdbcType=INTEGER}, #{amount,jdbcType=DECIMAL},
#{status,jdbcType=TINYINT}, #{type,jdbcType=TINYINT}, #{createTime,jdbcType=INTEGER},
#{status,jdbcType=INTEGER}, #{type,jdbcType=INTEGER}, #{createTime,jdbcType=INTEGER},
#{updateTime,jdbcType=INTEGER})
</insert>
<insert id="insertSelective" parameterType="com.yohoufo.dal.order.model.SellerWallet" >
<insert id="insertSelective" parameterType="com.yohoufo.dal.order.model.SellerWallet" keyColumn="id" keyProperty="id" useGeneratedKeys="true">
insert into seller_wallet
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
... ... @@ -71,10 +75,10 @@
#{amount,jdbcType=DECIMAL},
</if>
<if test="status != null" >
#{status,jdbcType=TINYINT},
#{status,jdbcType=INTEGER},
</if>
<if test="type != null" >
#{type,jdbcType=TINYINT},
#{type,jdbcType=INTEGER},
</if>
<if test="createTime != null" >
#{createTime,jdbcType=INTEGER},
... ... @@ -94,10 +98,10 @@
amount = #{amount,jdbcType=DECIMAL},
</if>
<if test="status != null" >
status = #{status,jdbcType=TINYINT},
status = #{status,jdbcType=INTEGER},
</if>
<if test="type != null" >
type = #{type,jdbcType=TINYINT},
type = #{type,jdbcType=INTEGER},
</if>
<if test="createTime != null" >
create_time = #{createTime,jdbcType=INTEGER},
... ... @@ -112,10 +116,25 @@
update seller_wallet
set uid = #{uid,jdbcType=INTEGER},
amount = #{amount,jdbcType=DECIMAL},
status = #{status,jdbcType=TINYINT},
type = #{type,jdbcType=TINYINT},
status = #{status,jdbcType=INTEGER},
type = #{type,jdbcType=INTEGER},
create_time = #{createTime,jdbcType=INTEGER},
update_time = #{updateTime,jdbcType=INTEGER}
where id = #{id,jdbcType=INTEGER}
</update>
<select id="selectByUidAndType" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from seller_wallet
where uid = #{uid,jdbcType=INTEGER} and type = #{type,jdbcType=INTEGER}
</select>
<update id="addMoney" parameterType="com.yohoufo.dal.order.model.SellerWallet" >
update seller_wallet set amount = amount + #{amount,jdbcType=DECIMAL},update_time = #{updateTime,jdbcType=INTEGER} where id = #{id,jdbcType=INTEGER} and amount + #{amount,jdbcType=DECIMAL} &gt;= 0 and status=1
</update>
<update id="returnMoney" parameterType="com.yohoufo.dal.order.model.SellerWallet" >
update seller_wallet set amount = 0 ,status = 0,update_time = #{updateTime,jdbcType=INTEGER} where id = #{id,jdbcType=INTEGER} and amount = #{amount,jdbcType=DECIMAL} and status=1
</update>
</mapper>
\ No newline at end of file
... ...
package com.yohoufo.order.common;
public enum Payment {
WALLET(11, "wallet", "钱包"),
MINIAPP(3, "miniapp", "微信小程序"),
ALIPAY(2, "alipay", "支付宝"),
WECHAT(1, "wechat", "微信");
... ...
... ... @@ -103,6 +103,7 @@ public class SellerOrderController {
.storageId(storage_id)
.price(price)
.addressId(address_id)
.num(num)
.build();
logger.info("in ufo.sellerOrder.publishPrd, req {}", req);
OrderSubmitResp resp = sellerOrderService.publishPrd(req);
... ...
package com.yohoufo.order.convert;
import com.yohobuy.ufo.model.order.common.SkupStatus;
import com.yohoufo.common.helper.ImageUrlAssist;
import com.yohoufo.dal.order.model.SellerOrderGoods;
import com.yohoufo.order.model.response.GoodsInfo;
... ... @@ -21,4 +22,28 @@ public class GoodsInfoConvertor {
goodsInfo.setStorageId(sellerOrderGoods.getStorageId());
return goodsInfo;
}
/**
* StorageDataResp这个对象从商品取来,不论是否持久化,都应当有数据
* @param goodsInfo
* @return
*/
public static SellerOrderGoods resp2Do4AddNew(com.yohobuy.ufo.model.order.bo.GoodsInfo goodsInfo){
SellerOrderGoods sellerOrderGoods = new SellerOrderGoods();
//最关键的两个数据项
sellerOrderGoods.setUid(goodsInfo.getUid());
sellerOrderGoods.setStorageId(goodsInfo.getStorageId());
sellerOrderGoods.setStatus(SkupStatus.CAN_NOT_SELL.getCode());
sellerOrderGoods.setGoodsPrice(goodsInfo.getPrice());
//if not exist ,not
sellerOrderGoods.setProductId(goodsInfo.getProductId());
sellerOrderGoods.setProductName(goodsInfo.getProductName());
sellerOrderGoods.setColorId(goodsInfo.getColorId());
sellerOrderGoods.setColorName(goodsInfo.getColorName());
sellerOrderGoods.setSizeId(goodsInfo.getSizeId());
sellerOrderGoods.setSizeName(goodsInfo.getSizeName());
sellerOrderGoods.setImageUrl(goodsInfo.getImageUrl());
sellerOrderGoods.setBatchNo(goodsInfo.getBatchNo());
return sellerOrderGoods;
}
}
... ...
package com.yohoufo.order.event;
import com.yohoufo.common.alarm.Event;
import com.yohoufo.dal.order.model.SellerWallet;
import com.yohoufo.order.service.handler.SellerOrderSubmitHandler;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Builder;
/**
* Created by chao.chen on 2018/11/20.
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BatchPublishTailEvent extends Event {
private SellerOrderSubmitHandler.ForkJoinResult fjr;
private SellerWallet sellerWallet;
}
... ...
... ... @@ -28,6 +28,8 @@ public class PayRefundBo {
* 订单类型: 买家订单 or 卖家订单
*/
private int orderType;
private int uid;
}
... ...
... ... @@ -15,6 +15,8 @@ public class SellerOrderContext {
private int uid;
private boolean isEntryShop;
private long orderCode;
private int storageId;
... ...
package com.yohoufo.order.service;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.yoho.core.common.utils.DateUtil;
import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yoho.tools.common.beans.ApiResponse;
import com.yohobuy.ufo.model.order.bo.OrderInfo;
import com.yohobuy.ufo.model.order.common.OrderCodeType;
import com.yohobuy.ufo.model.order.common.OrderStatus;
import com.yohobuy.ufo.model.order.common.TabType;
import com.yohoufo.common.alarm.CommonAlarmEventPublisher;
import com.yohoufo.common.caller.UfoServiceCaller;
import com.yohoufo.common.utils.TimeUtils;
import com.yohoufo.dal.order.EntrySellerRechargeOrderMapper;
import com.yohoufo.dal.order.OrdersPayMapper;
import com.yohoufo.dal.order.OrdersPayRefundMapper;
import com.yohoufo.dal.order.SellerWalletDetailMapper;
import com.yohoufo.dal.order.SellerWalletMapper;
import com.yohoufo.dal.order.model.EntrySellerRechargeOrder;
import com.yohoufo.dal.order.model.OrdersPay;
import com.yohoufo.dal.order.model.OrdersPayRefund;
import com.yohoufo.dal.order.model.SellerWallet;
import com.yohoufo.dal.order.model.SellerWalletDetail;
import com.yohoufo.order.common.Payment;
import com.yohoufo.order.model.request.PaymentRequest;
import com.yohoufo.order.model.response.PrepayResponse;
import com.yohoufo.order.service.cache.CacheCleaner;
import com.yohoufo.order.service.cache.CacheKeyBuilder;
import com.yohoufo.order.service.impl.PaymentServiceImpl;
@Service
public class MerchantOrderPaymentService extends AbstractOrderPaymentService {
private final Logger logger = LoggerFactory.getLogger(getClass());
private static final int TYPE_FIRST_RECHARGE = 1;
@Autowired
SellerWalletMapper sellerWalletMapper;
@Autowired
SellerWalletDetailMapper sellerWalletDetailMapper;
@Autowired
EntrySellerRechargeOrderMapper entrySellerRechargeOrderMapper;
@Autowired
OrdersPayMapper ordersPayDao;
@Autowired
OrdersPayRefundMapper ordersPayRefundMapper;
@Autowired
private CacheCleaner cacheCleaner;
@Autowired
UfoServiceCaller ufoServiceCaller;
@Autowired
PaymentServiceImpl paymentService;
/**
* 更新订单状态
* @param orderInfo
*/
public void updateOrderStatusPaid(OrderInfo orderInfo) {
EntrySellerRechargeOrder order = new EntrySellerRechargeOrder();
order.setOrderCode(orderInfo.getOrderCode());
order.setStatus(OrderStatus.HAS_PAYED.getCode());
order.setUpdateTime(DateUtil.getCurrentTimeSecond());
// order.setPayment(orderInfo.getPayment());
entrySellerRechargeOrderMapper.updateByOrderCode(order);
orderInfo.setStatus(OrderStatus.HAS_PAYED.getCode());
}
@Override
public void processAfterPay(OrderInfo orderInfo) {
logger.info("充值后回调,处理processAfterPay,orderInfo={}", orderInfo);
// 首次充值,调用认证成功接口
if (orderInfo.getType() == TYPE_FIRST_RECHARGE) {
try {
logger.info("首次充值后回调,调用商家入驻接口,uid={}", orderInfo.getUid());
ufoServiceCaller.call("ufo.user.addUserAsStoredSeller", ApiResponse.class, orderInfo.getUid());
} catch (Exception e) {
logger.error("首次充值后回调,商家入驻接口失败,uid={}", orderInfo.getUid());
CommonAlarmEventPublisher.publish("商家入驻失败", "ufo.user.addUserAsStoredSeller", "首次充值后回调,商家入驻接口失败:uid=" + orderInfo.getUid() + ",充值订单号为:" + orderInfo.getOrderCode());
return;
}
}
BigDecimal amount = orderInfo.getAmount();
SellerWallet sw = sellerWalletMapper.selectByUidAndType(orderInfo.getUid(), 1);
logger.info("充值后回调,处理总账表,orderCode={}", orderInfo.getOrderCode());
if (orderInfo.getType() == TYPE_FIRST_RECHARGE) {
if (sw != null) {
logger.error("首次充值保证金余额{},发现钱包已存在,uid={}", amount, orderInfo.getUid());
CommonAlarmEventPublisher.publish("首次充值保证金余额失败", "ufo.order.recharge", "钱包已存在:uid=" + orderInfo.getUid() + ",充值订单号为:" + orderInfo.getOrderCode()+", 充值金额为:"+amount);
return;
}
// 首次充值,创建钱包信息
sw = new SellerWallet();
sw.setUid(orderInfo.getUid());
sw.setAmount(orderInfo.getAmount());
sw.setStatus(1);
sw.setType(1);
sw.setCreateTime(TimeUtils.getTimeStampSecond());
sw.setUpdateTime(0);
logger.info("首次充值后回调,处理总账表新增账号,bean={}", sw);
sellerWalletMapper.insert(sw);
logger.info("首次充值后回调,处理总账表新增账号成功,bean={}", sw);
} else {
// 修改钱包余额
if (sw == null) {
logger.error("充值保证金余额{},钱包不存在,uid={}", amount, orderInfo.getUid());
CommonAlarmEventPublisher.publish("充值保证金余额失败", "ufo.order.recharge", "钱包不存在uid=" + orderInfo.getUid() + ",充值订单号为:" + orderInfo.getOrderCode()+", 充值金额为:"+amount);
return;
}
if (sw.getStatus() == null || sw.getStatus() == 0) {
logger.error("充值保证金余额{},钱包不可用,uid={}", amount, orderInfo.getUid());
CommonAlarmEventPublisher.publish("充值保证金余额失败", "ufo.order.recharge", "钱包不可用uid=" + orderInfo.getUid() + ",充值订单号为:" + orderInfo.getOrderCode()+", 充值金额为:"+amount);
return;
}
sw.setAmount(orderInfo.getAmount());
sw.setUpdateTime(TimeUtils.getTimeStampSecond());
logger.info("后期充值,处理总账表增加余额,bean={}", sw);
if (sellerWalletMapper.addMoney(sw) == 0) {
logger.error("充值保证金余额{},更新表返回0,uid={}", amount, orderInfo.getUid());
CommonAlarmEventPublisher.publish("充值保证金余额失败", "ufo.order.recharge", "更新表返回0,uid=" + orderInfo.getUid() + ",充值订单号为:" + orderInfo.getOrderCode()+", 充值金额为:"+amount);
return;
}
}
logger.info("{}修改钱包表余额成功,orderCode={}", orderInfo.getOrderCode());
// 增加充值记录
SellerWalletDetail swd = new SellerWalletDetail();
swd.setOrderCode(orderInfo.getOrderCode());
swd.setType(1);
swd.setUid(orderInfo.getUid());
swd.setWalletId(sw.getId());
swd.setAmount(orderInfo.getAmount());
swd.setIsBatch(0);
swd.setCreateTime(TimeUtils.getTimeStampSecond());
logger.info("充值后,处理增加钱包明细,bean={}", swd);
sellerWalletDetailMapper.insert(swd);
logger.info("充值后,处理增加钱包明细成功,orderCode={}", orderInfo.getOrderCode());
logger.info("充值后,删除订单列表缓存,uid={}", orderInfo.getUid());
cacheCleaner.delete(Arrays.asList(
CacheKeyBuilder.orderListKey(orderInfo.getUid(), TabType.SELL.getValue()),
CacheKeyBuilder.orderDetailKey(orderInfo.getUid(), TabType.SELL.getValue(), orderInfo.getOrderCode())));
}
/**
* 订单是否是待支付状态
* @param orderInfo
* @return
*/
public boolean isOrderWaitingPay(OrderInfo orderInfo){
if (orderInfo.getStatus() != null && orderInfo.getStatus().intValue() == OrderStatus.WAITING_PAY.getCode()){
return true;
}
return false;
}
/**
* 订单是 已支付的订单
* @param orderInfo
* @return
*/
public boolean isOrderPaid(OrderInfo orderInfo){
if (orderInfo.getStatus() != null && orderInfo.getStatus().intValue() == OrderStatus.HAS_PAYED.getCode()){
return true;
}
return false;
}
final static List<Integer> canRefundStatusList = Arrays.asList(OrderStatus.SELLER_CANCEL_AFTER_PAY.getCode(),
OrderStatus.SEND_OUT_TIMEOUT.getCode(), OrderStatus.CHECKING_FAKE.getCode());
@Override
public boolean canRefund(OrderInfo orderInfo) {
if (orderInfo.getStatus() != null && canRefundStatusList.contains(orderInfo.getStatus().intValue())){
return true;
}
return false;
}
/**
* 保存前回预支付结果
* @param orderInfo
* @param response
*/
public void saveAppPayRequest(OrderInfo orderInfo, PrepayResponse response) {
}
/**
* 获取前回的访问结果
* @param request
* @return
*/
public PrepayResponse getAppPayRequest(PaymentRequest request) {
return null;
}
/**
* 检查状态
* @param orderInfo
*/
public void checkOrderStatus(OrderInfo orderInfo){
// 订单不是未付款的状态
if (orderInfo.getStatus() == null || orderInfo.getStatus().intValue() != OrderStatus.WAITING_PAY.getCode()){
logger.warn("payment status not allow {}, orderCode is {}, uid is {}", orderInfo.getStatus(),
orderInfo.getOrderCode(), orderInfo.getUid());
throw new ServiceException(ServiceError.ORDER_PAY_NOT_ALLOW);
}
}
/**
* 预支付方式更新
* @param orderInfo
*/
public void updatePayment(OrderInfo orderInfo, int payment){
EntrySellerRechargeOrder order = new EntrySellerRechargeOrder();
order.setOrderCode(orderInfo.getOrderCode());
order.setUid(orderInfo.getUid());
// 更新预支付方式
order.setPayment(payment);
order.setUpdateTime(DateUtil.getCurrentTimeSecond());
entrySellerRechargeOrderMapper.updateByOrderCode(order);
}
/**
* 获取订单情报
* @param orderCode
* @param uid
* @return
*/
public OrderInfo getOrderInfo(long orderCode, int uid) {
EntrySellerRechargeOrder order = entrySellerRechargeOrderMapper.selectByOrderCodeUid(orderCode, uid);
if (order == null){
logger.warn("getOrderInfo order not exist, orderCode is {}, uid is {}", orderCode, uid);
throw new ServiceException(ServiceError.ORDER_NULL);
}
return buildOrderInfo(order);
}
private OrderInfo buildOrderInfo(EntrySellerRechargeOrder order) {
OrderInfo orderInfo = OrderInfo.builder()
.id(order.getId())
.uid(order.getUid())
.orderCode(order.getOrderCode())
.payment(order.getPayment())
.status(order.getStatus())
.amount(order.getAmount())
.createTime(order.getCreateTime())
.orderCodeType(OrderCodeType.BUYER_TYPE)
.sourceStatus(order.getStatus())
.type(order.getType())
.build();
return orderInfo;
}
/**
* 获取订单情报
* @param orderCode
* @return
*/
public OrderInfo getOrderInfo(long orderCode) {
EntrySellerRechargeOrder buyerOrder = entrySellerRechargeOrderMapper.selectByOrderCode(orderCode);
if (buyerOrder == null){
logger.warn("getOrderInfo order not exist, orderCode is {}", orderCode);
throw new ServiceException(ServiceError.ORDER_NULL);
}
return buildOrderInfo(buyerOrder);
}
// 支付保证金:总账修改
public SellerWallet useEarnest(Integer uid, BigDecimal money) {
return changeEarnest(uid, money, "支付保证金", 2);
}
// 修改价格保证金差价:总账修改
public SellerWallet changePriceUseEarnest(Integer uid, BigDecimal money) {
return changeEarnest(uid, money, "支付保证金(修改价格)", 4);
}
// 退还保证金:总账修改
public SellerWallet refundEarnest(Integer uid, BigDecimal money) {
return changeEarnest(uid, money, "退还保证金", 3);
}
// 支付保证金:明细记录+orders_pay记录
public void useEarnestAddWalletDetail(SellerWallet sw, List<OrderInfo> orderList) {
for(OrderInfo oi : orderList) {
SellerWalletDetail swd = addUseEarnestDetail(sw, oi.getOrderCode(), oi.getAmount(), 1);
addOrdersPay(swd);
}
}
// 修改价格:明细记录+orders_pay金额修改
public void changePriceAddWalletDetail(SellerWallet sw, List<OrderInfo> orderList) {
for(OrderInfo oi : orderList) {
SellerWalletDetail swd = addChangePriceWalletDetail(sw, oi.getOrderCode(), oi.getAmount(), 1);
changePriceUpdateOrdersPay(swd);
}
}
// 下架商品:明细记录+退款表记录
public void unshelveAddWalletDetail(SellerWallet sw, List<OrderInfo> orderList) {
for(OrderInfo oi : orderList) {
SellerWalletDetail swd = refundEarnestDetail(sw, oi.getOrderCode(), oi.getAmount(), 1);
addRefundRecord(swd, oi.getAmount());
}
}
// 商家退出入驻,钱包清空+转账
public boolean returnAllEarnest(Integer uid, long orderCode, String alipayAccount) {
BigDecimal money = returnEarnest(uid, orderCode);
if (money == null) {
return false;
}
return paymentService.transAllEarnest(orderCode, uid, money, alipayAccount);
}
// 退还保证金
public SellerWalletDetail refundEarnestDetail(SellerWallet sw, long orderCode, BigDecimal amount, Integer isBatch) {
SellerWalletDetail swd = new SellerWalletDetail();
swd.setOrderCode(orderCode);
swd.setType(3); // 单笔退还
swd.setUid(sw.getUid());
swd.setWalletId(sw.getId());
swd.setAmount(amount);
swd.setIsBatch(isBatch);
swd.setCreateTime(TimeUtils.getTimeStampSecond());
logger.info("退还保证金,钱包明细记录,bean={}", swd);
sellerWalletDetailMapper.insert(swd);
logger.info("退还保证金,钱包明细记录成功,bean={}", swd);
return swd;
}
// 退出入驻:归还所有保证金 总账+明细
private BigDecimal returnEarnest(Integer uid, long orderCode) {
logger.info("商家退出,退还保证金,钱包归零处理开始,uid={},orderCode={}", uid, orderCode);
SellerWallet sw = sellerWalletMapper.selectByUidAndType(uid, 1);
if (sw == null) {
logger.error("退还所有保证金,钱包不存在,uid={}", uid);
CommonAlarmEventPublisher.publish("退还所有保证金失败", "ufo.order.changeEarnest", "钱包不存在uid=" + uid);
return null;
}
BigDecimal amount = sw.getAmount();
logger.info("商家退出,退还保证金,钱包归零处理,钱包信息={}", sw);
if (sw.getStatus() == null || sw.getStatus() == 0) {
logger.error("退还所有保证金{},钱包不可用,uid={}", amount, uid);
CommonAlarmEventPublisher.publish("退还所有保证金失败", "ufo.order.changeEarnest", "钱包不可用uid=" + uid+", 退还金额为:"+amount);
return null;
}
sw.setUpdateTime(TimeUtils.getTimeStampSecond());
if (sellerWalletMapper.returnMoney(sw) == 0) {
logger.error("退还所有证金失败,更新表返回0,uid={}", uid);
CommonAlarmEventPublisher.publish("退还所有保证金失败", "ufo.order.changeEarnest", "更新表返回0,uid=" + uid + ", 退还金额为:"+ amount);
return null;
}
logger.info("商家退出,退还保证金,钱包归零处理,余额扣除成功,钱包信息={}", sw);
// 增加充值记录
SellerWalletDetail swd = new SellerWalletDetail();
swd.setOrderCode(orderCode);
swd.setType(5);// 退还所有保证金
swd.setUid(uid);
swd.setWalletId(sw.getId());
swd.setAmount(amount);
swd.setIsBatch(0);
swd.setCreateTime(TimeUtils.getTimeStampSecond());
logger.info("商家退出,退还保证金,钱包归零处理,增加扣减明细,bean={}", swd);
sellerWalletDetailMapper.insert(swd);
return amount;
}
// 支付保证金:明细
private SellerWalletDetail addUseEarnestDetail(SellerWallet sw, long orderCode, BigDecimal amount, Integer isBatch) {
Integer uid = sw.getId();
SellerWalletDetail swd = new SellerWalletDetail();
swd.setOrderCode(orderCode);
swd.setType(2);
swd.setUid(uid);
swd.setWalletId(sw.getId());
swd.setAmount(amount);
swd.setIsBatch(isBatch);
swd.setCreateTime(TimeUtils.getTimeStampSecond());
logger.info("支付保证金,钱包明细记录,bean={}", swd);
sellerWalletDetailMapper.insert(swd);
logger.info("支付保证金,钱包明细记录成功,bean={}", swd);
return swd;
}
// 修改价格支付保证金:明细
private SellerWalletDetail addChangePriceWalletDetail(SellerWallet sw, long orderCode, BigDecimal amount, Integer isBatch) {
Integer uid = sw.getId();
SellerWalletDetail swd = new SellerWalletDetail();
swd.setOrderCode(orderCode);
swd.setType(4);
swd.setUid(uid);
swd.setWalletId(sw.getId());
swd.setAmount(amount);
swd.setIsBatch(isBatch);
swd.setCreateTime(TimeUtils.getTimeStampSecond());
logger.info("修改价格支付保证金,钱包明细记录,bean={}", swd);
sellerWalletDetailMapper.insert(swd);
logger.info("修改价格支付保证金,钱包明细记录成功,bean={}", swd);
return swd;
}
private SellerWallet changeEarnest(Integer uid, BigDecimal money, String message, int type) {
logger.info("{}修改钱包表入口,uid={},money={}", message, uid, money);
// 使用钱包余额,支付保证金
SellerWallet sw = sellerWalletMapper.selectByUidAndType(uid, 1);
if (sw == null) {
logger.error(message + "失败,钱包不存在,uid={}", uid);
CommonAlarmEventPublisher.publish(message + "失败", "ufo.order.changePrice", "钱包不存在uid=" + uid+", 金额为:"+money);
return null;
}
if (sw.getStatus() == null || sw.getStatus() == 0) {
logger.error(message + "{}失败,钱包不可用,uid={}", money, uid);
CommonAlarmEventPublisher.publish(message + "失败", "ufo.order.changePrice", "钱包不可用uid=" + uid+", 金额为:"+money);
return null;
}
if (sw.getAmount().compareTo(money) < 0) {
logger.error(message + "{}失败,钱包余额不足,uid={}", money, uid);
CommonAlarmEventPublisher.publish(message + "失败", "ufo.order.changePrice", "钱包余额不足uid=" + uid+", 金额为:"+money+", 账户余额为:"+sw.getAmount());
return null;
}
sw.setAmount(money.multiply(new BigDecimal("-1")));
sw.setUpdateTime(TimeUtils.getTimeStampSecond());
logger.info("{}修改钱包表余额,bean={}", sw);
if (sellerWalletMapper.addMoney(sw) == 0) {
logger.error(message + "失败,(并发)更新表返回0,uid={}", uid);
CommonAlarmEventPublisher.publish(message + "失败", "ufo.order.changePrice", "(并发)更新表返回0,uid=" + uid + ", 金额为:"+ money);
return null;
}
logger.info("{}修改钱包表余额成功,bean={}", sw);
SellerWalletDetail swd = new SellerWalletDetail();
swd.setOrderCode(0L);
swd.setType(type);
swd.setUid(uid);
swd.setWalletId(sw.getId());
swd.setAmount(money);
swd.setIsBatch(0);
swd.setCreateTime(TimeUtils.getTimeStampSecond());
logger.info("增加钱包明细汇总记录,bean={}", swd);
sellerWalletDetailMapper.insert(swd);
logger.info("增加钱包明细汇总成功,bean={}", swd);
return sw;
}
private void addOrdersPay(SellerWalletDetail swd) {
// 增加支付记录
OrdersPay ordersPay = new OrdersPay();
ordersPay.setOrderCode(swd.getOrderCode());
ordersPay.setUid(swd.getUid());
ordersPay.setPayment(Payment.WALLET.getCode());
ordersPay.setAmount(swd.getAmount());
ordersPay.setPayOrderCode(String.valueOf(swd.getOrderCode()));
ordersPay.setSerialNo(Integer.toString(swd.getId()));
ordersPay.setCreateTime(TimeUtils.getTimeStampSecond());
JSONObject attach = new JSONObject();
attach.put("order_type", OrderCodeType.SELLER_TYPE.getType());
ordersPay.setAttach(attach.toJSONString());
logger.info("增加支付记录orders_pay,bean={}", ordersPay);
ordersPayDao.insertSelective(ordersPay);
logger.info("增加支付记录orders_pay成功,orderCode={}", swd.getOrderCode());
}
private int changePriceUpdateOrdersPay(SellerWalletDetail swd) {
// 增加支付记录
OrdersPay ordersPay = new OrdersPay();
ordersPay.setOrderCode(swd.getOrderCode());
ordersPay.setUid(swd.getUid());
ordersPay.setAmount(swd.getAmount());
String message = "修改保证金order_pay记录金额";
logger.info("商家修改价格,修改支付记录金额orders_pay,bean={}", ordersPay);
int result;
if ((result = ordersPayDao.addMoney(ordersPay)) == 0) {
logger.error(message + "{}失败,修改DB返回记录数为0,orderCode={}", swd.getAmount(), swd.getOrderCode());
CommonAlarmEventPublisher.publish(message + "失败", "ufo.order.changePriceOrdersPay", "修改DB返回记录数为0,orderCode=" + swd.getOrderCode()+", 金额为:"+swd.getAmount());
}
logger.info("商家修改价格,修改支付记录金额orders_pay成功,orderCode={}", swd.getOrderCode());
return result;
}
private void addRefundRecord(SellerWalletDetail swd, BigDecimal amount) {
OrdersPayRefund newRecord = new OrdersPayRefund();
newRecord.setOrderCode(swd.getOrderCode());
newRecord.setRefundCode(Integer.toString(swd.getWalletId()));
newRecord.setAmount(amount);
newRecord.setStatus((byte) 0);
newRecord.setSerialNo(Integer.toString(swd.getId()));
newRecord.setOrderType(0);
int timeStamp = (int) (new Date().getTime() / 1000);
newRecord.setCreateTime(timeStamp);
newRecord.setUpdateTime(timeStamp);
logger.info("商品下架,添加退款记录,bean={}", newRecord);
ordersPayRefundMapper.insert(newRecord);
logger.info("商品下架,添加退款记录成功,orderCode={}", swd.getOrderCode());
}
}
... ...
package com.yohoufo.order.service.concurrent;
import java.util.concurrent.ForkJoinPool;
/**
* Created by chao.chen on 2018/11/20.
*/
public class ThreadPoolFactory {
static class GoodKids{
private volatile static ForkJoinPool forkJoinPool ;
static {
forkJoinPool = new ForkJoinPool(6);
}
}
public static ForkJoinPool getForkJoinPool(){
return GoodKids.forkJoinPool;
}
}
... ...
package com.yohoufo.order.service.handler;
import com.google.common.eventbus.Subscribe;
import com.yohobuy.ufo.model.order.bo.OrderInfo;
import com.yohoufo.common.alarm.IEventHandler;
import com.yohoufo.dal.order.model.SellerWallet;
import com.yohoufo.order.event.BatchPublishTailEvent;
import com.yohoufo.order.service.MerchantOrderPaymentService;
import com.yohoufo.order.service.proxy.ProductProxyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
/**
* Created by chao.chen on 2018/11/20.
*/
@Component
public class BatchPublishTailHandler implements IEventHandler<BatchPublishTailEvent> {
@Autowired
private MerchantOrderPaymentService merchantOrderPaymentService;
@Autowired
private ProductProxyService productProxyService;
@Override
@Subscribe
public void handle(BatchPublishTailEvent event) {
batchPublishTailProcess(event.getFjr(), event.getSellerWallet());
}
private void batchPublishTailProcess(SellerOrderSubmitHandler.ForkJoinResult fjr, SellerWallet sellerWallet){
// (异步实现)记录保证金流水
List<OrderInfo> orderList = fjr.getSellerOrderList().parallelStream().map(sellerOrder ->
OrderInfo.builder().orderCode(sellerOrder.getOrderCode())
.amount(sellerOrder.getEarnestMoney()).build()
).collect(Collectors.toList());
merchantOrderPaymentService.useEarnestAddWalletDetail(sellerWallet, orderList);
//(异步实现)同步数据到prd,记录支付,
productProxyService.batchCreateSkup(fjr.getSellerOrderGoodsList());
productProxyService.sellerBatchUpdateStatus(fjr.getSkupIds(), ProductProxyService.PrdShelvelStatus.on);
}
}
... ...
package com.yohoufo.order.service.handler;
import com.yoho.core.dal.datasource.annotation.Database;
import com.yohobuy.ufo.model.order.common.OrderCodeType;
import com.yohobuy.ufo.model.order.common.SkupStatus;
import com.yohoufo.common.exception.GatewayException;
import com.yohoufo.dal.order.model.SellerOrder;
import com.yohoufo.dal.order.model.SellerOrderGoods;
import com.yohobuy.ufo.model.order.bo.GoodsInfo;
import com.yohoufo.order.convert.GoodsInfoConvertor;
import com.yohoufo.order.model.SellerOrderContext;
import com.yohoufo.order.service.MerchantOrderPaymentService;
import com.yohoufo.order.service.impl.SkupService;
import com.yohoufo.order.service.impl.SellerAddressService;
import com.yohoufo.order.service.impl.SellerFeeService;
import com.yohoufo.order.service.impl.SellerOrderCreateService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* Created by chenchao on 2018/9/17.
*/
... ... @@ -34,6 +45,9 @@ public class SellerOrderSubmitHandler {
@Autowired
private SellerFeeService sellerFeeService;
@Autowired
private MerchantOrderPaymentService merchantOrderPaymentService;
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Database(ForceMaster=true, DataSource="ufo_order")
public void submit(SellerOrderContext context) throws GatewayException {
... ... @@ -45,7 +59,7 @@ public class SellerOrderSubmitHandler {
SellerOrderGoods sellerOrderGoods = skupService.addSkup(goodsInfo);
int skup = sellerOrderGoods.getId();
if (skup <= 0){
log.warn("in computePublishPrd storageId not exist in prd , uid {}, storageId {}", uid, storageId);
log.warn("in submit storageId not exist in prd , uid {}, storageId {}", uid, storageId);
throw new GatewayException(501, "商品发布失败");
}
context.setSellerOrderGoods(sellerOrderGoods);
... ... @@ -59,6 +73,51 @@ public class SellerOrderSubmitHandler {
sellerFeeService.saveFee(context);
}
public ForkJoinResult submitMultiple(SellerOrderContext context, int num) throws GatewayException {
int uid = context.getUid();
int storageId = context.getStorageId();
log.info("in seller order submitMultiple uid {}, storageId {}, num {}", uid, storageId, num);
GoodsInfo goodsInfo = context.getSoldProduct();
//
List<SellerOrderGoods> sogList = new ArrayList<>(num);
for(int i=0; i<num; i++){
SellerOrderGoods sog = GoodsInfoConvertor.resp2Do4AddNew(goodsInfo);
sog.setStatus(SkupStatus.CAN_SELL.getCode());
sogList.add(sog);
}
int rows = skupService.batchAddSkup(sogList);
List<Integer> skupIds = sogList.parallelStream().filter(sog-> Objects.nonNull(sog.getId()))
.map(SellerOrderGoods::getId).collect(Collectors.toList());
if (skupIds == null || skupIds.size() == 0){
log.warn("in submitMultiple storageId not exist in prd , uid {}, storageId {}", uid, storageId);
throw new GatewayException(501, "商品发布失败");
}
//step 2: create order, set status(not pay)
//generate a new real code
List<SellerOrder> sellerOrders = sellerOrderCreateService.createBatchOrder(context, skupIds);
//寄回地址:back_delivery_address
sellerAddressService.saveBatchSendBackAddress(context, skupIds);
//record every fee items
sellerFeeService.saveBatchFee(context, skupIds);
ForkJoinResult fjr = new ForkJoinResult();
fjr.uid = uid;
fjr.storageId = storageId;
fjr.sellerOrderList = sellerOrders;
fjr.skupIds = skupIds;
fjr.sellerOrderGoodsList = sogList;
return fjr;
}
@Data
public static class ForkJoinResult{
int uid;
int storageId;
List<Integer> skupIds;
List<SellerOrder> sellerOrderList;
List<SellerOrderGoods> sellerOrderGoodsList;
}
}
... ...
... ... @@ -29,10 +29,12 @@ import com.yohoufo.order.model.response.PrepayResponse;
import com.yohoufo.order.service.AbstractOrderPaymentService;
import com.yohoufo.order.service.BuyerOrderPaymentService;
import com.yohoufo.order.service.IPaymentService;
import com.yohoufo.order.service.MerchantOrderPaymentService;
import com.yohoufo.order.service.SellerOrderPaymentService;
import com.yohoufo.order.service.handler.BuyerCancelCompensateComputeHandler;
import com.yohoufo.order.service.pay.AbstractPayService;
import com.yohoufo.order.service.pay.alipay.AlipayOuyinService;
import com.yohoufo.order.service.pay.wallet.WalletPayService;
import com.yohoufo.order.service.pay.weixin.WeixinMiniappPayService;
import com.yohoufo.order.service.pay.weixin.WeixinPayUFORealAppService;
import com.yohoufo.order.service.support.codegenerator.OrderCodeGenerator;
... ... @@ -74,6 +76,9 @@ public class PaymentServiceImpl implements IPaymentService {
@Autowired
SellerOrderPaymentService sellerOrderPaymentService;
@Autowired
MerchantOrderPaymentService merchantOrderPaymentService;
@Autowired
OrderCodeGenerator orderCodeGenerator;
... ... @@ -109,6 +114,9 @@ public class PaymentServiceImpl implements IPaymentService {
WeixinMiniappPayService weixinMiniappPayService;
@Autowired
WalletPayService walletPayService;
@Autowired
BuyerOrderMapper buyerOrderMapper;
@Autowired
... ... @@ -144,8 +152,7 @@ public class PaymentServiceImpl implements IPaymentService {
}else if(codeMeta.getType() == OrderCodeType.SELLER_TYPE.getType()){
paymentService = this.sellerOrderPaymentService;
}else if(codeMeta.getType() == OrderCodeType.SELLER_RECHARGE_EARNEST_TYPE.getType()){
// TODO
paymentService = this.sellerOrderPaymentService;
paymentService = this.merchantOrderPaymentService;
}
return paymentService;
... ... @@ -173,6 +180,8 @@ public class PaymentServiceImpl implements IPaymentService {
payService = alipayService;
}else if(payment == Payment.MINIAPP){
payService = weixinMiniappPayService;
}else if(payment == Payment.WALLET){
payService = walletPayService;
}
return payService;
... ... @@ -283,7 +292,7 @@ public class PaymentServiceImpl implements IPaymentService {
ordersPayDao.insertSelective(ordersPay);
// 支付方式适配
// 流水记录表支付方式适配
Integer recordPayment = orderInfo.getPayment();
if (recordPayment != null && recordPayment == 1) {
if (recordPayment == 1) {
... ... @@ -300,7 +309,10 @@ public class PaymentServiceImpl implements IPaymentService {
}
addPayBuyRecord(orderInfo.getUid(), orderInfo.getSellerUid(), goods.getSkup(), orderCode, recordPayment,
ordersPay.getAmount());
} else {
} else if (codeMeta.getType() == OrderCodeType.SELLER_TYPE.getType()) {
addPayEnsureRecord(orderInfo.getUid(), orderInfo.getSkup(), orderCode, recordPayment,
ordersPay.getAmount());
} else if (codeMeta.getType() == OrderCodeType.SELLER_RECHARGE_EARNEST_TYPE.getType()) {
addPayEnsureRecord(orderInfo.getUid(), orderInfo.getSkup(), orderCode, recordPayment,
ordersPay.getAmount());
}
... ... @@ -391,6 +403,7 @@ public class PaymentServiceImpl implements IPaymentService {
payRefundBo.setAmount(request.getRefundAmount());
payRefundBo.setOrderTotalFee(ordersPay.getAmount().doubleValue());
payRefundBo.setRefundOrderCode(String.valueOf(ordersPay.getOrderCode()) + ordersPay.getId());
payRefundBo.setUid(ordersPay.getUid());
return payRefundBo;
}
... ... @@ -603,6 +616,114 @@ public class PaymentServiceImpl implements IPaymentService {
}
}
@Database(ForceMaster = true)
public boolean transAllEarnest(long orderCode, Integer uid, BigDecimal amount, String alipayAccount){
logger.info("退还商家所有保证金,转账开始,orderCode = {}, uid={}, amount={}, alipayAccount={}", orderCode, uid, amount, alipayAccount);
int now = (int) (System.currentTimeMillis()/1000);
// 查看是否已经有转账记录
OrdersPayTransfer exist = ordersPayTransferMapper.selectByBuyerOrderCode(orderCode);
if (exist != null) {
logger.warn("transAllEarnestErr OrdersPayTransfer has exist, orderCode is {}", orderCode);
throw new ServiceException(400, "订单已经处理过");
}
OrdersPayTransfer transfer = new OrdersPayTransfer();
transfer.setBuyerOrderCode(orderCode);
transfer.setSellerOrderCode(orderCode);
transfer.setAlipayTradeId("");
transfer.setAlipayTradeResult("");
transfer.setAlipayAccount(alipayAccount);
transfer.setTransferType(6);
transfer.setUid(uid);
transfer.setAmount(amount);
transfer.setCreateTime(now);
transfer.setStatus(0);
try {
logger.info("transAllEarnest插入初始化转账信息orderCode is {}", orderCode);
ordersPayTransferMapper.insert(transfer);
} catch (Exception e) {
logger.warn("transAllEarnestErr insert ordersPayTransfer failed, orderCode is {}, msg is {}", orderCode, e.getMessage());
throw new ServiceException(400, "交易记录创建失败");
}
// 增加流水记录
TradeBills record = new TradeBills();
record.setUid(uid);
record.setOrderCode(orderCode);
record.setUserType(2);
record.setPayType(1);
record.setTradeType(1);
record.setIncomeOutcome(1);
record.setTradeStatus(0);
record.setCreateTime(now);
record.setAmount(amount);
record.setSystemAmount(amount.multiply(new BigDecimal("-1")));
if (amount == null || amount.compareTo(new BigDecimal("0.1")) < 0) {
logger.warn("transAllEarnestErr transferMon计算费用结果为 {}, 小于0.1或为null", amount);
alarm("转账金额小于0.1或为null", "ufo.order.transAllEarnest", "退还商家入驻所有金额,订单号:" + orderCode + "操作类型(" + 6 + ")计算金额结果为" + amount);
record.setTradeStatus(202);
addTradeBills(record);
throw new ServiceException(400, "不合法的金额:" + amount);
}
if (StringUtils.isBlank(alipayAccount)) {
logger.warn("transAllEarnestErr uid {} 支付宝账号不合法", alipayAccount);
record.setTradeStatus(201);
addTradeBills(record);
throw new ServiceException(400, "uid[" + uid + "]支付宝账号不合法");
}
logger.info("transAllEarnest参数检查成功!");
// 转账
try {
logger.info("transAllEarnest开始调用阿里接口参数buyerOrderCode={}, alipayAccount={}, transferAmount={}", orderCode, alipayAccount, amount);
JSONObject jsonObject = alipayService.transferMoney(Long.toString(orderCode), alipayAccount, amount);
if (jsonObject == null) {
logger.warn("transAllEarnestErr 转账失败 , orderCode is {}", orderCode);
transfer.setStatus(3);
throw new ServiceException(500, "转账失败:阿里接口返回null");
}
transfer.setAlipayTradeResult(jsonObject.toJSONString());
// 成功
Integer code = null;
String orderId = null;
if (jsonObject.containsKey("code")
&& (code = jsonObject.getInteger("code")) == 10000
&& jsonObject.containsKey("order_id")
&& StringUtils.isNotBlank(orderId = jsonObject.getString("order_id"))) {
logger.info("转账成功,targeAccount is {}, amount is {}", alipayAccount, amount);
transfer.setAlipayTradeId(orderId);
transfer.setStatus(1);
return true;
} else {
logger.warn("transAllEarnestErr 返回code或者order_id不是成功状态,code={}, orderId={}", code, orderId);
throw new ServiceException(500, "转账失败:code或者order_id不是成功状态");
}
} catch (Exception e) {
logger.warn("transAllEarnestErr 转账失败 , orderCode is {}, msg is {}", orderCode, e.getMessage());
alarm("转账失败", "ufo.order.transAllEarnest", "订单号:" + orderCode + "操作类型(" + 6 + ")转账失败,msg=" + e.getMessage());
transfer.setStatus(3);
if(e instanceof ServiceException) {
throw new ServiceException(((ServiceException) e).getCode(), e.getMessage());
} else {
throw new ServiceException(500, "转账失败");
}
} finally {
logger.info("transAllEarnest最后更新状态 status= {}", transfer.getStatus());
transfer.setUpdateTime(now);
ordersPayTransferMapper.updateByPrimaryKeySelective(transfer);
// 100:成功;201:没有支付宝账号;202:金额不合法;299:转账失败
record.setTradeStatus(transfer.getStatus() == 1 ? 100 : 299);
addTradeBills(record);
logger.info("transAllEarnest最后更新状态完成,转账结束, orderCode is {}!", orderCode);
}
}
/**
* 专门提供给鉴定通过,不通过的校验
* @param request
... ... @@ -845,6 +966,7 @@ public class PaymentServiceImpl implements IPaymentService {
payRefundBo.setAmount(amount.doubleValue());
payRefundBo.setOrderTotalFee(ordersPay.getAmount().doubleValue());
payRefundBo.setRefundOrderCode(String.valueOf(ordersPay.getOrderCode()) + ordersPay.getId());
payRefundBo.setUid(ordersPay.getUid());
PayRefundBo refundBo = payService.refundOpenApi(payRefundBo);
//退款申请成功的记录添加到orders_pay_refund表
... ...
... ... @@ -12,6 +12,9 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
/**
* Created by chenchao on 2018/9/17.
*/
... ... @@ -31,8 +34,7 @@ public class SellerAddressService {
String value = JSONObject.toJSONString(ctx.getBackAddress());
som.setMetaValue(value);
int result = somMapper.insertSelective(som);
//hidden
SellerOrderMeta hidddenSom = new SellerOrderMeta();
hidddenSom.setUid(ctx.getUid());
hidddenSom.setSkup(ctx.getSoldProduct().getSkup());
... ... @@ -44,14 +46,29 @@ public class SellerAddressService {
}
public AddressInfo getAddressInfo(int uid, int skup){
SellerOrderMeta som = somMapper.selectByMetaKey(uid, skup, MetaKey.BACK_2_SELLER_DELIVERY_ADDRESS);
String value;
if(som == null || (value=som.getMetaValue()) == null){
return null;
public int saveBatchSendBackAddress(SellerOrderContext ctx, List<Integer> skupIds){
int result = 0;
String value = JSONObject.toJSONString(ctx.getBackAddress());
String hValue = JSONObject.toJSONString(ctx.getBackHiddenAddress());
List<SellerOrderMeta> list = new ArrayList<>( 2*skupIds.size() );
for(Integer skupId : skupIds){
SellerOrderMeta som = new SellerOrderMeta();
som.setUid(ctx.getUid());
som.setSkup(skupId);
som.setMetaKey(MetaKey.BACK_2_SELLER_DELIVERY_ADDRESS);
som.setMetaValue(value);
list.add(som);
//hidden
SellerOrderMeta hidddenSom = new SellerOrderMeta();
hidddenSom.setUid(ctx.getUid());
hidddenSom.setSkup(skupId);
hidddenSom.setMetaKey(MetaKey.BACK_2_SELLER_DELIVERY_HIDDEN_ADDRESS);
hidddenSom.setMetaValue(hValue);
list.add(hidddenSom);
}
AddressInfo addressInfo = JSONObject.parseObject(value, AddressInfo.class);
return addressInfo;
result = somMapper.insertBatch(list);
return result;
}
... ...
... ... @@ -3,7 +3,10 @@ package com.yohoufo.order.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.yoho.core.dal.datasource.annotation.Database;
import com.yohoufo.common.utils.BigDecimalHelper;
import com.yohoufo.dal.order.*;
import com.yohoufo.dal.order.BuyerOrderGoodsMapper;
import com.yohoufo.dal.order.BuyerOrderMapper;
import com.yohoufo.dal.order.SellerOrderMapper;
import com.yohoufo.dal.order.SellerOrderMetaMapper;
import com.yohoufo.dal.order.model.BuyerOrder;
import com.yohoufo.dal.order.model.BuyerOrderGoods;
import com.yohoufo.dal.order.model.SellerOrder;
... ... @@ -22,6 +25,8 @@ import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* Created by chenchao on 2018/9/17.
... ... @@ -44,12 +49,6 @@ public class SellerFeeService {
@Autowired
private SellerOrderMapper sellerOrderMapper;
@Autowired
private SellerOrderGoodsMapper sellerOrderGoodsMapper;
@Autowired
private SellerOrderMetaMapper sellerOrderMetaMapper;
@Transactional(propagation = Propagation.REQUIRED)
@Database(ForceMaster=true, DataSource="ufo_order")
public int saveFee(SellerOrderContext ctx){
... ... @@ -63,6 +62,23 @@ public class SellerFeeService {
return somMapper.insertSelective(som);
}
public int saveBatchFee(SellerOrderContext ctx, List<Integer> skupIds){
logger.info("in seller saveBatchFee, uid {}, skupIds {}", ctx.getUid(), skupIds);
int result = 0;
String value = JSONObject.toJSONString(ctx.getSellerOrderComputeResult());
List<SellerOrderMeta> list = new ArrayList<>(skupIds.size());
for(Integer skupId : skupIds) {
SellerOrderMeta som = new SellerOrderMeta();
som.setUid(ctx.getUid());
som.setSkup(skupId);
som.setMetaKey(MetaKey.SELLER_FEE);
som.setMetaValue(value);
list.add(som);
}
result += somMapper.insertBatch(list);
return result;
}
public SellerOrderComputeResult getSellerOrderComputeResult(int uid, int skup){
try {
... ...
package com.yohoufo.order.service.impl;
import com.yoho.core.dal.datasource.annotation.Database;
import com.yohobuy.ufo.model.order.common.OrderCodeType;
import com.yohobuy.ufo.model.order.common.SellerOrderStatus;
import com.yohoufo.common.utils.DateUtil;
import com.yohoufo.dal.order.SellerOrderMapper;
import com.yohoufo.dal.order.model.SellerOrder;
import com.yohoufo.order.common.DelStatus;
import com.yohobuy.ufo.model.order.common.SellerOrderStatus;
import com.yohoufo.order.model.SellerOrderContext;
import com.yohoufo.order.service.support.codegenerator.OrderCodeGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
/**
* Created by chenchao on 2018/9/17.
*/
@Service
public class SellerOrderCreateService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private SellerOrderMapper sellerOrderMapper;
@Autowired
private OrderCodeGenerator orderCodeGenerator;
@Transactional(propagation = Propagation.REQUIRED)
@Database(ForceMaster=true, DataSource="ufo_order")
public int createOrder(SellerOrderContext context){
logger.info("create seller Order, uid {} storage id {} order code {} skup {}",
context.getUid(), context.getStorageId(), context.getOrderCode(), context.getSoldProduct().getSkup());
int currentTiem = DateUtil.getCurrentTimeSecond();
SellerOrder condition = new SellerOrder();
condition.setOrderCode(context.getOrderCode());
... ... @@ -36,4 +49,34 @@ public class SellerOrderCreateService {
condition.setIncome(context.getSellerOrderComputeResult().getIncome());
return sellerOrderMapper.insertSelective(condition);
}
public List<SellerOrder> createBatchOrder(SellerOrderContext context, List<Integer> skupIdList){
int currentTiem = DateUtil.getCurrentTimeSecond();
List<SellerOrder> list = new ArrayList<>(skupIdList.size());
for(Integer skupId : skupIdList){
SellerOrder condition = new SellerOrder();
long orderCode = orderCodeGenerator.generate(OrderCodeType.SELLER_TYPE);
if (orderCode <= 0L){
logger.warn("in createBatchOrder storageId not exist in prd , uid {}, storageId {} skup {}, compute result {}",
context.getUid(), context.getStorageId(), skupId, context.getSellerOrderComputeResult());
//todo alarm event
continue;
}
condition.setOrderCode(orderCode);
condition.setUid(context.getUid());
condition.setSkup(skupId);
condition.setIsDel(DelStatus.NOT_DEL.getCode());
condition.setCreateTime(currentTiem);
condition.setStatus(SellerOrderStatus.HAS_PAYED.getCode());
condition.setEarnestMoney(context.getSellerOrderComputeResult().getEarnestMoney().getEarnestMoney());
condition.setIncome(context.getSellerOrderComputeResult().getIncome());
condition.setPayment((int)OrderCodeType.SELLER_RECHARGE_EARNEST_TYPE.getType());
list.add(condition);
}
if (!list.isEmpty()){
sellerOrderMapper.insertBatch(list);
}
return list;
}
}
... ...
... ... @@ -13,16 +13,20 @@ import com.yohobuy.ufo.model.order.resp.PageResp;
import com.yohoufo.common.alarm.EventBusPublisher;
import com.yohoufo.common.alarm.SmsAlarmEvent;
import com.yohoufo.common.exception.GatewayException;
import com.yohoufo.common.utils.BigDecimalHelper;
import com.yohoufo.common.utils.DateUtil;
import com.yohoufo.common.utils.PageHelper;
import com.yohoufo.dal.order.BuyerOrderMapper;
import com.yohoufo.dal.order.SellerOrderGoodsMapper;
import com.yohoufo.dal.order.SellerOrderMapper;
import com.yohoufo.dal.order.model.BuyerOrder;
import com.yohoufo.dal.order.model.SellerOrder;
import com.yohoufo.dal.order.model.SellerOrderGoods;
import com.yohoufo.dal.order.model.SellerWallet;
import com.yohoufo.order.common.ActionStatusHold;
import com.yohoufo.order.common.DelStatus;
import com.yohoufo.order.convert.SellerOrderConvertor;
import com.yohoufo.order.event.BatchPublishTailEvent;
import com.yohoufo.order.event.ErpCancelSellerOrderEvent;
import com.yohoufo.order.event.EventHandlerContainer;
import com.yohoufo.order.event.OrderCancelEvent;
... ... @@ -35,8 +39,10 @@ import com.yohoufo.order.model.response.OrderSubmitResp;
import com.yohoufo.order.model.response.OrderSummaryResp;
import com.yohoufo.order.service.IOrderDetailService;
import com.yohoufo.order.service.IOrderListService;
import com.yohoufo.order.service.MerchantOrderPaymentService;
import com.yohoufo.order.service.cache.CacheCleaner;
import com.yohoufo.order.service.cache.OrderCacheService;
import com.yohoufo.order.service.concurrent.ThreadPoolFactory;
import com.yohoufo.order.service.handler.SellerOrderComputeHandler;
import com.yohoufo.order.service.handler.SellerOrderSubmitHandler;
import com.yohoufo.order.service.impl.processor.SellerOrderPrepareProcessor;
... ... @@ -45,24 +51,30 @@ import com.yohoufo.order.service.impl.visitor.UserCancelCase;
import com.yohoufo.order.service.proxy.ProductProxyService;
import com.yohoufo.order.service.support.codegenerator.OrderCodeGenerator;
import com.yohoufo.order.service.support.codegenerator.bean.CodeMeta;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.Collectors;
/**
* Created by chenchao on 2018/9/13.
*/
@Service
@Slf4j
public class SellerOrderService implements IOrderListService, IOrderDetailService {
private final Logger log = LoggerFactory.getLogger(getClass());
@Autowired
private SellerOrderMapper sellerOrderMapper;
... ... @@ -105,6 +117,13 @@ public class SellerOrderService implements IOrderListService, IOrderDetailServi
@Autowired
private SellerOrderPrepareProcessor sellerOrderPrepareProcessor;
@Autowired
private SkupBatchService skupBatchService;
@Autowired
private MerchantOrderPaymentService merchantOrderPaymentService;
public SoldPrdComputeBo computePublishPrd(SellerOrderComputeReq req) throws GatewayException {
log.info("in computePublishPrd, req {}", req);
int uid = req.getUid();
... ... @@ -150,33 +169,9 @@ public class SellerOrderService implements IOrderListService, IOrderDetailServi
return buildSoldPrdComputeBo(uid, num, prdPrice);
}
/**
* 发布商品 + 生成订单
* @param req
* @return
* @throws GatewayException
*/
public OrderSubmitResp publishPrd(SellerOrderSubmitReq req) throws GatewayException {
SellerOrderContext context = sellerOrderPrepareProcessor.buildSellerOrderContext(req);
private OrderSubmitResp publishSinglePrd(SellerOrderSubmitReq req, SellerOrderContext context) throws GatewayException {
int storageId = context.getStorageId();
int uid = context.getUid();
//step 1: rpc get product detail by storage id
//ufo.product.storage.data
GoodsInfo goodsInfo = sellerOrderPrepareProcessor.getProductDetail(context);
//step 2: generate skup ,action :set price status(unsaleable)
if (Objects.isNull(goodsInfo)){
log.warn("in publishPrd storageId not exist in prd service , uid {}, storageId {}", uid, storageId);
throw new ServiceException(ServiceError.ORDER_ORDERS_GOODS_IS_EMPTY);
}
context.setSoldProduct(goodsInfo);
sellerOrderPrepareProcessor.checkPrice(storageId, goodsInfo.getPrice(), true);
// compute every fee from price
SellerOrderComputeResult computeResult = computeHandler.compute(goodsInfo.getPrice());
sellerOrderPrepareProcessor.checkIncome(storageId, computeResult.getIncome());
log.info("in publishPrd , uid {}, storageId {}, price {}, computeResult {}", uid, storageId,
goodsInfo.getPrice(), computeResult);
context.setSellerOrderComputeResult(computeResult);
// step 2: create order, set status(not pay)
// generate a new real code
long orderCode = orderCodeGenerator.generate(OrderCodeType.SELLER_TYPE);
... ... @@ -184,6 +179,8 @@ public class SellerOrderService implements IOrderListService, IOrderDetailServi
log.warn("in publishPrd storageId not exist in prd , uid {}, storageId {}", uid, storageId);
throw new ServiceException(ServiceError.EARNESTMONEY_ORDER_CREATE_FAIL);
}
//允许入驻商家后,对于个体户而言,也需要批次号(1:1这种,直接使用订单号,若以后有变化 用skup_batch表自增)
context.getSoldProduct().setBatchNo(orderCode);
context.setOrderCode(orderCode);
//submit all as atomic operation, use transaction of DB
//all include : 1. skup, 2. order , 3. 寄回地址
... ... @@ -204,9 +201,27 @@ public class SellerOrderService implements IOrderListService, IOrderDetailServi
cacheCleaner.cleanList(uid, TabType.SELL.getValue());
// 发消息
GoodsInfo goodsInfo = context.getSoldProduct();
OrderSubmitResp resp = OrderSubmitResp.builder().orderCode(orderCode).productId(goodsInfo.getProductId()).build();
return resp;
}
/**
* 发布商品 + 生成订单
* @param req
* @return
* @throws GatewayException
*/
public OrderSubmitResp publishPrd(SellerOrderSubmitReq req) throws GatewayException {
SellerOrderContext context = sellerOrderPrepareProcessor.buildPublishPrdCtx(req);
boolean isEntryShop = context.isEntryShop();
OrderSubmitResp resp ;
if(isEntryShop){
resp = batchPublishPrds(context, req);
}else{
resp = publishSinglePrd(req, context);
}
return resp;
}
private void pushAutoCancelEvent(SellerOrderContext context){
int uid = context.getUid();
... ... @@ -219,40 +234,40 @@ public class SellerOrderService implements IOrderListService, IOrderDetailServi
}
/**
* 卖家支付完成后调用
* @param uid
* @param orderCode
*/
public void processAfterPay(int uid, long orderCode){
//todo update order info, set payment status
//todo update skup status
//todo sync skup to prd service by rpc
}
/**
* 发货
* @param buyerOrderCode
* @param expressNum
*/
public void deliverGoods(int uid, long buyerOrderCode,String expressNum){
//
}
@Autowired
private SkupBatchService skupBatchService;
public void batchPublishPrds(SellerOrderSubmitReq req) throws GatewayException {
public OrderSubmitResp batchPublishPrds(SellerOrderContext ctx, SellerOrderSubmitReq req) throws GatewayException {
// 一串校验
SellerOrderContext ctx = sellerOrderPrepareProcessor.buildBatchSellerOrderContext(req);
//TODO 扣减保证金
//TODO (异步实现)记录保证金流水
//TODO 生成批次号
skupBatchService.generateBatchNo(req.getUid(), req.getNum());
//TODO 批量生成订单(订单表,meta 地址,算费)--> 需要用到多线程并行处理
//TODO(异步实现)同步数据到prd,记录支付,
//扣减保证金
final int num = req.getNum();
int uid = req.getUid();
SellerOrderComputeResult socr = ctx.getSellerOrderComputeResult();
BigDecimal singleEarestMoney = socr.getEarnestMoney().getEarnestMoney();
BigDecimal mEarestMoney = BigDecimalHelper.halfUp(new BigDecimal(num).multiply(singleEarestMoney));
SellerWallet sellerWallet = merchantOrderPaymentService.useEarnest(uid, mEarestMoney);
// invoke pay by wallet
boolean paySuccess = Objects.nonNull(sellerWallet);
if (!paySuccess){
log.warn("batchPublishPrds pay fail, req {} mEarestMoney {}", req, mEarestMoney);
throw new ServiceException(ServiceError.WALLET_EARNESTMONEY_PAY_FAIL);
}
// 生成批次号
long batchNo = skupBatchService.generateBatchNo(req.getUid(), req.getNum());
ctx.getSoldProduct().setBatchNo(batchNo);
int times = PageHelper.getPageTotal(num, MAX_DEAL);
CountDownLatch cdl = new CountDownLatch(times);
//批量生成订单(订单表,meta 地址,算费)--> 需要用到多线程并行处理
List<ForkJoinTask<SellerOrderSubmitHandler.ForkJoinResult>> taskList = new ArrayList<>(times);
for(int i = 1; i <= times; i++){
int forkNum = MAX_DEAL;
if (times == i){
forkNum = num - (i-1) * MAX_DEAL;
}
log.info("batch publish uid {} storageId {} forkNum {} num {}", uid, req.getStorageId(), forkNum, num);
BatchProcessTask batchProcessTask = new BatchProcessTask(ctx, cdl, forkNum, sellerWallet);
ForkJoinTask<SellerOrderSubmitHandler.ForkJoinResult> fjt = ThreadPoolFactory.getForkJoinPool().submit(batchProcessTask);
taskList.add(fjt);
}
return OrderSubmitResp.builder().build();
}
... ... @@ -267,6 +282,11 @@ public class SellerOrderService implements IOrderListService, IOrderDetailServi
return true;
}
/**
* todo
* @param req
* @return
*/
public boolean batchCancel(SellerOrderBatchCancelReq req){
... ... @@ -366,20 +386,6 @@ public class SellerOrderService implements IOrderListService, IOrderDetailServi
}
}
/**
* 查物流详情
* 只查卖家自己填的物流单
* @param uid
* @param buyerOrderCode
* @param expressNum
* @return
*/
public Object queryLogistics(int uid, long buyerOrderCode, String expressNum){
return null;
}
private SoldPrdComputeBo buildSoldPrdComputeBo(int uid, int num, BigDecimal prdPrice){
SellerOrderComputeResult computeResult = computeHandler.compute(prdPrice);
/**
... ... @@ -451,7 +457,11 @@ public class SellerOrderService implements IOrderListService, IOrderDetailServi
.actor(orderRequest.getTabType()).build();
}
/**
* todo
* @param req
* @return
*/
public BatchChangePriceResp batchChangePrice(BatchChangePriceReq req){
BatchChangePriceResp resp = BatchChangePriceResp.builder().successCnt(1).failCnt(1)
.tips("变价成功1个,失败1个").build();
... ... @@ -461,6 +471,51 @@ public class SellerOrderService implements IOrderListService, IOrderDetailServi
private static final int MAX_DEAL = 10;
private class BatchProcessTask implements Callable<SellerOrderSubmitHandler.ForkJoinResult>{
private SellerOrderContext ctx;
private CountDownLatch countDownLatch;
private int num;
private SellerWallet sellerWallet;
public BatchProcessTask(SellerOrderContext ctx, CountDownLatch countDownLatch, int num, SellerWallet sellerWallet) {
this.ctx = ctx;
this.countDownLatch = countDownLatch;
this.num = num;
this.sellerWallet = sellerWallet;
}
@Override
public SellerOrderSubmitHandler.ForkJoinResult call() throws Exception {
int uid = ctx.getUid();
int storageId = ctx.getStorageId();
log.info("{}.compute, countDownLatch count {} uid {} storageId {}",
getClass().getSimpleName(),countDownLatch.getCount(), uid, storageId);
// 批量生成订单(订单表,meta 地址,算费)--> 需要用到多线程并行处理
SellerOrderSubmitHandler.ForkJoinResult fjr = null;
try {
fjr = orderSubmitHandler.submitMultiple(ctx, num);
// (异步实现)记录保证金流水
//(异步实现)同步数据到prd,记录支付,
BatchPublishTailEvent bpte = BatchPublishTailEvent.builder().fjr(fjr).sellerWallet(sellerWallet).build();
EventBusPublisher.publishEvent(bpte);
countDownLatch.countDown();
}catch (Exception ex){
countDownLatch.countDown();
log.warn("batch publish prd fork uid {} storageId {}", uid, storageId, ex);
}
log.info("{}.compute, countDownLatch count {} uid {} storageId {}",
getClass().getSimpleName(), countDownLatch.getCount(), uid, storageId);
return fjr;
}
}
/**
* 商家未完成订单数量
*/
... ... @@ -482,5 +537,4 @@ public class SellerOrderService implements IOrderListService, IOrderDetailServi
return total;
}
}
... ...
... ... @@ -5,6 +5,7 @@ import com.yohoufo.dal.order.SkupBatchMapper;
import com.yohoufo.dal.order.model.SkupBatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
... ... @@ -15,9 +16,11 @@ public class SkupBatchService {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private SkupBatchMapper skupBatchMapper;
public Long generateBatchNo(int uid, int num){
logger.info("in generateBatchNo uid {} num {}", uid, num);
SkupBatch record = new SkupBatch();
record.setUid(uid);
record.setNum(num);
... ...
... ... @@ -7,6 +7,7 @@ import com.yohoufo.dal.order.SkupBatchMapper;
import com.yohoufo.dal.order.model.SellerOrderGoods;
import com.yohobuy.ufo.model.order.common.SkupStatus;
import com.yohobuy.ufo.model.order.bo.GoodsInfo;
import com.yohoufo.order.convert.GoodsInfoConvertor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -14,6 +15,8 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* Created by chenchao on 2018/9/17.
*/
... ... @@ -33,39 +36,20 @@ public class SkupService {
@Database(ForceMaster=true, DataSource="ufo_order")
public SellerOrderGoods addSkup(GoodsInfo goodsInfo){
//validate data legal
SellerOrderGoods sellerOrderGoods = resp2Do4AddNew(goodsInfo);
//
sellerOrderGoodsMapper.insertSelective(sellerOrderGoods);
return sellerOrderGoods;
}
SellerOrderGoods sellerOrderGoods = GoodsInfoConvertor.resp2Do4AddNew(goodsInfo); //
/**
* StorageDataResp这个对象从商品取来,不论是否持久化,都应当有数据
* @param goodsInfo
* @return
*/
private SellerOrderGoods resp2Do4AddNew(GoodsInfo goodsInfo){
SellerOrderGoods sellerOrderGoods = new SellerOrderGoods();
//最关键的两个数据项
sellerOrderGoods.setUid(goodsInfo.getUid());
sellerOrderGoods.setStorageId(goodsInfo.getStorageId());
sellerOrderGoods.setStatus(SkupStatus.CAN_NOT_SELL.getCode());
sellerOrderGoods.setGoodsPrice(goodsInfo.getPrice());
//if not exist ,not
sellerOrderGoods.setProductId(goodsInfo.getProductId());
sellerOrderGoods.setProductName(goodsInfo.getProductName());
sellerOrderGoods.setColorId(goodsInfo.getColorId());
sellerOrderGoods.setColorName(goodsInfo.getColorName());
sellerOrderGoods.setSizeId(goodsInfo.getSizeId());
sellerOrderGoods.setSizeName(goodsInfo.getSizeName());
sellerOrderGoods.setImageUrl(goodsInfo.getImageUrl());
sellerOrderGoodsMapper.insertSelective(sellerOrderGoods);
return sellerOrderGoods;
}
public void batchPublishPrds(SellerOrderSubmitReq req){
public int batchAddSkup(List<SellerOrderGoods> sogList){
logger.info("in batchAddSameSkup, storage id {} size {}", sogList.get(0).getStorageId(), sogList.size());
int result = 0;
for(SellerOrderGoods sog : sogList){
result += sellerOrderGoodsMapper.insertSelective(sog);
}
return result;
}
... ...
... ... @@ -49,33 +49,31 @@ public class SellerOrderPrepareProcessor {
@Autowired
private SellerWalletMapper sellerWalletMapper;
public SellerOrderContext buildBatchSellerOrderContext(SellerOrderSubmitReq req) throws GatewayException {
public SellerOrderContext buildPublishPrdCtx(SellerOrderSubmitReq req) throws GatewayException {
SellerOrderContext ctx = buildSellerOrderContext(req);
int uid = ctx.getUid();
boolean isEntryShop = userProxyService.isEntryShop(uid);
ctx.setEntryShop(isEntryShop);
if (isEntryShop){
buildBatchSellerOrderContext(req,ctx);
}
return ctx;
}
public void buildBatchSellerOrderContext(SellerOrderSubmitReq req, SellerOrderContext ctx) throws GatewayException {
int storageId = ctx.getStorageId();
int uid = ctx.getUid();
int storageNum = req.getNum();
if (storageNum <=0){
log.warn("in buildBatchSellerOrderContext storageNum illegal , uid {}, storageId {} storageNum {}",
uid, storageId, storageNum);
throw new ServiceException(ServiceError.ORDER_ORDERS_GOODS_IS_EMPTY);
throw new ServiceException(ServiceError.SELLER_PUBLISH_PRD_NUM_ILLEGAL);
}
//step 1: rpc get product detail by storage id
//ufo.product.storage.data
GoodsInfo goodsInfo = getProductDetail(ctx);
//step 2: generate skup ,action :set price status(unsaleable)
if (Objects.isNull(goodsInfo)){
log.warn("in buildBatchSellerOrderContext storageId not exist in prd , uid {}, storageId {}", uid, storageId);
throw new ServiceException(ServiceError.ORDER_ORDERS_GOODS_IS_EMPTY);
}
GoodsInfo goodsInfo = ctx.getSoldProduct();
goodsInfo.setStorageNum(storageNum);
ctx.setSoldProduct(goodsInfo);
checkPrice(storageId, goodsInfo.getPrice(), true);
// compute every fee from price
SellerOrderComputeResult computeResult = computeHandler.compute(goodsInfo.getPrice());
checkIncome(storageId, computeResult.getIncome());
checkNGetMergeEarnestMoney(uid, computeResult, storageNum, goodsInfo.getPrice());
return ctx;
}
... ... @@ -133,6 +131,22 @@ public class SellerOrderPrepareProcessor {
//
context.setBackAddress(noHiddenBackAddress);
context.setBackHiddenAddress(hiddenBackAddress);
//step 1: rpc get product detail by storage id
//ufo.product.storage.data
GoodsInfo goodsInfo = getProductDetail(context);
//step 2: generate skup ,action :set price status(unsaleable)
if (Objects.isNull(goodsInfo)){
log.warn("in buildSellerOrderContext storageId not exist in prd service , uid {}, storageId {}", uid, storageId);
throw new ServiceException(ServiceError.ORDER_ORDERS_GOODS_IS_EMPTY);
}
context.setSoldProduct(goodsInfo);
checkPrice(storageId, goodsInfo.getPrice(), true);
// compute every fee from price
SellerOrderComputeResult computeResult = computeHandler.compute(goodsInfo.getPrice());
checkIncome(storageId, computeResult.getIncome());
log.info("in buildSellerOrderContext , uid {}, storageId {}, price {}, computeResult {}", uid, storageId,
goodsInfo.getPrice(), computeResult);
context.setSellerOrderComputeResult(computeResult);
return context;
}
... ...
package com.yohoufo.order.service.pay.wallet;
import java.math.BigDecimal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.fastjson.JSONObject;
import com.yohobuy.ufo.model.order.bo.OrderInfo;
import com.yohoufo.dal.order.model.SellerWallet;
import com.yohoufo.dal.order.model.SellerWalletDetail;
import com.yohoufo.order.constants.RefundContant;
import com.yohoufo.order.model.PayQueryBo;
import com.yohoufo.order.model.PayRefundBo;
import com.yohoufo.order.service.IPaymentService;
import com.yohoufo.order.service.MerchantOrderPaymentService;
import com.yohoufo.order.service.pay.AbstractPayService;
import org.springframework.stereotype.Service;
@Service
public class WalletPayService extends AbstractPayService {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
IPaymentService paymentService;
@Autowired
MerchantOrderPaymentService merchantOrderPaymentService;
public JSONObject prepayRequest(OrderInfo orderInfo) {
return null;
}
/**
* 查询订单支付结果
* @param orderCode
* @return
*/
public PayQueryBo payQuery(String orderCode) {
return null;
}
public PayRefundBo refundOpenApi(PayRefundBo refundBo) {
try {
BigDecimal amount = new BigDecimal(Double.toString(refundBo.getAmount()));
SellerWallet sw = merchantOrderPaymentService.refundEarnest(refundBo.getUid(), amount);
if (sw == null) {
refundBo.setRefundStatus(RefundContant.PAYMENT_REFUND_RESULTCODE_REQERR);
refundBo.setRefundMsg("钱包退款请求失败");
return refundBo;
}
SellerWalletDetail swd = merchantOrderPaymentService.refundEarnestDetail(sw, refundBo.getPayOrderCode(), amount, 0);
refundBo.setSerialNo(Integer.toString(swd.getId()));
refundBo.setRefundOrderCode(Integer.toString(sw.getId()));
return refundBo;
} catch (Exception e) {
logger.error("钱包退款失败msg=" + e.getMessage() + ",refundBo=" + refundBo, e);
refundBo.setRefundStatus(RefundContant.PAYMENT_REFUND_RESULTCODE_REQERR);
refundBo.setRefundMsg("钱包退款请求失败");
return refundBo;
}
}
}
... ...
... ... @@ -10,12 +10,15 @@ import com.yohoufo.product.model.ProductInfo;
import com.yohoufo.product.request.StoragePriceBo;
import com.yohoufo.product.response.ProductDetailResp;
import com.yohoufo.product.response.StorageDataResp;
import io.protostuff.LimitedInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
... ... @@ -43,9 +46,6 @@ public class ProductProxyService {
*/
private final static String RETURN_STORAGE = "ufo.product.cancelSaleSkup";
@Autowired
private SellerOrderGoodsMapper sogMapper;
public boolean subtractStorage(Integer productId, Integer skup){
... ... @@ -174,4 +174,50 @@ public class ProductProxyService {
ApiResponse resp = ufoServiceCaller.call(syncSkup, skupReq);
return (null == resp || null == resp.getData())? false : (boolean)resp.getData();
}
static String batchCreateSkup = "ufo.product.batchCreateSkup";
static String sellerBatchUpdateStatus = "ufo.product.sellerBatchUpdateStatus";
public boolean batchCreateSkup(List<SellerOrderGoods> sogList){
List<StoragePriceBo> skupBoList = new ArrayList<>(sogList.size());
List<Integer> skupList = new ArrayList<>(sogList.size());
for(SellerOrderGoods goods : sogList){
StoragePriceBo skupReq = new StoragePriceBo();
skupReq.setSkup(goods.getId());
skupReq.setProductId(goods.getProductId());
skupReq.setGoodsId(goods.getColorId());
skupReq.setStorageId(goods.getStorageId());
skupReq.setPrice(goods.getGoodsPrice());
skupReq.setSellerUid(goods.getUid());
skupBoList.add(skupReq);
skupList.add(goods.getId());
}
ApiResponse resp = ufoServiceCaller.call(batchCreateSkup, skupBoList);
logger.info("call {} resp {}", batchCreateSkup, resp);
return (null == resp || null == resp.getData())? false : (boolean)resp.getData();
}
public enum PrdShelvelStatus{
on(1),off(2);
int code;
PrdShelvelStatus(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
public boolean sellerBatchUpdateStatus(List<Integer> skupList, PrdShelvelStatus prdShelvelStatus){
ApiResponse resp = ufoServiceCaller.call(sellerBatchUpdateStatus, skupList, prdShelvelStatus.code);
logger.info("call {} skupList {} resp {}", sellerBatchUpdateStatus, skupList, resp);
return (null == resp || null == resp.getData())? false : (boolean)resp.getData();
}
}
... ...
... ... @@ -141,7 +141,7 @@ public class UserProxyService {
public boolean isEntryShop(int uid){
//入驻商户 method=ufo.user.isStoredSeller ,入参 uid
ApiResponse userInfo ;
com.yoho.tools.common.beans.ApiResponse userInfo ;
try {
userInfo = ufoServiceCaller.call("ufo.user.isStoredSeller", uid);
}catch (Exception ex){
... ...
... ... @@ -216,7 +216,7 @@ public class ProductController {
@RequestParam(value = "status", required = true) Integer status){
LOG.info("in method=ufo.product.sellerBatchUpdateStatus skupList is {}, status is {}", skupList, status);
int dbStatus = 1;//上架
if(1 != status.intValue() && 2 != status.intValue()) {
if(!(1 == status.intValue() || 2 == status.intValue())) {
throw new ServiceException(400, "status值不对,只能传1或2!");
}
//下架
... ...
... ... @@ -52,6 +52,9 @@ datasources:
- com.yohoufo.dal.order.OrdersPayTransferMapper
- com.yohoufo.dal.order.ManualTransferMapper
- com.yohoufo.dal.order.MachineIdGenerateMapper
- com.yohoufo.dal.order.SkupBatchMapper
- com.yohoufo.dal.order.SellerWalletMapper
- com.yohoufo.dal.order.SellerWalletDetailMapper
ufo_promotion:
servers:
... ...
... ... @@ -52,6 +52,9 @@ datasources:
- com.yohoufo.dal.order.OrdersPayTransferMapper
- com.yohoufo.dal.order.ManualTransferMapper
- com.yohoufo.dal.order.MachineIdGenerateMapper
- com.yohoufo.dal.order.SkupBatchMapper
- com.yohoufo.dal.order.SellerWalletMapper
- com.yohoufo.dal.order.SellerWalletDetailMapper
ufo_promotion:
servers:
... ...