Browse Source

Merge remote-tracking branch 'origin/master'

liweifan 3 years ago
parent
commit
1bc85d7811
38 changed files with 627 additions and 258 deletions
  1. 33 9
      cooleshow-mall/mall-admin/src/main/java/com/yonge/cooleshow/admin/service/impl/OmsOrderReturnApplyServiceImpl.java
  2. 5 6
      cooleshow-mall/mall-admin/src/main/java/com/yonge/cooleshow/admin/service/impl/PmsProductServiceImpl.java
  3. 1 0
      cooleshow-mall/mall-admin/src/main/resources/config/mybatis/PmsProductDao.xml
  4. 4 0
      cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/mapper/PmsProductMapper.java
  5. 8 0
      cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/mapper/UserOrderPaymentMapper.java
  6. 2 0
      cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/mapper/UserOrderRefundMapper.java
  7. 11 0
      cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/model/PmsProduct.java
  8. 26 3
      cooleshow-mall/mall-mbg/src/main/resources/config/mybatis/PmsProductMapper.xml
  9. 7 1
      cooleshow-mall/mall-mbg/src/main/resources/config/mybatis/UserOrderPaymentMapper.xml
  10. 7 0
      cooleshow-mall/mall-mbg/src/main/resources/config/mybatis/UserOrderRefundMapper.xml
  11. 1 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/component/CancelOrderReceiver.java
  12. 1 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/controller/OmsPortalOrderController.java
  13. 6 0
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/dao/PortalProductDao.java
  14. 29 0
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/domain/ProductStock.java
  15. 1 0
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/dto/OrderPayReq.java
  16. 1 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/OmsPortalOrderService.java
  17. 9 3
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/UserOrderPaymentService.java
  18. 15 10
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderReturnApplyServiceImpl.java
  19. 108 33
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderServiceImpl.java
  20. 39 10
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPromotionServiceImpl.java
  21. 8 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/UserOrderPaymentServiceImpl.java
  22. 1 0
      cooleshow-mall/mall-portal/src/main/resources/config/mybatis/PortalOrderDao.xml
  23. 21 5
      cooleshow-mall/mall-portal/src/main/resources/config/mybatis/PortalProductDao.xml
  24. 4 3
      cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/SmsCodeController.java
  25. 2 5
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleDao.java
  26. 15 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleStudentDao.java
  27. 12 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CourseSchedule.java
  28. 3 3
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CourseScheduleStudent.java
  29. 5 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CourseScheduleService.java
  30. 2 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/SmsCodeService.java
  31. 171 142
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseScheduleServiceImpl.java
  32. 16 2
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/SmsCodeServiceImpl.java
  33. 5 6
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml
  34. 10 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleStudentMapper.xml
  35. 3 4
      cooleshow-user/user-biz/src/main/resources/config/mybatis/UserBindingTeacherMapper.xml
  36. 4 3
      cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/SmsCodeController.java
  37. 4 3
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/SmsCodeController.java
  38. 27 0
      cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherCourseScheduleController.java

+ 33 - 9
cooleshow-mall/mall-admin/src/main/java/com/yonge/cooleshow/admin/service/impl/OmsOrderReturnApplyServiceImpl.java

@@ -8,15 +8,13 @@ import com.yonge.cooleshow.admin.dto.OmsOrderReturnApplyResult;
 import com.yonge.cooleshow.admin.dto.OmsReturnApplyQueryParam;
 import com.yonge.cooleshow.admin.dto.OmsUpdateStatusParam;
 import com.yonge.cooleshow.mall.common.exception.ApiException;
+import com.yonge.cooleshow.mall.common.service.RedisService;
+import com.yonge.cooleshow.mbg.model.*;
 import com.yonge.toolset.base.exception.BizException;
 import com.yonge.cooleshow.mbg.mapper.OmsOrderReturnApplyMapper;
 import com.yonge.cooleshow.mbg.mapper.UserOrderPaymentMapper;
 import com.yonge.cooleshow.mbg.mapper.UserOrderRefundMapper;
-import com.yonge.cooleshow.mbg.model.OmsOrderReturnApply;
-import com.yonge.cooleshow.mbg.model.OmsOrderReturnApplyExample;
 import com.yonge.cooleshow.admin.service.OmsOrderReturnApplyService;
-import com.yonge.cooleshow.mbg.model.UserOrderPayment;
-import com.yonge.cooleshow.mbg.model.UserOrderRefund;
 import com.yonge.toolset.base.result.BaseResult;
 import com.yonge.toolset.payment.base.enums.OpenEnum;
 import com.yonge.toolset.payment.base.enums.PayChannelEnum;
@@ -31,6 +29,7 @@ import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.List;
 
@@ -49,6 +48,10 @@ public class OmsOrderReturnApplyServiceImpl implements OmsOrderReturnApplyServic
     private OmsOrderReturnApplyMapper returnApplyMapper;
 
     @Autowired
+    private RedisService redisService;
+    private String REDIS_KEY_ORDER_ID= "redis.key.orderId";
+    private String REDIS_DATABASE = "redis.database";
+    @Autowired
     private PaymentClient paymentClient;
 
     @Autowired
@@ -119,10 +122,11 @@ public class OmsOrderReturnApplyServiceImpl implements OmsOrderReturnApplyServic
         if (userOrderPayment == null) {
             throw new ApiException("未找到付款信息");
         }
+        String orderSn = generateOrderSn(returnApply);
 
         RefundBill refundReq = new RefundBill(OpenEnum.valueOf(userOrderPayment.getOpenType()),
                 PaymentClientEnum.valueOf(userOrderPayment.getPaymentClient()), PayChannelEnum.valueOf(userOrderPayment.getPayChannel()));
-        refundReq.setRefundNo(returnApply.getOrderSn());
+        refundReq.setRefundNo(orderSn);
         refundReq.setRefundAmt(returnApply.getReturnAmount().setScale(2, RoundingMode.HALF_UP));
 
         refundReq.setReason(returnApply.getProductName());
@@ -133,10 +137,9 @@ public class OmsOrderReturnApplyServiceImpl implements OmsOrderReturnApplyServic
         if (refundBillBaseResult.getStatus()) {
             RefundBill refundBill = refundBillBaseResult.getData();
             UserOrderRefund userOrderRefund = new UserOrderRefund();
-
-            userOrderRefund.setOrderNo(refundBill.getRefundNo());
-            userOrderRefund.setTransNo(refundBill.getId());
-            userOrderRefund.setPayTransNo(refundBill.getTradeNo());
+            userOrderRefund.setReturnId(returnApply.getId());
+            userOrderRefund.setOrderNo(orderSn);
+            userOrderRefund.setPayTransNo(userOrderPayment.getTransNo());
             userOrderRefund.setRefundAmt(refundBill.getRefundAmt());
             userOrderRefund.setStatus(TradeStatusEnum.pending.getCode());
 
@@ -157,4 +160,25 @@ public class OmsOrderReturnApplyServiceImpl implements OmsOrderReturnApplyServic
 
         return returnApplyDao.selectReturnStatusCount();
     }
+
+
+    /**
+     * 生成18位退款订单编号:8位日期+2位平台号码+2位支付方式+6位以上自增id
+     */
+    private String generateOrderSn(OmsOrderReturnApply returnApply) {
+        StringBuilder sb = new StringBuilder();
+        String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
+        String key = REDIS_DATABASE+":"+ REDIS_KEY_ORDER_ID + date;
+        Long increment = redisService.incr(key, 1);
+        sb.append(date);
+        sb.append(String.format("%02d", returnApply.getStatus()));
+        sb.append(String.format("%02d", returnApply.getStatus()));
+        String incrementStr = increment.toString();
+        if (incrementStr.length() <= 6) {
+            sb.append(String.format("%06d", increment));
+        } else {
+            sb.append(incrementStr);
+        }
+        return sb.toString();
+    }
 }

+ 5 - 6
cooleshow-mall/mall-admin/src/main/java/com/yonge/cooleshow/admin/service/impl/PmsProductServiceImpl.java

