Files
hospital-admin-api/api/service/OrderInquiry.go
T

479 lines
14 KiB
Go

package service
import (
"errors"
"github.com/shopspring/decimal"
"gorm.io/gorm"
"hospital-admin-api/api/dao"
"hospital-admin-api/api/dto"
"hospital-admin-api/api/model"
"hospital-admin-api/api/requests"
"hospital-admin-api/config"
"hospital-admin-api/extend/weChat"
"hospital-admin-api/global"
"strconv"
"time"
)
type OrderInquiryService struct {
}
// CancelOrderInquiry 取消问诊订单
func (r *OrderInquiryService) CancelOrderInquiry(req requests.CancelOrderInquiry, orderInquiryId, adminUserId int64) (bool, error) {
// 获取订单数据
orderInquiryDao := dao.OrderInquiryDao{}
orderInquiry, err := orderInquiryDao.GetOrderInquiryById(orderInquiryId)
if err != nil || orderInquiry == nil {
return false, errors.New("订单数据错误")
}
// 检测订单状态 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消)
if orderInquiry.InquiryStatus == 6 {
return false, errors.New("订单已结束,无法取消")
}
if orderInquiry.InquiryStatus == 7 {
return false, errors.New("订单已取消,无法再次取消")
}
if orderInquiry.InquiryStatus == 1 {
return false, errors.New("订单处于待支付状态,无法取消")
}
if orderInquiry.InquiryStatus == 2 {
return false, errors.New("订单处于分配状态,无法取消")
}
if orderInquiry.InquiryStatus == 3 {
return false, errors.New("订单处于等待接诊状态,无法取消")
}
// 检测订单退款状态 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常)
if orderInquiry.InquiryRefundStatus == 1 {
return false, errors.New("订单申请退款中,无法取消")
}
if orderInquiry.InquiryRefundStatus == 2 {
return false, errors.New("订单正在退款中,无法取消")
}
if orderInquiry.InquiryRefundStatus == 3 {
return false, errors.New("订单已退款成功,无法取消")
}
if orderInquiry.InquiryRefundStatus == 6 {
return false, errors.New("订单退款异常,请联系技术人员")
}
// 检测支付状态 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款)
if orderInquiry.InquiryPayStatus != 2 {
return false, errors.New("订单未支付,无需取消")
}
// 检测问诊类型-服务包类型不允许取消
if orderInquiry.InquiryMode == 8 || orderInquiry.InquiryMode == 9 {
return false, errors.New("服务包类型订单不允许退款")
}
// 检测退款金额
if *req.RefundAmount > orderInquiry.PaymentAmountTotal {
return false, errors.New("退款金额不可超过实付金额")
}
// 订单完成时间预留5分钟进行操作
if !orderInquiry.CompleteTime.IsEmpty() {
// 计算三天后的时间
threeDaysLater := time.Time(orderInquiry.CompleteTime).Add(3 * 24 * time.Hour)
// 计算三天后的时间与当前时间的时间差
timeDifference := threeDaysLater.Sub(time.Now())
if timeDifference < 0 {
return false, errors.New("订单已完成,无法取消")
}
if 5*time.Minute > timeDifference {
return false, errors.New("距离订单完成时间不足5分钟,无法取消")
}
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 退款编号
refundNo := strconv.FormatInt(global.Snowflake.Generate().Int64(), 10)
// 退款状态转换
var refundStatus int
var successTime time.Time
var refundId string
// 发起退款
if orderInquiry.PaymentAmountTotal > 0 {
refundRequest := weChat.RefundRequest{
TransactionId: orderInquiry.EscrowTradeNo,
OutTradeNo: orderInquiry.InquiryNo,
OutRefundNo: refundNo,
Reason: "客服取消",
RefundAmount: int64(*req.RefundAmount * 100),
PaymentAmountTotal: int64(orderInquiry.PaymentAmountTotal * 100),
NotifyUrl: config.C.Wechat.RefundNotifyDomain + config.C.Wechat.PatientInquiryRefundNotifyUrl,
}
refund, err := refundRequest.Refund(1)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
if refund.Status == nil {
tx.Rollback()
return false, errors.New("退款状态错误")
}
if *refund.Status == "SUCCESS" {
// 退款成功
refundStatus = 3
if refund.SuccessTime != nil {
successTime = *refund.SuccessTime
}
} else if *refund.Status == "CLOSED" {
// 退款关闭
refundStatus = 5
} else if *refund.Status == "PROCESSING" {
// 退款处理中
refundStatus = 2
} else if *refund.Status == "ABNORMAL" {
// 退款异常
tx.Rollback()
return false, errors.New("退款状态错误")
} else {
tx.Rollback()
return false, errors.New("退款状态错误")
}
if refund.RefundId == nil {
tx.Rollback()
return false, errors.New("缺少退款订单编号")
}
// 退款编号
refundId = *refund.RefundId
} else {
// 支付金额为0,模拟退款
refundId = "模拟退款:" + strconv.FormatInt(global.Snowflake.Generate().Int64(), 10)
refundStatus = 3
successTime = time.Now()
// 模拟退款时手动退还优惠卷
if orderInquiry.CouponAmountTotal > 0 {
orderService := OrderService{}
res, err := orderService.ReturnOrderCoupon(orderInquiry.OrderId, tx)
if err != nil || !res {
// 退还优惠卷失败
tx.Rollback()
return false, err
}
}
}
// 修改订单为取消
orderData := make(map[string]interface{})
orderData["cancel_status"] = 1
orderData["cancel_time"] = time.Now().Format("2006-01-02 15:04:05")
orderData["cancel_remarks"] = req.CancelRemarks
orderDao := dao.OrderDao{}
err = orderDao.EditOrderById(tx, orderInquiry.OrderId, orderData)
if err != nil {
tx.Rollback()
return false, errors.New("取消订单失败")
}
// 修改问诊订单为取消
orderInquiryData := make(map[string]interface{})
orderInquiryData["inquiry_status"] = 7 // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消)
orderInquiryData["cancel_time"] = time.Now().Format("2006-01-02 15:04:05") // 订单取消时间
orderInquiryData["cancel_reason"] = 4 // 取消订单原因(1:医生未接诊 2:主动取消 3:无可分配医生 4:客服取消 5:支付超时)
orderInquiryData["cancel_remarks"] = req.CancelRemarks // 取消订单备注(自动添加)
err = orderInquiryDao.EditOrderInquiryById(tx, orderInquiryId, orderInquiryData)
if err != nil {
tx.Rollback()
return false, errors.New("取消订单失败")
}
// 新增退款表
orderRefund := &model.OrderRefund{
OrderId: orderInquiry.OrderId,
PatientId: orderInquiry.PatientId,
OrderNo: orderInquiry.InquiryNo,
RefundNo: refundNo,
RefundId: refundId,
RefundStatus: refundStatus,
RefundTotal: *req.RefundAmount,
RefundReason: req.CancelRemarks,
}
if refundStatus == 3 && !successTime.IsZero() {
orderRefund.SuccessTime = model.LocalTime(successTime)
}
orderRefundDao := dao.OrderRefundDao{}
orderRefund, err = orderRefundDao.AddOrderRefund(tx, orderRefund)
if err != nil || orderRefund == nil {
tx.Rollback()
return false, errors.New(err.Error())
}
// 新增问诊退款表
orderInquiryRefund := &model.OrderInquiryRefund{
PatientId: orderInquiry.PatientId,
OrderInquiryId: orderInquiryId,
InquiryNo: orderInquiry.InquiryNo,
InquiryRefundNo: refundNo,
RefundId: refundId,
InquiryRefundStatus: refundStatus,
RefundTotal: *req.RefundAmount,
RefundReason: req.CancelRemarks,
SuccessTime: model.LocalTime(successTime),
}
if refundStatus == 3 && !successTime.IsZero() {
orderInquiryRefund.SuccessTime = model.LocalTime(successTime)
}
orderInquiryRefundDao := dao.OrderInquiryRefundDao{}
orderInquiryRefund, err = orderInquiryRefundDao.AddOrderInquiryRefund(tx, orderInquiryRefund)
if err != nil || orderInquiryRefund == nil {
tx.Rollback()
return false, errors.New(err.Error())
}
// 记录日志
orderOperationLog := &model.OrderOperationLog{
OrderId: orderInquiry.OrderId,
OrderNo: orderInquiry.InquiryNo,
OrderType: 1,
OperatorId: adminUserId,
OperationContent: "取消订单并退款",
}
orderOperationLogDao := dao.OrderOperationLogDao{}
orderOperationLog, err = orderOperationLogDao.AddOrderOperationLog(tx, orderOperationLog)
if err != nil || orderOperationLog == nil {
tx.Rollback()
return false, errors.New(err.Error())
}
tx.Commit()
return true, nil
}
// ReturnInquiryCoupon 退还问诊订单优惠卷
func ReturnInquiryCoupon(tx *gorm.DB, orderInquiryId int64) bool {
orderInquiryCouponDao := dao.OrderInquiryCouponDao{}
userCouponDao := dao.UserCouponDao{}
// 获取用户优惠卷信息
orderInquiry, err := orderInquiryCouponDao.GetOrderInquiryCouponByOrderInquiryId(orderInquiryId)
if err != nil || orderInquiry == nil {
// 订单未使用优惠卷,无需退还
return true
}
// 获取用户优惠卷数据
userCoupon, err := userCouponDao.GetUserCouponById(orderInquiry.UserCouponId)
if err != nil || userCoupon == nil {
// 无该优惠卷数据,无需处理
return true
}
// 恢复优惠卷
userCouponData := make(map[string]interface{})
// 检测优惠卷过期时间。判断是否需要退还
if userCoupon.ValidEndTime.Before(time.Now()) {
userCouponData["user_coupon_status"] = 3
} else {
userCouponData["user_coupon_status"] = 0
userCouponData["coupon_use_date"] = nil
}
err = userCouponDao.EditUserCouponById(tx, userCoupon.UserCouponId, userCouponData)
if err != nil {
// 恢复优惠卷失败
return false
}
return true
}
// GetOrderInquiry 问诊订单详情
func (r *OrderInquiryService) GetOrderInquiry(orderInquiryId int64) (g *dto.OrderInquiryDto, err error) {
// 获取问诊订单数据
orderInquiryDao := dao.OrderInquiryDao{}
orderInquiry, err := orderInquiryDao.GetOrderInquiryPreloadById(orderInquiryId)
if err != nil || orderInquiry == nil {
return nil, errors.New(err.Error())
}
// 获取问诊订单优惠卷
orderInquiryCouponDao := dao.OrderInquiryCouponDao{}
orderInquiryCoupon, err := orderInquiryCouponDao.GetOrderInquiryCouponByOrderInquiryId(orderInquiryId)
// 获取问诊病例
orderInquiryCaseDao := dao.OrderInquiryCaseDao{}
orderInquiryCase, err := orderInquiryCaseDao.GetOrderInquiryCaseByOrderInquiryId(orderInquiryId)
if orderInquiryCase == nil {
return nil, errors.New("数据错误,无问诊病例")
}
// 获取退款数据
orderInquiryRefundDao := dao.OrderInquiryRefundDao{}
orderInquiryRefund, err := orderInquiryRefundDao.GetOrderInquiryRefundByOrderInquiryId(orderInquiryId)
// 获取订单评价
orderEvaluationDao := dao.OrderEvaluationDao{}
orderEvaluation, err := orderEvaluationDao.GetOrderEvaluationByOrderInquiryId(orderInquiryId)
// 医生数据
userDoctorService := UserDoctorService{}
userDoctor, err := userDoctorService.GetUserDoctorById(orderInquiry.DoctorId)
if err != nil {
return nil, errors.New(err.Error())
}
// 处理返回值
g = dto.GetOrderInquiryDto(orderInquiry)
// 加载医生数据
g.UserDoctor = userDoctor
// 加载订单退款数据
g.LoadOrderInquiryRefund(orderInquiryRefund)
// 加载问诊订单优惠卷
g.LoadOrderInquiryCoupon(orderInquiryCoupon)
// 加载问诊病例
g.LoadMaskOrderInquiryCase(orderInquiryCase)
// 加载订单评价
g.LoadOrderEvaluation(orderEvaluation)
return g, nil
}
// GetOrderInquiryRecord 问诊记录详情
func (r *OrderInquiryService) GetOrderInquiryRecord(orderInquiryId int64) (g *dto.OrderInquiryDto, err error) {
// 获取问诊订单数据
orderInquiryDao := dao.OrderInquiryDao{}
orderInquiry, err := orderInquiryDao.GetOrderInquiryPreloadById(orderInquiryId)
if err != nil || orderInquiry == nil {
return nil, errors.New(err.Error())
}
// 获取问诊病例
orderInquiryCaseDao := dao.OrderInquiryCaseDao{}
orderInquiryCase, err := orderInquiryCaseDao.GetOrderInquiryCaseByOrderInquiryId(orderInquiryId)
if orderInquiryCase == nil {
return nil, errors.New("数据错误,无问诊病例")
}
// 获取医生数据
userDoctorService := UserDoctorService{}
userDoctor, err := userDoctorService.GetUserDoctorById(orderInquiry.DoctorId)
if err != nil {
return nil, errors.New(err.Error())
}
// 获取聊天记录
messageImDao := dao.MessageImDao{}
messageIms, err := messageImDao.GetMessageImByOrderInquiryId(orderInquiryId)
// 处理返回值
g = dto.GetOrderInquiryRecordDto(orderInquiry)
// 加载医生数据
g.UserDoctor = userDoctor
// 加载问诊病例
g.LoadMaskOrderInquiryCase(orderInquiryCase)
// 加载聊天记录
g.LoadMessageIm(messageIms)
return g, nil
}
// GetOrderInquiryEntryStatus 获取订单入账状态
func (r *OrderInquiryService) GetOrderInquiryEntryStatus(inquiryStatus, statisticsStatus int) int {
// entryStatus 入账状态(0:未入账 1:已入账 2:入账中 3:入账失败 4:入账取消)
// 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消)
var entryStatus int
if inquiryStatus == 7 {
entryStatus = 4
}
if inquiryStatus == 1 || inquiryStatus == 2 || inquiryStatus == 3 {
entryStatus = 0
}
if inquiryStatus == 4 || inquiryStatus == 5 {
entryStatus = 2
}
if inquiryStatus == 6 {
if statisticsStatus == 1 {
entryStatus = 1
}
// 统计失败/已结束未统计
if inquiryStatus == 2 || inquiryStatus == 0 {
entryStatus = 3
}
}
return entryStatus
}
// GetOrderInquiryDoctorAmount 获取订单中医生收益
func (r *OrderInquiryService) GetOrderInquiryDoctorAmount(inquiryStatus int, amountTotal float64) float64 {
var doctorAmount float64
if inquiryStatus == 4 || inquiryStatus == 5 || inquiryStatus == 6 {
doctorAmount, _ = decimal.NewFromFloat(amountTotal).
Mul(decimal.NewFromFloat(0.75)).
Mul(decimal.NewFromFloat(100)).Floor().
Div(decimal.NewFromFloat(100)).Float64()
}
return doctorAmount
}
// PutAnnualReviewHide 修改问诊订单年度审查隐藏状态
func (r *OrderInquiryService) PutAnnualReviewHide(orderInquiryId int64, annualReviewHide int) error {
// 获取问诊订单数据
orderInquiryDao := dao.OrderInquiryDao{}
orderInquiry, err := orderInquiryDao.GetOrderInquiryById(orderInquiryId)
if err != nil || orderInquiry == nil {
return errors.New("订单数据错误")
}
// 修改问诊订单
orderInquiryData := make(map[string]interface{})
orderInquiryData["annual_review_hide"] = annualReviewHide
err = orderInquiryDao.EditOrderInquiryById(global.Db, orderInquiryId, orderInquiryData)
if err != nil {
return errors.New("修改隐藏状态失败")
}
return nil
}