订单15分钟到期 状态监听 库存回滚

商品排序值 初始化
出入库 日志记录
酒品管理
购物车次日清空
This commit is contained in:
wangw 2024-06-17 17:55:56 +08:00
parent 8d956b3cfd
commit 6c30aa2abd
20 changed files with 228 additions and 94 deletions

View File

@ -27,6 +27,8 @@ public interface CacheKey {
*/
String ACT_CODE = "act_code:";
String ORDER_EXPIRED = "ORDER:EXPIRED:";
/**
* 用户
*/

View File

@ -1,5 +1,6 @@
package cn.ysk.cashier.config;
import cn.ysk.cashier.service.order.TbOrderInfoService;
import cn.ysk.cashier.service.shop.TbShopInfoService;
import cn.ysk.cashier.system.service.UserService;
import cn.ysk.cashier.utils.CacheKey;
@ -30,6 +31,10 @@ public class RedisKeyExpirationListener implements MessageListener {
@Autowired
private UserService userServiceu;
@Lazy
@Autowired
private TbOrderInfoService tbOrderInfoService;
//redis key失效监听
@Bean
public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory) {
@ -50,6 +55,10 @@ public class RedisKeyExpirationListener implements MessageListener {
log.info("商户到期 账户名为:{}",account);
shopInfoService.update(account);
userServiceu.upEnableByusername(account);
}else if(expiredKey.startsWith(CacheKey.ORDER_EXPIRED)){
log.info("监听到订单过期,{}",expiredKey);
String orderId = expiredKey.substring(CacheKey.ORDER_EXPIRED.length());
tbOrderInfoService.expired(orderId);
}
}
}

View File