@@ -71,12 +71,12 @@ public class PmsProductServiceImpl implements PmsProductService {
     public int create(PmsProductParam productParam) {
         int count;
         //创建商品
-        PmsProduct product = productParam;
-        product.setId(null);
-        product.setVerifyStatus(1);
-        productMapper.insertSelective(product);
+        productParam.setId(null);
+        productParam.setVerifyStatus(1);
+        productParam.setLockStock(0);
+        productMapper.insertSelective(productParam);
         //根据促销类型设置价格:会员价格、阶梯价格、满减价格
-        Long productId = product.getId();
+        Long productId = productParam.getId();
         //会员价格
         relateAndInsertList(memberPriceDao, productParam.getMemberPriceList(), productId);
         //阶梯价格
@@ -209,7 +209,6 @@ public class PmsProductServiceImpl implements PmsProductService {
     @Override
     public List<PmsProduct> list(PmsProductQueryParam productQueryParam, Integer pageSize, Integer pageNum) {
         PageHelper.startPage(pageNum, pageSize);
-
         return productDao.list(productQueryParam);
 
     }

+ 1 - 0
cooleshow-mall/mall-admin/src/main/resources/config/mybatis/PmsProductDao.xml

@@ -104,5 +104,6 @@
                 and (pp.stock &gt; pp.low_stock and b.product_id is null)
             </if>
         </where>
+        order by pp.sort desc,pp.id desc
     </select>
 </mapper>

+ 4 - 0
cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/mapper/PmsProductMapper.java

@@ -2,7 +2,9 @@ package com.yonge.cooleshow.mbg.mapper;
 
 import com.yonge.cooleshow.mbg.model.PmsProduct;
 import com.yonge.cooleshow.mbg.model.PmsProductExample;
+
 import java.util.List;
+
 import org.apache.ibatis.annotations.Param;
 
 public interface PmsProductMapper {
@@ -33,4 +35,6 @@ public interface PmsProductMapper {
     int updateByPrimaryKeyWithBLOBs(PmsProduct record);
 
     int updateByPrimaryKey(PmsProduct record);
+
+    int lockStock(@Param("productId") Long productId, @Param("sum") int sum);
 }

+ 8 - 0
cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/mapper/UserOrderPaymentMapper.java

@@ -24,4 +24,12 @@ public interface UserOrderPaymentMapper {
     UserOrderPayment selectByOrderNoAndStatusPaying(@Param("orderSn") String orderSn);
 
     UserOrderPayment selectByOrderNoAndStatusSucceeded(@Param("orderSn") String orderSn);
+
+    /**
+     * 查询支付信息
+     *
+     * @param paymentNo 回调支付订单号
+     * @return
+     */
+    UserOrderPayment selectByAdapayNo(String paymentNo);
 }

+ 2 - 0
cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/mapper/UserOrderRefundMapper.java

@@ -38,4 +38,6 @@ public interface UserOrderRefundMapper {
     int updateByPrimaryKey(UserOrderRefund record);
 
     UserOrderRefund selectByTransNo(@Param("transNo") String transNo);
+
+    UserOrderRefund selectByRefundNo(@Param("refundOrderNo") String refundOrderNo);
 }

+ 11 - 0
cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/model/PmsProduct.java

@@ -68,6 +68,9 @@ public class PmsProduct implements Serializable {
     @ApiModelProperty(value = "库存")
     private Integer stock;
 
+    @ApiModelProperty("锁定库存")
+    private Integer lockStock;
+
     @ApiModelProperty(value = "库存预警值")
     private Integer lowStock;
 
@@ -522,4 +525,12 @@ public class PmsProduct implements Serializable {
         sb.append("]");
         return sb.toString();
     }
+
+    public Integer getLockStock() {
+        return lockStock;
+    }
+
+    public void setLockStock(Integer lockStock) {
+        this.lockStock = lockStock;
+    }
 }

+ 26 - 3
cooleshow-mall/mall-mbg/src/main/resources/config/mybatis/PmsProductMapper.xml

@@ -25,6 +25,7 @@
     <result column="sub_title" jdbcType="VARCHAR" property="subTitle" />
     <result column="original_price" jdbcType="DECIMAL" property="originalPrice" />
     <result column="stock" jdbcType="INTEGER" property="stock" />
+    <result column="lock_stock" jdbcType="INTEGER" property="lockStock" />
     <result column="low_stock" jdbcType="INTEGER" property="lowStock" />
     <result column="unit" jdbcType="VARCHAR" property="unit" />
     <result column="weight" jdbcType="DECIMAL" property="weight" />
@@ -111,7 +112,7 @@
     verify_status, sort, sale, price, promotion_price, gift_growth, gift_point, use_point_limit, 
     sub_title, original_price, stock, low_stock, unit, weight, preview_status, service_ids, 
     keywords, note, album_pics, detail_title, promotion_start_time, promotion_end_time, 
-    promotion_per_limit, promotion_type, brand_name, product_category_name
+    promotion_per_limit, promotion_type, brand_name, product_category_name,lock_stock
   </sql>
   <sql id="Blob_Column_List">
     description, detail_desc, detail_html, detail_mobile_html
@@ -181,7 +182,7 @@
       detail_title, promotion_start_time, promotion_end_time, 
       promotion_per_limit, promotion_type, brand_name, 
       product_category_name, description, detail_desc, 
-      detail_html, detail_mobile_html)
+      detail_html, detail_mobile_html,lock_stock)
     values (#{brandId,jdbcType=BIGINT}, #{productCategoryId,jdbcType=BIGINT}, #{feightTemplateId,jdbcType=BIGINT}, 
       #{productAttributeCategoryId,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{pic,jdbcType=VARCHAR}, 
       #{productSn,jdbcType=VARCHAR}, #{deleteStatus,jdbcType=INTEGER}, #{publishStatus,jdbcType=INTEGER}, 
@@ -195,7 +196,7 @@
       #{detailTitle,jdbcType=VARCHAR}, #{promotionStartTime,jdbcType=TIMESTAMP}, #{promotionEndTime,jdbcType=TIMESTAMP}, 
       #{promotionPerLimit,jdbcType=INTEGER}, #{promotionType,jdbcType=INTEGER}, #{brandName,jdbcType=VARCHAR}, 
       #{productCategoryName,jdbcType=VARCHAR}, #{description,jdbcType=LONGVARCHAR}, #{detailDesc,jdbcType=LONGVARCHAR}, 
-      #{detailHtml,jdbcType=LONGVARCHAR}, #{detailMobileHtml,jdbcType=LONGVARCHAR})
+      #{detailHtml,jdbcType=LONGVARCHAR}, #{detailMobileHtml,jdbcType=LONGVARCHAR},#{lockStock})
   </insert>
   <insert id="insertSelective" parameterType="com.yonge.cooleshow.mbg.model.PmsProduct">
     <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
@@ -326,6 +327,10 @@
       <if test="detailMobileHtml != null">
         detail_mobile_html,
       </if>
+
+      <if test="lockStock != null">
+        lock_stock,
+      </if>
     </trim>
     <trim prefix="values (" suffix=")" suffixOverrides=",">
       <if test="brandId != null">
@@ -451,6 +456,10 @@
       <if test="detailMobileHtml != null">
         #{detailMobileHtml,jdbcType=LONGVARCHAR},
       </if>
+
+      <if test="lockStock != null">
+        #{lockStock,jdbcType=INTEGER},
+      </if>
     </trim>
   </insert>
   <select id="countByExample" parameterType="com.yonge.cooleshow.mbg.model.PmsProductExample" resultType="java.lang.Long">
@@ -588,6 +597,9 @@
       <if test="record.detailMobileHtml != null">
         detail_mobile_html = #{record.detailMobileHtml,jdbcType=LONGVARCHAR},
       </if>
+      <if test="record.lockStock != null">
+        lock_stock = #{record.lockStock},
+      </if>
     </set>
     <if test="_parameter != null">
       <include refid="Update_By_Example_Where_Clause" />
@@ -618,6 +630,7 @@
       sub_title = #{record.subTitle,jdbcType=VARCHAR},
       original_price = #{record.originalPrice,jdbcType=DECIMAL},
       stock = #{record.stock,jdbcType=INTEGER},
+      lock_stock = #{record.lockStock,jdbcType=INTEGER},
       low_stock = #{record.lowStock,jdbcType=INTEGER},
       unit = #{record.unit,jdbcType=VARCHAR},
       weight = #{record.weight,jdbcType=DECIMAL},
@@ -666,6 +679,7 @@
       sub_title = #{record.subTitle,jdbcType=VARCHAR},
       original_price = #{record.originalPrice,jdbcType=DECIMAL},
       stock = #{record.stock,jdbcType=INTEGER},
+      lock_stock = #{record.lockStock,jdbcType=INTEGER},
       low_stock = #{record.lowStock,jdbcType=INTEGER},
       unit = #{record.unit,jdbcType=VARCHAR},
       weight = #{record.weight,jdbcType=DECIMAL},
@@ -811,6 +825,9 @@
       <if test="detailMobileHtml != null">
         detail_mobile_html = #{detailMobileHtml,jdbcType=LONGVARCHAR},
       </if>
+      <if test="lockStock != null">
+        lock_stock = #{lockStock,jdbcType=INTEGER},
+      </if>
     </set>
     where id = #{id,jdbcType=BIGINT}
   </update>
@@ -838,6 +855,7 @@
       sub_title = #{subTitle,jdbcType=VARCHAR},
       original_price = #{originalPrice,jdbcType=DECIMAL},
       stock = #{stock,jdbcType=INTEGER},
+      lock_stock = #{lockStock,jdbcType=INTEGER},
       low_stock = #{lowStock,jdbcType=INTEGER},
       unit = #{unit,jdbcType=VARCHAR},
       weight = #{weight,jdbcType=DECIMAL},
@@ -883,6 +901,7 @@
       sub_title = #{subTitle,jdbcType=VARCHAR},
       original_price = #{originalPrice,jdbcType=DECIMAL},
       stock = #{stock,jdbcType=INTEGER},
+      lock_stock = #{lockStock,jdbcType=INTEGER},
       low_stock = #{lowStock,jdbcType=INTEGER},
       unit = #{unit,jdbcType=VARCHAR},
       weight = #{weight,jdbcType=DECIMAL},
@@ -900,4 +919,8 @@
       product_category_name = #{productCategoryName,jdbcType=VARCHAR}
     where id = #{id,jdbcType=BIGINT}
   </update>
+
+  <update id="lockStock">
+    update pms_product set lock_stock = lock_stock + #{sum} where  id = #{productId} and stock &gt;= ( lock_stock + #{sum})
+  </update>
 </mapper>

+ 7 - 1
cooleshow-mall/mall-mbg/src/main/resources/config/mybatis/UserOrderPaymentMapper.xml

@@ -258,7 +258,7 @@
     <select id="selectByOrderNoAndStatusPaying" resultMap="BaseResultMap">
         select
         <include refid="Base_Column_List" />
-        from user_order_payment where order_no_ = #{orderSn} and status_ = 'paying'
+        from user_order_payment where order_no_ = #{orderSn} and status_ = 'pending'
     </select>
 
     <select id="selectByOrderNoAndStatus" resultMap="BaseResultMap">
@@ -273,4 +273,10 @@
         <include refid="Base_Column_List" />
         from user_order_payment where order_no_ = #{orderSn} and status_ = 'succeeded'
     </select>
+
+    <select id="selectByAdapayNo" resultMap="BaseResultMap">
+        select
+        <include refid="Base_Column_List" />
+        from user_order_payment where adapay_no_ = #{paymentNo} limit 1
+    </select>
 </mapper>

+ 7 - 0
cooleshow-mall/mall-mbg/src/main/resources/config/mybatis/UserOrderRefundMapper.xml

@@ -335,4 +335,11 @@
     from user_order_refund
     where #{transNo} = trans_no_ limit 1
   </select>
+
+  <select id="selectByRefundNo" resultMap="BaseResultMap">
+    select
+    <include refid="Base_Column_List" />
+    from user_order_refund
+    where #{refundOrderNo} = order_no_ limit 1
+    </select>
 </mapper>

+ 1 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/component/CancelOrderReceiver.java

@@ -20,7 +20,7 @@ public class CancelOrderReceiver {
     private OmsPortalOrderService portalOrderService;
     @RabbitHandler
     public void handle(Long orderId){
-        portalOrderService.cancelOrder(orderId, "超时取消");
+        portalOrderService.cancelOrder(orderId, "超时取消", null);
         LOGGER.info("process orderId:{}",orderId);
     }
 }

+ 1 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/controller/OmsPortalOrderController.java

@@ -109,7 +109,7 @@ public class OmsPortalOrderController {
     @RequestMapping(value = "/cancelUserOrder", method = RequestMethod.POST)
     @ResponseBody
     public CommonResult cancelUserOrder(Long orderId) {
-        portalOrderService.cancelOrder(orderId, "用户取消订单");
+        portalOrderService.cancelOrder(orderId, "用户取消订单", null);
         return CommonResult.success(null);
     }
 

+ 6 - 0
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/dao/PortalProductDao.java

@@ -2,6 +2,7 @@ package com.yonge.cooleshow.portal.dao;
 
 import com.yonge.cooleshow.mbg.model.SmsCoupon;
 import com.yonge.cooleshow.portal.domain.CartProduct;
+import com.yonge.cooleshow.portal.domain.ProductStock;
 import com.yonge.cooleshow.portal.domain.PromotionProduct;
 import org.apache.ibatis.annotations.Param;
 
@@ -26,4 +27,9 @@ public interface PortalProductDao {
      * 获取可用优惠券列表
      */
     List<SmsCoupon> getAvailableCouponList(@Param("productId") Long productId, @Param("productCategoryId") Long productCategoryId);
+
+    /**
+     * 改库存
+     */
+    void updateProductStock(@Param("itemList") List<ProductStock> productStockList);
 }

+ 29 - 0
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/domain/ProductStock.java

@@ -0,0 +1,29 @@
+package com.yonge.cooleshow.portal.domain;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-05-27
+ */
+public class ProductStock {
+    private Long productId;
+
+    private Integer stock;
+
+    public Long getProductId() {
+        return productId;
+    }
+
+    public void setProductId(Long productId) {
+        this.productId = productId;
+    }
+
+    public Integer getStock() {
+        return stock;
+    }
+
+    public void setStock(Integer stock) {
+        this.stock = stock;
+    }
+}

+ 1 - 0
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/dto/OrderPayReq.java

@@ -29,6 +29,7 @@ public class OrderPayReq {
     private String reason;
 
     @ApiModelProperty(value = "付款应用 STUDENT 学生端 TEACHER 老师端 (对应微信,支付宝平台的应用)",required = true)
+    @NotBlank(message = "付款应用不能为空")
     private String paymentClient;
 
     private Long userId;

+ 1 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/OmsPortalOrderService.java

@@ -46,7 +46,7 @@ public interface OmsPortalOrderService {
      * 取消单个超时订单
      */
     @Transactional
-    void cancelOrder(Long orderId,  String message);
+    void cancelOrder(Long orderId, String message, PaymentCallBack data);
 
     /**
      * 发送延迟消息取消订单

+ 9 - 3
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/UserOrderPaymentService.java

@@ -3,6 +3,7 @@ package com.yonge.cooleshow.portal.service;
 import com.yonge.cooleshow.mbg.model.UserOrderPayment;
 import com.yonge.toolset.payment.base.enums.PayChannelEnum;
 import com.yonge.toolset.payment.base.enums.TradeStatusEnum;
+import com.yonge.toolset.payment.base.model.callback.PaymentCallBack;
 
 import java.util.List;
 
@@ -43,11 +44,11 @@ public interface UserOrderPaymentService {
 
     /**
      * 关单
-     *
-     * @param orderSn 订单号
+     *  @param orderSn 订单号
      * @param message 信息
+     * @param data
      */
-    void closePayment(String orderSn, String message);
+    void closePayment(String orderSn, String message, PaymentCallBack data);
 
     /**
      * 查询支付中的订单, 最多只有一个
@@ -65,4 +66,9 @@ public interface UserOrderPaymentService {
      * @return
      */
     UserOrderPayment getByOrderNoAndStatusSucceeded(String orderSn);
+
+    /**
+     * 查询回调支付信息
+     */
+    UserOrderPayment getByAdapayNo(String paymentNo);
 }

+ 15 - 10
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderReturnApplyServiceImpl.java

@@ -1,13 +1,9 @@
 package com.yonge.cooleshow.portal.service.impl;
 
 import com.github.pagehelper.PageHelper;
-import com.yonge.cooleshow.mbg.mapper.OmsOrderItemMapper;
-import com.yonge.cooleshow.mbg.mapper.OmsOrderReturnApplyMapper;
-import com.yonge.cooleshow.mbg.mapper.PmsProductMapper;
-import com.yonge.cooleshow.mbg.mapper.PmsSkuStockMapper;
+import com.yonge.cooleshow.mbg.mapper.*;
 import com.yonge.cooleshow.mbg.model.*;
 
-import com.yonge.cooleshow.mbg.mapper.UserOrderRefundMapper;
 import com.yonge.cooleshow.mbg.model.OmsOrderReturnApply;
 import com.yonge.cooleshow.mbg.model.OmsOrderReturnApplyExample;
 import com.yonge.cooleshow.mbg.model.UserOrderRefund;
@@ -66,6 +62,9 @@ public class OmsPortalOrderReturnApplyServiceImpl implements OmsPortalOrderRetur
     @Autowired
     private UserOrderRefundMapper userOrderRefundMapper;
 
+    @Autowired
+    private OmsOrderMapper omsOrderMapper;
+
 
     @Override
     public int create(OmsOrderReturnApplyParam returnApply) {
@@ -75,6 +74,11 @@ public class OmsPortalOrderReturnApplyServiceImpl implements OmsPortalOrderRetur
         if (omsOrderItem == null || !omsOrderItem.getOrderId().equals(realApply.getOrderId())) {
             throw new BizException("当前订单不能退款");
         }
+        OmsOrder order = omsOrderMapper.selectByPrimaryKey(realApply.getOrderId());
+        if (order == null) {
+            throw new BizException("订单不存在");
+        }
+        realApply.setOrderSn(order.getOrderSn());
         PmsProduct pmsProduct = pmsProductMapper.selectByPrimaryKey(omsOrderItem.getProductId());
         realApply.setProductPic(pmsProduct.getPic());
         realApply.setProductName(pmsProduct.getName());
@@ -142,11 +146,12 @@ public class OmsPortalOrderReturnApplyServiceImpl implements OmsPortalOrderRetur
         if (data == null) {
             return;
         }
-        UserOrderRefund userOrderRefund = userOrderRefundMapper.selectByTransNo(
-                data.getRefundPaymentCallBack().getTransNo());
+        UserOrderRefund userOrderRefund = userOrderRefundMapper.selectByRefundNo(
+                data.getRefundPaymentCallBack().getBillNo());
         userOrderRefund.setArrivalTime(new Date());
         userOrderRefund.setStatus(TradeStatusEnum.failed.getCode());
         userOrderRefund.setPayFailMsg(errMsg);
+        userOrderRefund.setTransNo(data.getRefundPaymentCallBack().getTransNo());
 
         userOrderRefundMapper.updateByPrimaryKeySelective(userOrderRefund);
     }
@@ -158,11 +163,11 @@ public class OmsPortalOrderReturnApplyServiceImpl implements OmsPortalOrderRetur
         if (data == null) {
             return;
         }
-        UserOrderRefund userOrderRefund = userOrderRefundMapper.selectByTransNo(
-                data.getRefundPaymentCallBack().getTransNo());
+        UserOrderRefund userOrderRefund = userOrderRefundMapper.selectByRefundNo(
+                data.getRefundPaymentCallBack().getBillNo());
         userOrderRefund.setArrivalTime(new Date());
         userOrderRefund.setStatus(TradeStatusEnum.succeeded.getCode());
-
+        userOrderRefund.setTransNo(data.getRefundPaymentCallBack().getTransNo());
         userOrderRefund.setFeeAmt(new BigDecimal(data.getRefundPaymentCallBack().getFeeAmt()));
         userOrderRefund.setRefundAmt(new BigDecimal(data.getRefundPaymentCallBack().getRefundAmt()));
 

+ 108 - 33
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderServiceImpl.java

@@ -5,6 +5,7 @@ import cn.hutool.core.collection.CollUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.github.pagehelper.PageHelper;
+import com.yonge.cooleshow.portal.dao.PortalProductDao;
 import com.yonge.cooleshow.portal.dto.OrderPayReq;
 import com.yonge.cooleshow.portal.dto.OrderPayRes;
 import com.yonge.toolset.base.exception.BizException;
@@ -98,6 +99,13 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
     @Autowired
     private PaymentProperties paymentProperties;
 
+    @Autowired
+    private PmsProductMapper pmsProductMapper;
+
+
+    @Autowired
+    private PortalProductDao productDao;
+
     @Override
     public ConfirmOrderResult generateConfirmOrder(List<Long> cartIds) {
         ConfirmOrderResult result = new ConfirmOrderResult();
@@ -190,8 +198,12 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
         }
         //计算order_item的实付金额
         handleRealAmount(orderItemList);
-        //进行库存锁定
-        lockStock(cartPromotionItemList);
+        //进行sku库存锁定
+        lockSkuStock(cartPromotionItemList);
+
+        // 进行商品库存锁定
+        lockProductStock(cartPromotionItemList);
+
         //根据商品合计、运费、活动优惠、优惠券、积分计算应付金额
         OmsOrder order = new OmsOrder();
         StringBuilder cartIds = new StringBuilder();
@@ -253,7 +265,6 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
         if (CollUtil.isNotEmpty(orderSettings)) {
             order.setAutoConfirmDay(orderSettings.get(0).getConfirmOvertime());
         }
-        // TODO: 2018/9/3 bill_*,delivery_*
         //插入order表和order_item表
         orderMapper.insert(order);
         for (OmsOrderItem orderItem : orderItemList) {
@@ -291,10 +302,37 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
         orderMapper.updateByPrimaryKeySelective(order);
         //恢复所有下单商品的锁定库存,扣减真实库存
         OmsOrderDetail orderDetail = portalOrderDao.getDetail(orderId);
+        // 减sku库存
         int count = portalOrderDao.updateSkuStock(orderDetail.getOrderItemList());
+
+        // 减商品库存
+        updateProductStock(orderDetail);
+
         return count;
     }
 
+    /**
+     *  减商品库存
+     */
+    private void updateProductStock(OmsOrderDetail orderDetail) {
+        Map<Long, List<OmsOrderItem>> collect = orderDetail.getOrderItemList()
+                   .stream().collect(Collectors.groupingBy(OmsOrderItem::getProductId));
+
+        List<ProductStock> productStockList = new ArrayList<>();
+        for (Map.Entry<Long, List<OmsOrderItem>> entry : collect.entrySet()) {
+            ProductStock stock = new ProductStock();
+            stock.setProductId(entry.getKey());
+            List<OmsOrderItem> value = entry.getValue();
+            if(CollectionUtils.isEmpty(value)) {
+                continue;
+            }
+            int sum = value.stream().mapToInt(OmsOrderItem::getProductQuantity).sum();
+            stock.setStock(sum);
+            productStockList.add(stock);
+        }
+        productDao.updateProductStock(productStockList);
+    }
+
     @Override
     public Integer cancelTimeOutOrder() {
         Integer count = 0;
@@ -310,14 +348,14 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
             if (timeOutOrder.getStatus() == 0) {
                 payingOrderHandle(timeOutOrder);
             } else if (timeOutOrder.getStatus() == 6) {
-                cancelOrder(timeOutOrder.getId(), "超时取消");
+                cancelOrder(timeOutOrder.getId(), "超时取消", null);
             }
         }
         return timeOutOrders.size();
     }
 
     @Override
-    public void cancelOrder(Long orderId, String message) {
+    public void cancelOrder(Long orderId, String message, PaymentCallBack data) {
         //查询未付款的取消订单
         OmsOrderExample example = new OmsOrderExample();
         example.createCriteria().andIdEqualTo(orderId).andDeleteStatusEqualTo(0);
@@ -345,7 +383,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
                 memberService.updateIntegration(cancelOrder.getMemberId(), member.getIntegration() + cancelOrder.getUseIntegration());
             }
             // 发起关单
-            userOrderPaymentService.closePayment(cancelOrder.getOrderSn(), message);
+            userOrderPaymentService.closePayment(cancelOrder.getOrderSn(),message,data);
 
         }
     }
@@ -496,7 +534,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
         //构建汇付统一下单请求
         OpenEnum openType = OpenEnum.valueOf(paymentProperties.getOpenType());
         Payment payment = new Payment(openType,
-                PaymentClientEnum.valueOf(userOrderPayment.getPaymentClient()), payReq.getPayChannel());
+                PaymentClientEnum.valueOf(payReq.getPaymentClient()), payReq.getPayChannel());
         payment.setPaymentNo(generateOrderSn(detail));
         payment.setOrderNo(payReq.getOrderNo());
         payment.setOrderTitle("酷乐秀商城订单编号-" + detail.getOrderSn());
@@ -536,22 +574,22 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
         BaseResult<Payment> executePayment = paymentClient.executePayment(payment);
         if (!executePayment.getStatus()) {
             // 异常将取消订单
-            cancelOrder(detail.getId(), executePayment.getMsg());
+            cancelOrder(detail.getId(), executePayment.getMsg(), null);
             throw new BizException(executePayment.getMsg());
         }
         if (!executePayment.getData().getPayAmt().equals(detail.getPayAmount().setScale(2, RoundingMode.HALF_UP).toString())) {
-            cancelOrder(detail.getId(), "订单金额和实际支付金额不符");
+            cancelOrder(detail.getId(), "订单金额和实际支付金额不符", null);
             throw new BizException("订单金额和实际支付金额不符");
         }
 
 
-        saveOrderPayment(executePayment.getData(), detail);
+        saveOrderPayment(executePayment.getData(), detail,payReq.getPaymentClient());
 
         return orderPayRes;
     }
 
 
-    private void saveOrderPayment(Payment payment, OmsOrderDetail detail) {
+    private void saveOrderPayment(Payment payment, OmsOrderDetail detail,String paymentClient) {
         UserOrderPayment userOrderPayment;
         OmsOrder omsOrder = new OmsOrder();
         omsOrder.setId(detail.getId());
@@ -560,6 +598,8 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
         orderMapper.updateByPrimaryKeySelective(omsOrder);
         // 保存订单支付表
         userOrderPayment = new UserOrderPayment();
+        userOrderPayment.setPaymentClient(paymentClient);
+        userOrderPayment.setOpenType(paymentProperties.getOpenType());
         userOrderPayment.setOrderNo(detail.getOrderSn());
         userOrderPayment.setAdapayNo(payment.getPaymentNo());
         userOrderPayment.setPayChannel(payment.getPayChannel().getCode());
@@ -605,14 +645,14 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
      */
     private void paymentSucceededHandle(PaymentCallBack data) {
         //订单完成
-        UserOrderPayment userOrderPayment = userOrderPaymentService.getByTranNo(data.getPaymentNo());
+        UserOrderPayment userOrderPayment = userOrderPaymentService.getByAdapayNo(data.getPaymentNo());
         if (null == userOrderPayment) {
             log.error("汇付支付回调,订单未找到。 req is {}", JSON.toJSONString(data));
             return;
         }
         OmsOrderDetail detail = detail(userOrderPayment.getOrderNo());
         if (detail.getStatus() == 0) {
-            orderSuccess(detail, data);
+            orderSuccess(detail, data,data.getId());
         } else {
             log.error("汇付支付回调,订单状态异常。 req is {}", detail.getOrderSn());
         }
@@ -626,7 +666,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
      */
     private void paymentFailedHandle(PaymentCallBack data) {
         //订单完成
-        UserOrderPayment userOrderPayment = userOrderPaymentService.getByTranNo(data.getPaymentNo());
+        UserOrderPayment userOrderPayment = userOrderPaymentService.getByAdapayNo(data.getPaymentNo());
         if (null == userOrderPayment) {
             log.error("汇付支付回调,订单未找到。 req is {}", JSON.toJSONString(data));
             return;
@@ -639,7 +679,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
         }
         if (detail.getStatus() == 0) {
 
-            cancelOrder(detail.getId(), data.getErrMsg());
+            cancelOrder(detail.getId(), data.getErrMsg(),data);
         } else {
             log.error("汇付支付回调,订单状态异常。 req is {}", JSON.toJSONString(data));
         }
@@ -652,12 +692,14 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
      * @updateTime 2022/4/27 15:33
      */
     private void paymentCloseSucceededHandle(PaymentCallBack data) {
-        UserOrderPayment orderPayment = userOrderPaymentService.getByTranNo(data.getPaymentNo());
+        UserOrderPayment orderPayment = userOrderPaymentService.getByAdapayNo(data.getPaymentNo());
         if (null == orderPayment) {
             return;
         }
-        orderPayment.setStatus(TradeStatusEnum.succeeded.getCode());
-        orderPayment.setUpdateTime(new Date());
+        orderPayment.setStatus(TradeStatusEnum.failed.getCode());
+        orderPayment.setTransNo(data.getId());
+        orderPayment.setCloseStatus(TradeStatusEnum.succeeded.getCode());
+        orderPayment.setCloseTime(data.getClosePaymentCallBack().getTradeTime());
         userOrderPaymentService.saveOrUpdate(orderPayment);
     }
 
@@ -668,11 +710,13 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
      * @updateTime 2022/4/27 15:33
      */
     private void paymentCloseFailedHandle(PaymentCallBack data) {
-        UserOrderPayment orderPayment = userOrderPaymentService.getByTranNo(data.getPaymentNo());
+        UserOrderPayment orderPayment = userOrderPaymentService.getByAdapayNo(data.getPaymentNo());
         if (null == orderPayment) {
             return;
         }
         orderPayment.setStatus(TradeStatusEnum.failed.getCode());
+        orderPayment.setCloseStatus(TradeStatusEnum.failed.getCode());
+        orderPayment.setCloseTime(data.getClosePaymentCallBack().getTradeTime());
         orderPayment.setPayFailMsg("支付关单回调失败-" + data.getErrMsg());
         orderPayment.setUpdateTime(new Date());
         userOrderPaymentService.saveOrUpdate(orderPayment);
@@ -686,7 +730,7 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
         //判断汇付订单状态
         UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNoAndStatusPaying(userOrder.getOrderSn());
         if (null == orderPayment) {
-            cancelOrder(userOrder.getId(), "支付超时");
+            cancelOrder(userOrder.getId(), "支付超时", null);
         }
         OmsOrderDetail detail = detail(orderPayment.getOrderNo());
         try {
@@ -699,15 +743,15 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
             if (res.getStatus() && TradeStatusEnum.succeeded.getCode().equals(res.getData().getStatus())
                     && (detail.getStatus() == 0 || detail.getStatus() == 1)
             ) {
-                orderSuccess(detail);
+                orderSuccess(detail,res.getData().getId());
                 return;
             }
             //支付失败
             if (!res.getStatus()) {
-                cancelOrder(userOrder.getId(), res.getMsg());
+                cancelOrder(userOrder.getId(), res.getMsg(), null);
                 return;
             }
-            cancelOrder(userOrder.getId(), "支付超时");
+            cancelOrder(userOrder.getId(), "支付超时", null);
         } catch (Exception e) {
             e.printStackTrace();
             log.error("轮询处理支付中订单异常,异常参数: {}", JSONObject.toJSONString(userOrder));
@@ -715,8 +759,8 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
     }
 
 
-    void orderSuccess(OmsOrder detail) {
-        orderSuccess(detail, null);
+    void orderSuccess(OmsOrder detail, String tranId) {
+        orderSuccess(detail,null,tranId);
     }
 
     /**
@@ -726,26 +770,33 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
      * @updateTime 2022/4/13 17:17
      */
     @Transactional(rollbackFor = Exception.class)
-    void orderSuccess(OmsOrder detail, PaymentCallBack data) {
+    void orderSuccess(OmsOrder detail, PaymentCallBack data, String tranId) {
         //更新订单
         UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNoAndStatusPaying(detail.getOrderSn());
 
+        if (orderPayment == null) {
+            log.error("支付回调,支付中订单未找到。 orderNo is {}",detail.getOrderSn());
+            return;
+        }
         if (data != null) {
             String pay_amt = data.getExecutePaymentCallBack().getPayAmt();
             if (!pay_amt.equals(detail.getPayAmount().setScale(2, RoundingMode.HALF_UP).toString())) {
                 orderPayment.setPayFailMsg("订单金额和实际支付金额不符");
             }
         }
-        if (orderPayment.getPayChannel().equals("alipay")) {
-            paySuccess(detail.getId(), 1);
-        } else if (orderPayment.getPayChannel().equals("wx_lite")) {
-            paySuccess(detail.getId(), 2);
+        if (orderPayment.getPayChannel().equals("alipay") || orderPayment.getPayChannel().equals("ali_app")) {
+            paySuccess(detail.getId(),1);
+        } else if (orderPayment.getPayChannel().equals("wx_lite") || orderPayment.getPayChannel().equals("wx_app")) {
+            paySuccess(detail.getId(),2);
         }
 
         orderPayment.setStatus(TradeStatusEnum.succeeded.getCode());
         orderPayment.setArrivalTime(new Date());
+        orderPayment.setTransNo(tranId);
         if (null != data) {
             try {
+                orderPayment.setArrivalTime(data.getExecutePaymentCallBack().getTradeTime());
+                orderPayment.setTransNo(data.getId());
                 orderPayment.setPayAmt(new BigDecimal(data.getExecutePaymentCallBack().getPayAmt()));
                 orderPayment.setFeeAmt(new BigDecimal(data.getExecutePaymentCallBack().getFeeAmt()));
             } catch (Exception e) {
@@ -1048,11 +1099,35 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
     /**
      * 锁定下单商品的所有库存
      */
-    private void lockStock(List<CartPromotionItem> cartPromotionItemList) {
+    private void lockSkuStock(List<CartPromotionItem> cartPromotionItemList) {
         for (CartPromotionItem cartPromotionItem : cartPromotionItemList) {
-            int i = skuStockMapper.lockStock(cartPromotionItem.getProductSkuId(), cartPromotionItem.getQuantity());
+            if (cartPromotionItem.getProductSkuId() == null) {
+                continue;
+            }
+            int i = skuStockMapper.lockStock(cartPromotionItem.getProductSkuId(),cartPromotionItem.getQuantity());
             if (i == 0) {
-                Asserts.fail("库存不足,无法下单");
+                Asserts.fail("库存不足");
+            }
+        }
+    }
+
+    /**
+     * 锁定下单商品的所有库存
+     */
+    private void lockProductStock(List<CartPromotionItem> cartPromotionItemList) {
+        Map<Long, List<CartPromotionItem>> collect = cartPromotionItemList.stream()
+                                  .collect(Collectors.groupingBy(CartPromotionItem::getProductId));
+        for (Map.Entry<Long, List<CartPromotionItem>> entry : collect.entrySet()) {
+            List<CartPromotionItem> value = entry.getValue();
+            if(CollectionUtils.isEmpty(value)) {
+                continue;
+            }
+            int sum = value.stream().mapToInt(CartPromotionItem::getQuantity).sum();
+            if (sum >0 ) {
+                int i = pmsProductMapper.lockStock(entry.getKey(),sum);
+                if (i == 0) {
+                    Asserts.fail("库存不足");
+                }
             }
         }
     }

+ 39 - 10
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPromotionServiceImpl.java

@@ -45,12 +45,18 @@ public class OmsPromotionServiceImpl implements OmsPromotionService {
                     BeanUtils.copyProperties(item,cartPromotionItem);
                     cartPromotionItem.setPromotionMessage("单品促销");
                     //商品原价-促销价
+                    BigDecimal originalPrice = promotionProduct.getPrice();
                     PmsSkuStock skuStock = getOriginalPrice(promotionProduct, item.getProductSkuId());
-                    BigDecimal originalPrice = skuStock.getPrice();
-                    //单品促销使用原价
-                    cartPromotionItem.setPrice(originalPrice);
-                    cartPromotionItem.setReduceAmount(originalPrice.subtract(skuStock.getPromotionPrice()));
-                    cartPromotionItem.setRealStock(skuStock.getStock()-skuStock.getLockStock());
+                    if (skuStock  != null) {
+                        //单品促销使用原价
+                        cartPromotionItem.setPrice(originalPrice);
+                        cartPromotionItem.setReduceAmount(originalPrice.subtract(skuStock.getPromotionPrice()));
+                        cartPromotionItem.setRealStock(skuStock.getStock() - skuStock.getLockStock());
+                    } else {
+                        cartPromotionItem.setReduceAmount(originalPrice.subtract(promotionProduct.getPromotionPrice()));
+                        cartPromotionItem.setRealStock(promotionProduct.getStock() - promotionProduct.getLockStock());
+
+                    }
                     cartPromotionItem.setIntegration(promotionProduct.getGiftPoint());
                     cartPromotionItem.setGrowth(promotionProduct.getGiftGrowth());
                     cartPromotionItemList.add(cartPromotionItem);
@@ -66,11 +72,17 @@ public class OmsPromotionServiceImpl implements OmsPromotionService {
                         String message = getLadderPromotionMessage(ladder);
                         cartPromotionItem.setPromotionMessage(message);
                         //商品原价-折扣*商品原价
+                        BigDecimal originalPrice = promotionProduct.getPrice();
                         PmsSkuStock skuStock = getOriginalPrice(promotionProduct,item.getProductSkuId());
-                        BigDecimal originalPrice = skuStock.getPrice();
+                        if (skuStock  != null) {
+                            //单品促销使用原价
+                            originalPrice = skuStock.getPrice();
+                            cartPromotionItem.setRealStock(skuStock.getStock()-skuStock.getLockStock());
+                        } else {
+                            cartPromotionItem.setRealStock(promotionProduct.getStock() - promotionProduct.getLockStock());
+                        }
                         BigDecimal reduceAmount = originalPrice.subtract(ladder.getDiscount().multiply(originalPrice));
                         cartPromotionItem.setReduceAmount(reduceAmount);
-                        cartPromotionItem.setRealStock(skuStock.getStock()-skuStock.getLockStock());
                         cartPromotionItem.setIntegration(promotionProduct.getGiftPoint());
                         cartPromotionItem.setGrowth(promotionProduct.getGiftGrowth());
                         cartPromotionItemList.add(cartPromotionItem);
@@ -89,11 +101,17 @@ public class OmsPromotionServiceImpl implements OmsPromotionService {
                         String message = getFullReductionPromotionMessage(fullReduction);
                         cartPromotionItem.setPromotionMessage(message);
                         //(商品原价/总价)*满减金额
+                        BigDecimal originalPrice = promotionProduct.getPrice();
                         PmsSkuStock skuStock= getOriginalPrice(promotionProduct, item.getProductSkuId());
-                        BigDecimal originalPrice = skuStock.getPrice();
+                        if (skuStock  != null) {
+                            //单品促销使用原价
+                            originalPrice = skuStock.getPrice();
+                            cartPromotionItem.setRealStock(skuStock.getStock()-skuStock.getLockStock());
+                        } else {
+                            cartPromotionItem.setRealStock(promotionProduct.getStock() - promotionProduct.getLockStock());
+                        }
                         BigDecimal reduceAmount = originalPrice.divide(totalAmount,RoundingMode.HALF_EVEN).multiply(fullReduction.getReducePrice());
                         cartPromotionItem.setReduceAmount(reduceAmount);
-                        cartPromotionItem.setRealStock(skuStock.getStock()-skuStock.getLockStock());
                         cartPromotionItem.setIntegration(promotionProduct.getGiftPoint());
                         cartPromotionItem.setGrowth(promotionProduct.getGiftGrowth());
                         cartPromotionItemList.add(cartPromotionItem);
@@ -165,6 +183,8 @@ public class OmsPromotionServiceImpl implements OmsPromotionService {
             PmsSkuStock skuStock = getOriginalPrice(promotionProduct,item.getProductSkuId());
             if(skuStock!=null){
                 cartPromotionItem.setRealStock(skuStock.getStock()-skuStock.getLockStock());
+            } else {
+                cartPromotionItem.setRealStock(promotionProduct.getStock() - promotionProduct.getLockStock());
             }
             cartPromotionItem.setIntegration(promotionProduct.getGiftPoint());
             cartPromotionItem.setGrowth(promotionProduct.getGiftGrowth());
@@ -242,7 +262,13 @@ public class OmsPromotionServiceImpl implements OmsPromotionService {
             //计算出商品原价
             PromotionProduct promotionProduct = getPromotionProductById(item.getProductId(), promotionProductList);
             PmsSkuStock skuStock = getOriginalPrice(promotionProduct,item.getProductSkuId());
-            amount = amount.add(skuStock.getPrice().multiply(new BigDecimal(item.getQuantity())));
+            BigDecimal price = BigDecimal.ZERO;
+            if (skuStock != null) {
+                price = skuStock.getPrice();
+            } else if (promotionProduct != null){
+                price = promotionProduct.getPrice();
+            }
+            amount = amount.add(price.multiply(new BigDecimal(item.getQuantity())));
         }
         return amount;
     }
@@ -251,6 +277,9 @@ public class OmsPromotionServiceImpl implements OmsPromotionService {
      * 获取商品的原价
      */
     private PmsSkuStock getOriginalPrice(PromotionProduct promotionProduct, Long productSkuId) {
+        if (productSkuId == null) {
+            return null;
+        }
         for (PmsSkuStock skuStock : promotionProduct.getSkuStockList()) {
             if (productSkuId.equals(skuStock.getId())) {
                 return skuStock;

+ 8 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/UserOrderPaymentServiceImpl.java

@@ -9,6 +9,7 @@ import com.yonge.toolset.payment.base.enums.PayChannelEnum;
 import com.yonge.toolset.payment.base.enums.PaymentClientEnum;
 import com.yonge.toolset.payment.base.enums.TradeStatusEnum;
 import com.yonge.toolset.payment.base.model.ClosePayment;
+import com.yonge.toolset.payment.base.model.callback.PaymentCallBack;
 import com.yonge.toolset.payment.core.service.PaymentClient;
 import com.yonge.toolset.utils.string.StringUtil;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -63,7 +64,7 @@ public class UserOrderPaymentServiceImpl implements UserOrderPaymentService {
     }
 
     @Override
-    public void closePayment(String orderSn, String message) {
+    public void closePayment(String orderSn, String message, PaymentCallBack data) {
         UserOrderPayment orderPayment = userOrderPaymentMapper.selectByOrderNoAndStatusPaying(orderSn);
 
         if (orderPayment != null) {
@@ -71,6 +72,7 @@ public class UserOrderPaymentServiceImpl implements UserOrderPaymentService {
             orderPayment.setStatus(TradeStatusEnum.failed.getCode());
             orderPayment.setPayFailMsg(StringUtil.isEmpty(message) ? "交易取消" : message);
             orderPayment.setUpdateTime(new Date());
+            orderPayment.setTransNo(data.getId());
 
             //发送支付关单请求
             if (!StringUtil.isEmpty(orderPayment.getTransNo())) {
@@ -101,4 +103,9 @@ public class UserOrderPaymentServiceImpl implements UserOrderPaymentService {
     public UserOrderPayment getByOrderNoAndStatusSucceeded(String orderSn) {
         return userOrderPaymentMapper.selectByOrderNoAndStatusSucceeded(orderSn);
     }
+
+    @Override
+    public UserOrderPayment getByAdapayNo(String paymentNo) {
+        return userOrderPaymentMapper.selectByAdapayNo(paymentNo);
+    }
 }

+ 1 - 0
cooleshow-mall/mall-portal/src/main/resources/config/mybatis/PortalOrderDao.xml

@@ -15,6 +15,7 @@
             o.integration,
             o.member_id,
             ot.id ot_id,
+        ot.product_id ot_product_id,
             ot.product_name ot_product_name,
             ot.product_sku_id ot_product_sku_id,
             ot.product_sku_code ot_product_sku_code,

+ 21 - 5
cooleshow-mall/mall-portal/src/main/resources/config/mybatis/PortalProductDao.xml

@@ -44,11 +44,7 @@
     </select>
     <select id="getPromotionProductList" resultMap="promotionProductMap">
         SELECT
-            p.id,
-            p.`name`,
-            p.promotion_type,
-            p.gift_growth,
-            p.gift_point,
+            p.*,
             sku.id sku_id,
             sku.price sku_price,
             sku.sku_code sku_sku_code,
@@ -99,4 +95,24 @@
               AND cp.product_id = #{productId}
         )
     </select>
+
+    <update id="updateProductStock">
+        UPDATE pms_product
+        SET
+        stock = CASE id
+        <foreach collection="itemList" item="item">
+            WHEN #{item.productId} THEN stock - #{item.stock}
+        </foreach>
+        END,
+        lock_stock = CASE id
+        <foreach collection="itemList" item="item">
+            WHEN #{item.productId} THEN lock_stock - #{item.stock}
+        </foreach>
+        END
+        WHERE
+        id IN
+        <foreach collection="itemList" item="item" separator="," open="(" close=")">
+            #{item.productId}
+        </foreach>
+    </update>
 </mapper>

+ 4 - 3
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/SmsCodeController.java

@@ -47,13 +47,14 @@ public class SmsCodeController extends BaseController {
 
     @ApiOperation(value = "校验短信验证码")
     @ApiImplicitParams({ @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String"),
-            @ApiImplicitParam(name = "code", value = "短信验证码", required = true, dataType = "String") })
+            @ApiImplicitParam(name = "code", value = "短信验证码", required = true, dataType = "String"),
+                         @ApiImplicitParam(name = "type", value = "类型(PASSWD:修改密码,LOGIN:登录或注册,BANK:绑定银行卡,PHONE:修改手机号)", required = true, dataType = "String") })
     @PostMapping(value = "/verifySmsCode")
-    public Object verifySmsCode(String phone,String code) {
+    public Object verifySmsCode(String phone,String code,String type) {
         if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)){
             return failed(SecurityConstants.PARAM_VERIFY_EXCEPTION);
         }
-        if(smsCodeService.verifyValidCode(phone,code)){
+        if(smsCodeService.verifyValidCode(phone,code,type)){
             return succeed();
         }
         return failed("验证码校验失败");

+ 2 - 5
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleDao.java

@@ -215,17 +215,14 @@ public interface CourseScheduleDao extends BaseMapper<CourseSchedule> {
     List<CourseSchedule> selectSchedule(Integer courseId);
 
     //更新课程状态
-    void updateStartTime(List<Long> list);
+    void updateStartTime(List<CourseSchedule> list);
 
     //更新课程状态
-    void updateEndTime();
+    void updateEndTime(List<CourseSchedule> list);
 
     //根据日期查课程id
     List<Long> selectIdList(String day);
 
     //更新老师课酬
     void updateTeacherSalary(List<Long> list);
-
-    //查询课程id(开课时间 ≤ NOW ≤ 结束时间)
-    List<Long> selectUpStartIds();
 }

+ 15 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/CourseScheduleStudentDao.java

@@ -0,0 +1,15 @@
+package com.yonge.cooleshow.biz.dal.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.yonge.cooleshow.biz.dal.entity.CourseScheduleStudent;
+
+import java.util.List;
+
+/**
+ * @Author: cy
+ * @Date: 2022/5/27
+ */
+public interface CourseScheduleStudentDao extends BaseMapper<CourseScheduleStudent> {
+    //批量添加学员
+    void insertBatch(List<CourseScheduleStudent> list);
+}

+ 12 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CourseSchedule.java

@@ -65,6 +65,10 @@ public class CourseSchedule implements Serializable {
     @ApiModelProperty(value = "实际上课人数")
     private Integer exStudentNum;
 
+    @TableField("single_course_time_")
+    @ApiModelProperty(value = "单课时长")
+    private Integer singleCourseTime;
+
     @TableField("created_by_")
     @ApiModelProperty(value = "创建人")
     private Long createdBy;
@@ -81,6 +85,14 @@ public class CourseSchedule implements Serializable {
     @ApiModelProperty(value = "更新时间")
     private Date updatedTime;
 
+    public Integer getSingleCourseTime() {
+        return singleCourseTime;
+    }
+
+    public void setSingleCourseTime(Integer singleCourseTime) {
+        this.singleCourseTime = singleCourseTime;
+    }
+
     public static CourseSchedule build() {
         return new CourseSchedule();
     }

+ 3 - 3
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/CourseScheduleStudent.java

@@ -25,7 +25,7 @@ public class CourseScheduleStudent implements Serializable {
 
     @TableField("student_id_")
     @ApiModelProperty(value = "学生id")
-    private String studentId;
+    private Long studentId;
 
     public Long getId() {
         return id;
@@ -43,11 +43,11 @@ public class CourseScheduleStudent implements Serializable {
         this.courseId = courseId;
     }
 
-    public String getStudentId() {
+    public Long getStudentId() {
         return studentId;
     }
 
-    public void setStudentId(String studentId) {
+    public void setStudentId(Long studentId) {
         this.studentId = studentId;
     }
 }

+ 5 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CourseScheduleService.java

@@ -184,7 +184,7 @@ public interface CourseScheduleService extends IService<CourseSchedule> {
 
     void buyPracticeCourseFailed(UserOrderDetailVo orderParam);
 
-    void courseAdjust(CourseAdjustVo adjustVo,Long teacherId);
+    void courseAdjust(CourseAdjustVo adjustVo, Long teacherId);
 
     StudentHomePage queryLiveAndVideo(Long studentId, Long teacherId, YesOrNoEnum appAuditVersion);
 
@@ -227,7 +227,6 @@ public interface CourseScheduleService extends IService<CourseSchedule> {
     /**
      * 发送"当日陪练课未评价/布置作业
      * (每晚9点30,已评价/已布置不发)"
-     *
      */
     void sendTodayNotRepliedAndNotDecorateHomework();
 
@@ -240,5 +239,9 @@ public interface CourseScheduleService extends IService<CourseSchedule> {
     void teacherSalaryTask();
 
     PinaoRoomTimeVo selectRemainTime(Long teacherId);
+
+    PageInfo<CourseStudentVo> selectStudent(Map<String, Object> param);
+
+    void arrangeCourse(ArrangeCourseVo arrangeCourseVo, Long teacherId);
 }
 

+ 2 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/SmsCodeService.java

@@ -8,9 +8,10 @@ public interface SmsCodeService {
 	 * 校验验证码
 	 * @param mobile
 	 * @param authCode
+	 * @param type
 	 * @return
 	 */
-	boolean verifyValidCode(String mobile, String authCode);
+	boolean verifyValidCode(String mobile, String authCode, String type);
 
 	/**
 	 * 发送登录验证码

+ 171 - 142
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseScheduleServiceImpl.java

@@ -96,6 +96,10 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
     private HolidaysFestivalsDao holidaysFestivalsDao;
     @Autowired
     private PinaoRoomTimeDao pinaoRoomTimeDao;
+    @Autowired
+    private UserBindingTeacherDao userBindingTeacherDao;
+    @Autowired
+    private CourseScheduleStudentDao courseScheduleStudentDao;
 
     @Override
     public CourseScheduleDao getDao() {
@@ -1485,12 +1489,26 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
      */
     @Transactional(rollbackFor = Exception.class)
     public void scheduleTask() {
-        //查询课程id(开课时间 ≤ NOW ≤ 结束时间)
-        List<Long> startIds=baseMapper.selectUpStartIds();
-        if (CollectionUtils.isNotEmpty(startIds)){
-            baseMapper.updateStartTime(startIds);
+        //更新课程开始状态(开课时间 ≤ NOW ≤ 结束时间)
+        List<CourseSchedule> courseStart = baseMapper.selectList(Wrappers.<CourseSchedule>lambdaQuery()
+                .eq(CourseSchedule::getLock, 0)
+                .eq(CourseSchedule::getType, CourseScheduleEnum.NOT_START)
+                .le(CourseSchedule::getStartTime, new Date())
+                .ge(CourseSchedule::getEndTime, new Date()));
+        if (CollectionUtils.isNotEmpty(courseStart)) {
+            baseMapper.updateStartTime(courseStart);
+        }
+
+        //更新课程结束状态(NOW ≥ 结束时间)
+        List<String> typeList = Arrays.asList(CourseScheduleEnum.ING.getCode(), CourseScheduleEnum.NOT_START.getCode());
+        List<CourseSchedule> courseEnd = baseMapper.selectList(Wrappers.<CourseSchedule>lambdaQuery()
+                .in(CourseSchedule::getType, typeList)
+                .eq(CourseSchedule::getLock, 0)
+                .le(CourseSchedule::getEndTime, new Date()));
+        if (CollectionUtils.isNotEmpty(courseEnd)) {
+            baseMapper.updateEndTime(courseEnd);
+            //TODO 根据老师&学生id 更新绑定学员结课时间
         }
-        baseMapper.updateEndTime();
     }
 
     /**
@@ -1510,145 +1528,156 @@ public class CourseScheduleServiceImpl extends ServiceImpl<CourseScheduleDao, Co
         baseMapper.updateTeacherSalary(idList);
     }
 
+    /**
+     * @Description: 查询琴房剩余时长、冻结时长、统计学员人数
+     * @Author: cy
+     * @Date: 2022/5/27
+     */
     public PinaoRoomTimeVo selectRemainTime(Long teacherId) {
         return pinaoRoomTimeDao.selectRemainTime(teacherId);
     }
 
-//    public PageInfo<CourseStudentVo> selectStudent(Map<String, Object> param) {
-//        Integer courseId = (Integer) param.get("courseId");
-//        if (courseId != null) {
-//            CourseScheduleStudent teacherTime = baseMapper.selectOne(Wrappers.<CourseScheduleStudent>lambdaQuery().eq(CourseScheduleStudent::getCourseScheduleId, courseId));
-//            if (teacherTime == null) {
-//                throw new BizException("未查到课程");
-//            }
-//            String studentIdList = teacherTime.getStudentIdList();
-//            List<String> idList = Arrays.asList(studentIdList.split(","));
-//            param.put("idList", idList);//根据课程id查询报课学员
-//        }
-//        return PageUtil.pageInfo(userBindingTeacherDao.selectStudent(PageUtil.getPageInfo(param), param));
-//    }
-//
-//    public void arrangeCourse(ArrangeCourseVo arrangeCourseVo, Long teacherId) {
-//        DistributedLock.of(redissonClient)
-//                .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey("teacherId:" + teacherId)
-//                        , () -> this.checkArrangeCourse(arrangeCourseVo, teacherId), 60L, TimeUnit.SECONDS);
-//    }
-//
-//    @Transactional(rollbackFor = Exception.class)
-//    public void checkArrangeCourse(ArrangeCourseVo arrangeCourseVo, Long teacherId) {
-//        Integer classNum = arrangeCourseVo.getClassNum();//课时数
-//        Integer singleClssTime = arrangeCourseVo.getSingleClssTime();//单课时长
-//        List<Long> studentIds = arrangeCourseVo.getStudentIds();//学员id集合
-//        Integer consumTime = classNum * singleClssTime * studentIds.size();//消耗时长
-//        List<CourseTimeEntity> timeList = arrangeCourseVo.getTimeList();//选课时间
-//        Integer consumeTime = arrangeCourseVo.getConsumeTime();
-//
-//        //校验课时
-//        if (timeList.size() != classNum) {
-//            throw new BizException("课时数与排课数不符");
-//        }
-//
-//        //校验消耗时长
-//        if (!consumTime.equals(consumeTime)) {
-//            throw new BizException("时长计算错误");
-//        }
-//
-//        //校验上下课时间
-//        for (int i = 1; i <= timeList.size(); i++) {
-//            if (!DateUtil.offsetMinute(timeList.get(i).getStartTime(), singleClssTime).equals(timeList.get(i).getEndTime())) {
-//                throw new BizException("第{}节课结束时间计算错误", i);
-//            }
-//        }
-//
-//        //校验时长
-//        PinaoRoomTime pinaoRoomTime = pinaoRoomTimeDao.selectOne(Wrappers.<PinaoRoomTime>lambdaQuery().eq(PinaoRoomTime::getTeacherId, teacherId));
-//        if (pinaoRoomTime == null) {
-//            throw new BizException("未查询到老师剩余时长");
-//        }
-//        Long remainTime = pinaoRoomTime.getRemainTime();
-//        Long frozenTime = pinaoRoomTime.getFrozenTime();
-//        if (consumTime > remainTime) {
-//            throw new BizException("剩余时长不足");
-//        }
-//
-//        //校验学员是否绑定
-//        List<UserBindingTeacher> bindingTeachers = userBindingTeacherDao.selectList(Wrappers.<UserBindingTeacher>lambdaQuery().eq(UserBindingTeacher::getTeacherId, teacherId));
-//        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(bindingTeachers)) {
-//            throw new BizException("无绑定学员");
-//        }
-//        List<Long> studentList = bindingTeachers.stream().map(UserBindingTeacher::getStudentId).collect(Collectors.toList());
-//        for (Long studentId : studentIds) {
-//            if (!studentList.contains(studentId)) {
-//                throw new BizException("学员id:{},未绑定", studentId);
-//            }
-//        }
-//
-//        //校验传入时间是否交集
-//        if (timeList.size() > 1) {
-//            for (int i = 0; i < timeList.size(); i++) {
-//                if (i == timeList.size() - 1) {
-//                    break;
-//                }
-//                CourseTimeEntity o = timeList.get(i);
-//                List<CourseTimeEntity> newList = timeList.subList(i + 1, timeList.size());
-//                boolean checkParamTime = courseScheduleService.checkCourseTime(newList, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime, o.getStartTime(), o.getEndTime());
-//                if (checkParamTime) {
-//                    throw new BizException(DateUtil.dateToString(o.getStartTime(), "yyyy年MM月dd号 HH点mm分") + "的课程时间重复!");
-//                }
-//            }
-//        }
-//
-//        //批量检查老师课时在数据库是否重复
-//        groupService.batchCheckTeacherCourseTime(teacherId, timeList, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime);
-//
-//        //校验购买的课程组每节课时间是否和自己的课时冲突
-//        for (Long studentId : studentIds) {
-//            groupService.batchCheckStudentCourseTime(studentId, timeList, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime);
-//        }
-//
-//        //添加课程组
-//        CourseGroup courseGroup = new CourseGroup();
-//        courseGroup.setType(CourseScheduleEnum.PIANO_ROOM_CLASS.getCode());
-//        courseGroup.setTeacherId(teacherId);
-//        courseGroup.setName(arrangeCourseVo.getCourseName());
-//        courseGroup.setSubjectId(arrangeCourseVo.getSubjectId());
-//        courseGroup.setSingleCourseMinutes(singleClssTime);
-//        courseGroup.setCourseNum(classNum);
-//        courseGroup.setStatus(CourseGroupEnum.NOT_SALE.getCode());
-//        courseGroup.setCreatedBy(teacherId);
-//        courseGroupDao.insert(courseGroup);
-//
-//        for (int i = 0; i < timeList.size(); i++) {
-//            //添加课程
-//            CourseTimeEntity courseTimeEntity = timeList.get(i);
-//            CourseSchedule schedule = new CourseSchedule();
-//            schedule.setCourseGroupId(courseGroup.getId());
-//            schedule.setType(CourseScheduleEnum.PIANO_ROOM_CLASS.getCode());
-//            schedule.classNum(i + 1);
-//            schedule.setTeacherId(teacherId);
-//            schedule.setClassDate(DateUtil.trunc(courseTimeEntity.getStartTime()));
-//            schedule.setStartTime(courseTimeEntity.getStartTime());
-//            schedule.setEndTime(courseTimeEntity.getEndTime());
-//            schedule.setLock(0);
-//            schedule.setStatus(CourseScheduleEnum.NOT_START.getCode());
-//            schedule.setCreatedBy(teacherId);
-//            courseScheduleDao.insert(schedule);
-//
-//            //添加course_schedule_teacher_time
-//            CourseScheduleStudent teacherTime = new CourseScheduleStudent();
-//            teacherTime.setCourseGroupId(courseGroup.getId());
-//            teacherTime.setCourseScheduleId(schedule.getId());
-//            teacherTime.setTeacherId(teacherId);
-//            teacherTime.setStudentIdList(org.apache.commons.lang.StringUtils.join(studentIds, ","));
-//            teacherTime.setClassNum(i + 1);
-//            teacherTime.setConsumeTime(Long.valueOf(singleClssTime));
-//            baseMapper.insert(teacherTime);
-//        }
-//
-//        //扣减pinao_room_time
-//        PinaoRoomTime roomTime = new PinaoRoomTime();
-//        roomTime.setRemainTime(remainTime - consumTime);
-//        roomTime.setFrozenTime(frozenTime + consumTime);
-//        pinaoRoomTimeDao.update(roomTime, Wrappers.<PinaoRoomTime>lambdaQuery().eq(PinaoRoomTime::getTeacherId, teacherId));
-//    }
+    /**
+     * @Description: 我的学员&课内学员
+     * @Author: cy
+     * @Date: 2022/5/27
+     */
+    public PageInfo<CourseStudentVo> selectStudent(Map<String, Object> param) {
+        Integer courseId = (Integer) param.get("courseId");
+        if (courseId != null) {
+            List<CourseScheduleStudent> studentList = courseScheduleStudentDao.selectList(Wrappers.<CourseScheduleStudent>lambdaQuery().eq(CourseScheduleStudent::getCourseId, courseId));
+            param.put("studentList", studentList);//根据课程id查询报课学员
+        }
+        return PageUtil.pageInfo(userBindingTeacherDao.selectStudent(PageUtil.getPageInfo(param), param));
+    }
+
+    /**
+     * @Description: 排课
+     * @Author: cy
+     * @Date: 2022/5/27
+     */
+    public void arrangeCourse(ArrangeCourseVo arrangeCourseVo, Long teacherId) {
+        DistributedLock.of(redissonClient)
+                .runIfLockCanGet(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey("teacherId:" + teacherId)
+                        , () -> this.checkArrangeCourse(arrangeCourseVo, teacherId), 60L, TimeUnit.SECONDS);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    public void checkArrangeCourse(ArrangeCourseVo arrangeCourseVo, Long teacherId) {
+        Integer classNum = arrangeCourseVo.getClassNum();//课时数
+        Integer singleClssTime = arrangeCourseVo.getSingleClssTime();//单课时长
+        List<Long> studentIds = arrangeCourseVo.getStudentIds();//学员id集合
+        Integer consumTime = classNum * singleClssTime * studentIds.size();//消耗时长
+        List<CourseTimeEntity> timeList = arrangeCourseVo.getTimeList();//选课时间
+        Integer consumeTime = arrangeCourseVo.getConsumeTime();
+
+        //校验课时
+        if (timeList.size() != classNum) {
+            throw new BizException("课时数与排课数不符");
+        }
+
+        //校验消耗时长
+        if (!consumTime.equals(consumeTime)) {
+            throw new BizException("时长计算错误");
+        }
+
+        //校验上下课时间
+        for (int i = 0; i < timeList.size(); i++) {
+            if (!DateUtil.offsetMinute(timeList.get(i).getStartTime(), singleClssTime).equals(timeList.get(i).getEndTime())) {
+                throw new BizException("第{}节课结束时间计算错误", i + 1);
+            }
+        }
+
+        //校验时长
+        PinaoRoomTime pinaoRoomTime = pinaoRoomTimeDao.selectOne(Wrappers.<PinaoRoomTime>lambdaQuery().eq(PinaoRoomTime::getTeacherId, teacherId));
+        if (pinaoRoomTime == null) {
+            throw new BizException("未查询到老师剩余时长");
+        }
+        Long remainTime = pinaoRoomTime.getRemainTime();
+        Long frozenTime = pinaoRoomTime.getFrozenTime();
+        if (consumTime > remainTime) {
+            throw new BizException("剩余时长不足");
+        }
+
+        //校验学员是否绑定
+        List<UserBindingTeacher> bindingTeachers = userBindingTeacherDao.selectList(Wrappers.<UserBindingTeacher>lambdaQuery().eq(UserBindingTeacher::getTeacherId, teacherId));
+        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(bindingTeachers)) {
+            throw new BizException("无绑定学员");
+        }
+        List<Long> studentList = bindingTeachers.stream().map(UserBindingTeacher::getStudentId).collect(Collectors.toList());
+        for (Long studentId : studentIds) {
+            if (!studentList.contains(studentId)) {
+                throw new BizException("学员id:{},未绑定", studentId);
+            }
+        }
+
+        //校验传入时间是否交集
+        if (timeList.size() > 1) {
+            for (int i = 0; i < timeList.size(); i++) {
+                if (i == timeList.size() - 1) {
+                    break;
+                }
+                CourseTimeEntity o = timeList.get(i);
+                List<CourseTimeEntity> newList = timeList.subList(i + 1, timeList.size());
+                boolean checkParamTime = this.checkCourseTime(newList, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime, o.getStartTime(), o.getEndTime());
+                if (checkParamTime) {
+                    throw new BizException(DateUtil.dateToString(o.getStartTime(), "yyyy年MM月dd号 HH点mm分") + "的课程时间重复!");
+                }
+            }
+        }
+
+        //批量检查老师课时在数据库是否重复
+        this.batchCheckTeacherCourseTime(teacherId, timeList, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime);
+
+        //校验购买的课程组每节课时间是否和自己的课时冲突
+        for (Long studentId : studentIds) {
+            this.batchCheckStudentCourseTime(studentId, timeList, CourseTimeEntity::getStartTime, CourseTimeEntity::getEndTime);
+        }
+
+        //添加课程组
+        CourseGroup courseGroup = new CourseGroup();
+        courseGroup.setType(CourseScheduleEnum.PIANO_ROOM_CLASS.getCode());
+        courseGroup.setTeacherId(teacherId);
+        courseGroup.setName(arrangeCourseVo.getCourseName());
+        courseGroup.setSubjectId(arrangeCourseVo.getSubjectId());
+        courseGroup.setSingleCourseMinutes(singleClssTime);
+        courseGroup.setCourseNum(classNum);
+        courseGroup.setStatus(CourseGroupEnum.NOT_SALE.getCode());
+        courseGroup.setCreatedBy(teacherId);
+        courseGroupService.getDao().insert(courseGroup);
+
+        for (int i = 0; i < timeList.size(); i++) {
+            //添加课程
+            CourseTimeEntity courseTimeEntity = timeList.get(i);
+            CourseSchedule schedule = new CourseSchedule();
+            schedule.setCourseGroupId(courseGroup.getId());
+            schedule.setType(CourseScheduleEnum.PIANO_ROOM_CLASS.getCode());
+            schedule.classNum(i + 1);
+            schedule.setTeacherId(teacherId);
+            schedule.setClassDate(DateUtil.trunc(courseTimeEntity.getStartTime()));
+            schedule.setStartTime(courseTimeEntity.getStartTime());
+            schedule.setEndTime(courseTimeEntity.getEndTime());
+            schedule.setLock(0);
+            schedule.setStatus(CourseScheduleEnum.NOT_START.getCode());
+            schedule.setCreatedBy(teacherId);
+            schedule.setSingleCourseTime(singleClssTime);
+            baseMapper.insert(schedule);
+
+            //添加course_schedule_student
+            List<CourseScheduleStudent> list = new ArrayList<>();
+            for (Long studentId : studentIds) {
+                CourseScheduleStudent teacherTime = new CourseScheduleStudent();
+                teacherTime.setStudentId(studentId);
+                teacherTime.setCourseId(schedule.getId());
+                list.add(teacherTime);
+            }
+            courseScheduleStudentDao.insertBatch(list);
+        }
+
+        //扣减pinao_room_time
+        PinaoRoomTime roomTime = new PinaoRoomTime();
+        roomTime.setRemainTime(remainTime - consumTime);
+        roomTime.setFrozenTime(frozenTime + consumTime);
+        pinaoRoomTimeDao.update(roomTime, Wrappers.<PinaoRoomTime>lambdaQuery().eq(PinaoRoomTime::getTeacherId, teacherId));
+    }
 }

+ 16 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/SmsCodeServiceImpl.java

@@ -30,8 +30,22 @@ public class SmsCodeServiceImpl implements SmsCodeService {
 	private SysConfigService sysConfigService;
 
 	@Override
-	public boolean verifyValidCode(String mobile, String authCode) {
-		String verifyCode = sysMessageService.getSendedVerificationCode(MessageTypeEnum.SMS_VERIFY_CODE_LOGIN, mobile);
+	public boolean verifyValidCode(String mobile, String authCode, String type) {
+		MessageTypeEnum typeEnum;
+		if ("PASSWD".equals(type)) {
+			typeEnum  = MessageTypeEnum.SMS_VERIFY_CODE_UPDATE_PSW;
+		} else if ("LOGIN".equals(type)) {
+			typeEnum  = MessageTypeEnum.SMS_VERIFY_CODE_LOGIN;
+		} else if ("REGISTER".equals(type)) {
+			typeEnum  = MessageTypeEnum.SMS_VERIFY_CODE_REGISTER;
+		} else if ("BANK".equals(type)){
+			typeEnum  = MessageTypeEnum.SMS_VERIFY_CODE_BANK_CARD;
+		} else if ("PHONE".equals(type)) {
+			typeEnum  = MessageTypeEnum.SMS_VERIFY_CODE_UPDATE_PHONE;
+		} else {
+			typeEnum  = MessageTypeEnum.SMS_VERIFY_CODE;
+		}
+		String verifyCode = sysMessageService.getSendedVerificationCode(typeEnum, mobile);
 		if (StringUtils.isNoneEmpty(verifyCode) && StringUtils.equalsIgnoreCase(verifyCode, authCode)) {
 			return true;
 		}

+ 5 - 6
cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleMapper.xml

@@ -792,18 +792,17 @@
     <select id="selectIdList" resultType="java.lang.Long">
         SELECT id_ FROM course_schedule WHERE lock_=0 AND class_date_ &lt;= #{day}
     </select>
-    <select id="selectUpStartIds" resultType="java.lang.Long">
-        SELECT id_ FROM course_schedule WHERE lock_=0
-        AND status_='NOT_START' AND start_time_ &lt;= NOW() AND NOW() &lt;= end_time_
-    </select>
     <update id="updateStartTime">
         UPDATE course_schedule SET status_='ING' WHERE id_ IN(
         <foreach collection="list" item="item" index="index" open="" close="" separator=",">
-            #{item}
+            #{item.id}
         </foreach>)
     </update>
     <update id="updateEndTime">
-        UPDATE course_schedule SET status_='COMPLETE' WHERE status_ != 'CANCEL' <![CDATA[ AND end_time_ <= NOW() ]]>
+        UPDATE course_schedule SET status_='COMPLETE' WHERE id_ IN(
+        <foreach collection="list" item="item" index="index" open="" close="" separator=",">
+            #{item.id}
+        </foreach>)
     </update>
     <update id="updateTeacherSalary" parameterType="java.util.List">
         UPDATE course_schedule_teacher_salary

+ 10 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/CourseScheduleStudentMapper.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.yonge.cooleshow.biz.dal.dao.CourseScheduleStudentDao">
+    <insert id="insertBatch">
+        INSERT INTO course_schedule_student (course_id_, student_id_) VALUES
+        <foreach collection ="list" item="item" separator =",">
+            (#{item.courseId}, #{item.studentId})
+        </foreach >
+    </insert>
+</mapper>

+ 3 - 4
cooleshow-user/user-biz/src/main/resources/config/mybatis/UserBindingTeacherMapper.xml

@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.yonge.cooleshow.biz.dal.dao.UserBindingTeacherDao">
-
     <select id="selectStudent" resultType="com.yonge.cooleshow.biz.dal.vo.CourseStudentVo">
         SELECT
         su.id_ AS userId,
@@ -24,10 +23,10 @@
             <if test="param.userName !=null and param.userName !=''">
                 AND su.username_ LIKE CONCAT('%', #{param.userName}, '%')
             </if>
-            <if test="param.idList !=null and param.idList.size>0">
+            <if test="param.studentList !=null and param.studentList.size>0">
                 AND su.id_ IN
-                <foreach collection="param.idList" item="item" open="(" separator="," close=")">
-                    #{item}
+                <foreach collection="param.studentList" item="item" open="(" separator="," close=")">
+                    #{item.studentId}
                 </foreach>
             </if>
         </where>

+ 4 - 3
cooleshow-user/user-student/src/main/java/com/yonge/cooleshow/student/controller/SmsCodeController.java

@@ -47,13 +47,14 @@ public class SmsCodeController extends BaseController {
 
     @ApiOperation(value = "校验短信验证码")
     @ApiImplicitParams({ @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String"),
-            @ApiImplicitParam(name = "code", value = "短信验证码", required = true, dataType = "String") })
+                         @ApiImplicitParam(name = "code", value = "短信验证码", required = true, dataType = "String"),
+                         @ApiImplicitParam(name = "type", value = "类型(PASSWD:修改密码,LOGIN:登录或注册,BANK:绑定银行卡,PHONE:修改手机号)", required = true, dataType = "String") })
     @PostMapping(value = "/verifySmsCode")
-    public Object verifySmsCode(String phone,String code) {
+    public Object verifySmsCode(String phone,String code,String type) {
         if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)){
             return failed(SecurityConstants.PARAM_VERIFY_EXCEPTION);
         }
-        if(smsCodeService.verifyValidCode(phone,code)){
+        if(smsCodeService.verifyValidCode(phone, code, type)){
             return succeed();
         }
         return failed("验证码校验失败");

+ 4 - 3
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/SmsCodeController.java

@@ -47,13 +47,14 @@ public class SmsCodeController extends BaseController {
 
     @ApiOperation(value = "校验短信验证码")
     @ApiImplicitParams({ @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String"),
-            @ApiImplicitParam(name = "code", value = "短信验证码", required = true, dataType = "String") })
+                         @ApiImplicitParam(name = "code", value = "短信验证码", required = true, dataType = "String"),
+                         @ApiImplicitParam(name = "type", value = "类型(PASSWD:修改密码,LOGIN:登录或注册,BANK:绑定银行卡,PHONE:修改手机号)", required = true, dataType = "String") })
     @PostMapping(value = "/verifySmsCode")
-    public Object verifySmsCode(String phone,String code) {
+    public Object verifySmsCode(String phone,String code,String type) {
         if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)){
             return failed(SecurityConstants.PARAM_VERIFY_EXCEPTION);
         }
-        if(smsCodeService.verifyValidCode(phone,code)){
+        if(smsCodeService.verifyValidCode(phone, code, type)){
             return succeed();
         }
         return failed("验证码校验失败");

+ 27 - 0
cooleshow-user/user-teacher/src/main/java/com/yonge/cooleshow/teacher/controller/TeacherCourseScheduleController.java

@@ -168,5 +168,32 @@ public class TeacherCourseScheduleController extends BaseController {
         }
         return succeed(courseScheduleService.selectRemainTime(user.getId()));
     }
+
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "subjectId", dataType = "Long", value = "声部id"),
+            @ApiImplicitParam(name = "userName", dataType = "String", value = "学员姓名"),
+            @ApiImplicitParam(name = "courseId", dataType = "Long", value = "课程id"),
+    })
+    @ApiOperation("我的学员&课内学员")
+    @PostMapping("/selectStudent")
+    public HttpResponseResult<PageInfo<CourseStudentVo>> selectStudent(@RequestBody Map<String, Object> param) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        param.put("teacherId", user.getId());
+        return succeed(courseScheduleService.selectStudent(param));
+    }
+
+    @ApiOperation("排课")
+    @PostMapping("/arrangeCourse")
+    public HttpResponseResult<Object> arrangeCourse(@RequestBody ArrangeCourseVo arrangeCourseVo) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        courseScheduleService.arrangeCourse(arrangeCourseVo, user.getId());
+        return succeed();
+    }
 }