| @@ -149,6 +149,13 @@ public class WxCouponOrderController extends BaseController { | |||
| return wxCouponOrderService.listOnDateAsPageV2(getLoginBUser().getId(), startDate, endDate, pageNum, pageSize, true); | |||
| } | |||
| @ApiOperation("核销流水统计接口") | |||
| @GetMapping("sumVerified") | |||
| public ResultData sumVerified(@RequestParam("startDate") @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") Date startDate, | |||
| @RequestParam("endDate") @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") Date endDate) { | |||
| return wxCouponOrderService.sumVerified(getLoginBUser(), startDate, endDate); | |||
| } | |||
| @ApiOperation("某日期交易总流水") | |||
| @GetMapping("getUnverifiedAmountOnDate") | |||
| @ApiImplicitParams({ | |||
| @@ -276,6 +276,14 @@ public class WxMicroPayController extends BaseController { | |||
| return wxOrderService.microPayListOnDateAsPageV2(getLoginBUser().getId(), EnumOrderType.MICROPAY.getCode(), startDate, endDate, pageNum, pageSize); | |||
| } | |||
| @RedisCache | |||
| @ApiOperation("付款码支付交易流水分页列表接口") | |||
| @GetMapping("sumMicroPay") | |||
| public ResultData sumMicroPay(@RequestParam("startDate") @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") Date startDate, | |||
| @RequestParam("endDate") @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") Date endDate) { | |||
| return wxOrderService.sumMicroPay(getLoginBUser(), EnumOrderType.MICROPAY.getCode(), startDate, endDate); | |||
| } | |||
| @RedisCache | |||
| @ApiOperation("付款码支付某日期交易总流水") | |||
| @GetMapping("getMicroPayAmountOnDate") | |||
| @@ -13,6 +13,7 @@ import com.iformall.service.park.ParkFactory; | |||
| import com.iformall.service.park.entity.ParkNotifyParam; | |||
| import com.iformall.service.park.utils.ParkCacheUtils; | |||
| import com.iformall.utils.DateUtils; | |||
| import com.iformall.utils.RedisCacheUtils; | |||
| import org.apache.commons.collections.CollectionUtils; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.slf4j.Logger; | |||
| @@ -168,9 +169,15 @@ public class WxParkCallBackBaseController extends BaseController { | |||
| if (null == param) { | |||
| return new Result(); | |||
| } | |||
| // 回调去重 | |||
| String key = "callback:" + param.getCarNumber(); | |||
| if (RedisCacheUtils.hasKey(redisTemplate, key)) { | |||
| logger.info("回调数据重复=========>{}", JSON.toJSONString(param)); | |||
| return new Result(); | |||
| } | |||
| RedisCacheUtils.cache(redisTemplate, key, "", 60 * 2); | |||
| String carNumber = param.getCarNumber(); | |||
| ParkCacheUtils.removeCache(redisTemplate, vendor.getMessage(), carNumber); | |||
| ParkCacheUtils.setCarCouponUnUseCacheLock(redisTemplate, vendor.getMessage(), carNumber); | |||
| @@ -12,9 +12,9 @@ public class CallTest { | |||
| private static final String BASIC_URL = "https://openapitest.malls.iformall.com"; | |||
| public static void main(String[] args) { | |||
| String appId = "CP6nwHvZ"; | |||
| String appKey = "b257eb97bb9380714306a077a66086e8b1f10639"; | |||
| String signKey = "C61842C8570524AA81756C53B8096978A06AE00D"; | |||
| String appId = "YhCW8Dra"; | |||
| String appKey = "389ac85b768b19427685bcc4adea0474cef22a14"; | |||
| String signKey = "B0AB3E2CBCB484D04AEAD0BEF933F7CF5489450C"; | |||
| // 会员注册 | |||
| // userRegister(appId, appKey, signKey); | |||
| @@ -0,0 +1,11 @@ | |||
| package com.iformall.domain.vo; | |||
| import lombok.Data; | |||
| import java.math.BigDecimal; | |||
| @Data | |||
| public class SumMicroPayVO { | |||
| private BigDecimal amount; | |||
| private Integer total; | |||
| } | |||
| @@ -0,0 +1,11 @@ | |||
| package com.iformall.domain.vo; | |||
| import lombok.Data; | |||
| import java.math.BigDecimal; | |||
| @Data | |||
| public class SumVerifiedVO { | |||
| private BigDecimal amount; | |||
| private Integer total; | |||
| } | |||
| @@ -112,4 +112,14 @@ public interface WxCouponOrderMapper extends CommonMapper<WxCouponOrder, Long> { | |||
| * @return | |||
| */ | |||
| List<Long> findVerifiedUserIds(@Param("tenantId")String tenantId, @Param("verifiedStartTime")Date verifiedStartTime, @Param("verifiedEndTime")Date verifiedEndTime); | |||
| /** | |||
| * 统计核销记录总金额 | |||
| * @param tenantId | |||
| * @param merchantId | |||
| * @param startDate | |||
| * @param endDate | |||
| * @return {@link Integer} | |||
| */ | |||
| SumVerifiedVO sumVerified(@Param("tenantId") String tenantId, @Param("bMerchantId") Long merchantId, @Param("startDate") Date startDate, @Param("endDate") Date endDate); | |||
| } | |||
| @@ -67,4 +67,6 @@ public interface WxOrderMapper extends CommonMapper<WxOrder, Long> { | |||
| void updateCUserId(WxOrder updateOrder); | |||
| List<Long> getComposeOrderIds(WxOrder wxOrder); | |||
| SumMicroPayVO sumMicroPay(Map dateMap); | |||
| } | |||
| @@ -239,6 +239,7 @@ public interface WxCouponOrderService { | |||
| List<WxCouponOrderCVo> findAvailCouponOrder(TenantEntity tenantEntity,Long cUserId,Long merchantId,Long posOrderId); | |||
| PageInfo<WxMerchantTradeDetailVo> userTradeDetailList(WxMerchant wxMerchant,Date startTime,Date endTime,Integer pageIndex,Integer pageSize); | |||
| ResultData sumVerified(WxMerchantBUser bUser, Date startDate, Date endDate); | |||
| } | |||
| @@ -200,6 +200,14 @@ public interface WxOrderService { | |||
| void updateStatusByPressCouponId(Long couponId, TenantEntity tenantEntity,int orderStatus); | |||
| /** | |||
| * 通过优惠券id更新订单状态 | |||
| * @param tenantId | |||
| * @param couponId | |||
| * @param orderStatus | |||
| */ | |||
| void updateStatusByPressCouponId(String tenantId, Long couponId, int orderStatus); | |||
| void updateOrderStatus(WxOrder order); | |||
| void updateOrderGroupStatusByCouponId(Long id, TenantEntity tenantEntity, Integer code); | |||
| @@ -284,4 +292,5 @@ public interface WxOrderService { | |||
| ResultData handlerPushOrder(TenantEntity tenantEntity, Long composeOrderId, String batchExtParam, | |||
| List<CreateOrderCallback.Good> goods); | |||
| ResultData sumMicroPay(WxMerchantBUser bUser, Integer type, Date startDate, Date endDate); | |||
| } | |||
| @@ -2,10 +2,14 @@ package com.iformall.service.helper; | |||
| import com.iformall.common.ErrorCode; | |||
| import com.iformall.domain.po.WxCoupon; | |||
| import com.iformall.domain.po.base.TenantEntity; | |||
| import com.iformall.enums.EnumCacheKey; | |||
| import com.iformall.enums.EnumOrderStatus; | |||
| import com.iformall.enums.EnumYesOrNo; | |||
| import com.iformall.exception.MallinkException; | |||
| import com.iformall.service.WxCouponChannelService; | |||
| import com.iformall.service.WxCouponService; | |||
| import com.iformall.service.WxOrderService; | |||
| import com.iformall.utils.RedisLock; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| @@ -13,48 +17,63 @@ import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.context.annotation.Lazy; | |||
| import org.springframework.stereotype.Service; | |||
| import java.util.concurrent.CompletableFuture; | |||
| @Service | |||
| public class WxOrderServiceHelper { | |||
| private static final Logger logger = LoggerFactory.getLogger(WxOrderServiceHelper.class); | |||
| private static final Logger logger = LoggerFactory.getLogger(WxOrderServiceHelper.class); | |||
| @Lazy | |||
| @Autowired | |||
| WxCouponChannelService wxCouponChannelService; | |||
| @Lazy | |||
| @Autowired | |||
| WxCouponService wxCouponService; | |||
| @Lazy | |||
| @Autowired | |||
| private WxOrderService wxOrderService; | |||
| @Autowired | |||
| RedisLock redisLock; | |||
| /** | |||
| * 微信订单是否可以支付 | |||
| */ | |||
| public void reduceStock(boolean isChannelStockReduce, WxCoupon coupon,Long couponChannelId,int number) throws Exception{ | |||
| if (isChannelStockReduce) { | |||
| try { | |||
| wxCouponChannelService.reduceChannelStock(coupon,couponChannelId,number); | |||
| long stock = redisLock.decrease(EnumCacheKey.COUPON_CHANNEL_STOCK.getMessage()+couponChannelId, number); | |||
| if (stock < 0 ) { | |||
| throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(),"券["+coupon.getTitle()+"]渠道["+couponChannelId+"]库存已为零!"); | |||
| } | |||
| } catch (RuntimeException e) { | |||
| throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(),"券["+coupon.getTitle()+"]渠道["+couponChannelId+"]库存更新失败!"+e.getMessage()); | |||
| } | |||
| }else { | |||
| try { | |||
| wxCouponService.reduceRemainInventory(coupon,coupon.getId(),number); | |||
| long stock = redisLock.decrease(EnumCacheKey.COUPON_STOCK.getMessage()+coupon.getId(), number); | |||
| if (stock < 0 ) { | |||
| throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(),"券["+coupon.getTitle()+"]库存已为零!"); | |||
| } | |||
| } catch (RuntimeException e) { | |||
| logger.error("此券减库存失败, couponId: " + coupon.getId(),e); | |||
| throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(),"券["+coupon.getTitle()+"]库存更新失败!"+e.getMessage()); | |||
| } | |||
| } | |||
| public void reduceStock(boolean isChannelStockReduce, WxCoupon coupon, Long couponChannelId, int number, Boolean isPressOrder) throws Exception { | |||
| long stock; | |||
| if (isChannelStockReduce) { | |||
| try { | |||
| wxCouponChannelService.reduceChannelStock(coupon, couponChannelId, number); | |||
| stock = redisLock.decrease(EnumCacheKey.COUPON_CHANNEL_STOCK.getMessage() + couponChannelId, number); | |||
| if (stock < 0) { | |||
| throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(), "券[" + coupon.getTitle() + "]渠道[" + couponChannelId + "]库存已为零!"); | |||
| } | |||
| } catch (RuntimeException e) { | |||
| throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(), "券[" + coupon.getTitle() + "]渠道[" + couponChannelId + "]库存更新失败!" + e.getMessage()); | |||
| } | |||
| } else { | |||
| try { | |||
| wxCouponService.reduceRemainInventory(coupon, coupon.getId(), number); | |||
| stock = redisLock.decrease(EnumCacheKey.COUPON_STOCK.getMessage() + coupon.getId(), number); | |||
| if (stock < 0) { | |||
| throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(), "券[" + coupon.getTitle() + "]库存已为零!"); | |||
| } | |||
| } catch (RuntimeException e) { | |||
| logger.error("此券减库存失败, couponId: " + coupon.getId(), e); | |||
| throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(), "券[" + coupon.getTitle() + "]库存更新失败!" + e.getMessage()); | |||
| } | |||
| } | |||
| // 砍价订单,支付时扣库存,库存不足 则修改砍价订单状态 | |||
| CompletableFuture.runAsync(() -> { | |||
| if (isPressOrder && null != coupon.getPressPayReduceStock() && coupon.getPressPayReduceStock().intValue() == EnumYesOrNo.YES.getCode().intValue() && stock <= 0 ) { | |||
| wxOrderService.updateStatusByPressCouponId(coupon.getTenantId(), coupon.getCouponId(), EnumOrderStatus.ORDER_STATUS_PRESS_CANCEL.getCode()); | |||
| } | |||
| }); | |||
| } | |||
| } | |||
| @@ -320,8 +320,6 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||
| if (isVerified) { | |||
| PageInfo<WxCouponOrderBVo> pageResult = findListOfVerifiedByDateForBUser(wxMerchant, wxMerchant.getId(), startDate, endDate, pageIndex, pageSize); | |||
| resultMap.put("list", pageResult); | |||
| int amount = pageResult.getList() != null ? pageResult.getList().stream().mapToInt(WxCouponOrderBVo::getCouponPrice).sum() : 0; | |||
| resultMap.put("amount", amount); | |||
| }else { | |||
| resultMap.put("list", findListOfOrderedByDateForBUser(wxMerchant,wxMerchant.getId(),startDate,endDate,pageIndex,pageSize)); | |||
| } | |||
| @@ -3255,8 +3253,14 @@ public class WxCouponOrderServiceImpl implements WxCouponOrderService { | |||
| retPageInfo.setList(couponOrderListToTradeDetailVoList(wxMerchant,pageInfo.getList())); | |||
| return retPageInfo; | |||
| } | |||
| private List<WxMerchantTradeDetailVo> couponOrderListToTradeDetailVoList(TenantEntity tenantEntity,List<WxCouponOrder> couponOrderList) { | |||
| @Override | |||
| public ResultData sumVerified(WxMerchantBUser bUser, Date startDate, Date endDate) { | |||
| SumVerifiedVO vo = wxCouponOrderMapper.sumVerified(bUser.getTenantId(), bUser.getMerchantId(), startDate, endDate); | |||
| return new ResultData(vo); | |||
| } | |||
| private List<WxMerchantTradeDetailVo> couponOrderListToTradeDetailVoList(TenantEntity tenantEntity,List<WxCouponOrder> couponOrderList) { | |||
| if (null == couponOrderList || couponOrderList.size() <=0 ) { | |||
| return null; | |||
| } | |||
| @@ -312,8 +312,6 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| } else { | |||
| PageInfo<WxOrderPayVo> pageResult = orderPayVoPageInfo(wxMerchantBUser, pageIndex, pageSize, dateMap); | |||
| resultMap.put("list", pageResult); | |||
| int amount = pageResult.getList() != null ? pageResult.getList().stream().mapToInt(WxOrderPayVo::getPayment).sum() : 0; | |||
| resultMap.put("amount", amount); | |||
| } | |||
| return resultMap; | |||
| } | |||
| @@ -1121,7 +1119,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| } | |||
| if (isReduceStock) { | |||
| try { | |||
| wxOrderServiceHelper.reduceStock(isChannelStockReduce,coupon,couponChannelId, number); | |||
| wxOrderServiceHelper.reduceStock(isChannelStockReduce,coupon,couponChannelId, number, isPressOrder); | |||
| }catch (Exception e) { | |||
| throw new MallinkException(ErrorCode.DB_FAIL.getCode(),e.getMessage()); | |||
| } | |||
| @@ -3056,6 +3054,16 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| wxOrderMapper.updateStatusByPressCouponId(updateOrder); | |||
| } | |||
| @Override | |||
| public void updateStatusByPressCouponId(String tenantId, Long couponId, int orderStatus) { | |||
| WxOrder updateOrder = new WxOrder(); | |||
| updateOrder.setTenantId(tenantId); | |||
| updateOrder.setOrderStatus(orderStatus); | |||
| updateOrder.setProductId(couponId); | |||
| updateOrder.setUpdateDate(new Date()); | |||
| wxOrderMapper.updateStatusByPressCouponId(updateOrder); | |||
| } | |||
| @Autowired | |||
| @Qualifier("cUserBasicInfoRedisTemplate") | |||
| RedisTemplate<String, WxCUserBasicInfo> cUserBasicInfoRedisTemplate; | |||
| @@ -3951,6 +3959,27 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| // } | |||
| } | |||
| @Override | |||
| public ResultData sumMicroPay(WxMerchantBUser bUser, Integer type, Date startDate, Date endDate) { | |||
| Map dataMap = new HashMap(); | |||
| dataMap.put("startDate", startDate); | |||
| dataMap.put("endDate", endDate); | |||
| dataMap.put("merchantId", bUser.getMerchantId()); | |||
| dataMap.put("type", type); | |||
| dataMap.put("tenantId", bUser.getTenantId()); | |||
| dataMap.put("finalTenantId", bUser.getFinalTenantId()); | |||
| WxMerchantBUser merchantBUserQ = new WxMerchantBUser(); | |||
| merchantBUserQ.updateTenantInfo(bUser); | |||
| merchantBUserQ.setMerchantId(bUser.getMerchantId()); | |||
| List<Long> bUserIds = wxMerchantBUserMapper.findIdList(merchantBUserQ); | |||
| if (null == bUserIds || bUserIds.size() <= 0 ) { | |||
| throw new MallinkException(ErrorCode.MERCHANT_INFO_NOT_FOUND); | |||
| } | |||
| dataMap.put("bUserIds", bUserIds); | |||
| SumMicroPayVO vo = wxOrderMapper.sumMicroPay(dataMap); | |||
| return new ResultData(vo); | |||
| } | |||
| private Map<Long,List<WxOrderCouponVo>> getBatchOrderMap(TenantEntity tenantEntity,List<Long> batchOrderIds){ | |||
| WxOrder recordQ = new WxOrder(); | |||
| recordQ.updateTenantInfo(tenantEntity); | |||
| @@ -214,7 +214,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { | |||
| if (null != coupon && coupon.getType().intValue() == EnumCouponType.COUPON_PRESS.getCode().intValue() | |||
| && null != coupon.getPressPayReduceStock() && coupon.getPressPayReduceStock().intValue() == EnumYesOrNo.YES.getCode().intValue()) { | |||
| try { | |||
| wxOrderServiceHelper.reduceStock(false,coupon,order.getCouponChannelId(), 1); | |||
| wxOrderServiceHelper.reduceStock(false,coupon,order.getCouponChannelId(), 1, true); | |||
| return true; | |||
| }catch(Exception e) { | |||
| //如果此时扣库存失败,则需要给订单退款 | |||
| @@ -167,4 +167,8 @@ public class RedisCacheUtils { | |||
| Set keys = template.keys(prefix+"*"); | |||
| template.delete(keys); | |||
| } | |||
| public static Boolean hasKey(RedisTemplate<String, Object> template,String key) { | |||
| return template.hasKey(key); | |||
| } | |||
| } | |||
| @@ -1182,5 +1182,20 @@ | |||
| and update_date >= #{verifiedStartTime} | |||
| and update_date <= #{verifiedEndTime} | |||
| </select> | |||
| <select id="sumVerified" resultType="com.iformall.domain.vo.SumVerifiedVO"> | |||
| select IFNULL(SUM(co.coupon_price), 0) AS amount, COUNT(1) AS total | |||
| from wx_coupon_order co | |||
| where co.tenant_id = #{tenantId} | |||
| AND co.coupon_order_status = '1' | |||
| <if test=" null != bMerchantId "> | |||
| and co.b_merchant_id = #{bMerchantId} | |||
| </if> | |||
| <if test="startDate != null"> | |||
| AND co.update_date >= #{startDate,jdbcType=TIMESTAMP} | |||
| </if> | |||
| <if test="endDate != null"> | |||
| AND co.update_date <= #{endDate,jdbcType=TIMESTAMP} | |||
| </if> | |||
| </select> | |||
| </mapper> | |||
| @@ -1171,5 +1171,34 @@ | |||
| </if> | |||
| </select> | |||
| <select id="sumMicroPay" resultType="com.iformall.domain.vo.SumMicroPayVO"> | |||
| select IFNULL(SUM(o.payment), 0) AS amount, COUNT(1) AS total | |||
| from wx_order o | |||
| where o.order_status = '1' and o.`type` = 1 | |||
| <if test=" null != tenantId and '' != tenantId"> | |||
| and o.`tenant_id` = #{tenantId} | |||
| </if> | |||
| <if test=" null != parentTenantId and '' != parentTenantId"> | |||
| and o.`parent_tenant_id` = #{parentTenantId} | |||
| </if> | |||
| <if test=" null != payVendor "> | |||
| and o.pay_vendor = #{payVendor} | |||
| </if> | |||
| <if test=" null != payVersion "> | |||
| and o.pay_version = #{payVersion} | |||
| </if> | |||
| <if test=" null != bUserIds "> | |||
| and o.product_id in | |||
| <foreach collection="bUserIds" index="index" item="bUserIdItem" open="(" separator="," close=")"> | |||
| #{bUserIdItem} | |||
| </foreach> | |||
| </if> | |||
| <if test="startDate != null"> | |||
| AND o.create_date >= #{startDate,jdbcType=TIMESTAMP} | |||
| </if> | |||
| <if test="endDate != null"> | |||
| AND o.create_date <= #{endDate,jdbcType=TIMESTAMP} | |||
| </if> | |||
| </select> | |||
| </mapper> | |||