package service import ( "errors" "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 OrderServicePackageService struct { } // GetOrderServicePackage 服务包订单详情 func (r *OrderServicePackageService) GetOrderServicePackage(orderServiceId int64) (g *dto.OrderServicePackageDto, err error) { // 获取订单数据 orderServicePackageDao := dao.OrderServicePackageDao{} orderServicePackage, err := orderServicePackageDao.GetOrderServicePackageById(orderServiceId) if err != nil || orderServicePackage == nil { return nil, errors.New(err.Error()) } // 获取病例 orderServicePackageCaseDao := dao.OrderServicePackageCaseDao{} orderServicePackageCase, err := orderServicePackageCaseDao.GetOrderServicePackageCaseByOrderServicePackageId(orderServiceId) if orderServicePackageCase == nil { return nil, errors.New("数据错误,无问诊病例") } // 获取退款数据 orderServicePackageRefundDao := dao.OrderServicePackageRefundDao{} orderServicePackageRefund, err := orderServicePackageRefundDao.GetOrderServicePackageRefundByOrderServicePackageId(orderServiceId) // 医生数据 userDoctorService := UserDoctorService{} userDoctor, err := userDoctorService.GetUserDoctorById(orderServicePackage.DoctorId) if err != nil { return nil, errors.New(err.Error()) } // 处理返回值 g = dto.GetOrderServicePackageDto(orderServicePackage) // 加载医生数据 g.UserDoctor = userDoctor // 加载订单退款数据 g.LoadOrderServicePackageRefund(orderServicePackageRefund) // 加载问诊病例 g.LoadMaskOrderServicePackageCase(orderServicePackageCase) return g, nil } // GetOrderServicePackageDetailInfo 获取服务包订单服务权益详情 func (r *OrderServicePackageService) GetOrderServicePackageDetailInfo(orderServiceId int64) (g *dto.OrderServicePackageDetailInfoDto, err error) { // 获取订单数据 orderServicePackageDao := dao.OrderServicePackageDao{} orderServicePackage, err := orderServicePackageDao.GetOrderServicePackageById(orderServiceId) if err != nil || orderServicePackage == nil { return nil, errors.New(err.Error()) } // 获取关联问诊订单 orderServicePackageInquiryDao := dao.OrderServicePackageInquiryDao{} orderServicePackageInquiry, err := orderServicePackageInquiryDao.GetOrderServicePackageInquiryPreloadByOrderNo(orderServicePackage.OrderServiceNo) // 获取订单详情数据 orderServicePackageDDao := dao.OrderServicePackageDetailDao{} orderServicePackageDetail, err := orderServicePackageDDao.GetOrderServicePackageDetailByOrderServicePackageId(orderServiceId) if err != nil || orderServicePackageDetail == nil { return nil, errors.New(err.Error()) } // 获取关联病例 orderServicePackageCaseDao := dao.OrderServicePackageCaseDao{} orderServicePackageCase, err := orderServicePackageCaseDao.GetOrderServicePackageCaseByOrderId(orderServicePackage.OrderId) if err != nil || orderServicePackageDetail == nil { return nil, errors.New(err.Error()) } // 处理返回值 g = dto.GetOrderServicePackageDetailInfoDto(orderServicePackage) // 加载关联问诊订单数据 if len(orderServicePackageInquiry) > 0 { g.LoadOrderServicePackageInquiry(orderServicePackageInquiry) } // 加载服务包订单详情数据 g.LoadOrderServicePackageDetail(orderServicePackageDetail) // 加载服务包订单关联病例数据 g.LoadOrderServicePackageCase(orderServicePackageCase) // 获取服务包当前月时间区间 CurrentMonthStartDate, CurrentMonthFinishDate, err := r.getOrderServicePackageCurrentMonthDate(g.StartTime) g.CurrentMonthStartDate = CurrentMonthStartDate.Format("2006年01月02日 15时04分") g.CurrentMonthFinishDate = CurrentMonthFinishDate.Format("2006年01月02日 15时04分") // 获取服务包当月已问诊次数 g.MonthInquiryCount, err = r.GetCurrentMonthInquiryCount(g.OrderServiceType, orderServicePackage.UserId, orderServicePackage.DoctorId, CurrentMonthStartDate, CurrentMonthFinishDate) if err != nil { return nil, err } // 获取服务包当月剩余问诊次数 g.RemainingInquiryCount = r.GetRemainingInquiryCount(orderServicePackageDetail.MonthlyFrequency, g.MonthInquiryCount) // 健康包数据 if orderServicePackage.OrderServiceType == 1 { if g.OrderServiceStatus == 3 || g.OrderServiceStatus == 4 || g.OrderServiceStatus == 5 { // 获取用户某一类型优惠卷 userCouponDao := dao.UserCouponDao{} userCoupon, _ := userCouponDao.GetUserAllObjectTypeCoupon(orderServicePackage.UserId, 7) // 加载优惠卷数据 g.LoadUserCoupon(userCoupon) // 获取健康包药品订单数据-周期内所有药品订单 orderServicePackageProductDao := dao.OrderServicePackageProductDao{} orderServicePackageProduct, _ := orderServicePackageProductDao.GetOrderServicePackageProductPreloadByOrderServiceId( orderServicePackage.OrderServiceId) // 加载关联药品订单数据 g.LoadOrderServicePackageProduct(orderServicePackageProduct) // 获取服务包内所有药品 healthPackageProductDao := dao.HealthPackageProductDao{} healthPackageProducts, err := healthPackageProductDao.GetHealthPackageProductByPackageId(orderServicePackageDetail.PackageId) if err != nil { return nil, err } for _, healthPackageProduct := range healthPackageProducts { // 获取服务包内某一药品的剩余数量 remainingQuantity, err := r.GetOrderServiceProductCanUseQuantity(orderServicePackage.OrderServiceId, healthPackageProduct.ProductId, healthPackageProduct.Quantity) if err != nil { return nil, err } g.OrderServicePackageDetail.LoadRemainingQuantity(remainingQuantity) } } } return g, nil } // CancelOrderServicePackage 取消服务包订单 func (r *OrderServicePackageService) CancelOrderServicePackage(req requests.CancelOrderServicePackage, orderServiceId, adminUserId int64) (bool, error) { // 获取订单数据 orderServicePackageDao := dao.OrderServicePackageDao{} orderServicePackage, err := orderServicePackageDao.GetOrderServicePackagePreloadById(orderServiceId) if err != nil || orderServicePackage == nil { return false, errors.New("订单数据错误") } // 订单状态(1:待支付 2:未开始 3:服务中 4:服务完成 5:服务取消) if orderServicePackage.OrderServiceStatus == 5 { return false, errors.New("订单已取消,无法再次取消") } // 检测订单退款状态 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常) if orderServicePackage.RefundStatus == 1 { return false, errors.New("订单申请退款中,无法取消") } if orderServicePackage.RefundStatus == 2 { return false, errors.New("订单正在退款中,无法取消") } if orderServicePackage.RefundStatus == 3 { return false, errors.New("订单已退款成功,无法取消") } if orderServicePackage.RefundStatus == 6 { return false, errors.New("订单退款异常,请联系技术人员") } // 检测支付状态 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) if orderServicePackage.PayStatus != 2 { return false, errors.New("订单未支付,无需取消") } // 检测退款金额 if *req.RefundAmount > orderServicePackage.PaymentAmountTotal { return false, errors.New("退款金额不可超过实付金额") } // 开始事务 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 orderServicePackage.PaymentAmountTotal > 0 { refundRequest := weChat.RefundRequest{ TransactionId: orderServicePackage.EscrowTradeNo, OutTradeNo: orderServicePackage.OrderServiceNo, OutRefundNo: refundNo, Reason: "客服取消", RefundAmount: int64(*req.RefundAmount * 100), PaymentAmountTotal: int64(orderServicePackage.PaymentAmountTotal * 100), NotifyUrl: config.C.Wechat.RefundNotifyDomain + config.C.Wechat.PatientServiceRefundNotifyUrl, } refund, err := refundRequest.Refund(4) 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 orderServicePackage.CouponAmountTotal > 0 { orderService := OrderService{} res, err := orderService.ReturnOrderCoupon(orderServicePackage.OrderServiceNo, 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, orderServicePackage.OrderId, orderData) if err != nil { tx.Rollback() return false, errors.New("取消订单失败") } // 修改服务包订单为取消 orderServicePackageData := make(map[string]interface{}) orderServicePackageData["order_service_status"] = 5 // 订单状态(1:待支付 2:未开始 3:服务中 4:服务完成 5:服务取消) orderServicePackageData["cancel_time"] = time.Now().Format("2006-01-02 15:04:05") // 订单取消时间 orderServicePackageData["cancel_reason"] = 4 // 取消订单原因(1:医生未接诊 2:主动取消 3:无可分配医生 4:客服取消 5:支付超时) orderServicePackageData["cancel_remarks"] = req.CancelRemarks // 取消订单备注(自动添加) err = orderServicePackageDao.EditOrderServicePackageById(tx, orderServicePackage.OrderId, orderServicePackageData) if err != nil { tx.Rollback() return false, errors.New("取消订单失败") } // 新增退款表 orderRefund := &model.OrderRefund{ OrderId: orderServicePackage.OrderId, PatientId: orderServicePackage.PatientId, OrderNo: orderServicePackage.OrderServiceNo, 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()) } // 新增服务包退款表 orderServicePackageRefund := &model.OrderServicePackageRefund{ PatientId: orderServicePackage.PatientId, OrderServiceId: orderServicePackage.OrderServiceId, OrderServiceNo: orderServicePackage.OrderServiceNo, ServiceRefundNo: refundNo, RefundId: refundId, RefundStatus: refundStatus, RefundTotal: *req.RefundAmount, RefundReason: req.CancelRemarks, SuccessTime: model.LocalTime(successTime), } if refundStatus == 3 && !successTime.IsZero() { orderRefund.SuccessTime = model.LocalTime(successTime) } orderServicePackageRefundDao := dao.OrderServicePackageRefundDao{} orderServicePackageRefund, err = orderServicePackageRefundDao.AddOrderServicePackageRefund(tx, orderServicePackageRefund) if err != nil || orderServicePackageRefund == nil { tx.Rollback() return false, errors.New(err.Error()) } // 记录日志 orderOperationLog := &model.OrderOperationLog{ OrderId: orderServicePackage.OrderId, OrderNo: orderServicePackage.OrderServiceNo, OrderType: 4, 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 } // 获取服务包当前月时间区间 func (r *OrderServicePackageService) getOrderServicePackageCurrentMonthDate(startTime model.LocalTime) (startDate, finishDate time.Time, err error) { if startTime.IsEmpty() { return time.Time{}, time.Time{}, err } // 获取当前时间 now := time.Now() // 获取开启服务日期和今日的相差天数 diff := now.Sub(time.Time(startTime)).Hours() / 24 diffDays := int(diff) // 获取当前月次 monthTime := (diffDays + 29) / 30 // 向上取整 days := monthTime * 30 // 当前所属月结束时间 currentMonthFinishDate := time.Time(startTime).AddDate(0, 0, days) // 当前所属月开始时间 currentMonthStartDate := currentMonthFinishDate.AddDate(0, 0, -30) return currentMonthStartDate, currentMonthFinishDate, nil } // 检测问诊是否服务包首次问诊 func (r *OrderServicePackageService) isFirstInquiryServicePackage(orderNo string) (bool, error) { orderServicePackageDao := dao.OrderServicePackageDao{} maps := make(map[string]interface{}) maps["order_service_no"] = orderNo orderServicePackage, err := orderServicePackageDao.GetOrderServicePackageList(maps) if err != nil { return false, err } if len(orderServicePackage) == 1 { return true, nil } return false, err } // GetCurrentMonthInquiryCount 获取服务包当月已问诊次数 func (r *OrderServicePackageService) GetCurrentMonthInquiryCount(orderServiceType int, userId, doctorId int64, startDate, endDate time.Time) (int, error) { orderInquiryDao := dao.OrderInquiryDao{} maps := make(map[string]interface{}) maps["inquiry_type"] = 1 if orderServiceType == 1 { maps["inquiry_mode"] = 8 } else { maps["inquiry_mode"] = 9 } maps["user_id"] = userId maps["doctor_id"] = doctorId maps["inquiry_refund_status"] = 0 maps["inquiry_pay_status"] = 2 maps["inquiry_status"] = []int{1, 2, 3, 4, 5, 6} orderInquirys, err := orderInquiryDao.GetOrderInquiryTimeList(maps, startDate.Format("2006-01-02 15:04"), endDate.Format("2006-01-02 15:04:05")) if err != nil { return 0, err } return len(orderInquirys), err } // GetRemainingInquiryCount 获取服务包当月剩余问诊次数 func (r *OrderServicePackageService) GetRemainingInquiryCount(monthlyFrequency, monthInquiryCount int) string { result := "" if monthlyFrequency != 0 { monthInquiryCount = monthlyFrequency - monthInquiryCount if monthInquiryCount < 0 { result = "0" } else { result = strconv.Itoa(monthInquiryCount) } } else { result = "不限" } return result } // GetOrderServiceProductCanUseQuantity 获取服务包内某一药品的可使用数量 func (r *OrderServicePackageService) GetOrderServiceProductCanUseQuantity(orderServiceId, productId int64, totalQuantity int) (int, error) { orderServicePackageProductDao := dao.OrderServicePackageProductDao{} maps := make(map[string]interface{}) maps["order_service_id"] = orderServiceId maps["product_id"] = productId orderServicePackageProducts, err := orderServicePackageProductDao.GetOrderServicePackageProductList(maps) if err != nil { return 0, err } // 订单使用数量 usedQuantity := 0 for _, product := range orderServicePackageProducts { usedQuantity = usedQuantity + product.UsedQuantity } // 剩余数量 = 总数量-使用数量 remainingQuantity := totalQuantity - usedQuantity if remainingQuantity < 0 { remainingQuantity = 0 } return remainingQuantity, err }