Files
hospital-admin-api/api/service/orderServicePackage.go
T
2024-06-17 09:24:25 +08:00

643 lines
22 KiB
Go

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
}