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

431 lines
13 KiB
Go
Raw Permalink 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"
"github.com/shopspring/decimal"
"hospital-admin-api/api/dao"
"hospital-admin-api/api/dto"
"hospital-admin-api/api/requests"
"hospital-admin-api/global"
"hospital-admin-api/utils"
"time"
)
type DoctorWithdrawalService struct {
}
// GetDoctorWithdrawal 提现详情
func (r *DoctorWithdrawalService) GetDoctorWithdrawal(withdrawalId int64) (g *dto.DoctorWithdrawalDto, err error) {
doctorWithdrawalDao := dao.DoctorWithdrawalDao{}
doctorWithdrawal, err := doctorWithdrawalDao.GetDoctorWithdrawalById(withdrawalId)
if doctorWithdrawal == nil {
return nil, errors.New("数据错误")
}
// 获取医生数据
userDoctorDao := dao.UserDoctorDao{}
userDoctor, err := userDoctorDao.GetUserDoctorById(doctorWithdrawal.DoctorId)
if err != nil || userDoctor == nil {
return nil, errors.New("医生数据错误")
}
// 获取医生用户数据
userDao := dao.UserDao{}
user, err := userDao.GetUserById(userDoctor.UserId)
if err != nil || user == nil {
return nil, errors.New("医生数据错误")
}
// 获取医生详情数据
userDoctorInfoDao := dao.UserDoctorInfoDao{}
userDoctorInfo, err := userDoctorInfoDao.GetUserDoctorInfoByUserId(userDoctor.UserId)
if err != nil || userDoctorInfo == nil {
return nil, errors.New("医生详情数据错误")
}
// 获取提现关联银行数据
doctorWithdrawalBankDao := dao.DoctorWithdrawalBankDao{}
doctorWithdrawalBank, err := doctorWithdrawalBankDao.GetDoctorWithdrawalBankByWithdrawalId(doctorWithdrawal.WithdrawalId)
if err != nil || doctorWithdrawalBank == nil {
return nil, errors.New("银行卡数据错误")
}
// 获取基础银行数据
basicBankDao := dao.BasicBankDao{}
basicBank, err := basicBankDao.GetBasicBankById(doctorWithdrawalBank.BankId)
if err != nil || basicBank == nil {
return nil, errors.New("银行数据错误")
}
// 处理返回值
g = dto.GetDoctorWithdrawalDto(doctorWithdrawal)
// 加载医生名称
g.LoadDoctorName(userDoctor)
// 加载医生证件号码(掩码)
g.LoadDoctorCardNumMask(userDoctorInfo)
// 加载审核人员名称
g.LoadExamineByName(doctorWithdrawal.ExamineBy)
// 加载打款人员名称
g.LoadPaymentByName(doctorWithdrawal.ExamineBy)
// 加载提现关联银行数据
g.LoadDoctorWithdrawalBank(doctorWithdrawalBank)
// 加载基础银行数据
g.LoadBasicBank(basicBank)
// 加载医生user_id
g.LoadDoctorUserId(user)
return g, nil
}
// PutDoctorWithdrawalIncome 修改提现个人所得税
func (r *DoctorWithdrawalService) PutDoctorWithdrawalIncome(req requests.PutDoctorWithdrawalIncome, withdrawalId int64) (bool, error) {
doctorWithdrawalDao := dao.DoctorWithdrawalDao{}
doctorWithdrawal, _ := doctorWithdrawalDao.GetDoctorWithdrawalById(withdrawalId)
if doctorWithdrawal == nil {
return false, errors.New("数据错误")
}
// 判断审核状态
if doctorWithdrawal.ExamineStatus == 2 {
return false, errors.New("提现申请已审核通过,请勿再次操作")
}
if doctorWithdrawal.ExamineStatus == 3 {
return false, errors.New("提现申请已被驳回,请勿再次操作")
}
if doctorWithdrawal.PaymentStatus == 1 {
return false, errors.New("已打款,请勿再次操作")
}
if req.IncomeTax >= doctorWithdrawal.AppliedWithdrawalAmount {
return false, errors.New("个人所得税金额不可超出申请提现金额")
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 计算实际提现金额
var appliedWithdrawalAmount = decimal.NewFromFloat(doctorWithdrawal.AppliedWithdrawalAmount)
var incomeTax = decimal.NewFromFloat(req.IncomeTax)
// (计算提现金额-个人所得税金额) * 100 取小数点后3位
actualWithdrawalAmount := appliedWithdrawalAmount.Sub(incomeTax).Mul(decimal.NewFromFloat(100)).Floor().Div(decimal.NewFromFloat(100))
// 转为float64
result, _ := actualWithdrawalAmount.Float64()
// 提现申请修改数据-提现金额固定不动,修改个人所得税,实际提现金额跟随变动
doctorWithdrawalData := make(map[string]interface{})
doctorWithdrawalData["actual_withdrawal_amount"] = result // 实际提现金额
doctorWithdrawalData["income_tax"] = req.IncomeTax // 提现所得税金额
err := doctorWithdrawalDao.EditDoctorWithdrawalById(tx, doctorWithdrawal.WithdrawalId, doctorWithdrawalData)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
tx.Commit()
return true, nil
}
// PutDoctorWithdrawalExamine 修改提现审核状态
func (r *DoctorWithdrawalService) PutDoctorWithdrawalExamine(req requests.PutDoctorWithdrawalExamine, withdrawalId, adminUserId int64) (bool, error) {
doctorWithdrawalDao := dao.DoctorWithdrawalDao{}
doctorWithdrawal, _ := doctorWithdrawalDao.GetDoctorWithdrawalById(withdrawalId)
if doctorWithdrawal == nil {
return false, errors.New("数据错误")
}
// 判断审核状态
if doctorWithdrawal.ExamineStatus == 2 {
return false, errors.New("提现申请已审核通过,无法操作")
}
if doctorWithdrawal.ExamineStatus == 3 {
return false, errors.New("提现申请已被驳回,请勿再次操作")
}
if doctorWithdrawal.PaymentStatus == 1 {
return false, errors.New("已打款,请勿再次操作")
}
if req.ExamineStatus == 3 {
if req.ExamineFailReason == "" {
return false, errors.New("请填写拒绝原因")
}
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 提现申请修改数据
doctorWithdrawalData := make(map[string]interface{})
doctorWithdrawalData["examine_status"] = req.ExamineStatus
if req.ExamineFailReason != "" {
doctorWithdrawalData["examine_fail_reason"] = req.ExamineFailReason
}
doctorWithdrawalData["examine_time"] = time.Now().Format("2006-01-02 15:04:05")
doctorWithdrawalData["examine_by"] = adminUserId
err := doctorWithdrawalDao.EditDoctorWithdrawalById(tx, doctorWithdrawal.WithdrawalId, doctorWithdrawalData)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
// 获取医生账户数据
doctorAccountDao := dao.DoctorAccountDao{}
doctorAccount, err := doctorAccountDao.GetDoctorAccountByDoctorId(doctorWithdrawal.DoctorId)
if err != nil {
tx.Rollback()
return false, errors.New("医生账户数据错误")
}
// 获取医生分成总金额
amountTotal, err := r.getDoctorWithdrawalOrderAmountTotal(withdrawalId)
if err != nil {
tx.Rollback()
return false, err
}
// 重新计算医生个人所得税
incomeTax := utils.ComputeIndividualIncomeTax(amountTotal)
// 重新计算实际提现金额
withdrawalAmount := amountTotal - incomeTax
// 返还医生账户金额-审核不通过
if req.ExamineStatus == 3 {
// 账户余额-增加
maps := make(map[string]interface{})
maps["account_id"] = doctorAccount.AccountId
err = doctorAccountDao.Inc(tx, maps, amountTotal, "balance_account")
if err != nil {
tx.Rollback()
return false, err
}
// 提现金额-减少
maps = make(map[string]interface{})
maps["account_id"] = doctorAccount.AccountId
err = doctorAccountDao.Dec(tx, maps, amountTotal, "applied_withdrawal_amount")
if err != nil {
tx.Rollback()
return false, err
}
// 实际提现金额-减少
maps = make(map[string]interface{})
maps["account_id"] = doctorAccount.AccountId
err = doctorAccountDao.Dec(tx, maps, withdrawalAmount, "actual_withdrawal_amount")
if err != nil {
tx.Rollback()
return false, err
}
// 提现所得税金额-减少
maps = make(map[string]interface{})
maps["account_id"] = doctorAccount.AccountId
err = doctorAccountDao.Dec(tx, maps, incomeTax, "income_tax")
if err != nil {
tx.Rollback()
return false, err
}
// 获取医生提现-关联订单数据
doctorWithdrawalOrderDao := dao.DoctorWithdrawalOrderDao{}
doctorWithdrawalOrders, err := doctorWithdrawalOrderDao.GetDoctorWithdrawalOrderByWithdrawalId(withdrawalId)
if err != nil {
tx.Rollback()
return false, errors.New("关联订单数据错误")
}
// 修改问诊订单提现状态
orderDao := dao.OrderDao{}
orderInquiryDao := dao.OrderInquiryDao{}
for _, v := range doctorWithdrawalOrders {
// 获取订单数据
order, err := orderDao.GetOrderPreloadById(v.OrderId)
if order == nil {
tx.Rollback()
return false, errors.New("关联订单数据错误")
}
// 修改订单数据
orderData := make(map[string]interface{})
orderData["is_withdrawal"] = 0
orderData["withdrawal_time"] = nil
err = orderDao.EditOrderById(tx, v.OrderId, orderData)
if err != nil {
tx.Rollback()
return false, errors.New("回滚关联订单数据失败")
}
if order.OrderType == 1 {
orderInquiryData := make(map[string]interface{})
orderInquiryData["is_withdrawal"] = 0
orderInquiryData["withdrawal_time"] = nil
err = orderInquiryDao.EditOrderInquiryById(tx, order.OrderInquiry.OrderInquiryId, orderInquiryData)
if err != nil {
tx.Rollback()
return false, errors.New("操作关联订单数据失败")
}
}
}
}
tx.Commit()
return true, nil
}
// PutDoctorWithdrawalPayment 确认打款
func (r *DoctorWithdrawalService) PutDoctorWithdrawalPayment(withdrawalId, adminUserId int64) (bool, error) {
doctorWithdrawalDao := dao.DoctorWithdrawalDao{}
doctorWithdrawal, _ := doctorWithdrawalDao.GetDoctorWithdrawalById(withdrawalId)
if doctorWithdrawal == nil {
return false, errors.New("数据错误")
}
// 判断审核状态
if doctorWithdrawal.ExamineStatus != 2 {
return false, errors.New("请先确认打款金额并审核")
}
if doctorWithdrawal.PaymentStatus == 1 {
return false, errors.New("已打款,请勿再次操作")
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 提现申请修改数据
doctorWithdrawalData := make(map[string]interface{})
doctorWithdrawalData["payment_status"] = 1
doctorWithdrawalData["payment_time"] = time.Now().Format("2006-01-02 15:04:05")
doctorWithdrawalData["payment_by"] = adminUserId
err := doctorWithdrawalDao.EditDoctorWithdrawalById(tx, doctorWithdrawal.WithdrawalId, doctorWithdrawalData)
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
// 获取医生提现-关联订单数据
doctorWithdrawalOrderDao := dao.DoctorWithdrawalOrderDao{}
doctorWithdrawalOrders, err := doctorWithdrawalOrderDao.GetDoctorWithdrawalOrderByWithdrawalId(withdrawalId)
if err != nil {
tx.Rollback()
return false, errors.New("关联订单数据错误")
}
// 修改问诊订单提现状态
orderDao := dao.OrderDao{}
orderInquiryDao := dao.OrderInquiryDao{}
for _, v := range doctorWithdrawalOrders {
// 获取订单数据
order, err := orderDao.GetOrderPreloadById(v.OrderId)
if order == nil {
tx.Rollback()
return false, errors.New("关联订单数据错误")
}
// 修改订单数据
orderData := make(map[string]interface{})
orderData["is_withdrawal"] = 1
orderData["withdrawal_time"] = time.Now().Format("2006-01-02 15:04:05")
err = orderDao.EditOrderById(tx, v.OrderId, orderData)
if err != nil {
tx.Rollback()
return false, errors.New("关联订单数据错误")
}
if order.OrderType == 1 {
orderInquiryData := make(map[string]interface{})
orderInquiryData["is_withdrawal"] = 1
orderInquiryData["withdrawal_time"] = time.Now().Format("2006-01-02 15:04:05")
err = orderInquiryDao.EditOrderInquiryById(tx, order.OrderInquiry.OrderInquiryId, orderInquiryData)
if err != nil {
tx.Rollback()
return false, errors.New("操作关联订单数据失败")
}
}
}
tx.Commit()
return true, nil
}
// 获取提现关联订单医生分成总金额
func (r *DoctorWithdrawalService) getDoctorWithdrawalOrderAmountTotal(withdrawalId int64) (float64, error) {
// 获取医生提现-关联订单数据
doctorWithdrawalOrderDao := dao.DoctorWithdrawalOrderDao{}
doctorWithdrawalOrders, err := doctorWithdrawalOrderDao.GetDoctorWithdrawalOrderByWithdrawalId(withdrawalId)
if err != nil {
return 0, errors.New("关联订单数据错误")
}
orderDao := dao.OrderDao{}
// 总金额
var amountTotal = decimal.NewFromFloat(0)
for _, v := range doctorWithdrawalOrders {
// 获取订单数据
order, err := orderDao.GetOrderPreloadById(v.OrderId)
if err != nil {
return 0, errors.New("订单数据错误")
}
if order.OrderInquiry != nil {
if order.OrderInquiry.InquiryStatus != 6 {
return 0, errors.New("存在未结束订单,数据错误")
}
}
if order.IsWithdrawal == 1 {
return 0, errors.New("存在已被提现订单,数据错误")
}
if order.PayStatus != 2 {
return 0, errors.New("存在支付状态错误订单,数据错误")
}
var orderAmountTotal = decimal.NewFromFloat(order.AmountTotal)
amountTotal = amountTotal.Add(orderAmountTotal)
}
// 分成比例
var prop = decimal.NewFromFloat(0.75)
// 计算分成
amountTotal = amountTotal.Mul(prop)
// 转为float64
result, _ := amountTotal.Float64()
return result, nil
}