Kaynağa Gözat

佣金计算提交

yuhongqi 1 ay önce
ebeveyn
işleme
4526c16d80

+ 1 - 1
fs-api/src/main/java/com/fs/app/controller/PayController.java

@@ -275,7 +275,7 @@ public class PayController {
                 case "payment":
                     storePaymentService.refund(orderIds[1]);
                     return "success";
-                case "live":
+                case "refundLive":
                     LiveOrderPayment liveOrderPayment = liveOrderPaymentMapper.selectLiveOrderPaymentByPaymentCode(orderIds[1]);
                     if(liveOrderPayment!=null){
                         liveOrderPayment.setRefundMoney(BigDecimal.valueOf(Double.parseDouble(dto.getAmount())));

+ 1 - 1
fs-company/src/main/java/com/fs/company/controller/live/LiveController.java

@@ -319,7 +319,7 @@ public class LiveController extends BaseController
         String scene = "a="+ liveId+"&b="+user.getCompanyId()+"&c="+user.getUserId();
         jsonMap.put("scene",scene);
         //正式版为 "release",体验版为 "trial",开发版为 "develop"
-        jsonMap.put("env_version","trial");
+        jsonMap.put("env_version","release");
         byte[] bytes = HttpUtils.getWechatQrcodeByHttpURL(codeUrl, jsonMap);
         if(bytes.length == 0) return R.error("生成二维码失败");
         if (bytes.length > 0 && bytes.length < 500) {

+ 34 - 0
fs-company/src/main/java/com/fs/company/controller/live/LiveProfitController.java

@@ -0,0 +1,34 @@
+package com.fs.company.controller.live;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.live.service.ILiveUserFirstEntryService;
+import com.fs.live.vo.LiveUserFirstProfit;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * 业绩归属控制类Controller
+ *
+ * @author fs
+ * @date 2025-09-08
+ */
+@RestController
+@RequestMapping("/live/liveProfit")
+public class LiveProfitController extends BaseController {
+
+    @Autowired
+    private ILiveUserFirstEntryService liveUserFirstEntryService;
+
+    @GetMapping("/list")
+    public TableDataInfo list() {
+        startPage();
+        List<LiveUserFirstProfit> list = liveUserFirstEntryService.selectLiveProfitList();
+        return getDataTable(list);
+    }
+
+}

+ 3 - 0
fs-service-system/src/main/java/com/fs/company/service/ICompanyService.java

@@ -7,6 +7,7 @@ import com.fs.company.domain.Company;
 import com.fs.company.param.CompanyParam;
 import com.fs.company.vo.CompanyCrmVO;
 import com.fs.company.vo.CompanyVO;
+import com.fs.live.domain.LiveOrder;
 import com.fs.store.domain.FsStoreOrder;
 import com.fs.store.domain.FsStorePayment;
 import org.apache.ibatis.annotations.Param;
@@ -96,4 +97,6 @@ public interface ICompanyService
     List<Long> selectCompanyByOmsCode(String omsCode);
 
     Company selectCompanyByIdForUpdate(Long companyId);
+
+    void addCompanyTuiLiveMoney(LiveOrder order);
 }

+ 28 - 0
fs-service-system/src/main/java/com/fs/company/service/impl/CompanyServiceImpl.java

@@ -13,6 +13,8 @@ import com.fs.company.param.CompanyParam;
 import com.fs.company.service.ICompanyProfitService;
 import com.fs.company.vo.CompanyCrmVO;
 import com.fs.company.vo.CompanyVO;
+import com.fs.live.domain.LiveOrder;
+import com.fs.live.service.ILiveOrderService;
 import com.fs.store.config.StoreConfig;
 import com.fs.store.domain.FsStoreOrder;
 import com.fs.store.domain.FsStorePayment;
@@ -62,6 +64,8 @@ public class CompanyServiceImpl implements ICompanyService
     private FsStoreOrderMapper storeOrderMapper;
     @Autowired
     private ICompanyProfitService companyProfitService;
+    @Autowired
+    private ILiveOrderService liveOrderService;
 
 
     /**
@@ -240,6 +244,28 @@ public class CompanyServiceImpl implements ICompanyService
         }
     }
 
+    @Override
+    @Transactional
+    public void addCompanyTuiLiveMoney(LiveOrder order) {
+        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
+            Company company=companyMapper.selectCompanyByIdForUpdate(order.getCompanyId());
+            if(company!=null){
+                String json =configService.selectConfigByKey("store.config");
+                StoreConfig config= JSONUtil.toBean(json,StoreConfig.class);
+                //支付金额-(订单金额*rate%)
+                Double rate=config.getTuiMoneyRate()/100d;
+                BigDecimal tuiMoney=order.getPayPrice().subtract(order.getTotalPrice().multiply(new BigDecimal(rate)));
+                logger.info("写入公司推广佣金:"+tuiMoney);
+                company.setTuiMoney(company.getTuiMoney().add(tuiMoney));
+                companyMapper.updateCompany(company);
+                LiveOrder liveOrderMap=new LiveOrder();
+                liveOrderMap.setOrderId(order.getOrderId());
+                liveOrderMap.setTuiMoney(tuiMoney);
+                liveOrderService.updateLiveOrder(liveOrderMap);
+            }
+        }
+    }
+
     @Override
     @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
     public void addCompanyMoney(FsStoreOrder order) {
@@ -415,4 +441,6 @@ public class CompanyServiceImpl implements ICompanyService
     public Company selectCompanyByIdForUpdate(Long companyId) {
         return companyMapper.selectCompanyByIdForUpdate(companyId);
     }
+
+
 }

+ 6 - 0
fs-service-system/src/main/java/com/fs/live/mapper/LiveUserFirstEntryMapper.java

@@ -2,6 +2,7 @@ package com.fs.live.mapper;
 
 
 import com.fs.live.domain.LiveUserFirstEntry;
+import com.fs.live.vo.LiveUserFirstProfit;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 
@@ -65,4 +66,9 @@ public interface LiveUserFirstEntryMapper {
 
     @Select("select count(*) from live_user_first_entry where user_id=#{userId} and DATE(entry_date)=DATE(#{now})")
     int selectTodayEntry(@Param("userId") long userId,@Param("now") Date now);
+
+    List<LiveUserFirstProfit> selectLiveProfitList();
+
+    @Select("select * from live_user_first_entry where live_id=#{liveId} and user_id=#{userId}")
+    LiveUserFirstEntry selectEntityByLiveIdUserId(@Param("liveId") long liveId,@Param("userId") long userId);
 }

+ 5 - 0
fs-service-system/src/main/java/com/fs/live/service/ILiveUserFirstEntryService.java

@@ -2,6 +2,7 @@ package com.fs.live.service;
 
 
 import com.fs.live.domain.LiveUserFirstEntry;
+import com.fs.live.vo.LiveUserFirstProfit;
 
 import java.util.List;
 
@@ -61,4 +62,8 @@ public interface ILiveUserFirstEntryService {
     int deleteLiveUserFirstEntryById(Long id);
 
     int selectTodayEntry(long userId);
+
+    List<LiveUserFirstProfit> selectLiveProfitList();
+
+    LiveUserFirstEntry selectEntityByLiveIdUserId(long liveId, long userId);
 }

+ 24 - 1
fs-service-system/src/main/java/com/fs/live/service/impl/LiveOrderServiceImpl.java

@@ -53,6 +53,7 @@ import com.fs.live.param.FsUserLiveOrderPayUParam;
 import com.fs.live.param.LiveOrderConfirmParam;
 import com.fs.live.param.LiveOrderFinishParam;
 import com.fs.live.service.ILiveOrderLogsService;
+import com.fs.live.service.ILiveUserFirstEntryService;
 import com.fs.live.vo.LiveGoodsVo;
 import com.fs.live.vo.LiveOrderItemVo;
 import com.fs.live.vo.LiveOrderListVo;
@@ -207,6 +208,10 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     @Autowired
     private LiveOrderMapper liveOrderMapper;
 
+    @Autowired
+    private ILiveUserFirstEntryService liveUserFirstEntryService;
+
+
     public LiveOrderServiceImpl(RedisCache redisCache) {
         this.redisCache = redisCache;
     }
@@ -527,6 +532,18 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                 return "";
             }
 
+            // 佣金处理
+            if (order.getCompanyUserId() == -1L) {
+                companyService.addCompanyTuiLiveMoney(order);
+            } else {
+                // 目前是一级佣金
+                FsStoreProduct product = JSONUtil.toBean(order.getItemJson(), FsStoreProduct.class);
+                List<FsStoreProductAttrValue> productAttrValues = fsStoreProductAttrValueMapper.selectFsStoreProductAttrValueByProductId(product.getProductId());
+                if (productAttrValues != null && !productAttrValues.isEmpty()) {
+                    userService.addTuiLiveMoney(order, productAttrValues);
+                }
+            }
+
             //增加用户购买次数
             userService.incPayCount(Long.valueOf(order.getUserId()));
 
@@ -549,6 +566,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
     }
 
     @Override
+    @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
     public R wxPayment(FsUserLiveOrderPayUParam param) {
         LiveOrder order = baseMapper.selectLiveOrderByOrderId(String.valueOf(param.getOrderId()));
         if (order == null) {
@@ -839,7 +857,7 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
                     payProcessContext.setPaymentId(payment.getPaymentId());
                     payProcessContext.setPayCode(payment.getPayCode());
                     payProcessContext.setUserId(Long.valueOf(order.getUserId()));
-                    payProcessContext.setOrderPrefix("refund-");
+                    payProcessContext.setOrderPrefix("refundLive-");
                     best.refundLiveOrder(payProcessContext);
                 }
             }
@@ -1577,6 +1595,11 @@ public class LiveOrderServiceImpl implements ILiveOrderService {
             liveOrder.setStoreHouseCode("CQDS001");
         }
 
+        LiveUserFirstEntry liveUserFirstEntry = liveUserFirstEntryService.selectEntityByLiveIdUserId(liveOrder.getLiveId(), Long.parseLong(liveOrder.getUserId()));
+        liveOrder.setCompanyId(liveUserFirstEntry.getCompanyId());
+        liveOrder.setCompanyUserId(liveUserFirstEntry.getCompanyUserId());
+        liveOrder.setTuiUserId(liveUserFirstEntry.getCompanyUserId());
+
         String orderSn = SnowflakeUtils.nextId();
         log.info("订单生成:"+orderSn);
         liveOrder.setOrderCode(orderSn);

+ 12 - 0
fs-service-system/src/main/java/com/fs/live/service/impl/LiveUserFirstEntryServiceImpl.java

@@ -1,9 +1,11 @@
 package com.fs.live.service.impl;
 
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import com.fs.common.utils.DateUtils;
 
+import com.fs.live.vo.LiveUserFirstProfit;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.fs.live.mapper.LiveUserFirstEntryMapper;
@@ -100,4 +102,14 @@ public class LiveUserFirstEntryServiceImpl implements ILiveUserFirstEntryService
         Date now = DateUtils.getNowDate();
         return baseMapper.selectTodayEntry(userId, now);
     }
+
+    @Override
+    public List<LiveUserFirstProfit> selectLiveProfitList() {
+        return baseMapper.selectLiveProfitList();
+    }
+
+    @Override
+    public LiveUserFirstEntry selectEntityByLiveIdUserId(long liveId,long userId) {
+        return baseMapper.selectEntityByLiveIdUserId(liveId, userId);
+    }
 }

+ 48 - 0
fs-service-system/src/main/java/com/fs/live/vo/LiveUserFirstProfit.java

@@ -0,0 +1,48 @@
+package com.fs.live.vo;
+
+import com.fs.common.annotation.Excel;
+import com.fs.common.core.domain.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.math.BigDecimal;
+
+/**
+ * 用户每日首次进入直播间记录对象 live_user_first_entry
+ *
+ * @author fs
+ * @date 2025-09-04
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class LiveUserFirstProfit extends BaseEntity{
+
+    /** 主键ID */
+    private Long orderId;
+
+
+    private String orderCode;
+
+
+    private String userName;
+
+
+    private String userPhone;
+
+
+    private BigDecimal totalPrice;
+    private BigDecimal payPrice;
+
+    /** 支付状态 待支付 1已支付 */
+    @Excel(name = "支付状态 待支付 1已支付")
+    private String isPay;
+
+    /** 订单状态(-1 : 申请退款 -2 : 退货成功 0:已取消 1:待支付 2:待发货;3:待收货;4:待评价;5:已完成) */
+    @Excel(name = "订单状态", readConverterExp = "-=1,:=,申=请退款,-=2,:=,退=货成功,1=:待支付,2=:待发货;3:待收货;4:待评价;5:已完成")
+    private Integer status;
+
+    private Long companyUserId;
+    private String companyUserName;
+    private String companyName;
+
+}

+ 4 - 0
fs-service-system/src/main/java/com/fs/store/service/IFsUserService.java

@@ -5,8 +5,10 @@ import java.util.List;
 import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
 import com.fs.common.core.domain.R;
 import com.fs.live.domain.LiveOrder;
+import com.fs.live.domain.LiveOrderItem;
 import com.fs.store.domain.FsStoreOrder;
 import com.fs.store.domain.FsStoreOrderItem;
+import com.fs.store.domain.FsStoreProductAttrValue;
 import com.fs.store.domain.FsUser;
 
 import com.fs.store.param.LoginMpWxParam;
@@ -129,4 +131,6 @@ public interface IFsUserService
     void incrIntegral(List<Long> userIds, Long scoreAmount);
 
     void subLiveTuiMoney(LiveOrder order);
+
+    void addTuiLiveMoney(LiveOrder order, List<FsStoreProductAttrValue> productAttrValues);
 }