@ -76,6 +76,7 @@ public class TbProductStockOperateController {
@PostMapping("/outAndOn")
@ApiOperation("新增/product/StockOperate")
@Log("出入库")
// @PreAuthorize("@el.check('tbProductStockOperate:add')")
public ResponseEntity<Object> createOutAndONOperate(@RequestBody OutAndOnDto outAndOnDto){
return new ResponseEntity<>(tbProductStockOperateService.createOutAndONOperate(outAndOnDto),HttpStatus.CREATED);

View File

@ -37,7 +37,6 @@ public class TbShopStorageGoodController {
// }
@PostMapping("list")
@Log("查询酒品列表")
@ApiOperation("查询酒品列表")
public ResponseEntity<Object> queryTbShopStorageGood(@RequestBody TbShopStorageGoodQueryCriteria criteria){
Pageable pageable = PageRequest.of(criteria.getPage(), criteria.getSize(), Sort.by(Sort.Direction.DESC, "id"));
@ -53,7 +52,7 @@ public class TbShopStorageGoodController {
}
@PutMapping
@Log("修改酒品")
@Log("修改酒品:#resources.name")
@ApiOperation("修改酒品")
public ResponseEntity<Object> updateTbShopStorageGood(@Validated @RequestBody TbShopStorageGood resources){
tbShopStorageGoodService.update(resources);

View File

@ -39,4 +39,10 @@ public class TbShopStorageQueryCriteria {
this.shopId = shopId;
}
}
public void setStatus(Integer status) {
if (status != null) {
this.status = status;
}
}
}

View File

@ -1,20 +1,6 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.ysk.cashier.dto.shop;
import cn.ysk.cashier.utils.StringUtils;
import lombok.Data;
@Data
@ -29,4 +15,21 @@ public class TbShopUserQueryCriteria {
private Long page=1L;
private Long size=10L;
public void setName(String name) {
if (StringUtils.isNotBlank(name)) {
this.name = name;
}
}
public void setShopId(String shopId) {
if (StringUtils.isNotBlank(shopId) && !shopId.equals(1)) {
this.shopId = shopId;
}
}
public void setIsVip(Integer isVip) {
if(isVip!=null){
this.isVip = isVip;
}
}
}

View File

@ -16,9 +16,10 @@ public interface ShopUserMapper extends BaseMapper<TbShopUser> {
"u.birth_day as birthDay, su.is_vip as isVip, su.created_at as createAt, u.last_log_in_at as lastLoginAt " +
"FROM tb_shop_user su " +
"LEFT JOIN tb_user_info u ON su.user_id = u.id " +
"<where>" +
"<where> " +
"su.user_id is not null and su.user_id != ''" +
"<if test='param.shopId != null and param.shopId != &quot;&quot; and param.shopId != 1'>" +
"su.shop_id = #{param.shopId} " +
"AND su.shop_id = #{param.shopId} " +
"</if>" +
"<if test='param.name != null and param.name != &quot;&quot;'>" +
"AND (u.nick_name like concat('%', #{param.name}, '%') or u.telephone like concat('%', #{param.name}, '%'))" +

View File

@ -1,24 +1,21 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.ysk.cashier.quartz.task;
import cn.ysk.cashier.repository.shop.TbShopStorageRepository;
import cn.ysk.cashier.pojo.order.TbCashierCart;
import cn.ysk.cashier.repository.order.TbCashierCartRepository;
import cn.ysk.cashier.repository.product.TbProductSkuRepository;
import cn.ysk.cashier.service.shop.TbShopStorageService;
import cn.ysk.cashier.utils.CacheKey;
import cn.ysk.cashier.utils.QueryHelp;
import cn.ysk.cashier.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.criteria.Predicate;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 测试用
@ -30,7 +27,15 @@ import org.springframework.stereotype.Service;
public class TestTask {
@Autowired
private TbShopStorageRepository storageRepository;
private TbShopStorageService storageService;
@Autowired
private TbCashierCartRepository cartService;
@Autowired
private TbProductSkuRepository skuRepository;
@Autowired
private RedisUtils redisUtils;
public void run(){
log.info("run 执行成功");
@ -47,7 +52,31 @@ public class TestTask {
public void expStorage(){
log.info("存酒过期开始执行");
storageRepository.expStorage();
storageService.expStorage();
log.info("存酒过期执行结束");
}
@Transactional(rollbackFor = Exception.class)
public void cleanCart(){
log.info("购物车清楚记录开始");
List<TbCashierCart> all = cartService.findAll((root, criteriaQuery, criteriaBuilder) -> {
Predicate predicate = QueryHelp.getPredicate(root, null, criteriaBuilder);
predicate = criteriaBuilder.and(predicate, criteriaBuilder.isNull(root.get("masterId")));
predicate = criteriaBuilder.and(predicate, criteriaBuilder.equal(root.get("status"), "create"));
predicate = criteriaBuilder.and(predicate, criteriaBuilder.notEqual(root.get("tableId"), "0"));
predicate = criteriaBuilder.and(predicate, criteriaBuilder.lt(root.get("updatedAt"), System.currentTimeMillis() - 60 * 1000L * 60 * 24));
predicate = criteriaBuilder.and(predicate, criteriaBuilder.gt(root.get("updatedAt"), System.currentTimeMillis() - 60 * 1000L * 60 * 24 * 2));
return predicate;
});
Set<String> keys = new HashSet<>();
for (TbCashierCart cart : all) {
skuRepository.updateStockNumber(Integer.valueOf(cart.getSkuId()),cart.getNumber().doubleValue());
cart.setStatus("cancelled");
cartService.save(cart);
keys.add(CacheKey.PRODUCT_SKU + cart.getShopId() + ":" + cart.getSkuId());
}
String[] keysArray = keys.toArray(new String[keys.size()]);
redisUtils.del(keysArray);
log.info("购物车清楚记录开始结束");
}
}

View File

@ -1,23 +1,11 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.ysk.cashier.repository.order;
import cn.ysk.cashier.pojo.order.TbCashierCart;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
/**
* @website https://eladmin.vip
@ -25,4 +13,9 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
* @date 2024-03-02
**/
public interface TbCashierCartRepository extends JpaRepository<TbCashierCart, Integer>, JpaSpecificationExecutor<TbCashierCart> {
@Query(value = "update tb_cashier_cart set status='final' where order_id = :id",nativeQuery = true)
@Modifying
void updateToFinal(@Param("id") Integer id);
}

View File

@ -57,4 +57,8 @@ public interface TbProductSkuRepository extends JpaRepository<TbProductSku, Inte
@Param("firstShared")BigDecimal firstShared,@Param("memberPrice")BigDecimal memberPrice,@Param("originPrice") BigDecimal originPrice,
@Param("salePrice")BigDecimal salePrice,@Param("specSnap") String specSnap,@Param("id") Integer id);
@Modifying
@Query("update FROM TbProductSku sku set sku.stockNumber=sku.stockNumber+:stockNumber WHERE sku.id =:id")
Integer updateStockNumber(@Param("id") Integer id, @Param("stockNumber") Double stockNumber);
}

View File

@ -1,12 +1,12 @@
package cn.ysk.cashier.repository.shop;
import cn.ysk.cashier.dto.shop.TbCountStorageDto;
import cn.ysk.cashier.dto.shop.TbShopStorageQueryCriteria;
import cn.ysk.cashier.pojo.shop.TbShopStorage;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
/**
@ -29,6 +29,7 @@ public interface TbShopStorageRepository extends JpaRepository<TbShopStorage, In
"ORDER BY SUM(CASE WHEN storage.status = 1 THEN storage.num ELSE 0 END) desc")
Page<TbCountStorageDto> countStorage(Integer shopId, Pageable pageable);
@Modifying
@Query(value = "UPDATE tb_shop_storage SET `status` = '2' WHERE exp_time > DATE_ADD( NOW(), INTERVAL -2 DAY ) AND exp_time < NOW() AND `status` = '1'",nativeQuery = true)
void expStorage();
}

View File

@ -1,18 +1,3 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.ysk.cashier.repository.shop;
import cn.ysk.cashier.pojo.shop.TbShopTable;
@ -30,6 +15,9 @@ import java.util.List;
**/
public interface TbShopTableRepository extends JpaRepository<TbShopTable, Integer>, JpaSpecificationExecutor<TbShopTable> {
@Query
int countAllByShopId(@Param("shopId")Integer shopId);
@Query("select table from TbShopTable table where table.qrcode = :qrcode")
TbShopTable findByQrcode(@Param("qrcode") String qrcode);

View File

@ -1,39 +1,37 @@
/*
* Copyright 2019-2020 Zheng Jie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.ysk.cashier.service.impl.order;
import cn.hutool.core.util.ObjectUtil;
import cn.ysk.cashier.dto.order.TbOrderInfoDto;
import cn.ysk.cashier.dto.order.TbOrderInfoQueryCriteria;
import cn.ysk.cashier.dto.order.TbPayCountQueryCriteria;
import cn.ysk.cashier.mapper.order.TbOrderInfoMapper;
import cn.ysk.cashier.mybatis.entity.TbOrderPayment;
import cn.ysk.cashier.mybatis.service.TbOrderPaymentService;
import cn.ysk.cashier.pojo.TbShopPayType;
import cn.ysk.cashier.pojo.order.TbOrderDetail;
import cn.ysk.cashier.pojo.order.TbOrderInfo;
import cn.ysk.cashier.pojo.shop.TbMerchantThirdApply;
import cn.ysk.cashier.repository.TbShopPayTypeRepository;
import cn.ysk.cashier.repository.order.TbCashierCartRepository;
import cn.ysk.cashier.repository.order.TbOrderDetailRepository;
import cn.ysk.cashier.repository.order.TbOrderInfoRepository;
import cn.ysk.cashier.repository.product.TbProductSkuRepository;
import cn.ysk.cashier.repository.shop.TbMerchantThirdApplyRepository;
import cn.ysk.cashier.service.order.TbOrderInfoService;
import cn.ysk.cashier.thirdpay.resp.OrderStatusQueryResp;
import cn.ysk.cashier.thirdpay.resp.PublicResp;
import cn.ysk.cashier.thirdpay.service.ThirdPayService;
import cn.ysk.cashier.utils.*;
import cn.ysk.cashier.vo.TbOrderInfoVo;
import cn.ysk.cashier.vo.TbOrderPayCountVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
@ -62,6 +60,15 @@ public class TbOrderInfoServiceImpl implements TbOrderInfoService {
private final TbOrderDetailRepository tbOrderDetailRepository;
private final TbShopPayTypeRepository payTypeRepository;
private final TbProductSkuRepository skuRepository;
private final TbOrderPaymentService paymentService;
private final TbMerchantThirdApplyRepository thirdApplyRepository;
private final RedisUtils redisUtils;
private final ThirdPayService thirdPayService;
private final TbCashierCartRepository cartRepository;
@Value("${thirdPay.url}")
private String url;
@Override
public Map<String, Object> queryAllPage(TbOrderInfoQueryCriteria criteria) {
@ -214,6 +221,87 @@ public class TbOrderInfoServiceImpl implements TbOrderInfoService {
return tbOrderInfoMapper.toDto(tbOrderInfoRepository.save(resources));
}
@Async
@Override
@Transactional(rollbackFor = Exception.class)
public void expired(String orderId) {
Optional<TbOrderInfo> byId = tbOrderInfoRepository.findById(Integer.valueOf(orderId));
if (byId != null && byId.isPresent()) {
TbOrderInfo tbOrderInfo = byId.get();
if (tbOrderInfo.getStatus().equals("unpaid")) {
upOrderStatus(tbOrderInfo);
} else if (tbOrderInfo.getStatus().equals("paying") &&
(StringUtils.isBlank(tbOrderInfo.getPayType()) ||
!tbOrderInfo.getPayType().equals("deposit"))) {
QueryWrapper<TbOrderPayment> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("order_id", tbOrderInfo.getId());
TbOrderPayment payment = paymentService.getOne(queryWrapper);
if (payment != null && StringUtils.isNotBlank(payment.getTradeNumber())) {
if (System.currentTimeMillis() - payment.getCreatedAt() < 60 * 2 * 1000L) {
modfiyOrderInfo(tbOrderInfo);
redisUtils.set(CacheKey.ORDER_EXPIRED + tbOrderInfo.getId(), tbOrderInfo.getId(), 60 * 2);
} else {
upOrderStatus(tbOrderInfo);
}
}
}
}
}
@Transactional(rollbackFor = Exception.class)
public void modfiyOrderInfo(TbOrderInfo tbOrderInfo) {
QueryWrapper<TbOrderPayment> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("order_id", tbOrderInfo.getId());
TbOrderPayment payment = paymentService.getOne(queryWrapper);
if (ObjectUtil.isNotEmpty(payment) && ObjectUtil.isNotEmpty(payment.getTradeNumber())) {
TbMerchantThirdApply thirdApply = thirdApplyRepository.getById(Integer.valueOf(tbOrderInfo.getMerchantId()));
if (ObjectUtil.isEmpty(thirdApply) || ObjectUtil.isNull(thirdApply)) {
//支付通道不存在
}
PublicResp<OrderStatusQueryResp> publicResp = thirdPayService.queryOrder(url, thirdApply.getAppId(), payment.getTradeNumber(), null, thirdApply.getAppToken());
if (ObjectUtil.isNotNull(publicResp) && ObjectUtil.isNotEmpty(publicResp)) {
if ("000000".equals(publicResp.getCode())) {
String cartStatus = "";
switch (publicResp.getObjData().getState()) {
case "TRADE_SUCCESS":
//修改数据库中购物车数据
cartRepository.updateToFinal(tbOrderInfo.getId());
//更新子单状态
tbOrderDetailRepository.updateToClosed(tbOrderInfo.getId());
//修改主单状态
tbOrderInfo.setStatus("closed");
tbOrderInfo.setPayType("wx_lite");
tbOrderInfo.setPayOrderNo(payment.getTradeNumber());
tbOrderInfo.setPayAmount(tbOrderInfo.getOrderAmount());
tbOrderInfoRepository.save(tbOrderInfo);
// JSONObject jsonObject = new JSONObject();
// jsonObject.put("token", 0);
// jsonObject.put("type", "wxcreate");
// jsonObject.put("orderId", orderInfo.getId().toString());
// producer.putOrderCollect(jsonObject.toJSONString());
// log.info("发送打印数据");
// producer.printMechine(orderInfo.getId() + "");
}
}
}
}
}
@Transactional(rollbackFor = Exception.class)
public void upOrderStatus(TbOrderInfo tbOrderInfo) {
tbOrderInfo.setStatus("cancelled");
List<TbOrderDetail> details = tbOrderDetailRepository.searchDetailByOrderId(tbOrderInfo.getId());
Set<String> keys = new HashSet<>();
for (TbOrderDetail detail : details) {
detail.setStatus("cancelled");
skuRepository.updateStockNumber(detail.getId(), new Double(detail.getNum()));
tbOrderDetailRepository.save(detail);
keys.add(CacheKey.PRODUCT_SKU + detail.getShopId() + ":" + detail.getId());
}
String[] keysArray = keys.toArray(new String[keys.size()]);
redisUtils.del(keysArray);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void update(TbOrderInfo resources) {

View File

@ -341,7 +341,7 @@ public class TbProductServiceImpl implements TbProductService {
throw new BadRequestException("添加商品失败");
}
save.setSort(save.getId());
tbProductRepository.save(product);
tbProductRepository.save(save);
//sku
if (resources.getSkuList() != null) {
List<TbProductSku> skuList = new ArrayList<>();

View File

@ -244,13 +244,11 @@ public class TbProductStockOperateServiceImpl implements TbProductStockOperateSe
productStockDetail.setUnitName(productListDto.getUnitName());
entityManager.persist(productStockDetail);
//sku数量
TbProductSku sku = new TbProductSku();
sku.setId(productListDto.getId());
sku.setStockNumber(tbProductSku.getStockNumber()+productStockDetail.getStockNumber());
productSkuService.update(sku);
tbProductSku.setStockNumber(tbProductSku.getStockNumber()+productStockDetail.getStockNumber());
productSkuService.update(tbProductSku);
idStockMap.put(productListDto.getId(),productStockDetail.getStockNumber());
}
redisUtils.redisUp(1,resources.getShopId(),idStockMap);
redisUtils.redisUp(2,resources.getShopId(),idStockMap);
return resources;
}

View File

@ -149,7 +149,7 @@ public class TbShopInfoServiceImpl implements TbShopInfoService {
}
tbShopInfo.setExpireAt(DateUtil.addMonthsAndGetTimestamp(tbMerchantRegister.getPeriodYear()));
//向redis中存入key
redisUtils.set(CacheKey.ACT_CODE+resources.getAccount(),tbShopInfo.getExpireAt()-Instant.now().toEpochMilli());
redisUtils.set(CacheKey.ACT_CODE+resources.getAccount(),"1",tbShopInfo.getExpireAt()-Instant.now().toEpochMilli());
}
//增加商户详情
TbShopInfo save = tbShopInfoRepository.save(tbShopInfo);

View File

@ -122,6 +122,13 @@ public class TbShopStorageServiceImpl implements TbShopStorageService {
tbShopStorageRepository.save(tbShopStorage);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void expStorage() {
tbShopStorageRepository.expStorage();
}
@Override
public void deleteAll(Integer[] ids) {
for (Integer id : ids) {

View File

@ -84,8 +84,10 @@ public class TbShopTableServiceImpl implements TbShopTableService {
date.setQrcode(QRCODE+date.getQrcode().trim());
}
}
int i = tbShopTableRepository.countAllByShopId(criteria.getShopId());
HashMap<String, Object> map = new HashMap<>();
map.put("content",tbShopTableList);
map.put("total",i);
return map;
}

View File

@ -70,6 +70,7 @@ public interface TbOrderInfoService {
*/
TbOrderInfoDto create(TbOrderInfo resources);
void expired(String orderId);
/**
* 编辑
* @param resources /

View File

@ -1,15 +1,15 @@
package cn.ysk.cashier.service.shop;
import cn.ysk.cashier.dto.shop.TbCountStorageDto;
import cn.ysk.cashier.dto.shop.TbShopStorageDto;
import cn.ysk.cashier.dto.shop.TbShopStorageNumDto;
import cn.ysk.cashier.dto.shop.TbShopStorageQueryCriteria;
import cn.ysk.cashier.pojo.shop.TbShopStorage;
import org.springframework.data.domain.Pageable;
import java.util.Map;
import java.util.List;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* @author ww
@ -54,6 +54,8 @@ public interface TbShopStorageService {
*/
void update(TbShopStorage resources);
void expStorage();
void updateNum(TbShopStorageNumDto resources);
/**