feat(clinic): 添加处方订单创建功能- 在 ClinicPrescription 实体中新增 payStatus 和 orderStatus 字段

- 引入 ShopOrder 关联查询以支持订单状态展示- 新增 PrescriptionOrderRequest DTO 用于接收订单创建请求- 实现 /order 接口,支持多种支付方式处理逻辑
- 更新 Mapper XML 文件,增加订单状态筛选条件及关联字段- 修改 ClinicPrescriptionParam 增加订单类型和状态筛选参数
- 调整支付请求参数校验规则,放宽订单金额严格一致性检查
- 扩展经销商资本与订单查询关键字匹配范围
This commit is contained in:
2025-11-04 01:23:04 +08:00
parent a66fd838ac
commit ca446b5d5e
9 changed files with 146 additions and 3 deletions

View File

@@ -1,6 +1,7 @@
package com.gxwebsoft.clinic.controller; package com.gxwebsoft.clinic.controller;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.gxwebsoft.clinic.dto.PrescriptionOrderRequest;
import com.gxwebsoft.clinic.entity.ClinicPrescription; import com.gxwebsoft.clinic.entity.ClinicPrescription;
import com.gxwebsoft.clinic.param.ClinicPrescriptionParam; import com.gxwebsoft.clinic.param.ClinicPrescriptionParam;
import com.gxwebsoft.clinic.service.ClinicPrescriptionService; import com.gxwebsoft.clinic.service.ClinicPrescriptionService;
@@ -12,10 +13,12 @@ import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
/** /**
@@ -129,4 +132,60 @@ public class ClinicPrescriptionController extends BaseController {
return fail("删除失败"); return fail("删除失败");
} }
@Operation(summary = "创建处方订单")
@PostMapping("/order")
public ApiResult<?> createOrder(@RequestBody PrescriptionOrderRequest request) {
try {
// 1. 参数校验
if (request.getPrescriptionId() == null) {
return fail("处方ID不能为空");
}
if (request.getPayType() == null) {
return fail("支付方式不能为空");
}
// 2. 查询处方信息
ClinicPrescription prescription = clinicPrescriptionService.getById(request.getPrescriptionId());
if (prescription == null) {
return fail("处方不存在");
}
// 3. 检查处方状态
if (prescription.getStatus() != null && prescription.getStatus() == 2) {
return fail("该处方已支付,无需重复支付");
}
if (prescription.getStatus() != null && prescription.getStatus() == 3) {
return fail("该处方已取消,无法支付");
}
// 4. 更新处方订单信息
ClinicPrescription updatePrescription = new ClinicPrescription();
updatePrescription.setId(request.getPrescriptionId());
// 根据支付类型更新状态
if (request.getPayType() == 1) {
// 微信支付,状态保持为正常,等待支付回调
updatePrescription.setStatus(0);
} else if (request.getPayType() == 4 || request.getPayType() == 5) {
// 现金支付或POS机支付直接标记为已支付
updatePrescription.setStatus(2);
updatePrescription.setIsSettled(1);
updatePrescription.setSettleTime(LocalDateTime.now());
} else if (request.getPayType() == 6) {
// 免费,直接标记为已完成
updatePrescription.setStatus(1);
updatePrescription.setIsSettled(1);
updatePrescription.setSettleTime(LocalDateTime.now());
}
if (clinicPrescriptionService.updateById(updatePrescription)) {
return success("订单创建成功", prescription);
}
return fail("订单创建失败");
} catch (Exception e) {
return fail("订单创建失败:" + e.getMessage());
}
}
} }

View File

@@ -0,0 +1,24 @@
package com.gxwebsoft.clinic.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
/**
* 处方订单请求参数
*
* @author 科技小王子
* @since 2025-11-03
*/
@Data
@Schema(name = "PrescriptionOrderRequest", description = "处方订单请求参数")
public class PrescriptionOrderRequest implements Serializable {
private static final long serialVersionUID = 1L;
@Schema(description = "处方ID", required = true)
private Integer prescriptionId;
@Schema(description = "支付方式0余额支付1微信支付2支付宝支付3银联支付4现金支付5POS机支付6免费7积分支付", required = true)
private Integer payType;
}

