| @@ -7,7 +7,10 @@ import com.iformall.common.Result; | |||
| import com.iformall.common.ResultData; | |||
| import com.iformall.controller.base.BaseController; | |||
| import com.iformall.domain.dto.OrderSaveDto; | |||
| import com.iformall.domain.po.*; | |||
| import com.iformall.domain.po.WxCUser; | |||
| import com.iformall.domain.po.WxCoupon; | |||
| import com.iformall.domain.po.WxCouponChannel; | |||
| import com.iformall.domain.po.WxOrder; | |||
| import com.iformall.domain.po.base.BaseEntity; | |||
| import com.iformall.domain.vo.WxOrderQueryVo; | |||
| import com.iformall.enums.EnumCouponChannelStatus; | |||
| @@ -58,7 +61,9 @@ public class WxOrderController extends BaseController { | |||
| @SystemControllerLog(description = "订单管理-列表") | |||
| public ResultData list(@ModelAttribute WxOrder wxOrder, Integer pageNum, Integer pageSize) { | |||
| logger.debug("[" + getIpAddr() + "] WxOrderController::list"); | |||
| if (null == wxOrder) wxOrder = new WxOrder(); | |||
| if (null == wxOrder) { | |||
| wxOrder = new WxOrder(); | |||
| } | |||
| wxOrder.setTenantId(getTenantId()); | |||
| wxOrder.setSortColumns(BaseEntity.SortField.CreateDate_DESC,BaseEntity.SortField.Id_DESC); | |||
| final PageInfo<WxOrder> page = wxOrderService.listAsPage(wxOrder, pageNum, pageSize); | |||
| @@ -143,7 +148,9 @@ public class WxOrderController extends BaseController { | |||
| } | |||
| WxCouponChannel wxCouponChannel = wxCouponChannelService.getById(orderSaveDto.getCouponChannelId()); | |||
| ResultData resultData = couponChannelCheck(orderSaveDto, wxCouponChannel); | |||
| if (resultData != null) return resultData; | |||
| if (resultData != null) { | |||
| return resultData; | |||
| } | |||
| Long couponId = orderSaveDto.getCouponId() == null ? wxCouponChannel.getCouponId() : orderSaveDto.getCouponId(); | |||
| if (couponId == null) { | |||
| @@ -161,8 +168,9 @@ public class WxOrderController extends BaseController { | |||
| if (coupon == null) { | |||
| return new ResultData(ErrorCode.COUPON_IS_EMPTY); | |||
| } | |||
| if (!wxOrderService.checkCouponIsFree(coupon)) | |||
| if (!wxOrderService.checkCouponIsFree(coupon)) { | |||
| return new ResultData(ErrorCode.COUPON_IS_NOT_FREE); | |||
| } | |||
| // 免费券 | |||
| order = wxOrderService.saveFreeOrderForCoupon(user, coupon, orderSaveDto.getCouponChannelId(), orderSaveDto.getFormId(), null); | |||
| return new ResultData(order); | |||
| @@ -200,4 +208,29 @@ public class WxOrderController extends BaseController { | |||
| return null; | |||
| } | |||
| @ApiOperation("查看明细") | |||
| @GetMapping("/detail") | |||
| @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) | |||
| @SystemControllerLog(description = "订单管理-id查询") | |||
| public ResultData detail(Long id) { | |||
| logger.debug("[" + getIpAddr() + "] WxOrderController::detail"); | |||
| WxOrder order = new WxOrder(); | |||
| order.setId(id); | |||
| order.setTenantId(getTenantId()); | |||
| return new ResultData(Result.SUCCESS, "查询成功", wxOrderService.detailCUserVo(order)); | |||
| } | |||
| @ApiOperation("交易列表") | |||
| @GetMapping("summary") | |||
| @SystemControllerLog(description = "订单管理-总计") | |||
| public ResultData summary(@ModelAttribute WxOrderQueryVo wxOrderQueryVo) { | |||
| logger.debug("[" + getIpAddr() + "] WxOrderController::summary"); | |||
| if (null == wxOrderQueryVo) { | |||
| wxOrderQueryVo = new WxOrderQueryVo(); | |||
| } | |||
| wxOrderQueryVo.setTenantId(getTenantId()); | |||
| Map<String, Object> data = wxOrderService.summary(wxOrderQueryVo); | |||
| return new ResultData(data); | |||
| } | |||
| } | |||
| @@ -82,4 +82,9 @@ public class WxOrder extends BaseEntity { | |||
| @TableField(exist = false) | |||
| protected String statusStr; | |||
| @TableField(exist = false) | |||
| private String title; | |||
| @TableField(exist = false) | |||
| private Integer attribute; | |||
| } | |||
| @@ -87,4 +87,7 @@ public class WxOrderCouponVo { | |||
| @io.swagger.annotations.ApiModelProperty(value = "是否可转赠", name = "supportTransfer") | |||
| private Integer supportTransfer; | |||
| @io.swagger.annotations.ApiModelProperty(value = "补贴额", name = "subsidyNum") | |||
| private Integer subsidyNum; | |||
| } | |||
| @@ -36,4 +36,13 @@ public class WxOrderQueryVo extends BaseEntity { | |||
| @TableField(exist = false) | |||
| private Date createDate; | |||
| @io.swagger.annotations.ApiModelProperty(value = "产品名称", name = "title") | |||
| private String title; | |||
| @io.swagger.annotations.ApiModelProperty(value = "商品属性", name = "attribute") | |||
| private Integer attribute; | |||
| @io.swagger.annotations.ApiModelProperty(value = "订单号", name = "orderNumber") | |||
| private String orderNumber; | |||
| } | |||
| @@ -189,4 +189,6 @@ public interface WxOrderService { | |||
| */ | |||
| void actionAfterCouponOrderSuccess(WxOrder updateOrder, WxCoupon coupon, WxCUser user); | |||
| Map<String, Object> summary(WxOrderQueryVo wxOrderQueryVo); | |||
| } | |||
| @@ -29,6 +29,7 @@ import java.math.BigDecimal; | |||
| import java.text.ParseException; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.*; | |||
| import java.util.stream.Collectors; | |||
| @Service | |||
| public class WxOrderServiceImpl implements WxOrderService { | |||
| @@ -216,6 +217,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| /** | |||
| * 用户购买的订单数量 | |||
| * | |||
| * @param user | |||
| * @param counpon | |||
| * @return | |||
| @@ -244,6 +246,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| /** | |||
| * 用户购买的订单数量 | |||
| * | |||
| * @param user | |||
| * @param counpon | |||
| * @return | |||
| @@ -263,7 +266,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| statusS.add(EnumOrderStatus.ORDER_STATUS_COOPERATING_UNPAID.getCode()); | |||
| orderQ.setStatusS(statusS); | |||
| List<WxOrder> orders = wxOrderMapper.findList(orderQ); | |||
| if(orders.size() >= 1) { | |||
| if (orders.size() >= 1) { | |||
| return orders.get(0); | |||
| } | |||
| } catch (Exception e) { | |||
| @@ -275,6 +278,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| /** | |||
| * 用户正在参加的新手活动 | |||
| * | |||
| * @param user | |||
| * @return | |||
| */ | |||
| @@ -305,6 +309,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| /** | |||
| * 用户购买的券包数量- 待使用的券 | |||
| * | |||
| * @param user | |||
| * @param counpon | |||
| * @return | |||
| @@ -329,6 +334,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| /** | |||
| * 商户注券减库存 | |||
| * | |||
| * @param user | |||
| * @param coupon | |||
| * @param couponIdStr | |||
| @@ -343,8 +349,8 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| throw new MallinkException(ErrorCode.TOO_MANY_REQUEST.getCode(), coupon.getTitle() + ErrorCode.TOO_MANY_REQUEST.getMessage()); | |||
| } | |||
| JSONObject jo = JSONObject.parseObject(wxCouponSendVo.getConditions()) ; | |||
| int merchantSend = jo.getIntValue(WxCouponSend.KEY_MERCHANT_SEND) ; | |||
| JSONObject jo = JSONObject.parseObject(wxCouponSendVo.getConditions()); | |||
| int merchantSend = jo.getIntValue(WxCouponSend.KEY_MERCHANT_SEND); | |||
| int merchantRemain = jo.getIntValue(WxCouponSend.KEY_MERCHANT_REMAIN); | |||
| // 检查 优惠券 库存 | |||
| @@ -390,7 +396,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| try { | |||
| // 减库存 | |||
| wxCouponSendService.reduceMerchantSend(wxCouponSendVo.getId(), merchantRemain,merchantSend,1); | |||
| wxCouponSendService.reduceMerchantSend(wxCouponSendVo.getId(), merchantRemain, merchantSend, 1); | |||
| } catch (RuntimeException e) { | |||
| logger.error("此券减库存失败, couponId: {}, error: {}", couponIdStr, e.getMessage()); | |||
| throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(), coupon.getTitle() + ErrorCode.ORDER_IS_LIMITED.getMessage()); | |||
| @@ -403,6 +409,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| /** | |||
| * 减库存 | |||
| * | |||
| * @param user | |||
| * @param coupon | |||
| * @param couponIdStr | |||
| @@ -411,7 +418,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| long time = System.currentTimeMillis() + RedisLock.TIMEOUT; | |||
| String timeStr = String.valueOf(time); | |||
| // 库存加锁 | |||
| if (!redisLock.lock(couponIdStr, timeStr)) { | |||
| if (!redisLock.lock(couponIdStr, timeStr)) { | |||
| logger.error("此券被锁定, couponId: " + couponIdStr); | |||
| throw new MallinkException(ErrorCode.TOO_MANY_REQUEST); | |||
| } | |||
| @@ -525,6 +532,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| /** | |||
| * 检查券商户是否可用 | |||
| * | |||
| * @param couponId | |||
| * @return | |||
| */ | |||
| @@ -733,9 +741,9 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| Integer shareAmount = payOrder.getPayAmount() - fee; | |||
| cardInfo.setShareFeeAmount(shareAmount); | |||
| cardInfo.setRemainingShareFeeAmount(shareAmount); | |||
| if(payAccount.getRealRate() != null) { | |||
| if (payAccount.getRealRate() != null) { | |||
| int iRealChargeFee = PayUtils.getPayRate(payOrder.getPayAmount(), payAccount.getRealRate(), true); | |||
| if(fee > iRealChargeFee) { | |||
| if (fee > iRealChargeFee) { | |||
| cardInfo.setRateAmount(fee - iRealChargeFee); | |||
| } | |||
| } | |||
| @@ -774,7 +782,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| @Override | |||
| @Transactional(propagation = Propagation.NESTED, readOnly = false, rollbackFor = {Exception.class}) | |||
| public WxCouponOrder sendFreeCouponToUser(Long userId, Long couponId,WxCouponSendVo wxCouponSendVo) { | |||
| public WxCouponOrder sendFreeCouponToUser(Long userId, Long couponId, WxCouponSendVo wxCouponSendVo) { | |||
| // check 用户状态 | |||
| WxCUser user = null; | |||
| try { | |||
| @@ -805,7 +813,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| if (Objects.nonNull(wxCouponSendVo) && Objects.equals(EnumCouponSendSendType.MERCHANT.getCode(), wxCouponSendVo.getSendType())) { | |||
| // 商户注券减库存操作 | |||
| stockMerchantReduce(user,coupon,couponIdStr,wxCouponSendVo); | |||
| stockMerchantReduce(user, coupon, couponIdStr, wxCouponSendVo); | |||
| } else { | |||
| // 减库存操作 | |||
| stockReduce(user, coupon, couponIdStr); | |||
| @@ -951,6 +959,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| /** | |||
| * 下订单后操作 | |||
| * | |||
| * @param updateOrder | |||
| * @param coupon | |||
| * @param user | |||
| @@ -968,6 +977,19 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| } | |||
| @Override | |||
| public Map<String, Object> summary(WxOrderQueryVo wxOrderQueryVo) { | |||
| List<WxOrder> listOrder = wxOrderMapper.findListOrder(wxOrderQueryVo); | |||
| Long orderPay = listOrder.stream().collect(Collectors.summingLong(WxOrder::getPayment)); | |||
| Long pay = listOrder.stream().filter(o -> !o.getOrderStatus().equals(EnumOrderStatus.ORDER_STATUS_PENDING_PAYMENT.getCode()) | |||
| && !o.getOrderStatus().equals(EnumOrderStatus.ORDER_STATUS_OVERTIME_CANCEL.getCode())) | |||
| .collect(Collectors.summingLong(WxOrder::getPayment)); | |||
| Map<String, Object> data = new HashMap<>(); | |||
| data.put("orderPay", orderPay); | |||
| data.put("pay", pay); | |||
| return data; | |||
| } | |||
| /** | |||
| * 积分设置来源商户 | |||
| */ | |||
| @@ -1396,7 +1418,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| if (checkCouponIsFree(coupon)) { | |||
| // 免费券 | |||
| order = saveFreeOrderForCoupon(user, coupon, orderSaveDto.getCouponChannelId(), orderSaveDto.getFormId(), null); | |||
| if(order != null) { | |||
| if (order != null) { | |||
| // 6. 下订单完成,发送内部消息 | |||
| // 下订单完成,发送内部消息 | |||
| try { | |||
| @@ -1479,6 +1501,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| /** | |||
| * 保存订单-免费 | |||
| * | |||
| * @param record | |||
| * @param user | |||
| * @param coupon | |||
| @@ -1607,7 +1630,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| // 5. 第一次砍价 | |||
| try { | |||
| firstPress(record, user, coupon, orderNumber); | |||
| }catch (Exception e) { | |||
| } catch (Exception e) { | |||
| logger.error("第一次砍价失败:" + e.getMessage()); | |||
| throw new MallinkException(ErrorCode.ORDER_SAVE_ERR); | |||
| } | |||
| @@ -1617,6 +1640,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| /** | |||
| * 初始砍价 | |||
| * | |||
| * @param record | |||
| * @param user | |||
| * @param coupon | |||
| @@ -222,7 +222,7 @@ | |||
| <sql id="allCUserOrderDetailColumns"> | |||
| o.id,o.order_number,o.tenant_id,o.c_user_id,o.coupon_channel_id,o.product_id,o.payment_type,o.payment,o.payment_time,o.order_status,o.create_date,o.update_date, | |||
| c.type,c.cover_img,c.title,c.sub_title,c.sale_price,c.use_price,c.price,c.unit,c.detail,c.remark,c.valid_start_date,c.valid_end_date, | |||
| co.id as coupon_order_id,co.coupon_order_status,c.support_transfer | |||
| co.id as coupon_order_id,co.coupon_order_status,c.support_transfer,c.subside_num | |||
| </sql> | |||
| <update id="updateStatusByPressCouponId" parameterType="com.iformall.domain.po.WxOrder"> | |||
| @@ -278,7 +278,8 @@ | |||
| <result column="remark" jdbcType="VARCHAR" property="remark"/> | |||
| <result column="valid_start_date" jdbcType="TIMESTAMP" property="validStartDate"/> | |||
| <result column="valid_end_date" jdbcType="TIMESTAMP" property="validEndDate"/> | |||
| <result column="subsidy_num" jdbcType="INTEGER" property="subsidyNum"></result> | |||
| <result column="coupon_order_id" jdbcType="BIGINT" property="couponOrderId"/> | |||
| <result column="coupon_order_status" jdbcType="INTEGER" property="couponOrderStatus"/> | |||
| <result column="send_channel_type" jdbcType="INTEGER" property="sendChannelType" /> | |||
| @@ -538,43 +539,49 @@ | |||
| <result column="merchant_name" jdbcType="VARCHAR" property="merchantName"/> | |||
| <result column="c_user_name" jdbcType="VARCHAR" property="cUserName"/> | |||
| <result column="phone" jdbcType="VARCHAR" property="phone"/> | |||
| <result column="title" jdbcType="VARCHAR" property="title"/> | |||
| <result column="attribute" jdbcType="INTEGER" property="attribute"/> | |||
| </resultMap> | |||
| <select id="findListOrder" resultMap="orderMap" parameterType="com.iformall.domain.vo.WxOrderQueryVo"> | |||
| select o.* from ( | |||
| select o.id,o.order_number,o.tenant_id,o.c_user_id,o.coupon_channel_id,o.product_id,o.type,o.payment_type,o.payment,o.payment_time, | |||
| o.order_status,o.create_date,o.update_date,o.detail,'[多商户交易]' merchant_name,cubi.`name` c_user_name,cubi.phone | |||
| from | |||
| ( | |||
| select o.* from wx_order o where o.type=0 and o.order_status in (0,2,3,1,4) and o.id in( | |||
| select o.id from wx_order o left join wx_coupon_merchant cm | |||
| on o.product_id=cm.product_id group by o.id having count(o.id)>1)) o | |||
| left join wx_c_user_basic_info cubi on o.c_user_id=cubi.id where o.tenant_id =#{tenantId} | |||
| select o.id,o.order_number,o.tenant_id,o.product_id,o.payment,o.order_status, | |||
| c.title,cubi.`name` c_user_name,cubi.phone,o.create_date,1 attribute from wx_order o | |||
| left join wx_c_user_basic_info cubi on o.c_user_id=cubi.id | |||
| left join wx_coupon c on o.product_id=c.id | |||
| where o.tenant_id=#{tenantId} and c.type=100 | |||
| union all | |||
| select o.id,o.order_number,o.tenant_id,o.c_user_id,o.coupon_channel_id,o.product_id,o.type,o.payment_type,o.payment,o.payment_time, | |||
| o.order_status,o.create_date,o.update_date,o.detail,m.`name` merchant_name,cubi.`name` c_user_name,cubi.phone | |||
| from( | |||
| select o.*,cm.merchant_id from ( | |||
| select o.* from wx_order o where o.type=0 and o.order_status in (0,2,3,1,4) and o.id not in( | |||
| select o.id from wx_order o left join wx_coupon_merchant cm | |||
| on o.product_id=cm.product_id group by o.id having count(o.id)>1) | |||
| ) o | |||
| left join wx_coupon_merchant cm on o.product_id=cm.product_id where o.tenant_id =#{tenantId} | |||
| select o.id,o.order_number,o.tenant_id,o.product_id,o.payment,o.order_status, | |||
| c.title,cubi.`name` c_user_name,cubi.phone,o.create_date,2 attribute from wx_order o | |||
| left join wx_c_user_basic_info cubi on o.c_user_id=cubi.id | |||
| left join wx_coupon c on o.product_id=c.id | |||
| where o.tenant_id=#{tenantId} and c.type!=100 and o.payment=c.price | |||
| union all | |||
| select o.*,mbu.merchant_id from wx_order o | |||
| left join wx_merchant_b_user mbu on o.product_id=mbu.id | |||
| where o.type in (1,2) and o.order_status in (0,2,3,1,4) ) o | |||
| left join wx_merchant m on o.merchant_id=m.id | |||
| left join wx_c_user_basic_info cubi on o.c_user_id=cubi.id where o.tenant_id =#{tenantId} | |||
| select o.id,o.order_number,o.tenant_id,o.product_id,o.payment, | |||
| case o.order_status when 6 then 0 when 7 then 1 | |||
| when 8 then 2 when 9 then 2 else o.order_status end order_status, | |||
| c.title,cubi.`name` c_user_name,cubi.phone,o.create_date,3 attribute from wx_order o | |||
| left join wx_c_user_basic_info cubi on o.c_user_id=cubi.id | |||
| left join wx_coupon c on o.product_id=c.id | |||
| where o.tenant_id=#{tenantId} and c.type=8 and o.payment!=c.price | |||
| union all | |||
| select o.id,o.order_number,o.tenant_id,o.product_id,o.payment, | |||
| case o.order_status when 10 then 1 when 11 then 1 | |||
| when 12 then 4 when 13 then 4 when 14 then 4 when 15 then 0 when 16 then 2 | |||
| else o.order_status end order_status, | |||
| c.title,cubi.`name` c_user_name,cubi.phone,o.create_date,4 attribute from wx_order o | |||
| left join wx_c_user_basic_info cubi on o.c_user_id=cubi.id | |||
| left join wx_coupon c on o.product_id=c.id | |||
| where o.tenant_id=#{tenantId} and c.type=9 and o.payment!=c.price | |||
| ) o | |||
| <where> | |||
| <if test="tenantId!=null"> | |||
| and o.tenant_id =#{tenantId} | |||
| </if> | |||
| <if test="merchantName!=null and merchantName!=''"> | |||
| and o.`merchant_name` like concat('%',#{merchantName},'%') | |||
| <if test="title!=null and title!=''"> | |||
| and o.`title` like concat('%',#{title},'%') | |||
| </if> | |||
| <if test="payment!=null and (payment== '' or payment == 0)"> | |||
| and o.`payment` = 0 | |||
| @@ -589,6 +596,12 @@ | |||
| <if test="orderStatus!=null"> | |||
| and o.order_status = #{orderStatus} | |||
| </if> | |||
| <if test="attribute!=null"> | |||
| and o.attribute = #{attribute} | |||
| </if> | |||
| <if test="orderNumber!=null"> | |||
| and o.order_number like concat('%',#{orderNumber},'%') | |||
| </if> | |||
| </where> | |||
| <if test=" null != sortColumns"> order by ${sortColumns} </if> | |||