feat:钱包记账扣款记录

This commit is contained in:
dzc committed 2025-03-21 11:29:09 +08:00
1 parent a6c7ff821e
commit 96dbde3943
13 files changed
+160 -12

No files matched your search

@@ -19,12 +19,16 @@ public enum HardTypeEnum {
CANTEEN("2", "食堂"),
READ_CARD("3", "读卡器"),
DOOR("4", "生鲜柜"),
MERCHANT_QR_CODE("5", "商户二维码扣款牌"),
;
private final String type;
private final String description;
// 是否能预定
private static final List<HardTypeEnum> isReserveList = List.of(SUPERMARKET, CANTEEN);
public static final List<HardTypeEnum> isReserveList = List.of(SUPERMARKET, CANTEEN);
// 不需要创建购物车
public static final List<HardTypeEnum> isNoneCar = List.of(MERCHANT_QR_CODE);
public static Boolean isReserve(HardTypeEnum type) {
return isReserveList.contains(type);
@@ -15,6 +15,7 @@ import java.util.Arrays;
public enum HardPayTypeEnum {
WALLET_DEFAULT("1", "普通钱包支付"),
WALLET_QR_CODE("2", "钱包二维码支付"),
WALLET_QR_CODE_SCAN("22", "钱包扫一扫支付"),
WALLET_CARD("3", "钱包饭卡支付"),
FACE("4", "人脸识别支付"),
STRIDE_DEPT_QR_CODE("5", "跨单位二维码支付"),
@@ -0,0 +1,18 @@
package com.bsd.pjcloud.hard.api.dto.app;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class HardAppCreateOrderScancode {
@Schema(description = "商户id")
@NotNull(message = "商户id不能为空")
private Long merchantId;
@Schema(description = "用户输入的价格")
@NotNull(message = "自定义金额不能为空")
private Integer customPrice;
}
@@ -4,6 +4,7 @@ import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardPayTypeEnum;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
@@ -16,7 +17,6 @@ import lombok.NoArgsConstructor;
@Data
public class HardAppCreateOrderDto {
@NotNull(message = "父订单id不能为空")
private Long carParentId;
@NotNull(message = "用户id不能为空")
@@ -36,4 +36,10 @@ public class HardAppCreateOrderDto {
private Long orderSourceTypeId;
// 用户自定义的价格(分)不是通过计算购物车总价得来的
private Integer customPrice;
// 商户id
private Long merchantId;
}
@@ -23,6 +23,7 @@ import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardHourTypeEnum;
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.app.HardAppCreateOrderScancode;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderPreferencesDto;
import com.bsd.pjcloud.hard.api.dto.order.app.HardAppCreateOrderDto;
@@ -41,6 +42,7 @@ import org.springframework.http.HttpHeaders;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
@@ -102,6 +104,22 @@ public class HardOrderController {
HardAppCreateOrderDto dto = HardAppCreateOrderDto.builder().carParentId(carParentId).walletType(WalletTypeEnum.EAT).hardType(hardType).userId(user.getId()).orderType(HardOrderTypeEnum.RESERVE).payType(HardPayTypeEnum.WALLET_DEFAULT).build();
return R.ok(hardwareOrderService.appCreateOrder(dto));
}
@Operation(summary = "app创建订单扫一扫", description = "app创建订单扫一扫")
@PostMapping("/app/create-order-scan-qrcode")
@Idempotent(expireTime = 10, info = "正在创建订单中,请勿重复操作")
public R appCreateOrderScancode(@Validated @RequestBody HardAppCreateOrderScancode body) {
PjcloudUser user = SecurityUtils.getUser();
HardAppCreateOrderDto dto = HardAppCreateOrderDto.builder()
.customPrice(body.getCustomPrice())
.userId(user.getId())
.hardType(HardTypeEnum.MERCHANT_QR_CODE)
.orderType(HardOrderTypeEnum.RESERVE)
.walletType(WalletTypeEnum.EAT)
.payType(HardPayTypeEnum.WALLET_QR_CODE_SCAN)
.build();
return R.ok(hardwareOrderService.appCreateOrderScancode(dto));
}
/* ************************************* end app end ************************************* */
@Operation(summary = "分页查询", description = "分页查询")
@@ -30,6 +30,11 @@ public interface HardOrderService extends IService<HardOrderEntity> {
*/
Long appCreateOrder(@Valid HardAppCreateOrderDto dto);
/**
* 创建app订单
*/
Long appCreateOrderScancode(@Valid HardAppCreateOrderDto dto);
/**
* 快速扣款,离线订单使用
*/
@@ -337,6 +337,46 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
return orderObj.getId();
}
@Override
// @GlobalTransactional
@Transactional(rollbackFor = Exception.class)
public Long appCreateOrderScancode(HardAppCreateOrderDto dto) {
// 钱包
WalletManageEntity wallet = remoteWalletService.getWallet(dto.getUserId(), dto.getWalletType()).getData();
if (ObjectUtil.isEmpty(wallet)) throw new RuntimeException("用户钱包不存在");
Integer balance = wallet.getBalance();
int totalPrice = dto.getCustomPrice();
String subject = "未知商品 * ?";
if (balance < totalPrice) {
throw new RuntimeException("钱包余额不足");
}
// 添加硬件订单
HardOrderEntity orderObj = HardOrderEntity.builder()
.userId(dto.getUserId())
.parentCarId(dto.getCarParentId())
.sysType(dto.getHardType().getType())
.orderStatus(HardOrderStatusEnum.CREATE.getType())
.merchantId(null)
.orderType(dto.getOrderType().getType())
.payType(dto.getPayType().getType())
.orderSourceTypeId(dto.getOrderSourceTypeId())
.totalPrice(totalPrice)
.extraPrice(0)
.payPrice(totalPrice)
.isOfflineOrder(YesNoEnum.NO.getCode())
.productDesc(subject)
.build();
orderObj.setWalletId(wallet.getId());
baseMapper.insert(orderObj);
// 钱包扣款
getSelf().fastReduceBalance(orderObj);
// 是否需要创建二维码
getSelf().generateCode(orderObj);
// 扣减库存
// getSelf().fastenerInventory(orderObj, YesNoEnum.YES);
return orderObj.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void fastReduceBalance(HardOrderEntity order) {
@@ -12,10 +12,6 @@ public class MchCollectionCodeVo {
* 商户名
*/
private String name;
/**
* 商户类型
*/
private String type;
public String getFileName() {
return "merchant_collect_money_code_" + id;
@@ -105,6 +105,14 @@ public class MchManageController {
}
/* ************************************* end app end ************************************* */
@Operation(summary = "刷新商户二维码", description = "刷新商户二维码")
@GetMapping("/refresh-qrcode")
@PreAuthorize("@pms.hasPermission('wallet_mchManage_refresh_qrcode')")
public R refreshQrcode(@RequestParam("mchId") Long mchId) {
mchManageService.refreshQrcode(mchId);
return R.ok();
}
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('wallet_mchManage_view')")
@@ -100,6 +100,15 @@ public class WalletTransactionController {
return R.ok(walletTransactionService.scopePageList(page, dto, dataScope));
}
@Operation(summary = "后台记账扣款记录分页", description = "后台记账扣款记录分页")
@PostMapping("/page-jz")
public R pageJz(@ParameterObject Page page, @RequestBody WalletTransactionDto dto) {
dto.setBizTypes(WalletBizEnum.getTopUpCodes());
dto.setType(WalletTransactionDto.TYPE_EXPENSE);
DataScope dataScope = new DataScope();
return R.ok(walletTransactionService.scopePageList(page, dto, dataScope));
}
@Operation(summary = "后台消费分页", description = "后台消费分页")
@PostMapping("/page-xf")
public R pageXf(@ParameterObject Page page, @RequestBody WalletTransactionDto dto) {
@@ -167,6 +176,17 @@ public class WalletTransactionController {
walletTransactionService.exportByTemplate(response, dto, "file/个人充值明细.xlsx", list);
}
@Operation(summary = "记账扣款导出", description = "记账扣款导出")
@PostMapping("/export-jz")
@PreAuthorize("@pms.hasPermission('wallet_walletTransaction_export')")
public void exportJz(HttpServletResponse response, @RequestBody WalletTransactionDto dto) {
dto.setBizTypes(WalletBizEnum.getTopUpCodes());
dto.setType(WalletTransactionDto.TYPE_EXPENSE);
List<WalletTransactionVo> list = walletTransactionService.scopeList(dto, DataScope.of());
walletTransactionService.exportByTemplate(response, dto, "file/个人记账扣款明细.xlsx", list);
}
@Operation(summary = "消费导出", description = "消费导出")
@PostMapping("/export-xf")
@PreAuthorize("@pms.hasPermission('wallet_walletTransaction_export')")
@@ -30,4 +30,9 @@ public interface MchManageService extends IService<MchManageEntity> {
MchManageVo getFirstMch(List<Long> deptIds);
MchManageVo getFirstMchByDeptId(Long deptId);
/**
* 刷新商户二维码
*/
void refreshQrcode(Long mchId);
}
@@ -1,13 +1,13 @@
package com.bsd.pjcloud.wallet.service.impl;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.admin.api.dto.UserInfo;
import com.bsd.pjcloud.admin.api.entity.SysDept;
import com.bsd.pjcloud.admin.api.feign.RemoteDeptService;
import com.bsd.pjcloud.admin.api.feign.RemoteFileService;
@@ -24,16 +24,13 @@ import com.bsd.pjcloud.wallet.api.entity.MchManageEntity;
import com.bsd.pjcloud.wallet.api.entity.WalletTypeEntity;
import com.bsd.pjcloud.wallet.api.utils.WalletDataUtil;
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
import com.bsd.pjcloud.wallet.api.vo.WalletActiveVo;
import com.bsd.pjcloud.wallet.api.vo.code.MchCollectionCodeVo;
import com.bsd.pjcloud.wallet.mapper.MchManageMapper;
import com.bsd.pjcloud.wallet.mapper.WalletTypeMapper;
import com.bsd.pjcloud.wallet.service.MchManageService;
import com.bsd.pjcloud.wallet.service.WalletThirdZyService;
import com.bsd.pjcloud.wallet.service.WalletTypeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mock.web.MockMultipartFile;
@@ -88,12 +85,13 @@ public class MchManageServiceImpl extends ServiceImpl<MchManageMapper, MchManage
throw new RuntimeException("该部门已经绑定过商户");
}
baseMapper.insert(dto);
getSelf().refreshQrcode(dto.getId());
try {
MchCollectionCodeVo mchCollectionCode = new MchCollectionCodeVo();
BeanUtils.toBean(dto, MchCollectionCodeVo.class);
byte[] bytes = QRCodeImageGenerator.generateQrCodeImage(JSON.toJSONString(mchCollectionCode), 1024);
MultipartFile multipartFile = new MockMultipartFile("file", mchCollectionCode.getFileName() + ".png", "image/png", new ByteArrayInputStream(bytes));
R upload = remoteFileService.upload(multipartFile, null, null, null);
R upload = remoteFileService.innerUpload(multipartFile, null, null, null);
Map data = (Map) upload.getData();
String url = (String) data.get("url");
MchManageEntity merchantInfoEntity = new MchManageEntity();
@@ -239,6 +237,35 @@ public class MchManageServiceImpl extends ServiceImpl<MchManageMapper, MchManage
return getFirstMch(deptIds);
}
/**
* 刷新商户二维码
*/
@Override
public void refreshQrcode(Long mchId) {
// 查询商户
MchManageEntity mchDetail = baseMapper.selectById(mchId);
if (ObjectUtil.isEmpty(mchDetail)) return;
try {
MchCollectionCodeVo mchCollectionCode = new MchCollectionCodeVo();
mchCollectionCode.setId(mchDetail.getId());
mchCollectionCode.setName(mchDetail.getName());
String coeContent = Base64.encode(JSONUtil.toJsonStr(mchCollectionCode));
byte[] bytes = QRCodeImageGenerator.generateQrCodeImage(coeContent, 1024);
MultipartFile multipartFile = new MockMultipartFile("file", mchCollectionCode.getFileName() + ".png", "image/png", new ByteArrayInputStream(bytes));
R upload = remoteFileService.innerUpload(multipartFile, null, null, null);
Map data = (Map) upload.getData();
String url = (String) data.get("url");
MchManageEntity updateEntity = new MchManageEntity();
updateEntity.setId(mchDetail.getId());
updateEntity.setCollectionCode(url);
updateById(updateEntity);
} catch (Exception e) {
e.printStackTrace();
log.error("|{}|新增商户,生成收款码错误dto:|{}|error:|{}|", TAG, JSON.toJSONString(mchDetail), e.getMessage());
}
}
private boolean existName(String name, Long id) {
Long count = baseMapper.selectCount(new LambdaQueryWrapper<MchManageEntity>()
.eq(ObjectUtil.isNotEmpty(name), MchManageEntity::getName, name)