Merge remote-tracking branch 'origin/master'

This commit is contained in:
zjf committed 2025-09-03 19:22:11 +08:00
commit cdf7f43832
11 files changed
+237 -4

No files matched your search

@@ -153,5 +153,11 @@ public interface CacheConstants {
/* ************************************* end 第三方对接相关 end ************************************* */
/* ************************************* start 订单相关 start ************************************* */
String HARDER_ORDER_NON_PAY = "hard:order:non_pay";
/* ************************************* end 订单相关 end ************************************* */
}
@@ -0,0 +1,15 @@
package com.bsd.pjcloud.hard.api.dto.hard;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class HardDoneHardQrCodeScanOrderDto {
@NotNull(message = "订单ID不能为空")
private Long orderId;
@NotNull(message = "钱包类型ID不能为空")
private Long walletTypeId;
}
@@ -33,7 +33,7 @@ public class HardOrderDto extends HardOrderEntity implements BaseIsIncludeTreeIn
private List<String> orderStatusCodes;
private LocalDate[] createTimeList;
private LocalDateTime[] createTimeList;
private LocalDateTime[] payTimeList;
@@ -0,0 +1,20 @@
package com.bsd.pjcloud.hard.api.vo.order;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class HardCreateHardQrCodeScanOrderVo {
private Long orderId;
private Long mchId;
private String qrCodeData;
}
@@ -3,26 +3,33 @@ package com.bsd.pjcloud.hard.controller.hard;
import cn.hutool.core.util.ObjectUtil;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.idempotent.annotation.Idempotent;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.hard.api.constant.HardProductNatureEnum;
import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardPayTypeEnum;
import com.bsd.pjcloud.hard.api.dto.async.SyncOfflineReqVo;
import com.bsd.pjcloud.hard.api.dto.hard.HandCancelCodeDto;
import com.bsd.pjcloud.hard.api.dto.hard.HardBindDto;
import com.bsd.pjcloud.hard.api.dto.hard.HardCreateOrderDto;
import com.bsd.pjcloud.hard.api.dto.hard.HardDoneHardQrCodeScanOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.HardChartLatitudeVo;
import com.bsd.pjcloud.hard.api.dto.order.HardCreateCarDto;
import com.bsd.pjcloud.hard.api.vo.HardInvoiceVo;
import com.bsd.pjcloud.hard.api.vo.manager.HardManagerVo;
import com.bsd.pjcloud.hard.api.vo.android.HardAdUserVo;
import com.bsd.pjcloud.hard.api.vo.order.HardCarVo;
import com.bsd.pjcloud.hard.api.vo.order.HardCreateHardQrCodeScanOrderVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.hard.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
@@ -85,6 +92,34 @@ public class HardApiController {
return R.ok(hardwareOrderService.createOrder(dto));
}
@PostMapping("/create-hard-qr-code-order")
@Operation(summary = "创建设备二维码扫一扫订单")
@Idempotent(expireTime = 10, info = "正在创建订单中,请勿重复操作")
public R<HardCreateHardQrCodeScanOrderVo> createHardQrCodeScanOrder(@Valid @RequestBody HardCreateOrderDto dto) {
// 处理商品类型
if (ObjectUtil.isNotEmpty(dto.getList())) {
for (HardCreateCarDto item : dto.getList()) {
if (ObjectUtil.isEmpty(item.getProductNature())) continue;
if (ObjectUtil.isNotEmpty(item.getProductWeight()) && item.getProductWeight().compareTo(BigDecimal.valueOf(0)) != 0) {
item.setProductNature(HardProductNatureEnum.WEIGHT);
} else if (ObjectUtil.isNotEmpty(item.getProductCount())) {
item.setProductNature(HardProductNatureEnum.DEFAULT);
}
}
}
dto.setOrderPayType(HardPayTypeEnum.WALLET_QR_CODE_SCAN);
return R.ok(hardwareOrderService.createHardQrCodeScanOrder(dto));
}
@PostMapping("/done-hard-qr-code-order")
@Operation(summary = "用户确认设备二维码扫一扫订单")
@Idempotent(expireTime = 10, info = "订单支付中,请勿重复操作")
public R<Long> doneHardQrCodeScanOrder(@Validated @RequestBody HardDoneHardQrCodeScanOrderDto body) {
PjcloudUser user = SecurityUtils.getUser();
hardwareOrderService.doneHardQrCodeScanOrder(body, user);
return R.ok();
}
@PostMapping("/cancel-code")
@Operation(summary = "核销二维码")
@Idempotent(expireTime = 10, info = "正在核销中,请勿重复操作")
@@ -0,0 +1,18 @@
package com.bsd.pjcloud.hard.redis.config;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;
@Component
public class RedisConfig {
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
@@ -11,11 +11,13 @@ import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardPayTypeEnum;
import com.bsd.pjcloud.hard.api.dto.hard.HandCancelCodeDto;
import com.bsd.pjcloud.hard.api.dto.hard.HardCreateOrderDto;
import com.bsd.pjcloud.hard.api.dto.hard.HardDoneHardQrCodeScanOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.HardCreateCarDto;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.app.HardAppCreateOrderDto;
import com.bsd.pjcloud.hard.api.entity.order.HardCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardCreateHardQrCodeScanOrderVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.thirdparty.dto.ks.KsRecognitionCallbackDto;
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
@@ -43,6 +45,16 @@ public interface HardOrderService extends IService<HardOrderEntity> {
*/
Long createOrder(HardCreateOrderDto dto);
/**
* 创建设备二维码扫一扫订单
*/
HardCreateHardQrCodeScanOrderVo createHardQrCodeScanOrder(@Valid HardCreateOrderDto dto);
/**
* 用户确认设备二维码扫一扫订单
*/
void doneHardQrCodeScanOrder(HardDoneHardQrCodeScanOrderDto dto, PjcloudUser user);
/**
* app创建食堂预定订单
*/
@@ -5,6 +5,7 @@ import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.api.response.AlipayTradePayResponse;
import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -17,6 +18,7 @@ import com.bsd.pjcloud.admin.api.utils.DataUtil;
import com.bsd.pjcloud.admin.api.vo.UserVO;
import com.bsd.pjcloud.canteen.api.feign.RemoteOnlineCanteenSpuService;
import com.bsd.pjcloud.canteen.dto.CanteenSpuUpdateStockReqDTO;
import com.bsd.pjcloud.common.core.constant.CacheConstants;
import com.bsd.pjcloud.common.core.constant.enums.MerchantTypeEnum;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.core.util.BeanUtils;
@@ -31,6 +33,7 @@ import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardPayTypeEnum;
import com.bsd.pjcloud.hard.api.dto.ali.AliMicropayDto;
import com.bsd.pjcloud.hard.api.dto.ali.AliReverseDto;
import com.bsd.pjcloud.hard.api.dto.hard.HardDoneHardQrCodeScanOrderDto;
import com.bsd.pjcloud.hard.api.dto.manager.HardManagerDto;
import com.bsd.pjcloud.hard.api.dto.hard.HandCancelCodeDto;
import com.bsd.pjcloud.hard.api.dto.hard.HardCreateOrderDto;
@@ -50,6 +53,7 @@ import com.bsd.pjcloud.hard.api.utils.HardUtil;
import com.bsd.pjcloud.hard.api.vo.HardDoorFlowVo;
import com.bsd.pjcloud.hard.api.vo.manager.HardManagerVo;
import com.bsd.pjcloud.hard.api.vo.order.HardCarVo;
import com.bsd.pjcloud.hard.api.vo.order.HardCreateHardQrCodeScanOrderVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.hard.api.vo.wechat.WechatMicropayVo;
import com.bsd.pjcloud.hard.mapper.manager.HardManagerMapper;
@@ -79,9 +83,11 @@ import com.bsd.pjcloud.wallet.api.vo.WalletManageVo;
import com.bsd.pjcloud.wallet.api.vo.WalletSettingVo;
import com.bsd.pjcloud.wallet.api.vo.mch.MchRuleJoinDtoVo;
import jakarta.validation.Valid;
import lombok.Locked;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
@@ -97,6 +103,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
/**
* 订单表
@@ -137,6 +144,8 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
private final HardManagerMapper hardManagerMapper;
private final StringRedisTemplate redisTemplate;
@Override
public Page<HardOrderVo> pagejoin(Page page, HardOrderDto dto) {
Page<HardOrderVo> list = baseMapper.pageJoin(page, dto);
@@ -354,6 +363,117 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
return orderObj.getId();
}
/**
* 创建设备二维码扫一扫订单
*/
@Override
// @GlobalTransactional
@Transactional(rollbackFor = Exception.class)
public HardCreateHardQrCodeScanOrderVo createHardQrCodeScanOrder(HardCreateOrderDto dto) {
MchManageVo mch = validateCreateOrderDto(dto);
if (ObjectUtil.isEmpty(mch)) throw new RuntimeException("机器绑定的商户不存在");
if (ObjectUtil.notEqual(mch.getTypes(), MerchantTypeEnum.SELF_SUPERMARKET.getType())) {
throw new RuntimeException("该订单不是设备扫一扫订单");
}
// 添加购物车
Long parentCarId = hardCarService.createCard(dto.getUserId(), dto.getMerchantId(), dto.getSysType(), dto.getOrderType(), dto.getList());
// 获取商品描述
String subject = hardCarService.computerCarSubject(dto.getSysType(), dto.getOrderType(), dto.getList());
// 是否需要支付额外金额
boolean isExtraPrice = isExtraPrice(dto.getSysType());
SysUser sysUser = null;
int totalPrice = 0, extraPrice = 0, payPrice = 0;
totalPrice = hardCarService.computerCarTotalPrice(dto.getSysType(), dto.getOrderType(), dto.getList());
if (isExtraPrice) extraPrice = computeExtraPrice(totalPrice, mch, sysUser);
payPrice = totalPrice + extraPrice;
// 添加硬件订单
HardOrderEntity orderObj = HardOrderEntity.builder()
.androidOrderCode(dto.getAndroidOrderCode())
.sysType(dto.getSysType().getType())
.hourType(String.valueOf(dto.getHourType()))
.parentCarId(parentCarId)
.hardId(dto.getHardwareId())
.orderStatus(HardOrderStatusEnum.CREATE.getType())
.merchantId(dto.getMerchantId())
.merchantType(mch.getTypes())
.merchantDeptId(mch.getDeptId())
.deptId(dto.getDeptId())
.orderType(dto.getOrderType().getType())
.payType(dto.getOrderPayType().getType())
.orderSourceTypeId(dto.getOrderSourceTypeId())
.totalPrice(totalPrice)
.extraPrice(extraPrice)
.payPrice(0)
.isOfflineOrder(YesNoEnum.NO.getCode())
.productDesc(subject)
.build();
orderObj.setUserId(-1L);
baseMapper.insert(orderObj);
// String qrCodeData = String.format("https://stgl.pj.gov.cn/h5/#/pages/pay/scanPay?action=harQrCodeScanPay&orderId=%s&mchId=%s", orderObj.getId(), orderObj.getMerchantId());
// 在redis里存储订单id如果5分钟没有支付就删除订单
String redisKey = String.format("%s:%s", CacheConstants.HARDER_ORDER_NON_PAY, orderObj.getId());
redisTemplate.opsForValue().set(redisKey, String.valueOf(orderObj.getId()), 300, TimeUnit.SECONDS);
String qrCodeData = String.format("http://192.168.101.173:8889/h5/#/pages/pay/scanPay?action=harQrCodeScanPay&orderId=%s&mchId=%s", orderObj.getId(), orderObj.getMerchantId());
return HardCreateHardQrCodeScanOrderVo.builder().orderId(orderObj.getId()).mchId(orderObj.getMerchantId()).qrCodeData(qrCodeData).build();
}
/**
* 用户确认设备二维码扫一扫订单
*/
@Override
@Lock4j(keys = {"#dto.orderId"})
@Transactional(rollbackFor = Exception.class)
public void doneHardQrCodeScanOrder(HardDoneHardQrCodeScanOrderDto dto, PjcloudUser user) {
// 查询订单
HardOrderEntity order = baseMapper.selectById(dto.getOrderId());
if (ObjectUtil.isEmpty(order)) throw new RuntimeException("订单不存在");
// 判断该订单是否为设备扫一扫订单
MchManageVo mch = remoteMchService.getById(order.getMerchantId()).getData();
if (ObjectUtil.notEqual(mch.getTypes(), MerchantTypeEnum.SELF_SUPERMARKET.getType())) {
throw new RuntimeException("该订单不是设备扫一扫订单");
}
// 判断是否已支付
if (HardOrderStatusEnum.getPaySuccessCodes().contains(order.getOrderStatus())) {
throw new RuntimeException("该订单已支付");
}
// 钱包查询
WalletManageEntity wallet = remoteWalletService.getWalletByWalletTypeId(user.getId(), dto.getWalletTypeId()).getData();
if (ObjectUtil.isEmpty(wallet)) throw new RuntimeException("用户钱包不存在");
// 查询用户
UserInfo userInfo = userService.getByUserId(wallet.getUserId()).getData();
if (ObjectUtil.isEmpty(userInfo)) throw new RuntimeException("钱包用户不存在");
// 更新订单
HardOrderEntity updateObj = HardOrderEntity.builder()
.id(order.getId())
.walletId(wallet.getId())
.userId(userInfo.getSysUser().getUserId())
.userDeptId(userInfo.getSysUser().getDeptId())
.payPrice(order.getTotalPrice() + order.getExtraPrice())
.build();
baseMapper.updateById(updateObj);
order = baseMapper.selectById(order.getId());
// 扣减库存
getSelf().fastenerInventory(order, YesNoEnum.YES);
// 钱包扣款
getSelf().fastReduceBalance(order);
// 在redis里存储订单id如果5分钟没有支付就删除订单(这里删除一下)
String redisKey = String.format("%s:%s", CacheConstants.HARDER_ORDER_NON_PAY, order.getId());
redisTemplate.delete(redisKey);
}
@Override
// @GlobalTransactional
@Transactional(rollbackFor = Exception.class)
@@ -35,7 +35,6 @@ public class SysUserCarEntity extends Model<SysUserCarEntity> {
* 用户ID
*/
@Schema(description = "用户ID")
@NotNull(message = "用户ID不能为空")
private Long userId;
/**
@@ -27,7 +27,6 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Objects;
/**
* 车辆管理
@@ -52,10 +51,18 @@ public class SysUserCarController {
/* ************************************* start app start ************************************* */
@PostMapping("/app/create")
public void appCreateCar(@Validated @RequestBody SysUserCarDto dto) {
public R appCreateCar(@Validated @RequestBody SysUserCarDto dto) {
PjcloudUser user = SecurityUtils.getUser();
dto.setUserId(user.getId());
sysUserCarService.appCreateCar(dto);
return R.ok();
}
@PostMapping("/app/page")
public R<Page<SysUserCarVo>> appCarPage(@ParameterObject Page page, @ParameterObject SysUserCarDto dto) {
PjcloudUser user = SecurityUtils.getUser();
dto.setUserId(user.getId());
return R.ok(sysUserCarService.scopePageJoin(page, dto, null));
}
/* ************************************* end app end ************************************* */
@@ -104,6 +104,7 @@ public class SysUserCarServiceImpl extends ServiceImpl<SysUserCarMapper, SysUser
// 查询申请部门
SysDept dept = deptService.getById(user.getDeptId());
dto.setProcessStatus(TaskCheckStatusEnum.PADDING.getCode());
baseMapper.insert(dto);
// 创建审批