feat:android机器硬件管理接口

This commit is contained in:
dzc committed 2025-01-06 16:13:03 +08:00
1 parent f922ddf09b
commit d1db95452e
46 files changed
+1440 -316

No files matched your search

@@ -122,6 +122,8 @@ public interface CacheConstants {
/* ************************************* start 钱包相关 start ************************************* */
String WALLET_DEFAULT = "wallet_default";
String WALLET_MCH = "wallet:detail:mch";
String WALLET_DETAIL = "wallet:detail:manage";
@@ -0,0 +1,26 @@
package com.bsd.pjcloud.hard.api.constant;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import javax.xml.stream.events.StartDocument;
import java.util.Arrays;
/**
* 打印状态
*/
@AllArgsConstructor
@Getter
public enum HardPrintStatusEnum {
GENERATE("1", "已生成"),
PRINT("2", "已打印"),
;
private final String type;
private final String description;
public static HardPrintStatusEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
}
@@ -0,0 +1,26 @@
package com.bsd.pjcloud.hard.api.constant.order;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
@AllArgsConstructor
@Getter
public enum HardOrderStatusEnum {
CREATE("1", "创建订单(未支付)"),
OFFLINE_CREATE("2", "离线创建订单(未支付)"),
PAY("5", "已经支付"),
OFFLINE_PAY("6", "没有网络本地支付"),
REFUND("10", "退款"),
CANCEL("20", "已核销"),
;
private final String type;
private final String description;
public static HardOrderStatusEnum valueOfByType(Integer type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
}
@@ -12,15 +12,15 @@ import java.util.Arrays;
@AllArgsConstructor
@Getter
public enum HardOrderTypeEnum {
BELOW(1, "线下购买"),
RESERVE(2, "线上订餐"),
FOREIGN_TICKET(3, "外来人员"),
STRIDE_DEPT(4, "跨单位"),
BELOW("1", "线下购买"),
RESERVE("2", "线上订餐"),
FOREIGN_TICKET("3", "外来人员"),
STRIDE_DEPT("4", "跨单位"),
;
private final Integer type;
private final String type;
private final String description;
public static HardOrderTypeEnum valueOfByType(Integer type) {
public static HardOrderTypeEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
@@ -13,19 +13,19 @@ import java.util.Arrays;
@AllArgsConstructor
@Getter
public enum HardPayTypeEnum {
WALLET_DEFAULT(1, "普通钱包支付"),
WALLET_QR_CODE(2, "钱包二维码支付"),
WALLET_CARD(3, "钱包饭卡支付"),
FACE(4, "人脸识别支付"),
STRIDE_DEPT_QR_CODE(5, "跨单位二维码支付"),
FOREIGN_TICKET_QR_CODE(6, "外来人员二维码支付"),
RESERVE_QR_CODE(7, "线上订餐二维码支付"),
CASH(8, "现金支付"),
WALLET_DEFAULT("1", "普通钱包支付"),
WALLET_QR_CODE("2", "钱包二维码支付"),
WALLET_CARD("3", "钱包饭卡支付"),
FACE("4", "人脸识别支付"),
STRIDE_DEPT_QR_CODE("5", "跨单位二维码支付"),
FOREIGN_TICKET_QR_CODE("6", "外来人员二维码支付"),
RESERVE_QR_CODE("7", "线上订餐二维码支付"),
CASH("8", "现金支付"),
;
private final Integer type;
private final String type;
private final String description;
public static HardPayTypeEnum valueOfByType(Integer type) {
public static HardPayTypeEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
@@ -0,0 +1,41 @@
package com.bsd.pjcloud.hard.api.dto.async;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class OfflineCar {
@Schema(description = "sqlite自增ID")
private Long id;
@Schema(description = "购物车的id字段")
private Long orderId;
@Schema(description = "商品id")
private Long productServiceUniqueCode;
@Schema(description = "商品名")
private String productName;
@Schema(description = "商品图片")
private String productPic;
// 商品价格(分)
@Schema(description = "商品价格(分)")
private Long productPrice;
// TODO 食堂特有
@Schema(description = "数量")
private Integer productNumber;
// TODO 超市特有
@Schema(description = "重量")
private BigDecimal productWidget;
@Schema(description = "单商品总价(分)")
private Long totalPrice;
}
@@ -0,0 +1,80 @@
package com.bsd.pjcloud.hard.api.dto.async;
import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderStatusEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardPayTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Data
public class OfflineOrder {
@Schema(description = "sqlite自增ID")
private Long id;
@Schema(description = "android唯一code")
private String uniqueCode;
@Schema(description = "服务端唯一标识")
private String serviceUniqueCode;
@Schema(description = "平台类型")
private HardTypeEnum sysType;
@Schema(description = "用户唯一标识")
private Long userCode;
@Schema(description = "用户名")
private String username;
// 订单用餐类型:早、中、晚
private String hourType;
@Schema(description = "购物车的总金额")
private Integer price;
@Schema(description = "购物车的额外金额")
private Integer extraPrice;
@Schema(description = "结算总金额")
private Integer payPrice;
@Schema(description = "钱包id")
private Long walletId;
@Schema(description = "订单类型渠道id")
private Long orderSourceTypeId;
@Schema(description = "订单类型")
private HardOrderTypeEnum type;
@Schema(description = "订单状态")
private HardOrderStatusEnum status;
@Schema(description = "支付方式")
private HardPayTypeEnum payType;
@Schema(description = "商品描述")
private String productDesc;
// TODO 食堂特有
@Schema(description = "商品总数量")
private Integer count;
// TODO 超市特有
@Schema(description = "重量")
private Double weight;
@Schema(description = "支付时间")
private String payTime;
@Schema(description = "创建时间")
private Date createTime;
@Schema(description = "购物车列表")
private List<OfflineCar> carList;
}
@@ -0,0 +1,24 @@
package com.bsd.pjcloud.hard.api.dto.async;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
@Data
public class SyncOfflineReqVo {
@Schema(description = "硬件id")
@NotNull(message = "硬件id不能为空")
private Long hardwareId;
@Schema(description = "商户id")
@NotNull(message = "商户id不能为空")
private Long merchantId;
@Schema(description = "订单列表")
@NotEmpty(message = "订单列表不能为空")
private List<OfflineOrder> list;
}
@@ -0,0 +1,23 @@
package com.bsd.pjcloud.hard.api.dto.hard;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class HandCancelCodeDto {
@Schema(description = "生成的订单id")
@NotNull(message = "生成的订单id不能为空")
private Long orderId;
@Schema(description = "设备id")
@NotNull(message = "设备id不能为空")
private Long hardwareId;
@Schema(description = "安卓订单code")
@NotNull(message = "安卓订单code不能为空")
private String androidOrderCode;
@Schema(description = "用户id")
private Long userId;
}
@@ -62,8 +62,6 @@ public class HardCreateOrderDto {
@Schema(description = "商品的简短描述")
private String productDesc;
private String clientIP;
private Long deptId;
@Schema(description = "离线支付是否成功")
@@ -1,8 +1,8 @@
package com.bsd.pjcloud.hard.api.dto.order;
import com.bsd.pjcloud.hard.api.entity.order.HardwareOrderEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import lombok.Data;
@Data
public class HardOrderDto extends HardwareOrderEntity {
public class HardOrderDto extends HardOrderEntity {
}
@@ -3,8 +3,7 @@ package com.bsd.pjcloud.hard.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.*;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
@@ -14,6 +13,9 @@ import java.time.LocalDateTime;
* @author dzc
* @date 2025-01-05 14:17:32
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@TenantTable
@TableName("hard_invoice")
@@ -60,7 +60,7 @@ public class HardCarEntity extends Model<HardCarEntity> {
* 商品价格
*/
@Schema(description="商品价格")
private Long productPrice;
private Integer productPrice;
/**
* 数量
@@ -3,8 +3,7 @@ package com.bsd.pjcloud.hard.api.entity.order;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.*;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
@@ -14,12 +13,15 @@ import java.time.LocalDateTime;
* @author dzc
* @date 2025-01-05 16:46:25
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@TenantTable
@TableName("hardware_order")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "订单表")
public class HardwareOrderEntity extends Model<HardwareOrderEntity> {
public class HardOrderEntity extends Model<HardOrderEntity> {
/**
@@ -0,0 +1,229 @@
package com.bsd.pjcloud.hard.api.utils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class Drawing2D {
/**
* start ****************** config ****************** start
*/
private Graphics2D graphics;
private BufferedImage canvas;
/**
* 固定尺寸
* static int mm58 = 384;
* static const mm80_Old = 500;
* static const mm80 = 570;
*/
private final int canvasWidth = 340;
private final int canvasHeight = 200;
private int currentWidth = canvasWidth;
private int currentHeight = canvasHeight;
private final int horizontalPadding = 20;
private final String fontFamily = "宋体";
/**
* end ****************** config ****************** end
*/
private int currentY = 0;
private int getCurrentY() {
computedHeight();
int size = graphics.getFont().getSize();
FontMetrics metrics = graphics.getFontMetrics(graphics.getFont());
int lineHeight = metrics.getHeight();
int offset = (lineHeight - size) / 2;
return currentY + offset;
}
private int[] getPaddingX() {
return new int[]{horizontalPadding, canvasWidth - horizontalPadding};
}
public Drawing2D() {
canvas = new BufferedImage(canvasWidth, canvasHeight, BufferedImage.TYPE_INT_RGB);
graphics = canvas.createGraphics();
// 设置背景颜色为白色
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, canvasWidth, canvasHeight);
}
// 虚线
public Drawing2D drawingDottedLine() {
return drawingDottedLine(5);
}
public Drawing2D drawingDottedLine(int padding) {
if (padding != 0) currentY += padding;
float[] dashPattern = {10f, 5f};
Stroke dashedStroke = new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0f, dashPattern, 0f);
graphics.setStroke(dashedStroke);
graphics.setColor(Color.BLACK);
currentY += 5;
int y = getCurrentY();
graphics.drawLine(0, y, canvasWidth, y);
if (padding != 0) currentY += padding;
return this;
}
public Drawing2D drawingText(String str) {
textPadding();
computedLineHeight();
graphics.drawString(str, 0, getCurrentY());
textPadding();
return this;
}
public Drawing2D drawingCenterText(String str) {
textPadding();
computedLineHeight();
Point point = centerPosition(str);
graphics.drawString(str, point.x, getCurrentY());
textPadding();
return this;
}
public Drawing2D drawingRowText(String leftStr, String rightStr) {
textPadding();
computedLineHeight();
FontMetrics metrics = graphics.getFontMetrics(graphics.getFont());
int leftTextWidth = metrics.stringWidth(leftStr);
int rightTextWidth = metrics.stringWidth(rightStr);
int y = getCurrentY();
graphics.drawString(leftStr, 0, y);
graphics.drawString(rightStr, canvasWidth - rightTextWidth, y);
textPadding();
return this;
}
public Drawing2D drawingRowText(String str1, String str2, String str3) {
textPadding();
computedLineHeight();
int y = getCurrentY();
int width = canvasWidth / 3;
FontMetrics metrics = graphics.getFontMetrics(graphics.getFont());
int str1Width = metrics.stringWidth(str1);
int str2Width = metrics.stringWidth(str2);
int str3Width = metrics.stringWidth(str3);
int str1x = 0;
int str2x = width + (width - str2Width) / 2;
int str3x = width * 2 + (width - str3Width);
graphics.drawString(str1, str1x, y);
graphics.drawString(str2, str2x, y);
graphics.drawString(str3, str3x, y);
textPadding();
return this;
}
public Drawing2D setTitleTextStyle() {
graphics.setColor(Color.BLACK);
graphics.setFont(new Font(fontFamily, Font.BOLD, 24));
return this;
}
public Drawing2D setDefaultStyle() {
graphics.setColor(Color.BLACK);
graphics.setFont(new Font(fontFamily, Font.PLAIN, 20));
return this;
}
public InputStream getInputStream() throws IOException {
drawingWhiteSide();
graphics.dispose();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
ImageIO.write(canvas, "png", bytes);
bytes.flush();
byte[] imageBytes = bytes.toByteArray();
bytes.close();
return new ByteArrayInputStream(imageBytes);
}
public byte[] getBytes() throws IOException {
drawingWhiteSide();
graphics.dispose();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
ImageIO.write(canvas, "png", bytes);
bytes.flush();
byte[] imageBytes = bytes.toByteArray();
bytes.close();
return imageBytes;
}
// 计算居中的x,y
private Point centerPosition(String str) {
FontMetrics metrics = graphics.getFontMetrics(graphics.getFont());
int textWidth = metrics.stringWidth(str);
int textHeight = metrics.getHeight();
// 中心X坐标
int x = (canvasWidth - textWidth) / 2;
// 中心Y坐标
int y = (currentHeight - textHeight) / 2 + metrics.getAscent();
return new Point(x, y);
}
private void drawingWhiteSide() {
int borderSize = 15;
BufferedImage borderedCanvas = new BufferedImage(currentWidth + borderSize * 2, currentHeight + borderSize * 2, BufferedImage.TYPE_INT_RGB);
Graphics2D g2dBordered = borderedCanvas.createGraphics();
g2dBordered.setColor(Color.WHITE);
g2dBordered.fillRect(0, 0, borderedCanvas.getWidth(), borderedCanvas.getHeight());
g2dBordered.drawImage(canvas, borderSize, borderSize, null);
graphics = g2dBordered;
canvas = borderedCanvas;
}
private void computedHeight() {
Font font = graphics.getFont();
FontMetrics metrics = graphics.getFontMetrics(font);
int height = currentY + metrics.getAscent();
if (height <= currentHeight) return;
graphics.dispose();
currentHeight = height + metrics.getAscent();
BufferedImage newCanvas = new BufferedImage(currentWidth, currentHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D newGraphics = newCanvas.createGraphics();
newGraphics.setColor(Color.WHITE);
newGraphics.fillRect(0, 0, newCanvas.getWidth(), newCanvas.getHeight());
newGraphics.drawImage(canvas, 0, 0, null);
canvas = newCanvas;
newGraphics.setColor(graphics.getColor());
newGraphics.setFont(graphics.getFont());
graphics = newGraphics;
}
private void textPadding() {
currentY += 10;
}
private void computedLineHeight() {
int size = graphics.getFont().getSize();
FontMetrics metrics = graphics.getFontMetrics(graphics.getFont());
int lineHeight = metrics.getHeight();
int offset = (lineHeight - size) / 2;
currentY += size + offset;
}
}
@@ -7,8 +7,10 @@ import lombok.Data;
@Data
public class HardInvoiceVo extends HardInvoiceEntity implements BaseDeptInterface, BaseMchInterface {
private String deptName;
private Long merchantId;
private String merchantName;
}
@@ -1,8 +1,8 @@
package com.bsd.pjcloud.hard.api.vo.order;
import com.bsd.pjcloud.hard.api.entity.order.HardwareOrderEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import lombok.Data;
@Data
public class HardOrderVo extends HardwareOrderEntity {
public class HardOrderVo extends HardOrderEntity {
}
@@ -3,26 +3,25 @@ package com.bsd.pjcloud.hard.controller.hard;
import com.bsd.pjcloud.common.core.util.BeanUtils;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.idempotent.annotation.Idempotent;
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.vo.HardInvoiceVo;
import com.bsd.pjcloud.hard.api.vo.HardManagerVo;
import com.bsd.pjcloud.hard.api.vo.order.HardCarVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.hard.service.HardCarService;
import com.bsd.pjcloud.hard.service.HardManagerService;
import com.bsd.pjcloud.hard.service.HardwareOrderService;
import com.bsd.pjcloud.hard.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static cn.hutool.extra.servlet.JakartaServletUtil.getClientIP;
@RestController
@RequiredArgsConstructor
@RequestMapping("/hard-api")
@@ -31,8 +30,10 @@ import static cn.hutool.extra.servlet.JakartaServletUtil.getClientIP;
public class HardApiController {
private final HardManagerService hardManagerService;
private final HardInvoiceService hardInvoiceService;
private final HardCarService hardCarService;
private final HardwareOrderService hardwareOrderService;
private final HardOrderService hardwareOrderService;
private final HardOrderSyncService hardOrderSyncService;
@PostMapping("/bind")
@Operation(summary = "绑定服务端设备")
@@ -61,9 +62,35 @@ public class HardApiController {
@PostMapping("/create-order")
@Operation(summary = "创建订单")
@Idempotent(expireTime = 10, info = "正在创建订单中,请勿重复操作")
public R<Long> createOrder(HttpServletRequest request, @RequestBody HardCreateOrderDto dto) {
dto.setClientIP(getClientIP(request));
public R<Long> createOrder(@Valid @RequestBody HardCreateOrderDto dto) {
return R.ok(hardwareOrderService.createOrder(dto));
}
@PostMapping("/cancel-code")
@Operation(summary = "核销二维码")
@Idempotent(expireTime = 10, info = "正在支付中,请勿重复操作")
public R<Boolean> handCancelCode(@Valid @RequestBody HandCancelCodeDto dto) {
return R.ok(hardwareOrderService.handCancelCode(dto));
}
@GetMapping("/generate-invoice")
@Operation(summary = "生成发票")
@Idempotent(expireTime = 10, info = "正在生成中,请勿重复操作")
public R<HardInvoiceVo> generateInvoice(@RequestParam Long orderId) {
return R.ok(hardInvoiceService.generateInvoice(orderId));
}
@GetMapping("/print-invoice")
@Operation(summary = "打印成功")
public R<Boolean> printInvoice(@RequestParam("orderId") Long orderId, @RequestParam("historyId") Long historyId) {
return R.ok(hardInvoiceService.printInvoice(orderId, historyId));
}
@PostMapping("/sync-offline-order")
@Operation(summary = "同步离线订单")
@Idempotent(expireTime = 10, info = "正在处理中,请勿重复操作")
public R<List<String>> syncOfflineOrder(@Valid @RequestBody SyncOfflineReqVo dto) {
return R.ok(hardOrderSyncService.syncOfflineOrder(dto));
}
}
@@ -8,8 +8,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.entity.order.HardwareOrderEntity;
import com.bsd.pjcloud.hard.service.HardwareOrderService;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.service.HardOrderService;
import org.springframework.security.access.prepost.PreAuthorize;
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -35,13 +35,13 @@ import java.util.List;
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class HardwareOrderController {
private final HardwareOrderService hardwareOrderService;
private final HardOrderService hardwareOrderService;
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('hard_hardwareOrder_view')")
public R getHardwareOrderPage(@ParameterObject Page page, @ParameterObject HardwareOrderEntity hardwareOrder) {
LambdaQueryWrapper<HardwareOrderEntity> wrapper = Wrappers.lambdaQuery();
public R getHardwareOrderPage(@ParameterObject Page page, @ParameterObject HardOrderEntity hardwareOrder) {
LambdaQueryWrapper<HardOrderEntity> wrapper = Wrappers.lambdaQuery();
return R.ok(hardwareOrderService.page(page, wrapper));
}
@@ -63,7 +63,7 @@ public class HardwareOrderController {
@SysLog("新增订单表")
@PostMapping
@PreAuthorize("@pms.hasPermission('hard_hardwareOrder_add')")
public R save(@RequestBody HardwareOrderEntity hardwareOrder) {
public R save(@RequestBody HardOrderEntity hardwareOrder) {
return R.ok(hardwareOrderService.save(hardwareOrder));
}
@@ -71,7 +71,7 @@ public class HardwareOrderController {
@SysLog("修改订单表")
@PutMapping
@PreAuthorize("@pms.hasPermission('hard_hardwareOrder_edit')")
public R updateById(@RequestBody HardwareOrderEntity hardwareOrder) {
public R updateById(@RequestBody HardOrderEntity hardwareOrder) {
return R.ok(hardwareOrderService.updateById(hardwareOrder));
}
@@ -86,7 +86,7 @@ public class HardwareOrderController {
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('hard_hardwareOrder_export')")
public List<HardwareOrderEntity> export(HardwareOrderEntity hardwareOrder, Long[] ids) {
return hardwareOrderService.list(Wrappers.lambdaQuery(hardwareOrder).in(ArrayUtil.isNotEmpty(ids), HardwareOrderEntity::getId, ids));
public List<HardOrderEntity> export(HardOrderEntity hardwareOrder, Long[] ids) {
return hardwareOrderService.list(Wrappers.lambdaQuery(hardwareOrder).in(ArrayUtil.isNotEmpty(ids), HardOrderEntity::getId, ids));
}
}
@@ -3,22 +3,22 @@ package com.bsd.pjcloud.hard.mapper.order;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.entity.order.HardwareOrderEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface HardOrderMapper extends PjcloudBaseMapper<HardwareOrderEntity> {
public interface HardOrderMapper extends PjcloudBaseMapper<HardOrderEntity> {
default Page<HardOrderVo> pageJoin(Page page, HardOrderDto dto) {
MPJLambdaWrapper<HardwareOrderEntity> wrapper = new MPJLambdaWrapper<HardwareOrderEntity>()
.selectAll(HardwareOrderEntity.class);
MPJLambdaWrapper<HardOrderEntity> wrapper = new MPJLambdaWrapper<HardOrderEntity>()
.selectAll(HardOrderEntity.class);
return selectJoinPage(page, HardOrderVo.class, wrapper);
}
default HardOrderVo join(HardOrderDto dto) {
MPJLambdaWrapper<HardwareOrderEntity> wrapper = new MPJLambdaWrapper<HardwareOrderEntity>()
.selectAll(HardwareOrderEntity.class);
MPJLambdaWrapper<HardOrderEntity> wrapper = new MPJLambdaWrapper<HardOrderEntity>()
.selectAll(HardOrderEntity.class);
return selectJoinOne(HardOrderVo.class, wrapper);
}
}
@@ -21,11 +21,19 @@ public interface HardCarService extends IService<HardCarEntity> {
Integer computerCarTotalPrice(@NotNull HardTypeEnum sysType, @NotEmpty List<HardCreateCarDto> list);
/**
* @param userId 用户id
* @param userId 用户id
* @param merchantId 商户id
* @param sysType 硬件设备类型
* @param list g购物车类表
* @param sysType 硬件设备类型
* @param list g购物车类表
* @return 父购物车id
*/
Long createCard(Long userId, Long merchantId, HardTypeEnum sysType, List<HardCreateCarDto> list);
/**
* 生成购买商品的描述
* @param sysType 订单类型
* @param list 购物车列表
* @return
*/
String computerCarSubject(HardTypeEnum sysType, List<HardCreateCarDto> list);
}
@@ -3,10 +3,45 @@ package com.bsd.pjcloud.hard.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.hard.api.dto.HardInvoiceDto;
import com.bsd.pjcloud.hard.api.dto.async.SyncOfflineReqVo;
import com.bsd.pjcloud.hard.api.entity.HardInvoiceEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.HardInvoiceVo;
import jakarta.validation.Valid;
import java.util.List;
public interface HardInvoiceService extends IService<HardInvoiceEntity> {
Page<HardInvoiceVo> pageJoin(Page page, HardInvoiceDto dto);
/**
* 生成发票
* @param order
* @return 订单详情
*/
String generateInvoice(HardOrderEntity order);
/**
* 生成发票
* @param order 订单详情
* @param code 取消码
* @return
*/
String generateInvoice(HardOrderEntity order, String code);
/**
* 生成发票图片
* @param orderId
* @return
*/
HardInvoiceVo generateInvoice(Long orderId);
/**
* 打印成功通知
* @param orderId
* @param historyId
* @return
*/
Boolean printInvoice(Long orderId, Long historyId);
}
@@ -2,12 +2,14 @@ package com.bsd.pjcloud.hard.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
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.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.entity.order.HardwareOrderEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import jakarta.validation.Valid;
public interface HardwareOrderService extends IService<HardwareOrderEntity> {
public interface HardOrderService extends IService<HardOrderEntity> {
Page<HardOrderVo> pageJoin(Page page, HardOrderDto dto);
@@ -15,6 +17,13 @@ public interface HardwareOrderService extends IService<HardwareOrderEntity> {
Long createOrder(HardCreateOrderDto dto);
/**
* 快速扣款
*
* @param order 订单详情
*/
void fastReduceBalance(HardOrderEntity order);
/**
* 计算额外金额
*
@@ -22,4 +31,17 @@ public interface HardwareOrderService extends IService<HardwareOrderEntity> {
* @return
*/
Integer computeExtraPrice(Integer price);
/**
* 核销二维码
*/
void cancelCode(HardOrderEntity order);
/**
* 核销硬件二维码
*
* @param dto
* @return
*/
Boolean handCancelCode(@Valid HandCancelCodeDto dto);
}
@@ -0,0 +1,17 @@
package com.bsd.pjcloud.hard.service;
import com.bsd.pjcloud.hard.api.dto.async.SyncOfflineReqVo;
import jakarta.validation.Valid;
import java.util.List;
public interface HardOrderSyncService {
/**
* 同步安卓机离线订单
* @param dto
* @return
*/
List<String> syncOfflineOrder(@Valid SyncOfflineReqVo dto);
}
@@ -1,16 +1,48 @@
package com.bsd.pjcloud.hard.service.impl;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.SysUser;
import com.bsd.pjcloud.admin.api.feign.RemoteFileService;
import com.bsd.pjcloud.admin.api.feign.RemoteUserService;
import com.bsd.pjcloud.common.core.util.BeanUtils;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.hard.api.constant.HardPrintStatusEnum;
import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
import com.bsd.pjcloud.hard.api.dto.HardInvoiceDto;
import com.bsd.pjcloud.hard.api.entity.HardInvoiceEntity;
import com.bsd.pjcloud.hard.api.entity.HardManagerEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.utils.Drawing2D;
import com.bsd.pjcloud.hard.api.vo.HardInvoiceVo;
import com.bsd.pjcloud.hard.mapper.HardInvoiceMapper;
import com.bsd.pjcloud.hard.service.HardCarService;
import com.bsd.pjcloud.hard.service.HardInvoiceService;
import com.bsd.pjcloud.hard.service.HardManagerService;
import com.bsd.pjcloud.hard.service.HardOrderService;
import com.bsd.pjcloud.wallet.api.feign.RemoteMchService;
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* 发票记录
@@ -24,9 +56,123 @@ import org.springframework.validation.annotation.Validated;
@Service
public class HardInvoiceServiceImpl extends ServiceImpl<HardInvoiceMapper, HardInvoiceEntity> implements HardInvoiceService {
static private final String TAG = "发票记录";
private final HardManagerService hardManagerService;
private final HardOrderService orderService;
private final HardCarService carService;
private final RemoteUserService userService;
private final RemoteMchService mchService;
private final RemoteFileService fileService;
@Override
public Page<HardInvoiceVo> pageJoin(Page page, HardInvoiceDto dto) {
Page<HardInvoiceVo> list = baseMapper.pageJoin(page, dto);
return list;
}
@Override
public String generateInvoice(HardOrderEntity order) {
return generateInvoice(order, null);
}
@Override
public String generateInvoice(HardOrderEntity order, String code) {
List<HardCarEntity> carList = carService.list(new LambdaQueryWrapper<HardCarEntity>()
.eq(HardCarEntity::getParentCarId, order.getParentCarId())
);
// 查询用户
UserInfo user = Optional.of(userService.getByUserId(order.getUserId())).map(R::getData).orElseThrow(() -> new RuntimeException("用户不存在"));
SysUser sysUser = user.getSysUser();
// 查询商户
MchManageVo mch = Optional.of(mchService.getById(order.getMerchantId())).map(R::getData).orElseThrow(() -> new RuntimeException("商户不存在"));
// 订单类型
String orderType = "- -";
HardOrderTypeEnum orderTypeEnum = HardOrderTypeEnum.valueOf(order.getOrderType());
if (ObjectUtil.isNotEmpty(orderTypeEnum)) {
orderType = orderTypeEnum.getDescription();
}
// 硬件类型
String hardwareName = HardTypeEnum.CANTEEN.getType();
HardTypeEnum sysTypeEnum = HardTypeEnum.valueOf(order.getSysType());
if (ObjectUtil.isNotEmpty(sysTypeEnum)) {
hardwareName = sysTypeEnum.getDescription();
}
Drawing2D drawing = new Drawing2D();
drawing.setTitleTextStyle()
.drawingCenterText(String.format("智慧%s", hardwareName))
.drawingDottedLine();
String createTime = LocalDateTimeUtil.format(order.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN);
String payTime = LocalDateTimeUtil.format(order.getPayTime(), DatePattern.NORM_DATETIME_PATTERN);
drawing.setDefaultStyle()
.drawingRowText("订单号", order.getId().toString())
.drawingRowText("订单类型", orderType)
.drawingRowText("用户", sysUser.getName())
.drawingRowText("手机号", sysUser.getPhone())
.drawingRowText("商户", mch.getName())
.drawingRowText("部门", mch.getDeptName())
.drawingRowText("下单时间", createTime)
.drawingRowText("支付时间", payTime);
if (ObjectUtil.isNotEmpty(carList)) {
drawing.drawingDottedLine();
drawing.drawingRowText("商品", "数量", "总价");
carList.forEach(v -> {
String name = v.getProductName();
String count = v.getProductCount().toString();
if (count.length() > 4) {
count = count.substring(0, 4) + "...";
}
String totalPrice = String.valueOf((v.getTotalPrice() / 100));
drawing.drawingRowText(name, count, totalPrice);
});
String totalPrice = String.valueOf(order.getTotalPrice() / 100);
String amountMealPrice = String.valueOf(order.getExtraPrice() / 100);
if (ObjectUtil.isNotEmpty(order.getExtraPrice()) && ObjectUtil.notEqual(order.getExtraPrice(), 0)) {
drawing.drawingRowText("额外支付金额", amountMealPrice);
}
drawing.drawingRowText("小记", totalPrice).drawingDottedLine();
}
String currentTime = LocalDateTimeUtil.format(LocalDateTimeUtil.now(), DatePattern.NORM_DATETIME_PATTERN);
drawing.drawingRowText("打印时间", currentTime).drawingDottedLine();
if (ObjectUtil.isNotEmpty(code)) {
drawing.drawingDottedLine().drawingRowText("取件码", code).drawingDottedLine();
}
try {
String fileName = String.format("invoice_%s_%s.png", order.getId(), LocalDateTimeUtil.now());
byte[] bytes = drawing.getBytes();
MultipartFile multipartFile = new MockMultipartFile("file", fileName + ".png", "image/png", new ByteArrayInputStream(bytes));
Map<String, Object> uploadMap = (Map<String, Object>) fileService.innerUpload(multipartFile, null, null, null).getData();
return (String) uploadMap.get("url");
} catch (IOException e) {
e.printStackTrace();
log.error("|{}|生成发票意外的错误dto:|{}|error:|{}|", TAG, JSON.toJSONString(order), e.getMessage());
return "";
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public HardInvoiceVo generateInvoice(Long orderId) {
HardOrderEntity order = orderService.getById(orderId);
if (ObjectUtil.isEmpty(order)) throw new RuntimeException("设备订单不存在");
HardManagerEntity hardManager = hardManagerService.getById(order.getHardId());
if (ObjectUtil.isEmpty(order)) throw new RuntimeException("设备不存在");
String image = generateInvoice(order);
if (ObjectUtil.isEmpty(image)) return null;
HardInvoiceEntity insertObj = HardInvoiceEntity.builder().hardId(hardManager.getId()).hardOrderId(orderId).pic(image).status(HardPrintStatusEnum.GENERATE.getType()).build();
baseMapper.insert(insertObj);
return BeanUtils.toBean(insertObj, HardInvoiceVo.class);
}
@Override
public Boolean printInvoice(Long orderId, Long historyId) {
HardOrderEntity order = orderService.getById(orderId);
if (ObjectUtil.isEmpty(order)) throw new RuntimeException("设备订单不存在");
HardInvoiceEntity detail = baseMapper.selectById(historyId);
if (ObjectUtil.isEmpty(detail)) throw new RuntimeException("开票记录不存在");
if (!ObjectUtil.equals(detail.getStatus(), HardPrintStatusEnum.GENERATE.getType())) return false;
HardInvoiceEntity updateObj = HardInvoiceEntity.builder().id(historyId).status(HardPrintStatusEnum.PRINT.getType()).build();
return baseMapper.updateById(updateObj) > 0;
}
}
@@ -4,19 +4,20 @@ import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.canteen.api.feign.RemoteCanteenSpuService;
import com.bsd.pjcloud.canteen.entity.CanteenSpuEntity;
import com.bsd.pjcloud.common.core.util.BeanUtils;
import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.dto.order.HardCarDto;
import com.bsd.pjcloud.hard.api.dto.order.HardCreateCarDto;
import com.bsd.pjcloud.hard.api.entity.order.HardCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardParentCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardwareOrderEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardCarVo;
import com.bsd.pjcloud.hard.mapper.order.HardCarMapper;
import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper;
import com.bsd.pjcloud.hard.mapper.order.HardParentCarMapper;
import com.bsd.pjcloud.hard.service.HardCarService;
import com.bsd.pjcloud.hard.service.HardParentCarService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -26,6 +27,7 @@ import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 购物车表
@@ -42,6 +44,8 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
private final HardOrderMapper hardCarMapper;
private final HardParentCarMapper hardParentCarMapper;
private final RemoteCanteenSpuService canteenSpuService;
@Override
public Page<HardCarVo> pageJoin(Page page, HardCarDto dto) {
return baseMapper.pageJoin(page, dto);
@@ -49,7 +53,7 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
@Override
public List<HardCarVo> getByOrderId(Long orderId) {
HardwareOrderEntity order = hardCarMapper.selectById(orderId);
HardOrderEntity order = hardCarMapper.selectById(orderId);
if (ObjectUtil.isEmpty(order)) return null;
List<HardCarEntity> list = baseMapper.selectList(new LambdaQueryWrapper<HardCarEntity>()
.eq(HardCarEntity::getParentCarId, order.getParentCarId())
@@ -59,13 +63,19 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
@Override
public Integer computerCarTotalPrice(HardTypeEnum sysType, List<HardCreateCarDto> list) {
List<Long> productIds = list.stream().map(HardCreateCarDto::getProductId).toList();
return switch (sysType) {
case CANTEEN -> {
int canteenTotalPrice = 0;
// 查询食堂商品
List<CanteenSpuEntity> supList = (List<CanteenSpuEntity>) canteenSpuService.getSpuListByIds(productIds).getData();
AtomicInteger canteenTotalPrice = new AtomicInteger();
for (HardCreateCarDto v : list) {
supList.stream().filter(i -> ObjectUtil.equals(i.getId(), v.getProductId())).findFirst().ifPresent(spu -> {
int itemTotalPrice = v.getProductCount() * spu.getPrice();
canteenTotalPrice.addAndGet(itemTotalPrice);
});
}
yield canteenTotalPrice;
yield canteenTotalPrice.get();
}
case SUPERMARKET -> {
int supermarketTotalPrice = 0;
@@ -81,21 +91,51 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
@Override
@Transactional(rollbackFor = Exception.class)
public Long createCard(Long userId, Long merchantId, HardTypeEnum sysType, List<HardCreateCarDto> list) {
List<Long> productIds = list.stream().map(HardCreateCarDto::getProductId).toList();
// 创建父订单
HardParentCarEntity parentCarObj = HardParentCarEntity.builder().userId(userId).merchantId(merchantId).orderStatus(sysType.getType()).build();
hardParentCarMapper.insert(parentCarObj);
List<HardCarEntity> carObjectList = new ArrayList<>();
for (HardCreateCarDto v : list) {
HardCarEntity item = HardCarEntity.builder().parentCarId(parentCarObj.getId()).build();
if (ObjectUtil.equals(sysType, HardTypeEnum.SUPERMARKET)) {
item.setProductCount(1);
item.setProductWeight(v.getProductWeight());
}
if (ObjectUtil.equals(sysType, HardTypeEnum.CANTEEN)) {
item.setProductCount(v.getProductCount());
item.setProductWeight(new BigDecimal(0));
// 食堂
if (ObjectUtil.equals(sysType, HardTypeEnum.CANTEEN)) {
List<CanteenSpuEntity> supList = (List<CanteenSpuEntity>) canteenSpuService.getSpuListByIds(productIds).getData();
for (HardCreateCarDto v : list) {
HardCarEntity item = HardCarEntity.builder().parentCarId(parentCarObj.getId()).build();
supList.stream().filter(i -> ObjectUtil.equals(i.getId(), v.getProductId())).findFirst().ifPresent(spu -> {
int totalPrice = v.getProductCount() * spu.getPrice();
item.setProductId(spu.getId());
item.setProductName(spu.getName());
item.setProductPrice(spu.getPrice());
item.setProductPic(spu.getPicUrl());
item.setTotalPrice((long) totalPrice);
item.setProductCount(v.getProductCount());
item.setProductWeight(new BigDecimal(0));
});
}
}
// 超市
if (ObjectUtil.equals(sysType, HardTypeEnum.SUPERMARKET)) {
}
baseMapper.insert(carObjectList);
return parentCarObj.getId();
}
@Override
public String computerCarSubject(HardTypeEnum sysType, List<HardCreateCarDto> list) {
StringBuffer str = new StringBuffer();
List<Long> productIds = list.stream().map(HardCreateCarDto::getProductId).toList();
if (ObjectUtil.equals(sysType, HardTypeEnum.CANTEEN)) {
List<CanteenSpuEntity> supList = (List<CanteenSpuEntity>) canteenSpuService.getSpuListByIds(productIds).getData();
for (HardCreateCarDto v : list) {
supList.stream().filter(i -> ObjectUtil.equals(i.getId(), v.getProductId())).findFirst().ifPresent(spu -> {
str.append(spu.getName()).append("x").append(v.getProductCount()).append(";");
});
}
}
if (ObjectUtil.equals(sysType, HardTypeEnum.SUPERMARKET)) {
}
return str.toString();
}
}
@@ -0,0 +1,168 @@
package com.bsd.pjcloud.hard.service.impl.order;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderStatusEnum;
import com.bsd.pjcloud.hard.api.dto.async.OfflineCar;
import com.bsd.pjcloud.hard.api.dto.async.OfflineOrder;
import com.bsd.pjcloud.hard.api.dto.async.SyncOfflineReqVo;
import com.bsd.pjcloud.hard.api.entity.order.HardCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardParentCarEntity;
import com.bsd.pjcloud.hard.service.HardCarService;
import com.bsd.pjcloud.hard.service.HardOrderSyncService;
import com.bsd.pjcloud.hard.service.HardOrderService;
import com.bsd.pjcloud.hard.service.HardParentCarService;
import com.bsd.pjcloud.wallet.api.feign.RemoteMchService;
import com.bsd.pjcloud.wallet.api.feign.RemoteWalletSettingService;
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
import com.bsd.pjcloud.wallet.api.vo.WalletSettingVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
import java.util.List;
/**
* 订单同步
*/
@Service
@Validated
@Slf4j
@RequiredArgsConstructor
public class HardOrderSyncServiceImpl implements HardOrderSyncService {
static private final String TAG = "订单同步";
private final RemoteMchService remoteMchService;
private final RemoteWalletSettingService walletSettingService;
private final HardCarService hardCarService;
private final HardParentCarService hardParentCarService;
private final HardOrderService orderService;
@Override
@Transactional(rollbackFor = Exception.class)
public List<String> syncOfflineOrder(SyncOfflineReqVo body) {
// 查询商户
MchManageVo merchant = remoteMchService.getById(body.getMerchantId()).getData();
if (ObjectUtil.isEmpty(merchant)) return null;
// 是否需要审批
Boolean offLineOrderApplyEnable = false;
WalletSettingVo setting = walletSettingService.get().getData();
if (ObjectUtil.isNotEmpty(setting) && ObjectUtil.isNotEmpty(setting.getOffLineOrderApplyEnable())) {
offLineOrderApplyEnable = ObjectUtil.equals(setting.getOffLineOrderApplyEnable(), YesNoEnum.YES.getCode());
}
List<String> createIdList = List.of();
List<OfflineOrder> list = body.getList();
for (OfflineOrder i : list) {
if (ObjectUtil.isEmpty(i.getCarList())) {
log.error("|{}|同步安卓机离线订单,错误购物车列表为空order:{}", TAG, JSON.toJSONString(i));
continue;
}
// 是否重复
HardOrderEntity findOrder = orderService.getOne(new LambdaQueryWrapper<HardOrderEntity>().eq(HardOrderEntity::getAndroidOrderCode, i.getUniqueCode()));
if (ObjectUtil.isNotEmpty(findOrder)) {
log.error("|{}|同步安卓机离线订单,重复同步order:{}", TAG, JSON.toJSONString(i));
createIdList.add(findOrder.getAndroidOrderCode());
continue;
}
HardOrderEntity order = parseOrder(i, body.getHardwareId(), body.getMerchantId(), merchant.getDeptId());
HardParentCarEntity parentCar = parseParentCar(i, body.getMerchantId());
List<HardCarEntity> carList = i.getCarList().stream().map(this::parseCar).toList();
if (!ObjectUtil.isAllNotEmpty(order, parentCar, carList)) {
log.error("|{}|同步安卓机离线订单,order、parentCar、carList任意一个为空order:{}", TAG, JSON.toJSONString(i));
continue;
}
Boolean isCreate = getSelf().createOfflineOrder(order, parentCar, carList, i, offLineOrderApplyEnable);
if (isCreate) createIdList.add(order.getAndroidOrderCode());
}
return createIdList;
}
// 同步安卓机单个离线订单 TODO 允许把金额扣为负数
@Transactional(rollbackFor = Exception.class)
public Boolean createOfflineOrder(HardOrderEntity order, HardParentCarEntity parentCar, List<HardCarEntity> list, OfflineOrder offlineOrder, boolean offLineOrderApplyEnable) {
try {
// 创建父订单
hardParentCarService.save(parentCar);
// 创建购物车
list.forEach(v -> v.setParentCarId(parentCar.getId()));
hardCarService.saveBatch(list);
// 创建订单
order.setParentCarId(parentCar.getId());
orderService.save(order);
// 支付
if (!offLineOrderApplyEnable) {
orderService.fastReduceBalance(order);
}
// 标记离线支付成功
if (!offLineOrderApplyEnable && ObjectUtil.isNotEmpty(order.getId())) {
HardOrderEntity updateObj = HardOrderEntity.builder().id(order.getId()).offlinePaySuccess(YesNoEnum.YES.getCode()).build();
orderService.updateById(updateObj);
}
return true;
} catch (Exception e) {
if (!offLineOrderApplyEnable) {
HardOrderEntity updateObj = HardOrderEntity.builder().id(order.getId()).offlinePaySuccess(YesNoEnum.NO.getCode()).build();
orderService.updateById(updateObj);
}
e.printStackTrace();
log.error("|{}|同步安卓机单个离线订单,意外的错误order:|{}|error|{}|", TAG, JSON.toJSONString(order), e.getMessage());
}
return false;
}
public HardOrderEntity parseOrder(OfflineOrder order, Long hardwareId, Long merchantId, Long merchantDeptId) {
HardOrderEntity res = new HardOrderEntity();
res.setAndroidOrderCode(order.getUniqueCode());
res.setUserId(order.getUserCode());
res.setHardId(hardwareId);
res.setMerchantId(merchantId);
res.setDeptId(merchantDeptId);
res.setSysType(order.getSysType().getType());
res.setWalletId(order.getWalletId());
res.setOrderType(order.getType().getType());
res.setOrderSourceTypeId(order.getOrderSourceTypeId());
res.setOrderStatus(HardOrderStatusEnum.OFFLINE_CREATE.getType());
res.setPayType(order.getPayType().getType());
res.setTotalPrice(order.getPrice());
res.setPayPrice(order.getPayPrice());
res.setExtraPrice(order.getExtraPrice());
res.setIsOfflineOrder(YesNoEnum.YES.getCode());
res.setProductDesc(order.getProductDesc());
res.setHourType(order.getHourType());
return res;
}
public HardParentCarEntity parseParentCar(OfflineOrder order, Long merchantId) {
HardParentCarEntity res = new HardParentCarEntity();
res.setUserId(order.getUserCode());
res.setMerchantId(merchantId);
res.setOrderStatus(HardOrderStatusEnum.OFFLINE_CREATE.getType());
return res;
}
public HardCarEntity parseCar(OfflineCar order) {
HardCarEntity res = new HardCarEntity();
res.setParentCarId(null);
res.setProductName(order.getProductName());
res.setProductPic(order.getProductPic());
res.setProductPrice(BigDecimal.valueOf(order.getProductPrice()).intValue());
res.setProductId(order.getProductServiceUniqueCode());
res.setProductCount(order.getProductNumber());
res.setProductWeight(order.getProductWidget());
res.setTotalPrice(order.getTotalPrice());
return res;
}
private HardOrderSyncServiceImpl getSelf() {
return SpringUtil.getBean(getClass());
}
}
@@ -3,31 +3,39 @@ package com.bsd.pjcloud.hard.service.impl.order;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderStatusEnum;
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.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.entity.HardManagerEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardwareOrderEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper;
import com.bsd.pjcloud.hard.service.HardCarService;
import com.bsd.pjcloud.hard.service.HardManagerService;
import com.bsd.pjcloud.hard.service.HardwareOrderService;
import com.bsd.pjcloud.hard.service.HardOrderService;
import com.bsd.pjcloud.wallet.api.constant.WalletBizEnum;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeCodeEnum;
import com.bsd.pjcloud.wallet.api.dto.WalletBalanceTransactionDto;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import com.bsd.pjcloud.wallet.api.feign.RemoteCodeUseService;
import com.bsd.pjcloud.wallet.api.feign.RemoteMchService;
import com.bsd.pjcloud.wallet.api.feign.RemoteWalletService;
import com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity;
import com.bsd.pjcloud.wallet.api.feign.*;
import com.bsd.pjcloud.wallet.api.vo.MchManageVo;
import com.bsd.pjcloud.wallet.api.vo.WalletSettingVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Optional;
/**
@@ -40,7 +48,9 @@ import java.util.Optional;
@Slf4j
@RequiredArgsConstructor
@Service
public class HardwareOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardwareOrderEntity> implements HardwareOrderService {
public class HardwareOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrderEntity> implements HardOrderService {
static private final String TAG = "订单";
private final HardManagerService hardManagerService;
private final HardCarService hardCarService;
@@ -48,6 +58,8 @@ public class HardwareOrderServiceImpl extends ServiceImpl<HardOrderMapper, Hardw
private final RemoteMchService remoteMchService;
private final RemoteCodeUseService remoteCodeUseService;
private final RemoteWalletService remoteWalletService;
private final RemoteWalletTransactionService walletTransactionService;
private final RemoteWalletSettingService walletSettingService;
@Override
public Page<HardOrderVo> pageJoin(Page page, HardOrderDto dto) {
@@ -85,23 +97,101 @@ public class HardwareOrderServiceImpl extends ServiceImpl<HardOrderMapper, Hardw
if (isPay && wallet.getBalance() < payPrice) throw new RuntimeException("钱包余额不足");
// 添加购物车
Long parentCarId = hardCarService.createCard(dto.getUserId(), dto.getMerchantId(), dto.getSysType(), dto.getList());
return 0L;
// 获取商品描述
String subject = hardCarService.computerCarSubject(dto.getSysType(), dto.getList());
// 添加硬件订单
HardOrderEntity orderObj = HardOrderEntity.builder()
.androidOrderCode(dto.getAndroidOrderCode())
.userId(dto.getUserId())
.sysType(dto.getSysType().getType())
.hourType(String.valueOf(dto.getHourType()))
.parentCarId(parentCarId)
.hardId(dto.getHardwareId())
.orderStatus(HardOrderStatusEnum.CREATE.getType())
.merchantId(dto.getMerchantId())
.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();
if (isPay) orderObj.setWalletId(wallet.getId());
baseMapper.insert(orderObj);
// 钱包扣款
if (isPay) fastReduceBalance(orderObj);
return orderObj.getId();
}
@Override
public void fastReduceBalance(HardOrderEntity order) {
boolean isPay = isPay(HardOrderTypeEnum.valueOfByType(order.getOrderType()), HardPayTypeEnum.valueOfByType(order.getPayType()));
WalletBalanceTransactionDto reduceBuild = WalletBalanceTransactionDto.builder().walletId(order.getWalletId()).price(order.getPayPrice()).bizId(String.valueOf(order.getId())).bizType(WalletBizEnum.PAYMENT).build();
WalletTransactionEntity walletTransaction = walletTransactionService.reduceWalletBalance(reduceBuild).getData();
if (ObjectUtil.isNotEmpty(walletTransaction)) {
Integer payPrice = isPay ? order.getTotalPrice() + order.getExtraPrice() : 0;
HardOrderEntity update = HardOrderEntity.builder().id(order.getId()).payTime(LocalDateTime.now()).orderStatus(HardOrderStatusEnum.PAY.getType()).payPrice(payPrice).build();
baseMapper.updateById(update);
// 核销二维码
cancelCode(order);
}
}
@Override
public Integer computeExtraPrice(Integer price) {
return 0;
int extraPrice = 0;
WalletSettingVo setting = walletSettingService.get().getData();
if (ObjectUtil.isEmpty(setting) || !ObjectUtil.isAllNotEmpty(setting.getPayAmountMealTimes(), setting.getPayAmountMealLimit())) {
log.error("|{}|支付配置不存在", TAG);
return extraPrice;
}
if (setting.getPayAmountMealTimes().compareTo(new BigDecimal(1)) <= 0) {
log.error("|{}|每一餐的倍数必须大于1", TAG);
return extraPrice;
}
if (ObjectUtil.equals(setting.getPayAmountEnable(), YesNoEnum.NO.getCode())) return extraPrice;
if (price > setting.getPayAmountMealLimit()) {
extraPrice = setting.getPayAmountMealTimes().multiply(BigDecimal.valueOf(price).subtract(BigDecimal.valueOf(setting.getPayAmountMealLimit()))).setScale(2, RoundingMode.HALF_UP).intValue();
log.info("|{}|增加的每一餐的金额 result:|{}|", TAG, extraPrice);
}
return extraPrice;
}
// 是否需要支付(目前只有线下的现金是不走平台扣款)
private boolean isPay(HardOrderTypeEnum type, HardPayTypeEnum payType) {
return ObjectUtil.equals(type, HardOrderTypeEnum.BELOW) && !ObjectUtil.equals(payType, HardPayTypeEnum.CASH);
@Override
public Boolean handCancelCode(HandCancelCodeDto dto) {
// 查询订单
HardOrderEntity order = baseMapper.selectById(dto.getOrderId());
if (ObjectUtil.isEmpty(order)) throw new RuntimeException("订单不存在");
// 判断是否被核销过
HardOrderTypeEnum orderType = HardOrderTypeEnum.valueOfByType(order.getOrderType());
boolean isCancel = validateCodeIsCancel(orderType, order.getId());
if (isCancel) throw new RuntimeException("该二维码已被核销");
// 核销二维码
cancelCode(order);
HardOrderEntity updateObj = HardOrderEntity.builder().id(order.getId()).androidOrderCode(dto.getAndroidOrderCode()).hardId(dto.getHardwareId()).orderStatus(HardOrderStatusEnum.CANCEL.getType()).build();
return baseMapper.updateById(updateObj) > 0;
}
// 是否需要额外支付(目前只有食堂需要)
private boolean isExtraPrice(HardTypeEnum hardType) {
return ObjectUtil.equals(hardType, HardTypeEnum.CANTEEN);
@Override
public void cancelCode(HardOrderEntity order) {
HardOrderTypeEnum orderTypeEnum = HardOrderTypeEnum.valueOfByType(order.getOrderType());
if (!ObjectUtil.isAllNotEmpty(orderTypeEnum, order.getOrderSourceTypeId())) return;
Long id = order.getOrderSourceTypeId();
switch (orderTypeEnum) {
// 线下购买
case BELOW -> {
}
// 线上订餐
case RESERVE -> {
}
// 外来人员 | 跨单位
case FOREIGN_TICKET, STRIDE_DEPT -> remoteCodeUseService.cancelCode(id);
}
}
// 二维码类型的订单是否被核销
@@ -119,6 +209,16 @@ public class HardwareOrderServiceImpl extends ServiceImpl<HardOrderMapper, Hardw
return flag;
}
// 是否需要支付(目前只有线下的现金是不走平台扣款)
private boolean isPay(HardOrderTypeEnum type, HardPayTypeEnum payType) {
return ObjectUtil.equals(type, HardOrderTypeEnum.BELOW) && !ObjectUtil.equals(payType, HardPayTypeEnum.CASH);
}
// 是否需要额外支付(目前只有食堂需要)
private boolean isExtraPrice(HardTypeEnum hardType) {
return ObjectUtil.equals(hardType, HardTypeEnum.CANTEEN);
}
private boolean validateCreateOrderDto(HardCreateOrderDto dto) {
R<MchManageVo> mch = remoteMchService.getById(dto.getMerchantId());
if (ObjectUtil.isEmpty(mch.getData())) {
@@ -3,7 +3,7 @@
<mapper namespace="com.bsd.pjcloud.hard.mapper.order.HardOrderMapper">
<resultMap id="hardwareOrderMap" type="com.bsd.pjcloud.hard.api.entity.order.HardwareOrderEntity">
<resultMap id="hardwareOrderMap" type="com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity">
<id property="id" column="id"/>
<result property="userId" column="user_id"/>
<result property="merchantId" column="merchant_id"/>
@@ -37,27 +37,39 @@ import java.util.Map;
@FeignClient(contextId = "remoteDeptService", value = ServiceNameConstants.UPMS_SERVICE)
public interface RemoteDeptService {
/**
* 获取所有部门接口
* @param parentDeptId 父部门ID
* @return R 返回结果对象,包含所有部门信息列表
*/
@GetMapping("/dept/list")
R<List<SysDept>> getAllDept(@RequestParam("parentDeptId") Long parentDeptId);
/**
* 获取所有部门接口
*
* @param parentDeptId 父部门ID
* @return R 返回结果对象,包含所有部门信息列表
*/
@GetMapping("/dept/list")
R<List<SysDept>> getAllDept(@RequestParam("parentDeptId") Long parentDeptId);
/**
* 通过部门ID获取负责人列表
* @param deptId 部门ID
* @return 负责人ID列表
*/
@GetMapping("/dept/leader/{deptId}")
R<List<Long>> getAllDeptLeader(@PathVariable("deptId") Long deptId);
/**
* 通过部门ID获取负责人列表
*
* @param deptId 部门ID
* @return 负责人ID列表
*/
@GetMapping("/dept/leader/{deptId}")
R<List<Long>> getAllDeptLeader(@PathVariable("deptId") Long deptId);
/**
* 根据部门id集合查询
* @param deptIds
* @return
*/
@GetMapping("/dept/getDeptListByDeptIds")
R<Map<Long, SysDept>> getDeptByDeptIds(@RequestParam("deptIds")List<Long> deptIds);
/**
* 根据部门id集合查询
*
* @param deptIds
* @return
*/
@GetMapping("/dept/getDeptListByDeptIds")
R<Map<Long, SysDept>> getDeptByDeptIds(@RequestParam("deptIds") List<Long> deptIds);
/**
* 根据部门id查询
*
* @param deptId
* @return
*/
@GetMapping("/dept/getDeptListByDeptId")
R<SysDept> getDeptByDeptId(@RequestParam("deptId") Long deptId);
}
@@ -54,132 +54,146 @@ import java.util.Map;
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class SysDeptController {
private final SysDeptService sysDeptService;
private final SysDeptService sysDeptService;
/**
* 通过ID查询
* @param id ID
* @return SysDept
*/
@GetMapping("/{id}")
public R getById(@PathVariable Long id) {
return R.ok(sysDeptService.getById(id));
}
/**
* 通过ID查询
*
* @param id ID
* @return SysDept
*/
@GetMapping("/{id}")
public R getById(@PathVariable Long id) {
return R.ok(sysDeptService.getById(id));
}
/**
* 查询全部部门
*/
@GetMapping("/list")
public R list() {
return R.ok(sysDeptService.list());
}
/**
* 查询全部部门
*/
@GetMapping("/list")
public R list() {
return R.ok(sysDeptService.list());
}
/**
* 返回树形菜单集合
* @param deptName 部门名称
* @return 树形菜单
*/
@GetMapping(value = "/tree")
public R getTree(String deptName, Long parentId) {
return R.ok(sysDeptService.selectTree(deptName, parentId));
}
/**
* 返回树形菜单集合
*
* @param deptName 部门名称
* @return 树形菜单
*/
@GetMapping(value = "/tree")
public R getTree(String deptName, Long parentId) {
return R.ok(sysDeptService.selectTree(deptName, parentId));
}
/**
* 添加
* @param sysDept 实体
* @return success/false
*/
@SysLog("添加部门")
@PostMapping
@HasPermission("sys_dept_add")
public R save(@Valid @RequestBody SysDept sysDept) {
return R.ok(sysDeptService.save(sysDept));
}
/**
* 添加
*
* @param sysDept 实体
* @return success/false
*/
@SysLog("添加部门")
@PostMapping
@HasPermission("sys_dept_add")
public R save(@Valid @RequestBody SysDept sysDept) {
return R.ok(sysDeptService.save(sysDept));
}
/**
* 删除
* @param id ID
* @return success/false
*/
@SysLog("删除部门")
@DeleteMapping("/{id}")
@HasPermission("sys_dept_del")
public R removeById(@PathVariable Long id) {
return R.ok(sysDeptService.removeDeptById(id));
}
/**
* 删除
*
* @param id ID
* @return success/false
*/
@SysLog("删除部门")
@DeleteMapping("/{id}")
@HasPermission("sys_dept_del")
public R removeById(@PathVariable Long id) {
return R.ok(sysDeptService.removeDeptById(id));
}
/**
* 编辑
* @param sysDept 实体
* @return success/false
*/
@SysLog("编辑部门")
@PutMapping
@HasPermission("sys_dept_edit")
public R update(@Valid @RequestBody SysDept sysDept) {
sysDept.setUpdateTime(LocalDateTime.now());
return R.ok(sysDeptService.updateById(sysDept));
}
/**
* 编辑
*
* @param sysDept 实体
* @return success/false
*/
@SysLog("编辑部门")
@PutMapping
@HasPermission("sys_dept_edit")
public R update(@Valid @RequestBody SysDept sysDept) {
sysDept.setUpdateTime(LocalDateTime.now());
return R.ok(sysDeptService.updateById(sysDept));
}
/**
* 查收子级列表
* @return 返回子级
*/
@GetMapping(value = "/getDescendantList/{deptId}")
public R getDescendantList(@PathVariable Long deptId) {
return R.ok(sysDeptService.listDescendant(deptId));
}
/**
* 查收子级列表
*
* @return 返回子级
*/
@GetMapping(value = "/getDescendantList/{deptId}")
public R getDescendantList(@PathVariable Long deptId) {
return R.ok(sysDeptService.listDescendant(deptId));
}
@GetMapping(value = "/leader/{deptId}")
public R getAllDeptLeader(@PathVariable Long deptId) {
return R.ok(sysDeptService.listDeptLeader(deptId));
}
@GetMapping(value = "/leader/{deptId}")
public R getAllDeptLeader(@PathVariable Long deptId) {
return R.ok(sysDeptService.listDeptLeader(deptId));
}
/**
* 导出部门
* @return
*/
@ResponseExcel
@GetMapping("/export")
public List<DeptExcelVO> export() {
return sysDeptService.listExcelVo();
}
/**
* 导出部门
*
* @return
*/
@ResponseExcel
@GetMapping("/export")
public List<DeptExcelVO> export() {
return sysDeptService.listExcelVo();
}
/**
* 导入部门
* @param excelVOList
* @param bindingResult
* @return
*/
@PostMapping("import")
public R importDept(@RequestExcel List<DeptExcelVO> excelVOList, BindingResult bindingResult) {
return sysDeptService.importDept(excelVOList, bindingResult);
}
/**
* 导入部门
*
* @param excelVOList
* @param bindingResult
* @return
*/
@PostMapping("import")
public R importDept(@RequestExcel List<DeptExcelVO> excelVOList, BindingResult bindingResult) {
return sysDeptService.importDept(excelVOList, bindingResult);
}
/**
* 查询全部部门包含用户
* @param parentDeptId 父部门ID
* @param type 查询类型
*/
@GetMapping("/org")
public R listOrgTree(Long parentDeptId, String type) {
return R.ok(sysDeptService.listOrgTree(parentDeptId, type));
}
/**
* 查询全部部门包含用户
*
* @param parentDeptId 父部门ID
* @param type 查询类型
*/
@GetMapping("/org")
public R listOrgTree(Long parentDeptId, String type) {
return R.ok(sysDeptService.listOrgTree(parentDeptId, type));
}
/**
* 模糊搜索用户
* @param username 用户名/拼音/首字母
* @return 匹配到的用户
*/
@GetMapping("/org/user/search")
public R getOrgTreeUser(@RequestParam String username) {
return R.ok(sysDeptService.getOrgTreeUser(username));
}
/**
* 模糊搜索用户
*
* @param username 用户名/拼音/首字母
* @return 匹配到的用户
*/
@GetMapping("/org/user/search")
public R getOrgTreeUser(@RequestParam String username) {
return R.ok(sysDeptService.getOrgTreeUser(username));
}
@GetMapping("/getDeptListByDeptIds")
public R<Map<Long,SysDept>> getDeptListByDeptIds(@RequestParam("deptIds") List<Long> deptIds) {
@GetMapping("/getDeptListByDeptIds")
public R<Map<Long, SysDept>> getDeptListByDeptIds(@RequestParam("deptIds") List<Long> deptIds) {
return R.ok(sysDeptService.getDeptListByDeptIds(deptIds));
}
return R.ok(sysDeptService.getDeptListByDeptIds(deptIds));
}
@GetMapping("/getDeptListByDeptId")
public R<SysDept> getDeptByDeptId(@RequestParam("deptId") Long deptId) {
return R.ok(sysDeptService.getById(deptId));
}
}
@@ -12,6 +12,7 @@ public enum WalletBizEnum {
UPDATE("1", "更新余额"),
BATCH("2", "批量更新余额"),
RECHARGE("3", "充值"),
PAYMENT("4", "支付"),
;
private final String code;
@@ -0,0 +1,28 @@
package com.bsd.pjcloud.wallet.api.dto;
import com.bsd.pjcloud.wallet.api.constant.WalletBizEnum;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@Builder
@AllArgsConstructor
@NotEmpty
@Data
public class WalletBalanceTransactionDto {
@NotNull(message = "钱包id不能为空")
private Long walletId;
@NotNull(message = "操作金额不能为空")
private Integer price;
@NotEmpty(message = "业务类型关联id不能为空")
private String bizId;
@NotNull(message = "业务类型不能为空")
private WalletBizEnum bizType;
}
@@ -24,10 +24,10 @@ public class WalletSettingEntity extends Model<WalletSettingEntity> {
/**
* 创建者
* 编号
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description="创建者")
@Schema(description="编号")
private Long id;
/**
@@ -0,0 +1,24 @@
package com.bsd.pjcloud.wallet.api.feign;
import com.bsd.pjcloud.common.core.constant.ServiceNameConstants;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.feign.annotation.NoToken;
import com.bsd.pjcloud.wallet.api.dto.WalletBalanceTransactionDto;
import com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity;
import com.bsd.pjcloud.wallet.api.vo.WalletSettingVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(contextId = "remoteWalletTransactionService", value = ServiceNameConstants.WALLET_SERVICE)
public interface RemoteWalletTransactionService {
@NoToken
@GetMapping("/wallet-transaction/add-balance")
R<WalletTransactionEntity> addWalletBalance(@RequestBody WalletBalanceTransactionDto dto);
@NoToken
@GetMapping("/wallet-transaction/reduce-balance")
R<WalletTransactionEntity> reduceWalletBalance(@RequestBody WalletBalanceTransactionDto dto);
}
@@ -1,4 +1,5 @@
com.bsd.pjcloud.wallet.api.feign.RemoteWalletService
com.bsd.pjcloud.wallet.api.feign.RemoteCodeUseService
com.bsd.pjcloud.wallet.api.feign.RemoteMchService
com.bsd.pjcloud.wallet.api.feign.RemoteWalletSettingService
com.bsd.pjcloud.wallet.api.feign.RemoteWalletSettingService
com.bsd.pjcloud.wallet.api.feign.RemoteWalletTransactionService
@@ -46,9 +46,9 @@ public class MchManageController {
@Inner
@GetMapping("/get-by-id")
public R<MchManageVo> getById(@RequestParam Long id) {
MchManageEntity mchManage = mchManageService.getById(id);
if (ObjectUtil.isEmpty(mchManage)) return R.failed("商户不存在");
return R.ok(BeanUtils.toBean(mchManage, MchManageVo.class));
MchManageVo mchManageVo = mchManageService.join(id);
if (ObjectUtil.isEmpty(mchManageVo)) return R.failed("商户不存在");
return R.ok(mchManageVo);
}
@Inner
@@ -45,7 +45,6 @@ public class WalletManageController {
private final WalletManageService walletManageService;
/* ************************************* start 远程调用 start ************************************* */
@Inner
@GetMapping("/get-or-create-wallet")
public R getOrCreateWallet(@RequestParam Long userId, @RequestParam WalletTypeCodeEnum walletTypeCode) {
@@ -79,15 +78,13 @@ public class WalletManageController {
return R.ok(walletManageService.delWalletByUserIds(userIds));
}
@Inner
@GetMapping("/add-price")
public R<Object> addPrice(@RequestParam("userIds") List<Long> userIds){
return R.ok(walletManageService.delWalletByUserIds(userIds));
}
/* ************************************* start 远程调用 start ************************************* */
/**
* 分页查询
*
* @param page 分页对象
* @param walletManage 钱包管理
* @return
*/
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('wallet_walletManage_view')")
@@ -103,13 +100,6 @@ public class WalletManageController {
return walletManageService.pageJoin(page, dto);
}
/**
* 通过id查询钱包管理
*
* @param id id
* @return R
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{id}")
@PreAuthorize("@pms.hasPermission('wallet_walletManage_view')")
@@ -117,12 +107,6 @@ public class WalletManageController {
return R.ok(walletManageService.getWallet(id));
}
/**
* 新增钱包管理
*
* @param walletManage 钱包管理
* @return R
*/
@Operation(summary = "新增钱包管理", description = "新增钱包管理")
@SysLog("新增钱包管理")
@PostMapping
@@ -131,12 +115,6 @@ public class WalletManageController {
return R.ok(walletManageService.save(walletManage));
}
/**
* 修改钱包管理
*
* @param walletManage 钱包管理
* @return R
*/
@Operation(summary = "修改钱包管理", description = "修改钱包管理")
@SysLog("修改钱包管理")
@PutMapping
@@ -145,12 +123,6 @@ public class WalletManageController {
return R.ok(walletManageService.updateById(walletManage));
}
/**
* 通过id删除钱包管理
*
* @param ids id列表
* @return R
*/
@Operation(summary = "通过id删除钱包管理", description = "通过id删除钱包管理")
@SysLog("通过id删除钱包管理")
@DeleteMapping
@@ -159,14 +131,6 @@ public class WalletManageController {
return R.ok(walletManageService.removeBatchByIds(CollUtil.toList(ids)));
}
/**
* 导出excel 表格
*
* @param walletManage 查询条件
* @param ids 导出指定ID
* @return excel 文件流
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('wallet_walletManage_export')")
@@ -8,11 +8,15 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.common.security.annotation.Inner;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeCodeEnum;
import com.bsd.pjcloud.wallet.api.dto.WalletBalanceTransactionDto;
import com.bsd.pjcloud.wallet.api.dto.WalletTransactionDto;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity;
import com.bsd.pjcloud.wallet.service.WalletManageService;
import com.bsd.pjcloud.wallet.service.WalletTransactionService;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -33,26 +37,37 @@ import java.util.List;
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/walletTransaction")
@Tag(description = "walletTransaction", name = "会员钱包流水表管理")
@RequestMapping("/wallet-transaction")
@Tag(description = "wallet-transaction", name = "会员钱包流水表管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class WalletTransactionController {
private final WalletTransactionService walletTransactionService;
/* ************************************* start 远程调用 start ************************************* */
@Inner
@PostMapping("/add-balance")
public R<WalletTransactionEntity> addWalletBalance(@Valid @RequestBody WalletBalanceTransactionDto dto) {
WalletTransactionEntity walletTransaction = walletTransactionService.addWalletBalance(dto.getWalletId(), dto.getPrice(), dto.getBizId(), dto.getBizType());
if (ObjectUtil.isEmpty(walletTransaction)) return R.failed("增加钱包余额错误");
return R.ok(walletTransaction);
}
@Inner
@PostMapping("/reduce-balance")
public R<WalletTransactionEntity> reduceWalletBalance(@Valid @RequestBody WalletBalanceTransactionDto dto) {
WalletTransactionEntity walletTransaction = walletTransactionService.reduceWalletBalance(dto.getWalletId(), dto.getPrice(), dto.getBizId(), dto.getBizType());
if (ObjectUtil.isEmpty(walletTransaction)) return R.failed("扣减钱包余额");
return R.ok(walletTransaction);
}
/* ************************************* end 远程调用 end ************************************* */
@PutMapping("/update-balance")
@Operation(summary = "更新会员用户余额")
public R<Boolean> updateWalletBalance(@RequestBody WalletTransactionDto dto) {
return R.ok(walletTransactionService.updateWalletBalance(dto));
}
/**
* 分页查询
*
* @param page 分页对象
* @param dto 会员钱包流水表
* @return
*/
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('wallet_walletTransaction_view')")
@@ -68,13 +83,6 @@ public class WalletTransactionController {
return R.ok(walletTransactionService.pageJoin(page, dto));
}
/**
* 通过id查询会员钱包流水表
*
* @param id id
* @return R
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{id}")
@PreAuthorize("@pms.hasPermission('wallet_walletTransaction_view')")
@@ -82,12 +90,6 @@ public class WalletTransactionController {
return R.ok(walletTransactionService.getById(id));
}
/**
* 新增会员钱包流水表
*
* @param walletTransaction 会员钱包流水表
* @return R
*/
@Operation(summary = "新增会员钱包流水表", description = "新增会员钱包流水表")
@SysLog("新增会员钱包流水表")
@PostMapping
@@ -96,12 +98,6 @@ public class WalletTransactionController {
return R.ok(walletTransactionService.save(walletTransaction));
}
/**
* 修改会员钱包流水表
*
* @param walletTransaction 会员钱包流水表
* @return R
*/
@Operation(summary = "修改会员钱包流水表", description = "修改会员钱包流水表")
@SysLog("修改会员钱包流水表")
@PutMapping
@@ -110,12 +106,6 @@ public class WalletTransactionController {
return R.ok(walletTransactionService.updateById(walletTransaction));
}
/**
* 通过id删除会员钱包流水表
*
* @param ids id列表
* @return R
*/
@Operation(summary = "通过id删除会员钱包流水表", description = "通过id删除会员钱包流水表")
@SysLog("通过id删除会员钱包流水表")
@DeleteMapping
@@ -124,14 +114,6 @@ public class WalletTransactionController {
return R.ok(walletTransactionService.removeBatchByIds(CollUtil.toList(ids)));
}
/**
* 导出excel 表格
*
* @param walletTransaction 查询条件
* @param ids 导出指定ID
* @return excel 文件流
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('wallet_walletTransaction_export')")
@@ -31,4 +31,11 @@ public interface MchManageMapper extends PjcloudBaseMapper<MchManageEntity> {
.in(ObjectUtil.isNotEmpty(dto.getIds()), MchManageEntity::getId, dto.getIds());
return selectJoinList(MchManageVo.class, wrapper);
}
default MchManageVo join(Long id) {
MPJLambdaQueryWrapper<MchManageEntity> wrapper = new MPJLambdaQueryWrapper<MchManageEntity>()
.selectAll(MchManageEntity.class)
.eq(MchManageEntity::getId, id);
return selectJoinOne(MchManageVo.class, wrapper);
}
}
@@ -19,6 +19,8 @@ public interface MchManageService extends IService<MchManageEntity> {
Page<MchManageVo> pageJoin(Page page, MchManageDto dto);
MchManageVo join(Long id);
List<MchManageVo> list(MchManageDto dto);
MchManageVo getByDeptId(Long deptId);
@@ -20,7 +20,7 @@ public interface WalletTransactionService extends IService<WalletTransactionEnti
* @param bizType 业务关联分类
* @return 钱包流水
*/
WalletTransactionEntity reduceWalletBalance(Long walletId, Integer price, Long bizId, WalletBizEnum bizType);
WalletTransactionEntity reduceWalletBalance(Long walletId, Integer price, String bizId, WalletBizEnum bizType);
/**
@@ -129,6 +129,19 @@ public class MchManageServiceImpl extends ServiceImpl<MchManageMapper, MchManage
return list;
}
@Override
public MchManageVo join(Long id) {
MchManageVo detail = baseMapper.join(id);
if (ObjectUtil.isNotEmpty(detail)) {
// 部门
SysDept dept = remoteDeptService.getDeptByDeptId(id).getData();
if (ObjectUtil.isNotEmpty(dept)) {
DataUtil.convertDept(detail, dept);
}
}
return detail;
}
@Override
public List<MchManageVo> list(MchManageDto dto) {
return baseMapper.list(dto);
@@ -59,6 +59,7 @@ public class WalletManageServiceImpl extends ServiceImpl<WalletManageMapper, Wal
private final StringRedisTemplate redisTemplate;
@Override
@Transactional(rollbackFor = Exception.class)
public void createWallet(Long userId, Boolean checkPermission) {
@@ -1,20 +1,24 @@
package com.bsd.pjcloud.wallet.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.common.core.constant.CacheConstants;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.core.util.BeanUtils;
import com.bsd.pjcloud.wallet.api.dto.WalletSettingDto;
import com.bsd.pjcloud.wallet.api.entity.WalletSettingEntity;
import com.bsd.pjcloud.wallet.api.vo.WalletSettingVo;
import com.bsd.pjcloud.wallet.mapper.WalletSettingMapper;
import com.bsd.pjcloud.wallet.service.WalletSettingService;
import lombok.Data;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* 支付设置
*
@@ -25,14 +29,19 @@ import org.springframework.stereotype.Service;
public class WalletSettingServiceImpl extends ServiceImpl<WalletSettingMapper, WalletSettingEntity> implements WalletSettingService {
@Override
@Cacheable(value = CacheConstants.WALLET_SETTING_DETAIL, unless = "#result == null")
@Cacheable(value = CacheConstants.WALLET_SETTING_DETAIL)
public WalletSettingVo getSetting() {
WalletSettingEntity setting = baseMapper.selectOne(new QueryWrapper<>());
if (ObjectUtil.isEmpty(setting)) {
DefaultWalletSetting defaultWalletSetting = new DefaultWalletSetting();
baseMapper.insert(defaultWalletSetting);
return BeanUtils.toBean(defaultWalletSetting, WalletSettingVo.class);
}
return BeanUtils.toBean(setting, WalletSettingVo.class);
}
@Override
@CachePut(value = CacheConstants.WALLET_SETTING_DETAIL, condition = "dto.getId() != null", unless = "#result == null")
@CacheEvict(value = CacheConstants.WALLET_SETTING_DETAIL, allEntries = true)
public void edit(WalletSettingDto dto) {
WalletSettingEntity setting = baseMapper.selectById(dto.getId());
if (ObjectUtil.isEmpty(setting)) {
@@ -42,4 +51,52 @@ public class WalletSettingServiceImpl extends ServiceImpl<WalletSettingMapper, W
baseMapper.updateById(updateObj);
}
@Data
private class DefaultWalletSetting extends WalletSettingEntity {
/**
* 编号
*/
private Long id = null;
/**
* 每一餐的上限(分)
*/
private Integer payAmountMealLimit = 20;
/**
* 每一餐的倍数
*/
private BigDecimal payAmountMealTimes = BigDecimal.valueOf(1.5);
/**
* 是否开启每一餐的额外缴费
*/
private String payAmountEnable = YesNoEnum.NO.getCode();
/**
* 是否开启钱包二维码刷新
*/
private String refreshQrCodeEnable = YesNoEnum.NO.getCode();
/**
* 二维码刷新频率
*/
private Integer refreshQrCodeFre = 60;
/**
* 是否开启离线订单的审批
*/
private String offLineOrderApplyEnable = YesNoEnum.YES.getCode();
/**
* 退款理由
*/
private String afterSaleRefundReasons = "";
/**
* 退货理由
*/
private String afterSaleReturnReasons = "";
}
}
@@ -52,7 +52,7 @@ public class WalletTransactionServiceImpl extends ServiceImpl<WalletTransactionM
@Override
@Transactional(rollbackFor = Exception.class)
@CacheEvict(value = CacheConstants.WALLET_DETAIL, key = "#walletId")
public WalletTransactionEntity reduceWalletBalance(Long walletId, Integer price, Long bizId, WalletBizEnum bizType) {
public WalletTransactionEntity reduceWalletBalance(Long walletId, Integer price, String bizId, WalletBizEnum bizType) {
WalletManageEntity wallet = walletManageService.getById(walletId);
if (ObjectUtil.isEmpty(wallet)) {
log.error("|{}|,用户钱包id({})不存在.", TAG, walletId);