hospital-admin-api/api/service/orderServicePackage.go

643 lines
22 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"errors"
"fmt"
"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"
"math"
"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)
if g.OrderServiceStatus == 3 || g.OrderServiceStatus == 4 || g.OrderServiceStatus == 5 {
if !g.StartTime.IsEmpty() {
// 获取服务包当前月时间区间
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分")
// 检测问诊是否服务包首次问诊
isFirst, err := r.isFirstInquiryServicePackage(g.OrderServiceNo)
if isFirst {
g.MonthInquiryCount = 1
} else {
// 获取服务包当月已问诊次数
g.MonthInquiryCount, err = r.GetCurrentMonthInquiryCount(g.OrderServiceType, orderServicePackage.UserId, orderServicePackage.DoctorId, g.PayTime)
if err != nil {
return nil, err
}
}
fmt.Println(g.MonthInquiryCount)
// 获取服务包当月剩余问诊次数
g.RemainingInquiryCount = r.GetRemainingInquiryCount(orderServicePackageDetail.MonthlyFrequency, g.MonthInquiryCount)
fmt.Println(g.RemainingInquiryCount)
}
}
// 健康包数据
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.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, 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() {
orderServicePackageRefund.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())
}
// 获取服务包关联问诊订单
for _, inquiry := range orderServicePackage.OrderServicePackageInquiry {
// 获取订单数据
orderInquiryDao := dao.OrderInquiryDao{}
orderInquiry, err := orderInquiryDao.GetOrderInquiryById(inquiry.OrderInquiryId)
if err != nil || orderInquiry == nil {
tx.Rollback()
return false, errors.New("取消订单失败")
}
// 检测订单状态 问诊订单状态1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消)
if orderInquiry.InquiryStatus == 6 {
continue
}
// 检测订单状态 问诊订单状态1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消)
if orderInquiry.InquiryStatus == 7 {
continue
}
// 支付金额为0模拟退款
refundId = "模拟退款:" + strconv.FormatInt(global.Snowflake.Generate().Int64(), 10)
refundStatus = 3
successTime = time.Now()
// 退款编号
refundNo = strconv.FormatInt(global.Snowflake.Generate().Int64(), 10)
// 修改订单为取消
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, orderInquiry.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: orderInquiry.PaymentAmountTotal,
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: orderInquiry.OrderInquiryId,
InquiryNo: orderInquiry.InquiryNo,
InquiryRefundNo: refundNo,
RefundId: refundId,
InquiryRefundStatus: refundStatus,
RefundTotal: orderInquiry.PaymentAmountTotal,
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())
}
}
// 记录日志
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().Unix()
// 获取开启服务日期和今日的相差天数
diff := math.Abs(float64(now - time.Time(startTime).Unix()))
diffDays := math.Ceil(diff / 60 / 60 / 24)
// 获取当前月次
monthTime := math.Ceil(diffDays / 30) // 向上取整
days := monthTime * 30
// 当前所属月结束时间
currentMonthFinishDate := time.Time(startTime).AddDate(0, 0, int(days))
// 当前所属月开始时间
currentMonthStartDate := currentMonthFinishDate.AddDate(0, 0, -30)
return currentMonthStartDate, currentMonthFinishDate, nil
}
// 检测问诊是否服务包首次问诊
func (r *OrderServicePackageService) isFirstInquiryServicePackage(orderNo string) (bool, error) {
orderServicePackageInquiryDao := dao.OrderServicePackageInquiryDao{}
maps := make(map[string]interface{})
maps["order_service_no"] = orderNo
orderServicePackageInquiry, err := orderServicePackageInquiryDao.GetOrderServicePackageInquiryList(maps)
if err != nil {
return false, err
}
if len(orderServicePackageInquiry) == 1 {
return true, nil
}
return false, err
}
// GetCurrentMonthInquiryCount 获取服务包当月已问诊次数
func (r *OrderServicePackageService) GetCurrentMonthInquiryCount(orderServiceType int, userId, doctorId int64, startTime model.LocalTime) (int, error) {
orderInquiryDao := dao.OrderInquiryDao{}
CurrentMonthStartDate, CurrentMonthFinishDate, err := r.getOrderServicePackageCurrentMonthDate(startTime)
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.GetOrderInquiryCreatedTimeList(maps, CurrentMonthStartDate.Format("2006-01-02 15:04:05"), CurrentMonthFinishDate.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
}
// GetPatientFamilyInProgressServicePackage 获取患者家庭成员进行中的服务包订单
func (r *OrderServicePackageService) GetPatientFamilyInProgressServicePackage(patientUserId, familyId, doctorId int64, serviceType int) (*model.OrderServicePackage, error) {
orderServicePackageDao := dao.OrderServicePackageDao{}
maps := make(map[string]interface{})
maps["user_id"] = patientUserId
maps["doctor_id"] = doctorId
maps["family_id"] = familyId
maps["order_service_type"] = serviceType
maps["order_service_status"] = 3
orderServicePackage, err := orderServicePackageDao.GetOrderServicePackage(maps)
if err != nil {
return nil, err
}
return orderServicePackage, err
}