+ 21 - 4
fs-service-system/src/main/java/com/fs/store/service/impl/FsUserServiceImpl.java

@@ -15,9 +15,8 @@ import com.fs.common.core.domain.R;
 import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.IpUtil;
 import com.fs.live.domain.LiveOrder;
-import com.fs.store.domain.FsStoreOrder;
-import com.fs.store.domain.FsStoreOrderItem;
-import com.fs.store.domain.FsUserBill;
+import com.fs.live.domain.LiveOrderItem;
+import com.fs.store.domain.*;
 import com.fs.store.dto.FsStoreCartDTO;
 import com.fs.store.enums.BillDetailEnum;
 import com.fs.store.mapper.FsStoreOrderMapper;
@@ -44,7 +43,6 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import com.fs.store.mapper.FsUserMapper;
-import com.fs.store.domain.FsUser;
 import com.fs.store.service.IFsUserService;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -204,6 +202,25 @@ public class FsUserServiceImpl implements IFsUserService
         return fsUserMapper.selectFsUserCount(type,companyId);
     }
 
+    @Override
+    @Transactional
+    public void addTuiLiveMoney(LiveOrder order, List<FsStoreProductAttrValue> productAttrValues) {
+        BigDecimal brokerage=BigDecimal.ZERO;
+        //返佣金
+        FsUser user= fsUserMapper.selectFsUserById(order.getCompanyUserId());
+        for (FsStoreProductAttrValue productAttrValue : productAttrValues) {
+            brokerage=brokerage.add(productAttrValue.getBrokerage().multiply(new BigDecimal(order.getTotalNum())));
+        }
+        if(brokerage.compareTo(BigDecimal.ZERO)==1){
+            FsUser tuiUserMap=new FsUser();
+            tuiUserMap.setUserId(user.getUserId());
+            tuiUserMap.setBrokeragePrice(user.getBrokeragePrice().add(brokerage));
+            fsUserMapper.updateFsUser(tuiUserMap);
+            logger.info("拿一级佣金:"+tuiUserMap.getUserId()+":"+brokerage);
+            billService.addBill(tuiUserMap.getUserId(), CATEGORY_3.getValue(),1,BillDetailEnum.TYPE_5.getDesc(),brokerage.doubleValue(),tuiUserMap.getBrokeragePrice().doubleValue(),"订单返佣金",order.getOrderId().toString(),order.getCompanyUserId());
+        }
+    }
+
     @Override
     @Transactional
     public void     addTuiMoney(FsStoreOrder order , List<FsStoreOrderItem> items) {

+ 20 - 0
fs-service-system/src/main/resources/mapper/live/LiveUserFirstEntryMapper.xml

@@ -86,4 +86,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{id}
         </foreach>
     </delete>
+
+    <select id="selectLiveProfitList"  resultType="com.fs.live.vo.LiveUserFirstProfit">
+        SELECT
+            lo.order_id,lo.order_code,lo.user_name,lo.user_phone,lo.total_price,lo.pay_price,lo.is_pay,lo.status,
+            cu.user_id AS company_user_id,
+            cu.nick_name AS company_user_name,
+            c.company_name
+        FROM
+            live_order lo
+                LEFT JOIN
+            live_user_first_entry lufe
+            ON lo.user_id = lufe.user_id
+                AND DATE(lo.create_time) = lufe.entry_date
+            LEFT JOIN
+            company_user cu
+        ON lufe.company_user_id = cu.user_id
+            left join company c on cu.company_id = c.company_id
+        ORDER BY
+            lo.create_time DESC
+    </select>
 </mapper>

+ 23 - 8
fs-user-app/src/main/java/com/fs/app/websocket/service/WebSocketServer.java

@@ -63,17 +63,19 @@ public class WebSocketServer {
         long liveId = (long) userProperties.get("liveId");
         long userId = (long) userProperties.get("userId");
         long userType = (long) userProperties.get("userType");
-        long companyId = 0L;
-        long companyUserId = 0L;
+        Live live = liveService.selectLiveByLiveId(liveId);
+        if (live == null) {
+            throw new BaseException("未找到直播间");
+        }
+        long companyId = live.getCompanyId();
+        long companyUserId = -1L;
         if (!Objects.isNull(userProperties.get("companyId"))) {
             companyId = (long) userProperties.get("companyId");
         }
         if (!Objects.isNull(userProperties.get("companyUserId"))) {
             companyUserId = (long) userProperties.get("companyUserId");
         }
-        if (liveService.selectLiveByLiveId(liveId) == null) {
-            throw new BaseException("未找到直播间");
-        }
+
 
         ConcurrentHashMap<Long, Session> room = getRoom(liveId);
         List<Session> adminRoom = getAdminRoom(liveId);
@@ -125,10 +127,23 @@ public class WebSocketServer {
             sendMsgVo.setData(JSONObject.toJSONString(liveWatchUserVO));
             sendMsgVo.setNickName(fsUser.getNickname());
             sendMsgVo.setAvatar(fsUser.getAvatar());
-            int i = liveUserFirstEntryService.selectTodayEntry(userId);
-            if (!(i > 0)) {
+            LiveUserFirstEntry liveUserFirstEntry = liveUserFirstEntryService.selectEntityByLiveIdUserId(liveId, userId);
+            if (liveUserFirstEntry != null) {
+                // 处理第一次自己进入,第二次扫码销售进入
+                if (liveUserFirstEntry.getCompanyUserId() == -1L && companyUserId != -1L) {
+                    liveUserFirstEntry.setCompanyId(companyId);
+                    liveUserFirstEntry.setCompanyUserId(companyUserId);
+                    liveUserFirstEntryService.updateLiveUserFirstEntry(liveUserFirstEntry);
+                }
+            } else {
+                // 这个用户A邀请用户b,b的业绩算a的销售的
+                if (companyUserId == -2L) {
+                    LiveUserFirstEntry clientB = liveUserFirstEntryService.selectEntityByLiveIdUserId(liveId, companyUserId);
+                    companyId = clientB.getCompanyId();
+                    companyUserId = clientB.getCompanyUserId();
+                }
                 Date date = new Date();
-                LiveUserFirstEntry liveUserFirstEntry = new LiveUserFirstEntry();
+                liveUserFirstEntry = new LiveUserFirstEntry();
                 liveUserFirstEntry.setUserId(userId);
                 liveUserFirstEntry.setLiveId(liveId);
                 liveUserFirstEntry.setCompanyId(companyId);