From 5e5d25f1bd1aa853949bc6305b1eea38df8847d2 Mon Sep 17 00:00:00 2001 From: wucongxing <815046773@qq.com> Date: Wed, 1 Nov 2023 10:45:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=8F=90=E7=8E=B0=E5=AE=A1=E6=A0=B8=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/controller/doctorWithdrawal.go | 81 ++++++++++++ api/dao/doctorAccount.go | 90 +++++++++++++ api/dao/doctorWithdrawalOrder.go | 6 +- api/model/doctorAccount.go | 37 ++++++ api/requests/doctorWithdrawal.go | 13 ++ api/router/router.go | 4 +- api/service/doctorWithdrawa.go | 203 +++++++++++++++++++++++++++++ utils/compute.go | 35 +++++ 8 files changed, 464 insertions(+), 5 deletions(-) create mode 100644 api/dao/doctorAccount.go create mode 100644 api/model/doctorAccount.go create mode 100644 utils/compute.go diff --git a/api/controller/doctorWithdrawal.go b/api/controller/doctorWithdrawal.go index a882a89..9af00b4 100644 --- a/api/controller/doctorWithdrawal.go +++ b/api/controller/doctorWithdrawal.go @@ -122,3 +122,84 @@ func (r *DoctorWithdrawal) GetDoctorWithdrawalOrderPage(c *gin.Context) { result["data"] = res responses.OkWithData(result, c) } + +// PutDoctorWithdrawalIncome 修改提现个人所得税 +func (r *DoctorWithdrawal) PutDoctorWithdrawalIncome(c *gin.Context) { + doctorWithdrawalRequest := requests.DoctorWithdrawalRequest{} + req := doctorWithdrawalRequest.PutDoctorWithdrawalIncome + if err := c.ShouldBind(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 参数验证 + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + id := c.Param("withdrawal_id") + if id == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + // 将 id 转换为 int64 类型 + withdrawalId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + // 业务处理 + doctorWithdrawaService := service.DoctorWithdrawaService{} + _, err = doctorWithdrawaService.PutDoctorWithdrawalIncome(req, withdrawalId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.Ok(c) +} + +// PutDoctorWithdrawalExamine 修改提现审核状态 +func (r *DoctorWithdrawal) PutDoctorWithdrawalExamine(c *gin.Context) { + doctorWithdrawalRequest := requests.DoctorWithdrawalRequest{} + req := doctorWithdrawalRequest.PutDoctorWithdrawalExamine + if err := c.ShouldBind(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 参数验证 + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + id := c.Param("withdrawal_id") + if id == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + // 将 id 转换为 int64 类型 + withdrawalId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + // 后台用户id + adminUserId := c.GetInt64("UserId") + + // 业务处理 + doctorWithdrawaService := service.DoctorWithdrawaService{} + _, err = doctorWithdrawaService.PutDoctorWithdrawalExamine(req, withdrawalId, adminUserId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.Ok(c) +} diff --git a/api/dao/doctorAccount.go b/api/dao/doctorAccount.go new file mode 100644 index 0000000..36376b5 --- /dev/null +++ b/api/dao/doctorAccount.go @@ -0,0 +1,90 @@ +package dao + +import ( + "gorm.io/gorm" + "hospital-admin-api/api/model" + "hospital-admin-api/global" +) + +type DoctorAccountDao struct { +} + +// GetDoctorAccountById 获取医生账户数据-账户id +func (r *DoctorAccountDao) GetDoctorAccountById(accountId int64) (m *model.DoctorAccount, err error) { + err = global.Db.First(&m, accountId).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetDoctorAccountByDoctorId 获取医生账户数据-医生id +func (r *DoctorAccountDao) GetDoctorAccountByDoctorId(doctorId int64) (m *model.DoctorAccount, err error) { + err = global.Db.Where("doctor_id = ?", doctorId).First(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// DeleteDoctorAccount 删除医生账户 +func (r *DoctorAccountDao) DeleteDoctorAccount(tx *gorm.DB, maps interface{}) error { + err := tx.Where(maps).Delete(&model.DoctorAccount{}).Error + if err != nil { + return err + } + return nil +} + +// EditDoctorAccount 修改医生账户 +func (r *DoctorAccountDao) EditDoctorAccount(tx *gorm.DB, maps interface{}, data interface{}) error { + err := tx.Model(&model.DoctorAccount{}).Where(maps).Updates(data).Error + if err != nil { + return err + } + return nil +} + +// EditDoctorAccountById 修改医生账户-医生账户id +func (r *DoctorAccountDao) EditDoctorAccountById(tx *gorm.DB, accountId int64, data interface{}) error { + err := tx.Model(&model.DoctorAccount{}).Where("account_id = ?", accountId).Updates(data).Error + if err != nil { + return err + } + return nil +} + +// GetDoctorAccountList 获取医生账户列表 +func (r *DoctorAccountDao) GetDoctorAccountList(maps interface{}) (m []*model.DoctorAccount, err error) { + err = global.Db.Where(maps).Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// AddDoctorAccount 新增医生账户 +func (r *DoctorAccountDao) AddDoctorAccount(tx *gorm.DB, model *model.DoctorAccount) (*model.DoctorAccount, error) { + if err := tx.Create(model).Error; err != nil { + return nil, err + } + return model, nil +} + +// Dec 自减 +func (r *DoctorAccountDao) Dec(tx *gorm.DB, maps interface{}, numeral float64, field string) error { + err := tx.Model(&model.DoctorAccount{}).Where(maps).Update(field, gorm.Expr(field+" - ?", numeral)).Error + if err != nil { + return err + } + return nil +} + +// Inc 自增 +func (r *DoctorAccountDao) Inc(tx *gorm.DB, maps interface{}, numeral float64, field string) error { + err := tx.Model(&model.DoctorAccount{}).Where(maps).Update(field, gorm.Expr(field+" + ?", numeral)).Error + if err != nil { + return err + } + return nil +} diff --git a/api/dao/doctorWithdrawalOrder.go b/api/dao/doctorWithdrawalOrder.go index c706b2b..79f5ca0 100644 --- a/api/dao/doctorWithdrawalOrder.go +++ b/api/dao/doctorWithdrawalOrder.go @@ -11,7 +11,7 @@ type DoctorWithdrawalOrderDao struct { } // GetDoctorWithdrawalOrderById 获取医生提现关联订单数据-id -func (r *DoctorWithdrawalOrderDao) GetDoctorWithdrawalOrderById(withdrawalBankId int64) (m *model.DoctorWithdrawalBank, err error) { +func (r *DoctorWithdrawalOrderDao) GetDoctorWithdrawalOrderById(withdrawalBankId int64) (m *model.DoctorWithdrawalOrder, err error) { err = global.Db.First(&m, withdrawalBankId).Error if err != nil { return nil, err @@ -20,8 +20,8 @@ func (r *DoctorWithdrawalOrderDao) GetDoctorWithdrawalOrderById(withdrawalBankId } // GetDoctorWithdrawalOrderByWithdrawalId 获取医生提现关联订单数据-提现id -func (r *DoctorWithdrawalOrderDao) GetDoctorWithdrawalOrderByWithdrawalId(withdrawalId int64) (m *model.DoctorWithdrawalBank, err error) { - err = global.Db.Where("withdrawal_id = ?", withdrawalId).First(&m).Error +func (r *DoctorWithdrawalOrderDao) GetDoctorWithdrawalOrderByWithdrawalId(withdrawalId int64) (m []*model.DoctorWithdrawalOrder, err error) { + err = global.Db.Where("withdrawal_id = ?", withdrawalId).Find(&m).Error if err != nil { return nil, err } diff --git a/api/model/doctorAccount.go b/api/model/doctorAccount.go new file mode 100644 index 0000000..d1c8a83 --- /dev/null +++ b/api/model/doctorAccount.go @@ -0,0 +1,37 @@ +package model + +import ( + "gorm.io/gorm" + "hospital-admin-api/global" + "time" +) + +// DoctorAccount 医生账户总表-已结束订单 +type DoctorAccount struct { + AccountId int64 `gorm:"column:account_id;type:bigint(19);primary_key;comment:账户id" json:"account_id"` + DoctorId int64 `gorm:"column:doctor_id;type:bigint(19);comment:医生id" json:"doctor_id"` + TotalAmount float64 `gorm:"column:total_amount;type:decimal(18,8) unsigned;comment:总金额(已结束订单的总金额)" json:"total_amount"` + BalanceAccount float64 `gorm:"column:balance_account;type:decimal(18,8) unsigned;default:0.00000000;comment:账户余额" json:"balance_account"` + AppliedWithdrawalAmount float64 `gorm:"column:applied_withdrawal_amount;type:decimal(18,8) unsigned;default:0.00000000;comment:提现金额" json:"applied_withdrawal_amount"` + ActualWithdrawalAmount float64 `gorm:"column:actual_withdrawal_amount;type:decimal(18,8) unsigned;default:0.00000000;comment:实际提现金额" json:"actual_withdrawal_amount"` + IncomeTax float64 `gorm:"column:income_tax;type:decimal(18,8) unsigned;default:0.00000000;comment:所得税金额" json:"income_tax"` + Model +} + +func (m *DoctorAccount) TableName() string { + return "gdxz_doctor_account" +} + +func (m *DoctorAccount) BeforeCreate(tx *gorm.DB) error { + if m.AccountId == 0 { + m.AccountId = global.Snowflake.Generate().Int64() + } + + m.CreatedAt = LocalTime(time.Now()) + tx.Statement.SetColumn("CreatedAt", m.CreatedAt) + + m.UpdatedAt = LocalTime(time.Now()) + tx.Statement.SetColumn("UpdatedAt", m.UpdatedAt) + + return nil +} diff --git a/api/requests/doctorWithdrawal.go b/api/requests/doctorWithdrawal.go index 19d69a0..b273590 100644 --- a/api/requests/doctorWithdrawal.go +++ b/api/requests/doctorWithdrawal.go @@ -3,6 +3,8 @@ package requests type DoctorWithdrawalRequest struct { GetDoctorWithdrawalPage // 获取医生提现列表-分页 GetDoctorWithdrawalOrderPage // 提现详情-关联订单列表-分页 + PutDoctorWithdrawalIncome // 修改提现个人所得税 + PutDoctorWithdrawalExamine // 修改提现审核状态 } // GetDoctorWithdrawalPage 获取医生提现列表-分页 @@ -22,3 +24,14 @@ type GetDoctorWithdrawalOrderPage struct { Page int `json:"page" form:"page" label:"页码"` PageSize int `json:"page_size" form:"page_size" label:"每页个数"` } + +// PutDoctorWithdrawalIncome 修改提现个人所得税 +type PutDoctorWithdrawalIncome struct { + IncomeTax float64 `json:"income_tax" form:"income_tax" validate:"required" label:"个人所得税金额"` +} + +// PutDoctorWithdrawalExamine 修改提现审核状态 +type PutDoctorWithdrawalExamine struct { + ExamineStatus int `json:"examine_status" form:"examine_status" validate:"required,oneof=2 3" label:"审核状态"` // (1:审核中 2:审核通过 3:审核未通过) + ExamineFailReason string `json:"examine_fail_reason" form:"examine_fail_reason" label:"审核失败原因"` +} diff --git a/api/router/router.go b/api/router/router.go index 7e1fb16..9cf91c9 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -521,10 +521,10 @@ func privateRouter(r *gin.Engine, api controller.Api) { withdrawalGroup.GET("/order/:withdrawal_id", api.DoctorWithdrawal.GetDoctorWithdrawalOrderPage) // 修改提现个人所得税 - withdrawalGroup.PUT("/income/:withdrawal_id", api.OrderPrescription.GetOrderPrescriptionPage) + withdrawalGroup.PUT("/income/:withdrawal_id", api.DoctorWithdrawal.PutDoctorWithdrawalIncome) // 修改提现审核状态 - withdrawalGroup.PUT("/examine/:withdrawal_id", api.OrderPrescription.GetOrderPrescriptionPage) + withdrawalGroup.PUT("/examine/:withdrawal_id", api.DoctorWithdrawal.PutDoctorWithdrawalExamine) // 修改打款审核状态 withdrawalGroup.PUT("/payment/:withdrawal_id", api.OrderPrescription.GetOrderPrescriptionPage) diff --git a/api/service/doctorWithdrawa.go b/api/service/doctorWithdrawa.go index ab7634b..5760e97 100644 --- a/api/service/doctorWithdrawa.go +++ b/api/service/doctorWithdrawa.go @@ -4,6 +4,11 @@ import ( "errors" "hospital-admin-api/api/dao" "hospital-admin-api/api/dto" + "hospital-admin-api/api/requests" + "hospital-admin-api/global" + "hospital-admin-api/utils" + "math" + "time" ) type DoctorWithdrawaService struct { @@ -68,3 +73,201 @@ func (r *DoctorWithdrawaService) GetDoctorWithdrawal(withdrawalId int64) (g *dto return g, nil } + +// PutDoctorWithdrawalIncome 修改提现个人所得税 +func (r *DoctorWithdrawaService) 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() + } + }() + + // 计算实际提现金额 + actualWithdrawalAmount := math.Floor((doctorWithdrawal.AppliedWithdrawalAmount-req.IncomeTax)*0.75*100) / 100 + + // 提现申请修改数据-提现金额固定不动,修改个人所得税,实际提现金额跟随变动 + doctorWithdrawalData := make(map[string]interface{}) + doctorWithdrawalData["income_tax"] = req.IncomeTax // 提现所得税金额 + doctorWithdrawalData["actual_withdrawal_amount"] = actualWithdrawalAmount // 实际提现金额 + 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 *DoctorWithdrawaService) 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()) + } + + // 返还医生账户金额 + if req.ExamineStatus == 3 { + // 获取医生账户数据 + 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 := math.Floor((amountTotal-incomeTax)*0.75*100) / 100 + + incomeTax = math.Floor(incomeTax*100) / 100 + + // 账户余额-增加 + 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, withdrawalAmount, "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, incomeTax, "income_tax") + if err != nil { + tx.Rollback() + return false, err + } + } + + tx.Commit() + return true, nil +} + +// 获取提现关联订单医生分成总金额 +func (r *DoctorWithdrawaService) getDoctorWithdrawalOrderAmountTotal(withdrawalId int64) (float64, error) { + // 获取医生提现-关联订单数据 + doctorWithdrawalOrderDao := dao.DoctorWithdrawalOrderDao{} + doctorWithdrawalOrders, err := doctorWithdrawalOrderDao.GetDoctorWithdrawalOrderByWithdrawalId(withdrawalId) + if err != nil { + return 0, errors.New("关联订单数据错误") + } + + // 总金额 + var amountTotal float64 + for _, v := range doctorWithdrawalOrders { + // 获取订单数据 + orderInquiryDao := dao.OrderInquiryDao{} + orderInquiry, err := orderInquiryDao.GetOrderInquiryById(v.OrderInquiryId) + if err != nil { + return 0, errors.New("订单数据错误") + } + + if orderInquiry.InquiryStatus != 6 { + return 0, errors.New("存在未结束订单,数据错误") + } + + if orderInquiry.IsWithdrawal != 0 { + return 0, errors.New("存在已被提现订单,数据错误") + } + + if orderInquiry.InquiryPayStatus != 2 { + return 0, errors.New("存在支付状态错误订单,数据错误") + } + + amountTotal = amountTotal + orderInquiry.AmountTotal + } + + // 医生分成金额 + if amountTotal > 0 { + amountTotal = math.Floor(amountTotal*0.75*100) / 100 + } + + return amountTotal, nil +} diff --git a/utils/compute.go b/utils/compute.go new file mode 100644 index 0000000..e85894b --- /dev/null +++ b/utils/compute.go @@ -0,0 +1,35 @@ +package utils + +// 一些计算 + +// ComputeIndividualIncomeTax 计算个人所得税 +func ComputeIndividualIncomeTax(income float64) float64 { + if income <= 800 { + return 0 + } + + if income <= 4000 { + income = income - 800 + } + + // 实际纳税金额 + income = income * 0.8 + + // 税率、速算扣除数 + var taxRate, quickDeduction float64 + + if income <= 20000 { + taxRate = 0.2 + quickDeduction = 0 + } else if income <= 50000 { + taxRate = 0.3 + quickDeduction = 2000 + } else { + taxRate = 0.4 + quickDeduction = 7000 + } + + incomeTax := income*taxRate - quickDeduction + + return incomeTax +}