diff --git a/api/controller/doctorAccount.go b/api/controller/doctorAccount.go index fc8a1cb..b96d5b6 100644 --- a/api/controller/doctorAccount.go +++ b/api/controller/doctorAccount.go @@ -3,6 +3,7 @@ package controller import ( "github.com/gin-gonic/gin" "hospital-admin-api/api/dao" + "hospital-admin-api/api/dto" "hospital-admin-api/api/requests" "hospital-admin-api/api/responses" "hospital-admin-api/api/service" @@ -37,19 +38,31 @@ func (r *DoctorAccount) GetDoctorAccountPage(c *gin.Context) { } doctorAccountDao := dao.DoctorAccountDao{} - doctorAccount, total, err := doctorAccountDao.GetDoctorAccountPage(req, req.Page, req.PageSize) + doctorAccounts, total, err := doctorAccountDao.GetDoctorAccountPage(req, req.Page, req.PageSize) if err != nil { responses.FailWithMessage(err.Error(), c) return } - // 业务处理 - doctorAccountService := service.DoctorAccountService{} - res, err := doctorAccountService.GetDoctorAccountPage(doctorAccount) - if err != nil { - responses.FailWithMessage(err.Error(), c) - return + // 处理返回值 + res := dto.GetDoctorAccountListDto(doctorAccounts) + + for _, v := range res { + // 将 id 转换为 int64 类型 + doctorId, err := strconv.ParseInt(v.DoctorId, 10, 64) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + userDoctorService := service.UserDoctorService{} + + // 获取医生已完成待入账金额 + v.CompletedWaitEntryAmount, _ = userDoctorService.GetDoctorCompletedWaitEntryAmount(doctorId) + + // 获取医生今日预计收入 + v.EstimateIncome, _ = userDoctorService.GetDoctorEstimateIncome(doctorId) } result := make(map[string]interface{}) diff --git a/api/controller/export.go b/api/controller/export.go index ef7e8f2..388b8df 100644 --- a/api/controller/export.go +++ b/api/controller/export.go @@ -151,3 +151,37 @@ func (r *Export) UserDoctorBankCard(c *gin.Context) { responses.OkWithData(ossAddress, c) } + +// DoctorAccount 医生账户 +func (r *Export) DoctorAccount(c *gin.Context) { + doctorAccountRequest := requests.DoctorAccountRequest{} + req := doctorAccountRequest.DoctorAccountExportList + 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 + } + + // 获取数据 + doctorAccountDao := dao.DoctorAccountDao{} + doctorAccounts, err := doctorAccountDao.GetDoctorAccountExportListSearch(req) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 业务处理 + exportService := service.ExportService{} + ossAddress, err := exportService.DoctorAccount(doctorAccounts) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.OkWithData(ossAddress, c) +} diff --git a/api/dao/doctorAccount.go b/api/dao/doctorAccount.go index 5d4ede6..a7f35c4 100644 --- a/api/dao/doctorAccount.go +++ b/api/dao/doctorAccount.go @@ -1,10 +1,12 @@ package dao import ( + "errors" "gorm.io/gorm" "hospital-admin-api/api/model" "hospital-admin-api/api/requests" "hospital-admin-api/global" + "strings" ) type DoctorAccountDao struct { @@ -90,7 +92,7 @@ func (r *DoctorAccountDao) Inc(tx *gorm.DB, maps interface{}, numeral float64, f return nil } -// GetDoctorAccountPage 获取医生列表-分页 +// GetDoctorAccountPage 获取医生账户列表-分页 func (r *DoctorAccountDao) GetDoctorAccountPage(req requests.GetDoctorAccountPage, page, pageSize int) (m []*model.DoctorAccount, total int64, err error) { var totalRecords int64 @@ -144,3 +146,64 @@ func (r *DoctorAccountDao) GetDoctorAccountPage(req requests.GetDoctorAccountPag } return m, totalRecords, nil } + +// GetDoctorAccountExportListSearch 医生账户-导出 +func (r *DoctorAccountDao) GetDoctorAccountExportListSearch(req requests.DoctorAccountExportList) (m []*model.DoctorAccount, err error) { + // 构建查询条件 + query := global.Db.Model(&model.DoctorAccount{}) + + // 医生 + query = query.Preload("UserDoctor", func(db *gorm.DB) *gorm.DB { + return db.Omit("open_id", "union_id", "wx_session_key") + }) + + // 用户 + query = query.Preload("UserDoctor.User", func(db *gorm.DB) *gorm.DB { + return db.Omit("user_password", "salt") + }) + + // 当前搜索数据 + if req.Type == 1 { + // 手机号 + if req.Mobile != "" { + // 医生 + doctorUserSubQuery := global.Db.Model(&model.User{}). + Select("user_id"). + Where("mobile = ?", req.Mobile) + + doctorSubQuery := global.Db.Model(&model.UserDoctor{}). + Select("doctor_id"). + Where(gorm.Expr("user_id IN (?)", doctorUserSubQuery)) + + query = query.Where("doctor_id IN (?)", doctorSubQuery) + } + + // 用户名称 + if req.UserName != "" { + subQuery := global.Db.Model(&model.UserDoctor{}). + Select("doctor_id"). + Where("user_name LIKE ?", "%"+req.UserName+"%") + + query = query.Where(gorm.Expr("doctor_id IN (?)", subQuery)) + } + } + + // 当前选择数据 + if req.Type == 2 { + if req.Id == "" { + return nil, errors.New("未提供需导出数据编号") + } + + id := strings.Split(req.Id, ",") + query = query.Where("account_id IN (?)", id) + } + + // 排序 + query = query.Order("created_at desc") + + err = query.Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} diff --git a/api/requests/doctorAccount.go b/api/requests/doctorAccount.go index 2930a61..3797e4f 100644 --- a/api/requests/doctorAccount.go +++ b/api/requests/doctorAccount.go @@ -1,7 +1,8 @@ package requests type DoctorAccountRequest struct { - GetDoctorAccountPage // 获取医生账户列表-分页 + GetDoctorAccountPage // 获取医生账户列表-分页 + DoctorAccountExportList // 医生账户 } // GetDoctorAccountPage 获取医生账户列表-分页 @@ -11,3 +12,11 @@ type GetDoctorAccountPage struct { Mobile string `json:"mobile" form:"mobile" label:"手机号"` UserName string `json:"user_name" form:"user_name" label:"用户名"` } + +// DoctorAccountExportList 医生账户 +type DoctorAccountExportList struct { + Type int `json:"type" form:"type" label:"类型" validate:"required,oneof=1 2 3"` // 1:当前搜索数据 2:当前选择数据 3:全部数据 + Id string `json:"id" form:"id" label:"id"` // 选择数据的id,逗号分隔,当type为2时必填 + Mobile string `json:"mobile" form:"mobile" label:"手机号"` + UserName string `json:"user_name" form:"user_name" label:"用户名"` +} diff --git a/api/router/router.go b/api/router/router.go index 1685883..bf1138f 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -615,7 +615,7 @@ func privateRouter(r *gin.Engine, api controller.Api) { doctorGroup.POST("/bank/card", api.Export.UserDoctorBankCard) // 医生账户 - doctorGroup.POST("/account", api.UserCaCert.RenewUserCloudCert) + doctorGroup.POST("/account", api.Export.DoctorAccount) // 医生账户-关联订单 doctorGroup.POST("/account/order", api.UserCaCert.RenewUserCloudCert) diff --git a/api/service/DoctorAccount.go b/api/service/DoctorAccount.go index da3b34f..09e94f7 100644 --- a/api/service/DoctorAccount.go +++ b/api/service/DoctorAccount.go @@ -4,7 +4,6 @@ import ( "errors" "hospital-admin-api/api/dao" "hospital-admin-api/api/dto" - "hospital-admin-api/api/model" "math" "time" ) @@ -105,72 +104,3 @@ func (r *DoctorAccountService) GetDoctorAccount(doctorId int64) (g *dto.DoctorAc return g, nil } - -// GetDoctorAccountPage 获取医生账户列表-分页 -func (r *DoctorAccountService) GetDoctorAccountPage(doctorAccounts []*model.DoctorAccount) (g []*dto.DoctorAccountDto, err error) { - // 处理返回值 - res := dto.GetDoctorAccountListDto(doctorAccounts) - - // 已完成待入账金额 - var completedWaitEntryAmount float64 - - // 今日预计收入 - var estimateIncome float64 - - for _, v := range res { - // 获取医生全部已完成订单 - orderInquiryDao := dao.OrderInquiryDao{} - - maps := make(map[string]interface{}) - maps["doctor_id"] = v.DoctorId - maps["inquiry_status"] = 5 // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) - maps["inquiry_refund_status"] = 0 // 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常) - maps["inquiry_pay_status"] = 2 // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) - maps["is_withdrawal"] = 0 // 是否提现(0:否 1:是 2:提现中) - orderInquirys, err := orderInquiryDao.GetOrderInquiryList(maps) - if err != nil { - return nil, err - } - - if len(orderInquirys) > 0 { - for _, inquiry := range orderInquirys { - completedWaitEntryAmount = math.Floor((completedWaitEntryAmount+inquiry.AmountTotal)*0.75*100) / 100 - } - } - - // 获取医生当日接诊订单金额 - today := time.Now() - - // 获取今天的开始时间 - startOfDay := time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, today.Location()) - - // 获取今天的结束时间 - endOfDay := time.Date(today.Year(), today.Month(), today.Day(), 23, 59, 59, 999999999, today.Location()) - - // 格式化为数据库的 datetime 格式 - startTime := startOfDay.Format("2006-01-02 15:04:05") - endTime := endOfDay.Format("2006-01-02 15:04:05") - - maps = make(map[string]interface{}) - maps["doctor_id"] = v.DoctorId - maps["inquiry_refund_status"] = 0 // 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭) - maps["inquiry_pay_status"] = 2 // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) - maps["is_withdrawal"] = 0 // 是否提现(0:否 1:是 2:提现中) - maps["inquiry_status"] = []int{4, 5} // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) - orderInquirys, err = orderInquiryDao.GetOrderInquiryTimeList(maps, startTime, endTime) - if err != nil { - return nil, err - } - - if len(orderInquirys) > 0 { - for _, inquiry := range orderInquirys { - estimateIncome = math.Floor((estimateIncome+inquiry.AmountTotal)*0.75*100) / 100 - } - } - - v.CompletedWaitEntryAmount = completedWaitEntryAmount - v.EstimateIncome = estimateIncome - } - - return res, err -} diff --git a/api/service/export.go b/api/service/export.go index e112140..2410271 100644 --- a/api/service/export.go +++ b/api/service/export.go @@ -111,6 +111,7 @@ type UserDoctorData struct { BankCardAddress string // 开户银行地址 } +// DoctorBankCardData 医生银行卡列表 type DoctorBankCardData struct { DoctorName string // 医生姓名 DoctorMobile string // 医生手机号 @@ -122,6 +123,19 @@ type DoctorBankCardData struct { CreatedAt time.Time // 创建时间 } +// DoctorAccountData 医生账户 +type DoctorAccountData struct { + DoctorName string // 医生姓名 + DoctorMobile string // 医生手机号 + TotalAmount float64 // 总金额(已结束订单的总金额) + BalanceAccount float64 // 账户余额 + AppliedWithdrawalAmount float64 // 提现金额 + IncomeTax float64 // 个人所得税 + ActualWithdrawalAmount float64 // 实际提现金额 + CompletedWaitEntryAmount float64 // 已完成待入账金额 + EstimateIncome float64 // 今日预计收入 +} + // DoctorWithdrawal 提现记录 func (r *ExportService) DoctorWithdrawal(doctorWithdrawals []*model.DoctorWithdrawal) (string, error) { header := []utils.HeaderCellData{ @@ -759,3 +773,69 @@ func (r *ExportService) UserDoctorBankCard(d []*model.DoctorBankCard) (string, e ossPath = utils.AddOssDomain("/" + ossPath) return ossPath, nil } + +// DoctorAccount 医生账户 +func (r *ExportService) DoctorAccount(d []*model.DoctorAccount) (string, error) { + header := []utils.HeaderCellData{ + {Value: "医生姓名", CellType: "string", NumberFmt: "", ColWidth: 18}, + {Value: "医生手机号", CellType: "string", NumberFmt: "", ColWidth: 18}, + {Value: "总金额", CellType: "float64", NumberFmt: "0.0000", ColWidth: 18}, + {Value: "账户余额", CellType: "float64", NumberFmt: "0.0000", ColWidth: 18}, + {Value: "提现金额", CellType: "float64", NumberFmt: "0.0000", ColWidth: 18}, + {Value: "个人所得税", CellType: "float64", NumberFmt: "0.0000", ColWidth: 18}, + {Value: "实际提现金额", CellType: "float64", NumberFmt: "0.0000", ColWidth: 18}, + {Value: "已完成待入账金额", CellType: "float64", NumberFmt: "0.0000", ColWidth: 22}, + {Value: "今日预计收入", CellType: "float64", NumberFmt: "0.0000", ColWidth: 18}, + } + + var dataSlice []interface{} + for _, v := range d { + data := DoctorAccountData{ + TotalAmount: v.TotalAmount, + BalanceAccount: v.BalanceAccount, + AppliedWithdrawalAmount: v.AppliedWithdrawalAmount, + ActualWithdrawalAmount: v.ActualWithdrawalAmount, + IncomeTax: v.IncomeTax, + } + + if v.UserDoctor != nil { + // 医生姓名 + data.DoctorName = v.UserDoctor.UserName + + if v.UserDoctor.User != nil { + // 手机号 + data.DoctorMobile = v.UserDoctor.User.Mobile + } + } + + userDoctorService := UserDoctorService{} + + // 获取医生已完成待入账金额 + data.CompletedWaitEntryAmount, _ = userDoctorService.GetDoctorCompletedWaitEntryAmount(v.DoctorId) + + // 获取医生今日预计收入 + data.EstimateIncome, _ = userDoctorService.GetDoctorEstimateIncome(v.DoctorId) + + dataSlice = append(dataSlice, data) + } + + file, err := utils.Export(header, dataSlice) + if err != nil { + return "", err + } + + // 设置文件名字 + now := time.Now() + dateTimeString := now.Format("20060102150405") // 当前时间字符串 + rand.Seed(time.Now().UnixNano()) // 设置随机数 + ossPath := "admin/export/output" + dateTimeString + fmt.Sprintf("%d", rand.Intn(9000)+1000) + ".xlsx" + + // 上传oss + _, err = aliyun.PutObjectByte(ossPath, file.Bytes()) + if err != nil { + return "", err + } + + ossPath = utils.AddOssDomain("/" + ossPath) + return ossPath, nil +} diff --git a/api/service/userDoctor.go b/api/service/userDoctor.go index 0238333..eff8fe7 100644 --- a/api/service/userDoctor.go +++ b/api/service/userDoctor.go @@ -3,6 +3,7 @@ package service import ( "errors" "fmt" + "github.com/shopspring/decimal" "hospital-admin-api/api/dao" "hospital-admin-api/api/dto" "hospital-admin-api/api/model" @@ -1524,3 +1525,77 @@ func (r *UserDoctorService) GetUserDoctorById(doctorId int64) (g *dto.UserDoctor return g, nil } + +// GetDoctorCompletedWaitEntryAmount 获取医生已完成待入账金额 +func (r *UserDoctorService) GetDoctorCompletedWaitEntryAmount(doctorId int64) (g float64, err error) { + // 已完成待入账金额 + var completedWaitEntryAmount = decimal.NewFromFloat(0) + + // 获取医生全部已完成订单 + orderInquiryDao := dao.OrderInquiryDao{} + + maps := make(map[string]interface{}) + maps["doctor_id"] = doctorId + maps["inquiry_status"] = 5 // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + maps["inquiry_refund_status"] = 0 // 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常) + maps["inquiry_pay_status"] = 2 // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) + maps["is_withdrawal"] = 0 // 是否提现(0:否 1:是 2:提现中) + orderInquirys, err := orderInquiryDao.GetOrderInquiryList(maps) + if err != nil { + return 0, err + } + + if len(orderInquirys) > 0 { + for _, inquiry := range orderInquirys { + // 等同于math.Floor((completedWaitEntryAmount+inquiry.AmountTotal)*0.75*100) / 100 + amountTotal := decimal.NewFromFloat(inquiry.AmountTotal) + completedWaitEntryAmount = completedWaitEntryAmount.Add(amountTotal).Mul(decimal.NewFromFloat(0.75)).Mul(decimal.NewFromFloat(100)).Floor().Div(decimal.NewFromFloat(100)) + } + } + + result, _ := completedWaitEntryAmount.Float64() + return result, nil +} + +// GetDoctorEstimateIncome 获取医生今日预计收入 +func (r *UserDoctorService) GetDoctorEstimateIncome(doctorId int64) (g float64, err error) { + // 今日预计收入 + var estimateIncome = decimal.NewFromFloat(0) + + // 获取医生当日接诊订单金额 + today := time.Now() + + // 获取今天的开始时间 + startOfDay := time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, today.Location()) + + // 获取今天的结束时间 + endOfDay := time.Date(today.Year(), today.Month(), today.Day(), 23, 59, 59, 999999999, today.Location()) + + // 格式化为数据库的 datetime 格式 + startTime := startOfDay.Format("2006-01-02 15:04:05") + endTime := endOfDay.Format("2006-01-02 15:04:05") + + orderInquiryDao := dao.OrderInquiryDao{} + + maps := make(map[string]interface{}) + maps["doctor_id"] = doctorId + maps["inquiry_refund_status"] = 0 // 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭) + maps["inquiry_pay_status"] = 2 // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) + maps["is_withdrawal"] = 0 // 是否提现(0:否 1:是 2:提现中) + maps["inquiry_status"] = []int{4, 5} // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) + orderInquirys, err := orderInquiryDao.GetOrderInquiryTimeList(maps, startTime, endTime) + if err != nil { + return 0, err + } + + if len(orderInquirys) > 0 { + for _, inquiry := range orderInquirys { + // 等同于math.Floor((estimateIncome+inquiry.AmountTotal)*0.75*100) / 100 + amountTotal := decimal.NewFromFloat(inquiry.AmountTotal) + estimateIncome = estimateIncome.Add(amountTotal).Mul(decimal.NewFromFloat(0.75)).Mul(decimal.NewFromFloat(100)).Floor().Div(decimal.NewFromFloat(100)) + } + } + + result, _ := estimateIncome.Float64() + return result, nil +} diff --git a/output.xlsx b/output.xlsx index 753c93d..9ddeeba 100755 Binary files a/output.xlsx and b/output.xlsx differ diff --git a/utils/export.go b/utils/export.go index 4d60000..a726458 100644 --- a/utils/export.go +++ b/utils/export.go @@ -290,7 +290,7 @@ func Export(header []HeaderCellData, data []interface{}) (*bytes.Buffer, error) return buffer, nil - // // 保存文件 + // 保存文件 // if err := f.SaveAs("output.xlsx"); err != nil { // return nil, err // }