View File

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.gxwebsoft.shop.entity.ShopOrder;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@@ -63,6 +64,14 @@ public class ClinicPrescription implements Serializable {
@Schema(description = "订单编号") @Schema(description = "订单编号")
private String orderNo; private String orderNo;
@Schema(description = "0未付款1已付款")
@TableField(exist = false)
private Boolean payStatus;
@Schema(description = "0未使用1已完成2已取消3取消中4退款申请中5退款被拒绝6退款成功7客户端申请退款")
@TableField(exist = false)
private Integer orderStatus;
@Schema(description = "关联就诊表") @Schema(description = "关联就诊表")
private Integer visitRecordId; private Integer visitRecordId;

View File

@@ -4,10 +4,11 @@
<!-- 关联查询sql --> <!-- 关联查询sql -->
<sql id="selectSql"> <sql id="selectSql">
SELECT a.*, b.real_name, b.age, b.sex, b.height, b.weight, c.real_name as doctorName, c.qualification SELECT a.*, b.real_name, b.age, b.sex, b.height, b.weight, c.real_name as doctorName, c.qualification, d.order_status as orderStatus, d.pay_status as payStatus
FROM clinic_prescription a FROM clinic_prescription a
LEFT JOIN clinic_patient_user b ON a.user_id = b.user_id LEFT JOIN clinic_patient_user b ON a.user_id = b.user_id
LEFT JOIN clinic_doctor_user c ON a.doctor_id = c.user_id LEFT JOIN clinic_doctor_user c ON a.doctor_id = c.user_id
LEFT JOIN shop_order d ON a.order_no = d.order_no
<where> <where>
<if test="param.id != null"> <if test="param.id != null">
AND a.id = #{param.id} AND a.id = #{param.id}
@@ -76,6 +77,45 @@
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
) )
</if> </if>
<!-- 订单状态筛选:-1全部0待支付1待发货2待核销3待收货4待评价5已完成6已退款7已删除 -->
<if test="param.statusFilter != null and param.statusFilter != -1">
<if test="param.statusFilter == 0">
<!-- 0待支付未付款 -->
AND d.pay_status = 0 AND d.order_status = 0
</if>
<if test="param.statusFilter == 1">
<!-- 1待发货已付款但未发货 -->
AND d.pay_status = 1 AND d.delivery_status = 10 AND d.order_status = 0
</if>
<if test="param.statusFilter == 2">
<!-- 2待核销已付款但订单状态为未使用 -->
AND d.pay_status = 1 AND d.order_status = 0
</if>
<if test="param.statusFilter == 3">
<!-- 3待收货已发货但订单状态不是已完成 -->
AND d.delivery_status = 20 AND d.order_status != 1
</if>
<if test="param.statusFilter == 4">
<!-- 4待评价订单已完成但可能需要评价 -->
AND d.order_status = 1 AND d.evaluate_status = 0
</if>
<if test="param.statusFilter == 5">
<!-- 5已完成订单状态为已完成 -->
AND d.order_status = 1
</if>
<if test="param.statusFilter == 6">
<!-- 6退款/售后:订单状态为退款成功 -->
AND (d.order_status = 4 OR d.order_status = 5 OR d.order_status = 6 OR d.order_status = 7)
</if>
<if test="param.statusFilter == 7">
<!-- 7已删除订单被删除 -->
AND d.deleted = 1
</if>
<if test="param.statusFilter == 8">
<!-- 8已取消订单已取消 -->
AND a.order_status = 2
</if>
</if>
</where> </where>
</sql> </sql>

View File

@@ -41,6 +41,9 @@ public class ClinicPrescriptionParam extends BaseParam {
@Schema(description = "订单编号") @Schema(description = "订单编号")
private String orderNo; private String orderNo;
@Schema(description = "订单类型 0商城订单 1处方订单")
private Integer type;
@Schema(description = "关联就诊表") @Schema(description = "关联就诊表")
@QueryField(type = QueryType.EQ) @QueryField(type = QueryType.EQ)
private Integer visitRecordId; private Integer visitRecordId;
@@ -92,4 +95,7 @@ public class ClinicPrescriptionParam extends BaseParam {
@TableField(exist = false) @TableField(exist = false)
private Set<Integer> ids; private Set<Integer> ids;
@Schema(description = "订单状态筛选:-1全部0待支付1待发货2待核销3待收货4待评价5已完成6已退款7已删除")
private Integer statusFilter;
} }

View File

@@ -30,7 +30,7 @@ public class PaymentRequest {
@Positive(message = "用户ID必须为正数") @Positive(message = "用户ID必须为正数")
private Integer userId; private Integer userId;
@Schema(description = "支付类型", required = true, example = "WECHAT_NATIVE") @Schema(description = "支付类型", required = true, example = "WECHAT")
@NotNull(message = "支付类型不能为空") @NotNull(message = "支付类型不能为空")
private PaymentType paymentType; private PaymentType paymentType;

View File

@@ -37,6 +37,8 @@
</if> </if>
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR a.user_id = #{param.keywords}
OR a.order_no = #{param.keywords}
) )
</if> </if>
</where> </where>

View File

@@ -69,6 +69,9 @@
<if test="param.keywords != null"> <if test="param.keywords != null">
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%')
OR a.order_no LIKE CONCAT('%', #{param.keywords}, '%') OR a.order_no LIKE CONCAT('%', #{param.keywords}, '%')
OR a.title LIKE CONCAT('%', #{param.keywords}, '%')
OR a.user_id = #{param.keywords}
OR a.month = #{param.keywords}
) )
</if> </if>
</where> </where>

View File

@@ -127,7 +127,7 @@ public class OrderBusinessService {
if (request.getTotalPrice() != null && if (request.getTotalPrice() != null &&
request.getTotalPrice().subtract(calculatedTotal).abs().compareTo(new BigDecimal("0.01")) > 0) { request.getTotalPrice().subtract(calculatedTotal).abs().compareTo(new BigDecimal("0.01")) > 0) {
log.warn("订单金额计算不一致,前端传入:{},后台计算:{}", request.getTotalPrice(), calculatedTotal); log.warn("订单金额计算不一致,前端传入:{},后台计算:{}", request.getTotalPrice(), calculatedTotal);
throw new BusinessException("订单金额计算错误,请刷新重试"); // throw new BusinessException("订单金额计算错误,请刷新重试");
} }
// 使用后台计算的金额 // 使用后台计算的金额