From 943ee17b2a3fa743c1bcee9f4932f79b7bfe0cd9 Mon Sep 17 00:00:00 2001 From: haomingming Date: Mon, 7 Sep 2026 10:37:01 +0800 Subject: [PATCH 01/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8D=AF=E6=88=BF?= =?UTF-8?q?=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/controller/base.go | 1 + api/controller/pharmacy.go | 234 +++++++++++++++++++++++++++++++++ api/dao/pharmacy.go | 111 ++++++++++++++++ api/dto/Pharmacy.go | 62 +++++++++ api/model/pharmacy.go | 45 +++++++ api/requests/pharmacy.go | 65 +++++++++ api/router/router.go | 32 +++++ api/service/pharmacy.go | 261 +++++++++++++++++++++++++++++++++++++ 8 files changed, 811 insertions(+) create mode 100644 api/controller/pharmacy.go create mode 100644 api/dao/pharmacy.go create mode 100644 api/dto/Pharmacy.go create mode 100644 api/model/pharmacy.go create mode 100644 api/requests/pharmacy.go create mode 100644 api/service/pharmacy.go diff --git a/api/controller/base.go b/api/controller/base.go index 3dbea4e..1c35f58 100644 --- a/api/controller/base.go +++ b/api/controller/base.go @@ -41,6 +41,7 @@ type userDoctorManage struct { type basic struct { Department // 科室管理 Hospital // 医院管理 + Pharmacy // 药房管理 DiseaseClassExpertise // 专长管理 Bank // 银行管理 } diff --git a/api/controller/pharmacy.go b/api/controller/pharmacy.go new file mode 100644 index 0000000..302e64d --- /dev/null +++ b/api/controller/pharmacy.go @@ -0,0 +1,234 @@ +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" + "hospital-admin-api/global" + "hospital-admin-api/utils" + "strconv" +) + +type Pharmacy struct{} + +// GetPharmacyPage 获取药房列表-分页 +func (r *Pharmacy) GetPharmacyPage(c *gin.Context) { + pharmacyRequest := requests.PharmacyRequest{} + req := pharmacyRequest.GetPharmacyPage + if err := c.ShouldBindJSON(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + if req.Page <= 0 { + req.Page = 1 + } + + if req.PageSize <= 0 { + req.PageSize = 20 + } + + pharmacyDao := dao.PharmacyDao{} + pharmacies, total, err := pharmacyDao.GetPharmacyPageSearch(req, req.Page, req.PageSize) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + resList := dto.GetPharmacyListDto(pharmacies) + + result := make(map[string]interface{}) + result["page"] = req.Page + result["page_size"] = req.PageSize + result["total"] = total + result["data"] = resList + responses.OkWithData(result, c) +} + +// GetPharmacyList 获取药房列表(下拉/限制条件) +func (r *Pharmacy) GetPharmacyList(c *gin.Context) { + pharmacyRequest := requests.PharmacyRequest{} + req := pharmacyRequest.GetPharmacyList + if err := c.ShouldBind(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + maps := make(map[string]interface{}) + if req.PharmacyName != "" { + maps["pharmacy_name"] = req.PharmacyName + } + if req.PharmacyCode != "" { + maps["pharmacy_code"] = req.PharmacyCode + } + if req.Status != nil { + maps["status"] = *req.Status + } else { + maps["status"] = 1 // 默认只查正常启用的 + } + if req.IsPickup != nil { + maps["is_pickup"] = *req.IsPickup + } + + pharmacyDao := dao.PharmacyDao{} + pharmacies, err := pharmacyDao.GetPharmacyList(maps) + if err != nil { + responses.Ok(c) + return + } + + resList := dto.GetPharmacyListDto(pharmacies) + responses.OkWithData(resList, c) +} + +// GetPharmacy 获取药房详情 +func (r *Pharmacy) GetPharmacy(c *gin.Context) { + id := c.Param("pharmacy_id") + if id == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + pharmacyId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + pharmacyService := service.PharmacyService{} + pharmacyDto, err := pharmacyService.GetPharmacy(pharmacyId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.OkWithData(pharmacyDto, c) +} + +// AddPharmacy 新增药房 +func (r *Pharmacy) AddPharmacy(c *gin.Context) { + pharmacyRequest := requests.PharmacyRequest{} + req := pharmacyRequest.AddPharmacy + if err := c.ShouldBindJSON(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + pharmacyService := service.PharmacyService{} + _, err := pharmacyService.AddPharmacy(req) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.Ok(c) +} + +// PutPharmacy 修改药房 +func (r *Pharmacy) PutPharmacy(c *gin.Context) { + pharmacyRequest := requests.PharmacyRequest{} + req := pharmacyRequest.PutPharmacy + if err := c.ShouldBindJSON(&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("pharmacy_id") + if id == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + pharmacyId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + pharmacyService := service.PharmacyService{} + _, err = pharmacyService.PutPharmacy(pharmacyId, req) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.Ok(c) +} + +// PutPharmacyStatus 修改药房状态 +func (r *Pharmacy) PutPharmacyStatus(c *gin.Context) { + pharmacyRequest := requests.PharmacyRequest{} + req := pharmacyRequest.PutPharmacyStatus + if err := c.ShouldBindJSON(&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("pharmacy_id") + if id == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + pharmacyId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + pharmacyService := service.PharmacyService{} + _, err = pharmacyService.PutPharmacyStatus(pharmacyId, req) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.Ok(c) +} + +// DeletePharmacy 删除药房 +func (r *Pharmacy) DeletePharmacy(c *gin.Context) { + id := c.Param("pharmacy_id") + if id == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + pharmacyId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + pharmacyService := service.PharmacyService{} + _, err = pharmacyService.DeletePharmacy(pharmacyId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.Ok(c) +} diff --git a/api/dao/pharmacy.go b/api/dao/pharmacy.go new file mode 100644 index 0000000..2d0d2ac --- /dev/null +++ b/api/dao/pharmacy.go @@ -0,0 +1,111 @@ +package dao + +import ( + "gorm.io/gorm" + "hospital-admin-api/api/model" + "hospital-admin-api/api/requests" + "hospital-admin-api/global" +) + +type PharmacyDao struct{} + +// GetPharmacyById 获取药房数据-药房id +func (r *PharmacyDao) GetPharmacyById(pharmacyId int64) (m *model.Pharmacy, err error) { + err = global.Db.Where("pharmacy_id = ? AND status != ?", pharmacyId, 2).First(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetPharmacyByCode 获取药房数据-药房代码 +func (r *PharmacyDao) GetPharmacyByCode(code string) (m *model.Pharmacy, err error) { + err = global.Db.Where("pharmacy_code = ? AND status != ?", code, 2).First(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// AddPharmacy 新增药房 +func (r *PharmacyDao) AddPharmacy(tx *gorm.DB, m *model.Pharmacy) (*model.Pharmacy, error) { + if err := tx.Create(m).Error; err != nil { + return nil, err + } + return m, nil +} + +// EditPharmacyById 修改药房-药房id +func (r *PharmacyDao) EditPharmacyById(tx *gorm.DB, pharmacyId int64, data interface{}) error { + err := tx.Model(&model.Pharmacy{}).Where("pharmacy_id = ?", pharmacyId).Updates(data).Error + if err != nil { + return err + } + return nil +} + +// DeletePharmacyById 软删除药房-药房id +func (r *PharmacyDao) DeletePharmacyById(tx *gorm.DB, pharmacyId int64) error { + err := tx.Model(&model.Pharmacy{}).Where("pharmacy_id = ?", pharmacyId).Update("status", 2).Error + if err != nil { + return err + } + return nil +} + +// GetPharmacyList 获取药房列表 +func (r *PharmacyDao) GetPharmacyList(maps interface{}) (m []*model.Pharmacy, err error) { + err = global.Db.Where(maps).Where("status != ?", 2).Order("created_at desc").Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetPharmacyPageSearch 获取药房列表-分页 +func (r *PharmacyDao) GetPharmacyPageSearch(req requests.GetPharmacyPage, page, pageSize int) (m []*model.Pharmacy, total int64, err error) { + var totalRecords int64 + + query := global.Db.Model(&model.Pharmacy{}).Where("status != ?", 2) + + if req.PharmacyName != "" { + query = query.Where("pharmacy_name LIKE ?", "%"+req.PharmacyName+"%") + } + + if req.PharmacyCode != "" { + query = query.Where("pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") + } + + if req.Status != nil { + query = query.Where("status = ?", *req.Status) + } + + if req.IsPickup != nil { + query = query.Where("is_pickup = ?", *req.IsPickup) + } + + if req.ProvinceId != 0 { + query = query.Where("province_id = ?", req.ProvinceId) + } + + if req.CityId != nil { + query = query.Where("city_id = ?", req.CityId) + } + + if req.CountyId != nil { + query = query.Where("county_id = ?", req.CountyId) + } + + query = query.Order("created_at desc") + + if err := query.Count(&totalRecords).Error; err != nil { + return nil, 0, err + } + + err = query.Scopes(model.Paginate(page, pageSize)).Find(&m).Error + if err != nil { + return nil, 0, err + } + + return m, totalRecords, nil +} diff --git a/api/dto/Pharmacy.go b/api/dto/Pharmacy.go new file mode 100644 index 0000000..175e6a4 --- /dev/null +++ b/api/dto/Pharmacy.go @@ -0,0 +1,62 @@ +package dto + +import ( + "fmt" + "hospital-admin-api/api/model" +) + +type PharmacyDto struct { + PharmacyId string `json:"pharmacy_id"` // 主键id + PharmacyName string `json:"pharmacy_name"` // 药房名称 + PharmacyCode string `json:"pharmacy_code"` // 药房代码 + Postage float64 `json:"postage"` // 基础邮费 + FreeShippingThreshold float64 `json:"free_shipping_threshold"` // 满XX包邮门槛金额 + IsPickup int `json:"is_pickup"` // 是否支持自提(0:否 1:是) + Telephone string `json:"telephone"` // 电话 + ProvinceId int `json:"province_id"` // 省份id + Province string `json:"province"` // 省份 + CityId int `json:"city_id"` // 城市id + City string `json:"city"` // 城市 + CountyId int `json:"county_id"` // 区县id + County string `json:"county"` // 区县 + Address string `json:"address"` // 详细地址 + FullAddress string `json:"full_address"` // 完整地址(省市区+详细地址) + Status int `json:"status"` // 状态(0:禁用 1:正常 2:删除) + CreatedAt model.LocalTime `json:"created_at"` // 创建时间 + UpdatedAt model.LocalTime `json:"updated_at"` // 修改时间 +} + +func GetPharmacyDto(m *model.Pharmacy) *PharmacyDto { + if m == nil { + return nil + } + fullAddress := fmt.Sprintf("%s%s%s%s", m.Province, m.City, m.County, m.Address) + return &PharmacyDto{ + PharmacyId: fmt.Sprintf("%d", m.PharmacyId), + PharmacyName: m.PharmacyName, + PharmacyCode: m.PharmacyCode, + Postage: m.Postage, + FreeShippingThreshold: m.FreeShippingThreshold, + IsPickup: m.IsPickup, + Telephone: m.Telephone, + ProvinceId: m.ProvinceId, + Province: m.Province, + CityId: m.CityId, + City: m.City, + CountyId: m.CountyId, + County: m.County, + Address: m.Address, + FullAddress: fullAddress, + Status: m.Status, + CreatedAt: m.CreatedAt, + UpdatedAt: m.UpdatedAt, + } +} + +func GetPharmacyListDto(m []*model.Pharmacy) []PharmacyDto { + responses := make([]PharmacyDto, len(m)) + for i, v := range m { + responses[i] = *GetPharmacyDto(v) + } + return responses +} diff --git a/api/model/pharmacy.go b/api/model/pharmacy.go new file mode 100644 index 0000000..6f00cde --- /dev/null +++ b/api/model/pharmacy.go @@ -0,0 +1,45 @@ +package model + +import ( + "gorm.io/gorm" + "hospital-admin-api/global" + "time" +) + +// Pharmacy 药房信息表 +type Pharmacy struct { + PharmacyId int64 `gorm:"column:pharmacy_id;type:bigint(20);primary_key;comment:主键id" json:"pharmacy_id"` + PharmacyName string `gorm:"column:pharmacy_name;type:varchar(100);comment:药房名称;NOT NULL" json:"pharmacy_name"` + PharmacyCode string `gorm:"column:pharmacy_code;type:varchar(64);comment:药房代码;NOT NULL" json:"pharmacy_code"` + Postage float64 `gorm:"column:postage;type:decimal(10,2);default:0.00;comment:基础邮费" json:"postage"` + FreeShippingThreshold float64 `gorm:"column:free_shipping_threshold;type:decimal(10,2);default:0.00;comment:满XX包邮门槛金额" json:"free_shipping_threshold"` + IsPickup int `gorm:"column:is_pickup;type:tinyint(1);default:0;comment:是否支持自提(0:否 1:是)" json:"is_pickup"` + Telephone string `gorm:"column:telephone;type:varchar(30);comment:电话" json:"telephone"` + ProvinceId int `gorm:"column:province_id;type:int(11);default:0;comment:省份id" json:"province_id"` + Province string `gorm:"column:province;type:varchar(50);comment:省份" json:"province"` + CityId int `gorm:"column:city_id;type:int(11);default:0;comment:城市id" json:"city_id"` + City string `gorm:"column:city;type:varchar(50);comment:城市" json:"city"` + CountyId int `gorm:"column:county_id;type:int(11);default:0;comment:区县id" json:"county_id"` + County string `gorm:"column:county;type:varchar(50);comment:区县" json:"county"` + Address string `gorm:"column:address;type:varchar(255);comment:地址" json:"address"` + Status int `gorm:"column:status;type:tinyint(1);default:1;comment:状态(0:禁用 1:正常 2:删除)" json:"status"` + Model +} + +func (m *Pharmacy) TableName() string { + return "gdxz_pharmacy" +} + +func (m *Pharmacy) BeforeCreate(tx *gorm.DB) error { + if m.PharmacyId == 0 { + m.PharmacyId = 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/pharmacy.go b/api/requests/pharmacy.go new file mode 100644 index 0000000..65e6372 --- /dev/null +++ b/api/requests/pharmacy.go @@ -0,0 +1,65 @@ +package requests + +type PharmacyRequest struct { + GetPharmacyList // 获取药房列表 + GetPharmacyPage // 获取药房列表-分页 + AddPharmacy // 新增药房 + PutPharmacy // 修改药房 + PutPharmacyStatus // 修改药房状态 +} + +// GetPharmacyList 获取药房列表 +type GetPharmacyList struct { + PharmacyName string `json:"pharmacy_name" form:"pharmacy_name" label:"药房名称"` + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"药房代码"` + Status *int `json:"status" form:"status" label:"状态"` + IsPickup *int `json:"is_pickup" form:"is_pickup" label:"是否支持自提"` +} + +// GetPharmacyPage 获取药房列表-分页 +type GetPharmacyPage struct { + Page int `json:"page" form:"page" label:"页码"` + PageSize int `json:"page_size" form:"page_size" label:"每页个数"` + PharmacyName string `json:"pharmacy_name" form:"pharmacy_name" label:"药房名称"` + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"药房代码"` + Status *int `json:"status" form:"status" label:"状态"` + IsPickup *int `json:"is_pickup" form:"is_pickup" label:"是否支持自提"` + ProvinceId int `json:"province_id" form:"province_id" label:"省份id"` + CityId *int `json:"city_id" form:"city_id" label:"城市id"` + CountyId *int `json:"county_id" form:"county_id" label:"区县id"` +} + +// AddPharmacy 新增药房 +type AddPharmacy struct { + PharmacyName string `json:"pharmacy_name" form:"pharmacy_name" label:"药房名称" validate:"required"` + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"药房代码" validate:"required"` + Postage *float64 `json:"postage" form:"postage" label:"邮费" validate:"required,gte=0"` + FreeShippingThreshold *float64 `json:"free_shipping_threshold" form:"free_shipping_threshold" label:"满XX包邮" validate:"required,gte=0"` + IsPickup *int `json:"is_pickup" form:"is_pickup" label:"是否支持自提" validate:"required,oneof=0 1"` + Telephone string `json:"telephone" form:"telephone" label:"电话"` + ProvinceId int `json:"province_id" form:"province_id" label:"省份id"` + CityId int `json:"city_id" form:"city_id" label:"城市id"` + CountyId int `json:"county_id" form:"county_id" label:"区县id"` + Address string `json:"address" form:"address" label:"地址" validate:"required"` + Status *int `json:"status" form:"status" label:"状态" validate:"omitempty,oneof=0 1"` +} + +// PutPharmacy 修改药房 +type PutPharmacy struct { + PharmacyName string `json:"pharmacy_name" form:"pharmacy_name" label:"药房名称" validate:"required"` + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"药房代码" validate:"required"` + Postage *float64 `json:"postage" form:"postage" label:"邮费" validate:"required,gte=0"` + FreeShippingThreshold *float64 `json:"free_shipping_threshold" form:"free_shipping_threshold" label:"满XX包邮" validate:"required,gte=0"` + IsPickup *int `json:"is_pickup" form:"is_pickup" label:"是否支持自提" validate:"required,oneof=0 1"` + Telephone string `json:"telephone" form:"telephone" label:"电话"` + ProvinceId int `json:"province_id" form:"province_id" label:"省份id"` + CityId int `json:"city_id" form:"city_id" label:"城市id"` + CountyId int `json:"county_id" form:"county_id" label:"区县id"` + Address string `json:"address" form:"address" label:"地址" validate:"required"` + Status *int `json:"status" form:"status" label:"状态" validate:"omitempty,oneof=0 1"` +} + +// PutPharmacyStatus 修改药房状态 +type PutPharmacyStatus struct { + Status *int `json:"status" form:"status" label:"状态" validate:"required,oneof=0 1"` +} diff --git a/api/router/router.go b/api/router/router.go index 58f7e3d..160fccf 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -161,6 +161,13 @@ func basicRouter(r *gin.Engine, api controller.Api) { hospitalGroup.GET("/list", api.Hospital.GetHospitalList) } + // 药房管理-基础数据 + pharmacyGroup := basicGroup.Group("/pharmacy") + { + // 获取药房列表 + pharmacyGroup.GET("/list", api.Pharmacy.GetPharmacyList) + } + // 医生专长管理-基础数据 expertiseGroup := basicGroup.Group("/expertise") { @@ -885,6 +892,31 @@ func privateRouter(r *gin.Engine, api controller.Api) { hospitalGroup.PUT("/:hospital_id", api.Hospital.PutHospital) } + // 药房管理 + pharmacyGroup := basicGroup.Group("/pharmacy") + { + // 获取药房列表-分页 + pharmacyGroup.POST("/page", api.Pharmacy.GetPharmacyPage) + + // 获取药房列表 + pharmacyGroup.GET("/list", api.Pharmacy.GetPharmacyList) + + // 获取药房详情 + pharmacyGroup.GET("/:pharmacy_id", api.Pharmacy.GetPharmacy) + + // 新增药房 + pharmacyGroup.POST("", api.Pharmacy.AddPharmacy) + + // 修改药房 + pharmacyGroup.PUT("/:pharmacy_id", api.Pharmacy.PutPharmacy) + + // 修改药房状态 + pharmacyGroup.PUT("/status/:pharmacy_id", api.Pharmacy.PutPharmacyStatus) + + // 删除药房 + pharmacyGroup.DELETE("/:pharmacy_id", api.Pharmacy.DeletePharmacy) + } + // 科普分类管理 articleClassGroup := basicGroup.Group("/article/class") { diff --git a/api/service/pharmacy.go b/api/service/pharmacy.go new file mode 100644 index 0000000..800b688 --- /dev/null +++ b/api/service/pharmacy.go @@ -0,0 +1,261 @@ +package service + +import ( + "errors" + "fmt" + "gorm.io/gorm" + "hospital-admin-api/api/dao" + "hospital-admin-api/api/dto" + "hospital-admin-api/api/model" + "hospital-admin-api/api/requests" + "hospital-admin-api/global" +) + +type PharmacyService struct{} + +// AddPharmacy 新增药房 +func (r *PharmacyService) AddPharmacy(req requests.AddPharmacy) (bool, error) { + pharmacyDao := dao.PharmacyDao{} + + // 检测药房代码是否已存在 + existPharmacy, err := pharmacyDao.GetPharmacyByCode(req.PharmacyCode) + if err == nil && existPharmacy != nil { + return false, errors.New("药房代码已存在,请勿重复添加") + } + + var province string + var city string + var county string + + areaDao := dao.AreaDao{} + if req.ProvinceId != 0 { + area, err := areaDao.GetAreaById(req.ProvinceId) + if err != nil || area == nil { + return false, errors.New("省份数据错误") + } + province = area.AreaName + } + + if req.CityId != 0 { + area, err := areaDao.GetAreaById(req.CityId) + if err != nil || area == nil { + return false, errors.New("城市数据错误") + } + city = area.AreaName + } + + if req.CountyId != 0 { + area, err := areaDao.GetAreaById(req.CountyId) + if err != nil || area == nil { + return false, errors.New("区县数据错误") + } + county = area.AreaName + } + + status := 1 + if req.Status != nil { + status = *req.Status + } + + // 开启事务 + tx := global.Db.Begin() + defer func() { + if rec := recover(); rec != nil { + tx.Rollback() + } + }() + + pharmacy := &model.Pharmacy{ + PharmacyName: req.PharmacyName, + PharmacyCode: req.PharmacyCode, + Postage: *req.Postage, + FreeShippingThreshold: *req.FreeShippingThreshold, + IsPickup: *req.IsPickup, + Telephone: req.Telephone, + ProvinceId: req.ProvinceId, + Province: province, + CityId: req.CityId, + City: city, + CountyId: req.CountyId, + County: county, + Address: req.Address, + Status: status, + } + + pharmacy, err = pharmacyDao.AddPharmacy(tx, pharmacy) + if err != nil || pharmacy == nil { + tx.Rollback() + return false, errors.New(err.Error()) + } + + tx.Commit() + return true, nil +} + +// PutPharmacy 修改药房 +func (r *PharmacyService) PutPharmacy(pharmacyId int64, req requests.PutPharmacy) (bool, error) { + pharmacyDao := dao.PharmacyDao{} + pharmacy, err := pharmacyDao.GetPharmacyById(pharmacyId) + if err != nil || pharmacy == nil { + return false, errors.New("药房不存在或已删除") + } + + // 如果修改了代码,需检查新代码是否被其他药房占用 + if req.PharmacyCode != pharmacy.PharmacyCode { + exist, err := pharmacyDao.GetPharmacyByCode(req.PharmacyCode) + if err == nil && exist != nil && exist.PharmacyId != pharmacyId { + return false, errors.New("药房代码已被占用") + } + } + + tx := global.Db.Begin() + defer func() { + if rec := recover(); rec != nil { + tx.Rollback() + fmt.Println(rec) + } + }() + + pharmacyData := make(map[string]interface{}) + + if req.PharmacyName != pharmacy.PharmacyName { + pharmacyData["pharmacy_name"] = req.PharmacyName + } + + if req.PharmacyCode != pharmacy.PharmacyCode { + pharmacyData["pharmacy_code"] = req.PharmacyCode + } + + if *req.Postage != pharmacy.Postage { + pharmacyData["postage"] = *req.Postage + } + + if *req.FreeShippingThreshold != pharmacy.FreeShippingThreshold { + pharmacyData["free_shipping_threshold"] = *req.FreeShippingThreshold + } + + if *req.IsPickup != pharmacy.IsPickup { + pharmacyData["is_pickup"] = *req.IsPickup + } + + if req.Telephone != pharmacy.Telephone { + pharmacyData["telephone"] = req.Telephone + } + + if req.ProvinceId != 0 && req.ProvinceId != pharmacy.ProvinceId { + areaDao := dao.AreaDao{} + area, err := areaDao.GetAreaById(req.ProvinceId) + if err != nil || area == nil { + return false, errors.New("省份数据错误") + } + pharmacyData["province_id"] = req.ProvinceId + pharmacyData["province"] = area.AreaName + } + + if req.CityId != 0 && req.CityId != pharmacy.CityId { + areaDao := dao.AreaDao{} + area, err := areaDao.GetAreaById(req.CityId) + if err != nil || area == nil { + return false, errors.New("城市数据错误") + } + pharmacyData["city_id"] = req.CityId + pharmacyData["city"] = area.AreaName + } + + if req.CountyId != 0 && req.CountyId != pharmacy.CountyId { + areaDao := dao.AreaDao{} + area, err := areaDao.GetAreaById(req.CountyId) + if err != nil || area == nil { + return false, errors.New("区县数据错误") + } + pharmacyData["county_id"] = req.CountyId + pharmacyData["county"] = area.AreaName + } + + if req.Address != pharmacy.Address { + pharmacyData["address"] = req.Address + } + + if req.Status != nil && *req.Status != pharmacy.Status { + pharmacyData["status"] = *req.Status + } + + if len(pharmacyData) > 0 { + err = pharmacyDao.EditPharmacyById(tx, pharmacyId, pharmacyData) + if err != nil { + tx.Rollback() + return false, errors.New(err.Error()) + } + } + + tx.Commit() + return true, nil +} + +// PutPharmacyStatus 修改药房状态 +func (r *PharmacyService) PutPharmacyStatus(pharmacyId int64, req requests.PutPharmacyStatus) (bool, error) { + pharmacyDao := dao.PharmacyDao{} + pharmacy, err := pharmacyDao.GetPharmacyById(pharmacyId) + if err != nil || pharmacy == nil { + return false, errors.New("药房不存在或已删除") + } + + data := map[string]interface{}{ + "status": *req.Status, + } + + tx := global.Db.Begin() + defer func() { + if rec := recover(); rec != nil { + tx.Rollback() + } + }() + + err = pharmacyDao.EditPharmacyById(tx, pharmacyId, data) + if err != nil { + tx.Rollback() + return false, errors.New(err.Error()) + } + + tx.Commit() + return true, nil +} + +// DeletePharmacy 软删除药房 +func (r *PharmacyService) DeletePharmacy(pharmacyId int64) (bool, error) { + pharmacyDao := dao.PharmacyDao{} + pharmacy, err := pharmacyDao.GetPharmacyById(pharmacyId) + if err != nil || pharmacy == nil { + return false, errors.New("药房不存在或已删除") + } + + tx := global.Db.Begin() + defer func() { + if rec := recover(); rec != nil { + tx.Rollback() + } + }() + + err = pharmacyDao.DeletePharmacyById(tx, pharmacyId) + if err != nil { + tx.Rollback() + return false, errors.New(err.Error()) + } + + tx.Commit() + return true, nil +} + +// GetPharmacy 药房详情 +func (r *PharmacyService) GetPharmacy(pharmacyId int64) (*dto.PharmacyDto, error) { + pharmacyDao := dao.PharmacyDao{} + pharmacy, err := pharmacyDao.GetPharmacyById(pharmacyId) + if err != nil || pharmacy == nil { + if errors.Is(err, gorm.ErrRecordNotFound) || pharmacy == nil { + return nil, errors.New("未找到相关药房信息") + } + return nil, err + } + + return dto.GetPharmacyDto(pharmacy), nil +} From dc9dee6c9829d4a969fb37ae33f5c81bc726736a Mon Sep 17 00:00:00 2001 From: haomingming Date: Mon, 7 Sep 2026 14:07:00 +0800 Subject: [PATCH 02/16] =?UTF-8?q?=E5=8C=BB=E7=94=9F=E7=BB=91=E5=AE=9A?= =?UTF-8?q?=E8=8D=AF=E6=88=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/controller/base.go | 1 + api/controller/doctorPharmacy.go | 169 ++++++++++++++++++++++++ api/dao/doctorPharmacy.go | 71 ++++++++++ api/dto/DoctorPharmacy.go | 64 +++++++++ api/dto/UserDoctor.go | 1 + api/model/doctorPharmacy.go | 36 +++++ api/requests/doctorPharmacy.go | 18 +++ api/requests/userDoctor.go | 2 + api/router/router.go | 19 +++ api/service/doctorPharmacy.go | 219 +++++++++++++++++++++++++++++++ api/service/userDoctor.go | 46 +++++++ 11 files changed, 646 insertions(+) create mode 100644 api/controller/doctorPharmacy.go create mode 100644 api/dao/doctorPharmacy.go create mode 100644 api/dto/DoctorPharmacy.go create mode 100644 api/model/doctorPharmacy.go create mode 100644 api/requests/doctorPharmacy.go create mode 100644 api/service/doctorPharmacy.go diff --git a/api/controller/base.go b/api/controller/base.go index 1c35f58..bffac3d 100644 --- a/api/controller/base.go +++ b/api/controller/base.go @@ -35,6 +35,7 @@ type sysSetting struct { type userDoctorManage struct { UserDoctor // 医生列表 DoctorAccount + DoctorPharmacy // 医生药房管理 } // Basic 基础数据 diff --git a/api/controller/doctorPharmacy.go b/api/controller/doctorPharmacy.go new file mode 100644 index 0000000..1a240dc --- /dev/null +++ b/api/controller/doctorPharmacy.go @@ -0,0 +1,169 @@ +package controller + +import ( + "github.com/gin-gonic/gin" + "hospital-admin-api/api/requests" + "hospital-admin-api/api/responses" + "hospital-admin-api/api/service" + "hospital-admin-api/global" + "hospital-admin-api/utils" + "strconv" +) + +type DoctorPharmacy struct{} + +// GetDoctorPharmacies 获取指定医生绑定的药房列表 +func (r *DoctorPharmacy) GetDoctorPharmacies(c *gin.Context) { + id := c.Param("doctor_id") + if id == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + doctorId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + doctorPharmacyService := service.DoctorPharmacyService{} + list, err := doctorPharmacyService.GetDoctorPharmacies(doctorId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.OkWithData(list, c) +} + +// BindDoctorPharmacies 批量设置/覆盖医生绑定的药房列表 +func (r *DoctorPharmacy) BindDoctorPharmacies(c *gin.Context) { + id := c.Param("doctor_id") + if id == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + doctorId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + req := requests.BindDoctorPharmacies{} + if err := c.ShouldBindJSON(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + doctorPharmacyService := service.DoctorPharmacyService{} + _, err = doctorPharmacyService.BindDoctorPharmacies(doctorId, req) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.Ok(c) +} + +// AddDoctorPharmacy 为医生新增单个药房绑定 +func (r *DoctorPharmacy) AddDoctorPharmacy(c *gin.Context) { + id := c.Param("doctor_id") + if id == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + doctorId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + req := requests.AddDoctorPharmacy{} + if err := c.ShouldBindJSON(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + doctorPharmacyService := service.DoctorPharmacyService{} + _, err = doctorPharmacyService.AddDoctorPharmacy(doctorId, req) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.Ok(c) +} + +// UnbindDoctorPharmacy 解除医生与指定药房的绑定 +func (r *DoctorPharmacy) UnbindDoctorPharmacy(c *gin.Context) { + docId := c.Param("doctor_id") + pharId := c.Param("pharmacy_id") + if docId == "" || pharId == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + doctorId, err := strconv.ParseInt(docId, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + pharmacyId, err := strconv.ParseInt(pharId, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + doctorPharmacyService := service.DoctorPharmacyService{} + _, err = doctorPharmacyService.UnbindDoctorPharmacy(doctorId, pharmacyId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.Ok(c) +} + +// SetDefaultDoctorPharmacy 设为医生的默认药房 +func (r *DoctorPharmacy) SetDefaultDoctorPharmacy(c *gin.Context) { + docId := c.Param("doctor_id") + pharId := c.Param("pharmacy_id") + if docId == "" || pharId == "" { + responses.FailWithMessage("缺少参数", c) + return + } + + doctorId, err := strconv.ParseInt(docId, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + pharmacyId, err := strconv.ParseInt(pharId, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + doctorPharmacyService := service.DoctorPharmacyService{} + _, err = doctorPharmacyService.SetDefaultPharmacy(doctorId, pharmacyId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.Ok(c) +} diff --git a/api/dao/doctorPharmacy.go b/api/dao/doctorPharmacy.go new file mode 100644 index 0000000..16a67ea --- /dev/null +++ b/api/dao/doctorPharmacy.go @@ -0,0 +1,71 @@ +package dao + +import ( + "gorm.io/gorm" + "hospital-admin-api/api/model" + "hospital-admin-api/global" +) + +type DoctorPharmacyDao struct{} + +// GetDoctorPharmacyListByDoctorId 获取医生绑定的药房列表(带预加载药房详情) +func (r *DoctorPharmacyDao) GetDoctorPharmacyListByDoctorId(doctorId int64) (m []*model.DoctorPharmacy, err error) { + err = global.Db.Preload("Pharmacy").Where("doctor_id = ? AND status = 1", doctorId).Order("is_default desc, created_at desc").Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// GetDoctorPharmacyByDoctorAndPharmacy 获取某医生与某药房的绑定关系 +func (r *DoctorPharmacyDao) GetDoctorPharmacyByDoctorAndPharmacy(doctorId, pharmacyId int64) (m *model.DoctorPharmacy, err error) { + err = global.Db.Where("doctor_id = ? AND pharmacy_id = ?", doctorId, pharmacyId).First(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + +// AddDoctorPharmacy 新增绑定 +func (r *DoctorPharmacyDao) AddDoctorPharmacy(tx *gorm.DB, m *model.DoctorPharmacy) (*model.DoctorPharmacy, error) { + if err := tx.Create(m).Error; err != nil { + return nil, err + } + return m, nil +} + +// DeleteDoctorPharmacy 删除绑定记录 +func (r *DoctorPharmacyDao) DeleteDoctorPharmacy(tx *gorm.DB, maps interface{}) error { + err := tx.Where(maps).Delete(&model.DoctorPharmacy{}).Error + if err != nil { + return err + } + return nil +} + +// DeleteDoctorPharmacyByDoctorAndPharmacy 解绑指定医生和指定药房 +func (r *DoctorPharmacyDao) DeleteDoctorPharmacyByDoctorAndPharmacy(tx *gorm.DB, doctorId, pharmacyId int64) error { + err := tx.Where("doctor_id = ? AND pharmacy_id = ?", doctorId, pharmacyId).Delete(&model.DoctorPharmacy{}).Error + if err != nil { + return err + } + return nil +} + +// ResetDoctorDefaultPharmacy 重置医生的默认药房(设为非默认) +func (r *DoctorPharmacyDao) ResetDoctorDefaultPharmacy(tx *gorm.DB, doctorId int64) error { + err := tx.Model(&model.DoctorPharmacy{}).Where("doctor_id = ?", doctorId).Update("is_default", 0).Error + if err != nil { + return err + } + return nil +} + +// SetDefaultPharmacy 设指定药房为默认 +func (r *DoctorPharmacyDao) SetDefaultPharmacy(tx *gorm.DB, doctorId, pharmacyId int64) error { + err := tx.Model(&model.DoctorPharmacy{}).Where("doctor_id = ? AND pharmacy_id = ?", doctorId, pharmacyId).Update("is_default", 1).Error + if err != nil { + return err + } + return nil +} diff --git a/api/dto/DoctorPharmacy.go b/api/dto/DoctorPharmacy.go new file mode 100644 index 0000000..8490ade --- /dev/null +++ b/api/dto/DoctorPharmacy.go @@ -0,0 +1,64 @@ +package dto + +import ( + "fmt" + "hospital-admin-api/api/model" +) + +type DoctorPharmacyDto struct { + DoctorPharmacyId string `json:"doctor_pharmacy_id"` // 绑定关系id + DoctorId string `json:"doctor_id"` // 医生id + PharmacyId string `json:"pharmacy_id"` // 药房id + PharmacyName string `json:"pharmacy_name"` // 药房名称 + PharmacyCode string `json:"pharmacy_code"` // 药房代码 + Postage float64 `json:"postage"` // 基础邮费 + FreeShippingThreshold float64 `json:"free_shipping_threshold"` // 满XX包邮门槛金额 + IsPickup int `json:"is_pickup"` // 是否支持自提(0:否 1:是) + Telephone string `json:"telephone"` // 电话 + Province string `json:"province"` // 省份 + City string `json:"city"` // 城市 + County string `json:"county"` // 区县 + Address string `json:"address"` // 详细地址 + FullAddress string `json:"full_address"` // 完整地址 + IsDefault int `json:"is_default"` // 是否默认药房(0:否 1:是) + Status int `json:"status"` // 状态(0:禁用 1:正常) + CreatedAt model.LocalTime `json:"created_at"` // 绑定时间 + UpdatedAt model.LocalTime `json:"updated_at"` // 更新时间 +} + +func GetDoctorPharmacyDto(m *model.DoctorPharmacy) *DoctorPharmacyDto { + if m == nil { + return nil + } + dto := &DoctorPharmacyDto{ + DoctorPharmacyId: fmt.Sprintf("%d", m.DoctorPharmacyId), + DoctorId: fmt.Sprintf("%d", m.DoctorId), + PharmacyId: fmt.Sprintf("%d", m.PharmacyId), + IsDefault: m.IsDefault, + Status: m.Status, + CreatedAt: m.CreatedAt, + UpdatedAt: m.UpdatedAt, + } + if m.Pharmacy != nil { + dto.PharmacyName = m.Pharmacy.PharmacyName + dto.PharmacyCode = m.Pharmacy.PharmacyCode + dto.Postage = m.Pharmacy.Postage + dto.FreeShippingThreshold = m.Pharmacy.FreeShippingThreshold + dto.IsPickup = m.Pharmacy.IsPickup + dto.Telephone = m.Pharmacy.Telephone + dto.Province = m.Pharmacy.Province + dto.City = m.Pharmacy.City + dto.County = m.Pharmacy.County + dto.Address = m.Pharmacy.Address + dto.FullAddress = fmt.Sprintf("%s%s%s%s", m.Pharmacy.Province, m.Pharmacy.City, m.Pharmacy.County, m.Pharmacy.Address) + } + return dto +} + +func GetDoctorPharmacyListDto(list []*model.DoctorPharmacy) []*DoctorPharmacyDto { + res := make([]*DoctorPharmacyDto, len(list)) + for i, v := range list { + res[i] = GetDoctorPharmacyDto(v) + } + return res +} diff --git a/api/dto/UserDoctor.go b/api/dto/UserDoctor.go index 22fcb1e..093a976 100644 --- a/api/dto/UserDoctor.go +++ b/api/dto/UserDoctor.go @@ -52,6 +52,7 @@ type UserDoctorDto struct { Hospital *HospitalDto `json:"hospital"` // 医院 UserDoctorInfo *UserDoctorInfoDto `json:"user_doctor_info"` // 医生详情 DoctorExpertise []*DoctorExpertiseDto `json:"doctor_expertise"` // 医生专长 + DoctorPharmacy []*DoctorPharmacyDto `json:"doctor_pharmacy"` // 医生药房 DoctorBankCard *DoctorBankCardDto `json:"doctor_bank_card"` // 医生银行卡 InquiryType string `json:"inquiry_type"` // 服务类型 UserCaCert *UserCaCertDto `json:"user_ca_cert"` // ca监管证书 diff --git a/api/model/doctorPharmacy.go b/api/model/doctorPharmacy.go new file mode 100644 index 0000000..ab35604 --- /dev/null +++ b/api/model/doctorPharmacy.go @@ -0,0 +1,36 @@ +package model + +import ( + "gorm.io/gorm" + "hospital-admin-api/global" + "time" +) + +// DoctorPharmacy 医生-药房关联表 +type DoctorPharmacy struct { + DoctorPharmacyId int64 `gorm:"column:doctor_pharmacy_id;type:bigint(20);primary_key;comment:主键id" json:"doctor_pharmacy_id"` + DoctorId int64 `gorm:"column:doctor_id;type:bigint(19);comment:医生id;NOT NULL" json:"doctor_id"` + PharmacyId int64 `gorm:"column:pharmacy_id;type:bigint(20);comment:药房id;NOT NULL" json:"pharmacy_id"` + IsDefault int `gorm:"column:is_default;type:tinyint(1);default:0;comment:是否默认药房(0:否 1:是)" json:"is_default"` + Status int `gorm:"column:status;type:tinyint(1);default:1;comment:状态(0:禁用 1:正常)" json:"status"` + Model + Pharmacy *Pharmacy `gorm:"foreignKey:PharmacyId;references:pharmacy_id" json:"pharmacy"` +} + +func (m *DoctorPharmacy) TableName() string { + return "gdxz_doctor_pharmacy" +} + +func (m *DoctorPharmacy) BeforeCreate(tx *gorm.DB) error { + if m.DoctorPharmacyId == 0 { + m.DoctorPharmacyId = 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/doctorPharmacy.go b/api/requests/doctorPharmacy.go new file mode 100644 index 0000000..fb32db9 --- /dev/null +++ b/api/requests/doctorPharmacy.go @@ -0,0 +1,18 @@ +package requests + +type DoctorPharmacyRequest struct { + BindDoctorPharmacies // 批量绑定药房 + AddDoctorPharmacy // 新增单个药房绑定 +} + +// BindDoctorPharmacies 批量绑定药房 +type BindDoctorPharmacies struct { + PharmacyIds []string `json:"pharmacy_ids" form:"pharmacy_ids" label:"药房id列表"` + DefaultPharmacyId string `json:"default_pharmacy_id" form:"default_pharmacy_id" label:"默认药房id"` +} + +// AddDoctorPharmacy 单个药房绑定 +type AddDoctorPharmacy struct { + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"药房id" validate:"required"` + IsDefault *int `json:"is_default" form:"is_default" label:"是否默认" validate:"omitempty,oneof=0 1"` +} diff --git a/api/requests/userDoctor.go b/api/requests/userDoctor.go index 23f7117..f37e488 100644 --- a/api/requests/userDoctor.go +++ b/api/requests/userDoctor.go @@ -58,6 +58,7 @@ type PutUserDoctor struct { IdCardBack string `json:"id_card_back" form:"id_card_back" label:"身份证背面图片"` SignImage string `json:"sign_image" form:"sign_image" label:"签名图片"` DoctorExpertise []string `json:"doctor_expertise" form:"doctor_expertise" label:"专长"` + DoctorPharmacy []string `json:"doctor_pharmacy" form:"doctor_pharmacy" label:"药房"` Email string `json:"email" form:"email" label:"邮箱"` BankId string `json:"bank_id" form:"bank_id" validate:"required_with_all=BankCardCode BankCardProvinceId BankCardCityId BankCardCountyId" label:"银行id"` BankCardCode string `json:"bank_card_code" form:"bank_card_code" validate:"required_with_all=BankId BankCardProvinceId BankCardCityId BankCardCountyId" label:"银行卡号"` @@ -90,6 +91,7 @@ type AddUserDoctor struct { SignImage string `json:"sign_image" form:"sign_image" label:"签名图片"` CardNum string `json:"card_num" form:"card_num" validate:"required" label:"证件号码"` DoctorExpertise []string `json:"doctor_expertise" form:"doctor_expertise" label:"专长"` + DoctorPharmacy []string `json:"doctor_pharmacy" form:"doctor_pharmacy" label:"药房"` Email string `json:"email" form:"email" label:"邮箱"` BankId string `json:"bank_id" form:"bank_id" validate:"required_with_all=BankCardCode BankCardProvinceId BankCardCityId BankCardCountyId" label:"银行id"` BankCardCode string `json:"bank_card_code" form:"bank_card_code" validate:"required_with_all=BankId BankCardProvinceId BankCardCityId BankCardCountyId" label:"银行卡号"` diff --git a/api/router/router.go b/api/router/router.go index 160fccf..72d49f1 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -371,6 +371,25 @@ func privateRouter(r *gin.Engine, api controller.Api) { // 新增医生 doctorGroup.POST("", api.UserDoctor.AddUserDoctor) + // 医生药房管理 + doctorPharmacyGroup := doctorGroup.Group("/:doctor_id/pharmacy") + { + // 获取医生绑定的药房列表 + doctorPharmacyGroup.GET("", api.DoctorPharmacy.GetDoctorPharmacies) + + // 批量设置医生绑定的药房列表 + doctorPharmacyGroup.PUT("", api.DoctorPharmacy.BindDoctorPharmacies) + + // 为医生新增单个药房绑定 + doctorPharmacyGroup.POST("", api.DoctorPharmacy.AddDoctorPharmacy) + + // 解除医生与指定药房的绑定 + doctorPharmacyGroup.DELETE("/:pharmacy_id", api.DoctorPharmacy.UnbindDoctorPharmacy) + + // 设置医生的默认药房 + doctorPharmacyGroup.PUT("/default/:pharmacy_id", api.DoctorPharmacy.SetDefaultDoctorPharmacy) + } + // 身份审核列表 doctorPendingGroup := doctorGroup.Group("/pending") { diff --git a/api/service/doctorPharmacy.go b/api/service/doctorPharmacy.go new file mode 100644 index 0000000..da9059b --- /dev/null +++ b/api/service/doctorPharmacy.go @@ -0,0 +1,219 @@ +package service + +import ( + "errors" + "hospital-admin-api/api/dao" + "hospital-admin-api/api/dto" + "hospital-admin-api/api/model" + "hospital-admin-api/api/requests" + "hospital-admin-api/global" + "strconv" +) + +type DoctorPharmacyService struct{} + +// GetDoctorPharmacies 获取指定医生绑定的药房列表 +func (r *DoctorPharmacyService) GetDoctorPharmacies(doctorId int64) ([]*dto.DoctorPharmacyDto, error) { + doctorPharmacyDao := dao.DoctorPharmacyDao{} + list, err := doctorPharmacyDao.GetDoctorPharmacyListByDoctorId(doctorId) + if err != nil { + return nil, err + } + return dto.GetDoctorPharmacyListDto(list), nil +} + +// BindDoctorPharmacies 批量绑定医生药房(全量覆盖) +func (r *DoctorPharmacyService) BindDoctorPharmacies(doctorId int64, req requests.BindDoctorPharmacies) (bool, error) { + // 校验医生是否存在 + userDoctorDao := dao.UserDoctorDao{} + doctor, err := userDoctorDao.GetUserDoctorById(doctorId) + if err != nil || doctor == nil { + return false, errors.New("医生不存在或已删除") + } + + pharmacyDao := dao.PharmacyDao{} + var defaultPharmacyId int64 + if req.DefaultPharmacyId != "" { + defaultPharmacyId, _ = strconv.ParseInt(req.DefaultPharmacyId, 10, 64) + } + + // 开启事务 + tx := global.Db.Begin() + defer func() { + if rec := recover(); rec != nil { + tx.Rollback() + } + }() + + doctorPharmacyDao := dao.DoctorPharmacyDao{} + + // 删除原绑定记录 + if err := doctorPharmacyDao.DeleteDoctorPharmacy(tx, map[string]interface{}{"doctor_id": doctorId}); err != nil { + tx.Rollback() + return false, errors.New("清空原绑定关系失败") + } + + // 遍历新增绑定 + for i, v := range req.PharmacyIds { + pharmacyId, err := strconv.ParseInt(v, 10, 64) + if err != nil || pharmacyId == 0 { + continue + } + + // 检查药房是否存在且正常 + pharmacy, err := pharmacyDao.GetPharmacyById(pharmacyId) + if err != nil || pharmacy == nil { + tx.Rollback() + return false, errors.New("选择的药房不存在或已被禁用") + } + + isDefault := 0 + if defaultPharmacyId != 0 && pharmacyId == defaultPharmacyId { + isDefault = 1 + } else if defaultPharmacyId == 0 && i == 0 { + // 未指定默认药房时,默认第1个为默认药房 + isDefault = 1 + } + + dp := &model.DoctorPharmacy{ + DoctorId: doctorId, + PharmacyId: pharmacyId, + IsDefault: isDefault, + Status: 1, + } + + _, err = doctorPharmacyDao.AddDoctorPharmacy(tx, dp) + if err != nil { + tx.Rollback() + return false, errors.New("保存绑定关系失败: " + err.Error()) + } + } + + tx.Commit() + return true, nil +} + +// AddDoctorPharmacy 新增单个药房绑定 +func (r *DoctorPharmacyService) AddDoctorPharmacy(doctorId int64, req requests.AddDoctorPharmacy) (bool, error) { + pharmacyId, err := strconv.ParseInt(req.PharmacyId, 10, 64) + if err != nil || pharmacyId == 0 { + return false, errors.New("药房id无效") + } + + // 校验药房 + pharmacyDao := dao.PharmacyDao{} + pharmacy, err := pharmacyDao.GetPharmacyById(pharmacyId) + if err != nil || pharmacy == nil { + return false, errors.New("药房不存在或已禁用") + } + + doctorPharmacyDao := dao.DoctorPharmacyDao{} + // 检查是否已绑定 + exist, _ := doctorPharmacyDao.GetDoctorPharmacyByDoctorAndPharmacy(doctorId, pharmacyId) + if exist != nil { + return false, errors.New("该药房已绑定,请勿重复添加") + } + + isDefault := 0 + if req.IsDefault != nil && *req.IsDefault == 1 { + isDefault = 1 + } + + tx := global.Db.Begin() + defer func() { + if rec := recover(); rec != nil { + tx.Rollback() + } + }() + + // 如果要设为默认,先将该医生现有的其他药房设为非默认 + if isDefault == 1 { + if err := doctorPharmacyDao.ResetDoctorDefaultPharmacy(tx, doctorId); err != nil { + tx.Rollback() + return false, errors.New("重置默认药房失败") + } + } else { + // 检查当前是否已有绑定药房,若无任何药房,则当前第一个自动作为默认 + existingList, _ := doctorPharmacyDao.GetDoctorPharmacyListByDoctorId(doctorId) + if len(existingList) == 0 { + isDefault = 1 + } + } + + dp := &model.DoctorPharmacy{ + DoctorId: doctorId, + PharmacyId: pharmacyId, + IsDefault: isDefault, + Status: 1, + } + + _, err = doctorPharmacyDao.AddDoctorPharmacy(tx, dp) + if err != nil { + tx.Rollback() + return false, errors.New("添加绑定失败") + } + + tx.Commit() + return true, nil +} + +// UnbindDoctorPharmacy 解绑单个药房 +func (r *DoctorPharmacyService) UnbindDoctorPharmacy(doctorId, pharmacyId int64) (bool, error) { + doctorPharmacyDao := dao.DoctorPharmacyDao{} + exist, err := doctorPharmacyDao.GetDoctorPharmacyByDoctorAndPharmacy(doctorId, pharmacyId) + if err != nil || exist == nil { + return false, errors.New("未找到绑定记录") + } + + tx := global.Db.Begin() + defer func() { + if rec := recover(); rec != nil { + tx.Rollback() + } + }() + + if err := doctorPharmacyDao.DeleteDoctorPharmacyByDoctorAndPharmacy(tx, doctorId, pharmacyId); err != nil { + tx.Rollback() + return false, errors.New("解绑失败") + } + + // 如果解绑的是默认药房,尝试将剩余的第一个药房设为默认 + if exist.IsDefault == 1 { + list, _ := doctorPharmacyDao.GetDoctorPharmacyListByDoctorId(doctorId) + if len(list) > 0 { + _ = doctorPharmacyDao.SetDefaultPharmacy(tx, doctorId, list[0].PharmacyId) + } + } + + tx.Commit() + return true, nil +} + +// SetDefaultPharmacy 设为默认药房 +func (r *DoctorPharmacyService) SetDefaultPharmacy(doctorId, pharmacyId int64) (bool, error) { + doctorPharmacyDao := dao.DoctorPharmacyDao{} + exist, err := doctorPharmacyDao.GetDoctorPharmacyByDoctorAndPharmacy(doctorId, pharmacyId) + if err != nil || exist == nil { + return false, errors.New("该药房未绑定,无法设为默认") + } + + tx := global.Db.Begin() + defer func() { + if rec := recover(); rec != nil { + tx.Rollback() + } + }() + + if err := doctorPharmacyDao.ResetDoctorDefaultPharmacy(tx, doctorId); err != nil { + tx.Rollback() + return false, errors.New("重置默认药房状态失败") + } + + if err := doctorPharmacyDao.SetDefaultPharmacy(tx, doctorId, pharmacyId); err != nil { + tx.Rollback() + return false, errors.New("设置默认药房失败") + } + + tx.Commit() + return true, nil +} diff --git a/api/service/userDoctor.go b/api/service/userDoctor.go index f16f5c3..83ed782 100644 --- a/api/service/userDoctor.go +++ b/api/service/userDoctor.go @@ -60,6 +60,11 @@ func (r *UserDoctorService) GetUserDoctor(doctorId int64) (getUserDoctorResponse // 加载医生专长 getUserDoctorResponse.DoctorExpertise = doctorExpertise + // 加载医生药房 + doctorPharmacyDao := dao.DoctorPharmacyDao{} + doctorPharmacies, _ := doctorPharmacyDao.GetDoctorPharmacyListByDoctorId(doctorId) + getUserDoctorResponse.DoctorPharmacy = dto.GetDoctorPharmacyListDto(doctorPharmacies) + // 加载医生银行卡 getUserDoctorResponse.LoadDoctorBankCard(doctorBankCard) @@ -552,6 +557,47 @@ func (r *UserDoctorService) PutUserDoctor(doctorId int64, req requests.PutUserDo } } + // 修改药房数据 + if len(req.DoctorPharmacy) > 0 { + doctorPharmacyDao := dao.DoctorPharmacyDao{} + + // 删除原绑定 + maps := make(map[string]interface{}) + maps["doctor_id"] = userDoctor.DoctorId + err = doctorPharmacyDao.DeleteDoctorPharmacy(tx, maps) + if err != nil { + tx.Rollback() + return false, errors.New("清空药房绑定失败") + } + + for i, v := range req.DoctorPharmacy { + pharmacyId, err := strconv.ParseInt(v, 10, 64) + if err != nil { + tx.Rollback() + return false, errors.New("药房数据错误") + } + + isDefault := 0 + if i == 0 { + isDefault = 1 + } + + // 新增药房绑定数据 + doctorPharmacy := &model.DoctorPharmacy{ + DoctorId: userDoctor.DoctorId, + PharmacyId: pharmacyId, + IsDefault: isDefault, + Status: 1, + } + + _, err = doctorPharmacyDao.AddDoctorPharmacy(tx, doctorPharmacy) + if err != nil { + tx.Rollback() + return false, errors.New(err.Error()) + } + } + } + // 修改医生银行卡数据-新增 if doctorBankCard == nil { if provinceId != 0 && cityId != 0 && countyId != 0 && bankId != 0 && bankCardCode != "" { From 0cff5b3f8d2cbfbb0f19278d3f29ba963dfd1e8a Mon Sep 17 00:00:00 2001 From: haomingming Date: Mon, 7 Sep 2026 14:44:54 +0800 Subject: [PATCH 03/16] 2 --- api/controller/doctorPharmacy.go | 224 ++++++++++++++++++++++++------- api/dao/doctorPharmacy.go | 27 ++++ api/requests/doctorPharmacy.go | 21 ++- api/router/router.go | 13 +- api/service/doctorPharmacy.go | 72 +++++++++- 5 files changed, 298 insertions(+), 59 deletions(-) diff --git a/api/controller/doctorPharmacy.go b/api/controller/doctorPharmacy.go index 1a240dc..5821429 100644 --- a/api/controller/doctorPharmacy.go +++ b/api/controller/doctorPharmacy.go @@ -2,6 +2,7 @@ package controller import ( "github.com/gin-gonic/gin" + "hospital-admin-api/api/dao" "hospital-admin-api/api/requests" "hospital-admin-api/api/responses" "hospital-admin-api/api/service" @@ -14,9 +15,12 @@ type DoctorPharmacy struct{} // GetDoctorPharmacies 获取指定医生绑定的药房列表 func (r *DoctorPharmacy) GetDoctorPharmacies(c *gin.Context) { - id := c.Param("doctor_id") + id := c.Param("id") if id == "" { - responses.FailWithMessage("缺少参数", c) + id = c.Param("doctor_id") + } + if id == "" { + responses.FailWithMessage("缺少医生ID参数", c) return } @@ -38,9 +42,12 @@ func (r *DoctorPharmacy) GetDoctorPharmacies(c *gin.Context) { // BindDoctorPharmacies 批量设置/覆盖医生绑定的药房列表 func (r *DoctorPharmacy) BindDoctorPharmacies(c *gin.Context) { - id := c.Param("doctor_id") + id := c.Param("id") if id == "" { - responses.FailWithMessage("缺少参数", c) + id = c.Param("doctor_id") + } + if id == "" { + responses.FailWithMessage("缺少医生ID参数", c) return } @@ -73,16 +80,14 @@ func (r *DoctorPharmacy) BindDoctorPharmacies(c *gin.Context) { // AddDoctorPharmacy 为医生新增单个药房绑定 func (r *DoctorPharmacy) AddDoctorPharmacy(c *gin.Context) { - id := c.Param("doctor_id") + id := c.Param("id") if id == "" { - responses.FailWithMessage("缺少参数", c) - return + id = c.Param("doctor_id") } - doctorId, err := strconv.ParseInt(id, 10, 64) - if err != nil { - responses.Fail(c) - return + var doctorId int64 + if id != "" { + doctorId, _ = strconv.ParseInt(id, 10, 64) } req := requests.AddDoctorPharmacy{} @@ -91,13 +96,22 @@ func (r *DoctorPharmacy) AddDoctorPharmacy(c *gin.Context) { return } + if doctorId == 0 && req.DoctorId != "" { + doctorId, _ = strconv.ParseInt(req.DoctorId, 10, 64) + } + + if doctorId == 0 { + responses.FailWithMessage("缺少医生ID", c) + return + } + if err := global.Validate.Struct(req); err != nil { responses.FailWithMessage(utils.Translate(err), c) return } doctorPharmacyService := service.DoctorPharmacyService{} - _, err = doctorPharmacyService.AddDoctorPharmacy(doctorId, req) + _, err := doctorPharmacyService.AddDoctorPharmacy(doctorId, req) if err != nil { responses.FailWithMessage(err.Error(), c) return @@ -106,64 +120,174 @@ func (r *DoctorPharmacy) AddDoctorPharmacy(c *gin.Context) { responses.Ok(c) } -// UnbindDoctorPharmacy 解除医生与指定药房的绑定 +// UnbindDoctorPharmacy 解除医生与指定药房的绑定(DELETE /admin/doctor/pharmacy/:id) func (r *DoctorPharmacy) UnbindDoctorPharmacy(c *gin.Context) { - docId := c.Param("doctor_id") - pharId := c.Param("pharmacy_id") - if docId == "" || pharId == "" { - responses.FailWithMessage("缺少参数", c) - return + idStr := c.Param("id") + if idStr == "" { + idStr = c.Param("doctor_pharmacy_id") } - doctorId, err := strconv.ParseInt(docId, 10, 64) - if err != nil { - responses.Fail(c) - return - } - - pharmacyId, err := strconv.ParseInt(pharId, 10, 64) - if err != nil { - responses.Fail(c) + id, err := strconv.ParseInt(idStr, 10, 64) + if err != nil || id == 0 { + responses.FailWithMessage("缺少ID参数", c) return } + doctorPharmacyDao := dao.DoctorPharmacyDao{} doctorPharmacyService := service.DoctorPharmacyService{} - _, err = doctorPharmacyService.UnbindDoctorPharmacy(doctorId, pharmacyId) - if err != nil { + + // 1. 优先作为 doctor_pharmacy_id 判定 + dp, _ := doctorPharmacyDao.GetDoctorPharmacyById(id) + if dp != nil { + _, err = doctorPharmacyService.UnbindDoctorPharmacyById(id) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + responses.Ok(c) + return + } + + // 2. 若作为 doctor_id,从 query 或 body 获取 pharmacy_id + pharmacyIdStr := c.Query("pharmacy_id") + if pharmacyIdStr != "" { + pharmacyId, err := strconv.ParseInt(pharmacyIdStr, 10, 64) + if err == nil && pharmacyId > 0 { + _, err = doctorPharmacyService.UnbindDoctorPharmacy(id, pharmacyId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + responses.Ok(c) + return + } + } + + responses.FailWithMessage("未找到绑定记录或缺少药房ID", c) +} + +// UnbindDoctorPharmacyPost 解绑药房(POST /admin/doctor/pharmacy/unbind) +func (r *DoctorPharmacy) UnbindDoctorPharmacyPost(c *gin.Context) { + req := requests.UnbindDoctorPharmacy{} + if err := c.ShouldBindJSON(&req); err != nil { responses.FailWithMessage(err.Error(), c) return } - responses.Ok(c) + doctorPharmacyService := service.DoctorPharmacyService{} + + // 优先按 doctor_pharmacy_id + if req.DoctorPharmacyId != "" { + dpid, err := strconv.ParseInt(req.DoctorPharmacyId, 10, 64) + if err == nil && dpid > 0 { + _, err = doctorPharmacyService.UnbindDoctorPharmacyById(dpid) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + responses.Ok(c) + return + } + } + + // 其次按 doctor_id + pharmacy_id + if req.DoctorId != "" && req.PharmacyId != "" { + docId, err1 := strconv.ParseInt(req.DoctorId, 10, 64) + pharId, err2 := strconv.ParseInt(req.PharmacyId, 10, 64) + if err1 == nil && err2 == nil { + _, err := doctorPharmacyService.UnbindDoctorPharmacy(docId, pharId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + responses.Ok(c) + return + } + } + + responses.FailWithMessage("缺少解绑参数", c) } -// SetDefaultDoctorPharmacy 设为医生的默认药房 +// SetDefaultDoctorPharmacy 设置默认药房(PUT /admin/doctor/pharmacy/default/:id) func (r *DoctorPharmacy) SetDefaultDoctorPharmacy(c *gin.Context) { - docId := c.Param("doctor_id") - pharId := c.Param("pharmacy_id") - if docId == "" || pharId == "" { - responses.FailWithMessage("缺少参数", c) - return - } - - doctorId, err := strconv.ParseInt(docId, 10, 64) - if err != nil { - responses.Fail(c) - return - } - - pharmacyId, err := strconv.ParseInt(pharId, 10, 64) - if err != nil { - responses.Fail(c) + idStr := c.Param("id") + id, err := strconv.ParseInt(idStr, 10, 64) + if err != nil || id == 0 { + responses.FailWithMessage("缺少ID参数", c) return } + doctorPharmacyDao := dao.DoctorPharmacyDao{} doctorPharmacyService := service.DoctorPharmacyService{} - _, err = doctorPharmacyService.SetDefaultPharmacy(doctorId, pharmacyId) - if err != nil { + + // 1. 优先作为 doctor_pharmacy_id 判定 + dp, _ := doctorPharmacyDao.GetDoctorPharmacyById(id) + if dp != nil { + _, err = doctorPharmacyService.SetDefaultPharmacyById(id) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + responses.Ok(c) + return + } + + // 2. 若作为 doctor_id,从 query 或 body 获取 pharmacy_id + pharmacyIdStr := c.Query("pharmacy_id") + if pharmacyIdStr != "" { + pharmacyId, err := strconv.ParseInt(pharmacyIdStr, 10, 64) + if err == nil && pharmacyId > 0 { + _, err = doctorPharmacyService.SetDefaultPharmacy(id, pharmacyId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + responses.Ok(c) + return + } + } + + responses.FailWithMessage("未找到绑定记录或缺少药房ID", c) +} + +// SetDefaultDoctorPharmacyPut 设置默认药房(PUT /admin/doctor/pharmacy/default) +func (r *DoctorPharmacy) SetDefaultDoctorPharmacyPut(c *gin.Context) { + req := requests.SetDefaultDoctorPharmacy{} + if err := c.ShouldBindJSON(&req); err != nil { responses.FailWithMessage(err.Error(), c) return } - responses.Ok(c) + doctorPharmacyService := service.DoctorPharmacyService{} + + // 优先按 doctor_pharmacy_id + if req.DoctorPharmacyId != "" { + dpid, err := strconv.ParseInt(req.DoctorPharmacyId, 10, 64) + if err == nil && dpid > 0 { + _, err = doctorPharmacyService.SetDefaultPharmacyById(dpid) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + responses.Ok(c) + return + } + } + + // 其次按 doctor_id + pharmacy_id + if req.DoctorId != "" && req.PharmacyId != "" { + docId, err1 := strconv.ParseInt(req.DoctorId, 10, 64) + pharId, err2 := strconv.ParseInt(req.PharmacyId, 10, 64) + if err1 == nil && err2 == nil { + _, err := doctorPharmacyService.SetDefaultPharmacy(docId, pharId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + responses.Ok(c) + return + } + } + + responses.FailWithMessage("缺少参数", c) } diff --git a/api/dao/doctorPharmacy.go b/api/dao/doctorPharmacy.go index 16a67ea..f37a28f 100644 --- a/api/dao/doctorPharmacy.go +++ b/api/dao/doctorPharmacy.go @@ -8,6 +8,15 @@ import ( type DoctorPharmacyDao struct{} +// GetDoctorPharmacyById 获取绑定关系-主键id +func (r *DoctorPharmacyDao) GetDoctorPharmacyById(doctorPharmacyId int64) (m *model.DoctorPharmacy, err error) { + err = global.Db.Where("doctor_pharmacy_id = ?", doctorPharmacyId).First(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + // GetDoctorPharmacyListByDoctorId 获取医生绑定的药房列表(带预加载药房详情) func (r *DoctorPharmacyDao) GetDoctorPharmacyListByDoctorId(doctorId int64) (m []*model.DoctorPharmacy, err error) { err = global.Db.Preload("Pharmacy").Where("doctor_id = ? AND status = 1", doctorId).Order("is_default desc, created_at desc").Find(&m).Error @@ -43,6 +52,15 @@ func (r *DoctorPharmacyDao) DeleteDoctorPharmacy(tx *gorm.DB, maps interface{}) return nil } +// DeleteDoctorPharmacyById 根据绑定关系主键id删除 +func (r *DoctorPharmacyDao) DeleteDoctorPharmacyById(tx *gorm.DB, doctorPharmacyId int64) error { + err := tx.Where("doctor_pharmacy_id = ?", doctorPharmacyId).Delete(&model.DoctorPharmacy{}).Error + if err != nil { + return err + } + return nil +} + // DeleteDoctorPharmacyByDoctorAndPharmacy 解绑指定医生和指定药房 func (r *DoctorPharmacyDao) DeleteDoctorPharmacyByDoctorAndPharmacy(tx *gorm.DB, doctorId, pharmacyId int64) error { err := tx.Where("doctor_id = ? AND pharmacy_id = ?", doctorId, pharmacyId).Delete(&model.DoctorPharmacy{}).Error @@ -69,3 +87,12 @@ func (r *DoctorPharmacyDao) SetDefaultPharmacy(tx *gorm.DB, doctorId, pharmacyId } return nil } + +// SetDefaultPharmacyById 根据主键设为默认 +func (r *DoctorPharmacyDao) SetDefaultPharmacyById(tx *gorm.DB, doctorPharmacyId int64) error { + err := tx.Model(&model.DoctorPharmacy{}).Where("doctor_pharmacy_id = ?", doctorPharmacyId).Update("is_default", 1).Error + if err != nil { + return err + } + return nil +} diff --git a/api/requests/doctorPharmacy.go b/api/requests/doctorPharmacy.go index fb32db9..9e9e982 100644 --- a/api/requests/doctorPharmacy.go +++ b/api/requests/doctorPharmacy.go @@ -1,8 +1,10 @@ package requests type DoctorPharmacyRequest struct { - BindDoctorPharmacies // 批量绑定药房 - AddDoctorPharmacy // 新增单个药房绑定 + BindDoctorPharmacies // 批量绑定药房 + AddDoctorPharmacy // 新增单个药房绑定 + UnbindDoctorPharmacy // 解绑药房 + SetDefaultDoctorPharmacy // 设置默认药房 } // BindDoctorPharmacies 批量绑定药房 @@ -13,6 +15,21 @@ type BindDoctorPharmacies struct { // AddDoctorPharmacy 单个药房绑定 type AddDoctorPharmacy struct { + DoctorId string `json:"doctor_id" form:"doctor_id" label:"医生id"` PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"药房id" validate:"required"` IsDefault *int `json:"is_default" form:"is_default" label:"是否默认" validate:"omitempty,oneof=0 1"` } + +// UnbindDoctorPharmacy 解除药房绑定 +type UnbindDoctorPharmacy struct { + DoctorPharmacyId string `json:"doctor_pharmacy_id" form:"doctor_pharmacy_id" label:"绑定关系id"` + DoctorId string `json:"doctor_id" form:"doctor_id" label:"医生id"` + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"药房id"` +} + +// SetDefaultDoctorPharmacy 设置默认药房 +type SetDefaultDoctorPharmacy struct { + DoctorPharmacyId string `json:"doctor_pharmacy_id" form:"doctor_pharmacy_id" label:"绑定关系id"` + DoctorId string `json:"doctor_id" form:"doctor_id" label:"医生id"` + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"药房id"` +} diff --git a/api/router/router.go b/api/router/router.go index 72d49f1..61defd7 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -372,22 +372,25 @@ func privateRouter(r *gin.Engine, api controller.Api) { doctorGroup.POST("", api.UserDoctor.AddUserDoctor) // 医生药房管理 - doctorPharmacyGroup := doctorGroup.Group("/:doctor_id/pharmacy") + doctorPharmacyGroup := doctorGroup.Group("/pharmacy") { // 获取医生绑定的药房列表 - doctorPharmacyGroup.GET("", api.DoctorPharmacy.GetDoctorPharmacies) + doctorPharmacyGroup.GET("/:doctor_id", api.DoctorPharmacy.GetDoctorPharmacies) // 批量设置医生绑定的药房列表 - doctorPharmacyGroup.PUT("", api.DoctorPharmacy.BindDoctorPharmacies) + doctorPharmacyGroup.PUT("/:doctor_id", api.DoctorPharmacy.BindDoctorPharmacies) // 为医生新增单个药房绑定 doctorPharmacyGroup.POST("", api.DoctorPharmacy.AddDoctorPharmacy) + doctorPharmacyGroup.POST("/:doctor_id", api.DoctorPharmacy.AddDoctorPharmacy) // 解除医生与指定药房的绑定 - doctorPharmacyGroup.DELETE("/:pharmacy_id", api.DoctorPharmacy.UnbindDoctorPharmacy) + doctorPharmacyGroup.DELETE("/:id", api.DoctorPharmacy.UnbindDoctorPharmacy) + doctorPharmacyGroup.POST("/unbind", api.DoctorPharmacy.UnbindDoctorPharmacyPost) // 设置医生的默认药房 - doctorPharmacyGroup.PUT("/default/:pharmacy_id", api.DoctorPharmacy.SetDefaultDoctorPharmacy) + doctorPharmacyGroup.PUT("/default/:id", api.DoctorPharmacy.SetDefaultDoctorPharmacy) + doctorPharmacyGroup.PUT("/default", api.DoctorPharmacy.SetDefaultDoctorPharmacyPut) } // 身份审核列表 diff --git a/api/service/doctorPharmacy.go b/api/service/doctorPharmacy.go index da9059b..6d19038 100644 --- a/api/service/doctorPharmacy.go +++ b/api/service/doctorPharmacy.go @@ -95,6 +95,13 @@ func (r *DoctorPharmacyService) BindDoctorPharmacies(doctorId int64, req request // AddDoctorPharmacy 新增单个药房绑定 func (r *DoctorPharmacyService) AddDoctorPharmacy(doctorId int64, req requests.AddDoctorPharmacy) (bool, error) { + if doctorId == 0 && req.DoctorId != "" { + doctorId, _ = strconv.ParseInt(req.DoctorId, 10, 64) + } + if doctorId == 0 { + return false, errors.New("医生id无效") + } + pharmacyId, err := strconv.ParseInt(req.PharmacyId, 10, 64) if err != nil || pharmacyId == 0 { return false, errors.New("药房id无效") @@ -157,7 +164,39 @@ func (r *DoctorPharmacyService) AddDoctorPharmacy(doctorId int64, req requests.A return true, nil } -// UnbindDoctorPharmacy 解绑单个药房 +// UnbindDoctorPharmacyById 根据绑定记录ID解绑 +func (r *DoctorPharmacyService) UnbindDoctorPharmacyById(doctorPharmacyId int64) (bool, error) { + doctorPharmacyDao := dao.DoctorPharmacyDao{} + exist, err := doctorPharmacyDao.GetDoctorPharmacyById(doctorPharmacyId) + if err != nil || exist == nil { + return false, errors.New("未找到绑定记录") + } + + tx := global.Db.Begin() + defer func() { + if rec := recover(); rec != nil { + tx.Rollback() + } + }() + + if err := doctorPharmacyDao.DeleteDoctorPharmacyById(tx, doctorPharmacyId); err != nil { + tx.Rollback() + return false, errors.New("解绑失败") + } + + // 如果解绑的是默认药房,尝试将剩余的第一个药房设为默认 + if exist.IsDefault == 1 { + list, _ := doctorPharmacyDao.GetDoctorPharmacyListByDoctorId(exist.DoctorId) + if len(list) > 0 { + _ = doctorPharmacyDao.SetDefaultPharmacy(tx, exist.DoctorId, list[0].PharmacyId) + } + } + + tx.Commit() + return true, nil +} + +// UnbindDoctorPharmacy 解绑单个药房(支持通过 doctor_pharmacy_id 或 (doctor_id, pharmacy_id)) func (r *DoctorPharmacyService) UnbindDoctorPharmacy(doctorId, pharmacyId int64) (bool, error) { doctorPharmacyDao := dao.DoctorPharmacyDao{} exist, err := doctorPharmacyDao.GetDoctorPharmacyByDoctorAndPharmacy(doctorId, pharmacyId) @@ -189,7 +228,36 @@ func (r *DoctorPharmacyService) UnbindDoctorPharmacy(doctorId, pharmacyId int64) return true, nil } -// SetDefaultPharmacy 设为默认药房 +// SetDefaultPharmacyById 根据绑定关系主键设为默认 +func (r *DoctorPharmacyService) SetDefaultPharmacyById(doctorPharmacyId int64) (bool, error) { + doctorPharmacyDao := dao.DoctorPharmacyDao{} + exist, err := doctorPharmacyDao.GetDoctorPharmacyById(doctorPharmacyId) + if err != nil || exist == nil { + return false, errors.New("该药房未绑定,无法设为默认") + } + + tx := global.Db.Begin() + defer func() { + if rec := recover(); rec != nil { + tx.Rollback() + } + }() + + if err := doctorPharmacyDao.ResetDoctorDefaultPharmacy(tx, exist.DoctorId); err != nil { + tx.Rollback() + return false, errors.New("重置默认药房状态失败") + } + + if err := doctorPharmacyDao.SetDefaultPharmacyById(tx, doctorPharmacyId); err != nil { + tx.Rollback() + return false, errors.New("设置默认药房失败") + } + + tx.Commit() + return true, nil +} + +// SetDefaultPharmacy 设为默认药房(通过 doctor_id 和 pharmacy_id) func (r *DoctorPharmacyService) SetDefaultPharmacy(doctorId, pharmacyId int64) (bool, error) { doctorPharmacyDao := dao.DoctorPharmacyDao{} exist, err := doctorPharmacyDao.GetDoctorPharmacyByDoctorAndPharmacy(doctorId, pharmacyId) From 338d56beda5acd473a2f59c53085e5673918a8a9 Mon Sep 17 00:00:00 2001 From: haomingming Date: Mon, 7 Sep 2026 15:21:06 +0800 Subject: [PATCH 04/16] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E8=8D=AF=E6=88=BF?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E5=8C=BB=E7=94=9F=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/controller/pharmacy.go | 50 ++++++++++++++++++++++++ api/dao/doctorPharmacy.go | 49 +++++++++++++++++++++++ api/dto/PharmacyDoctor.go | 78 +++++++++++++++++++++++++++++++++++++ api/model/doctorPharmacy.go | 3 +- api/requests/pharmacy.go | 26 ++++++++++--- api/router/router.go | 6 +++ api/service/pharmacy.go | 54 +++++++++++++++++++++++++ 7 files changed, 260 insertions(+), 6 deletions(-) create mode 100644 api/dto/PharmacyDoctor.go diff --git a/api/controller/pharmacy.go b/api/controller/pharmacy.go index 302e64d..3d725ce 100644 --- a/api/controller/pharmacy.go +++ b/api/controller/pharmacy.go @@ -232,3 +232,53 @@ func (r *Pharmacy) DeletePharmacy(c *gin.Context) { responses.Ok(c) } + +// GetPharmacyDoctorPage 获取药房绑定的医生列表-分页 +func (r *Pharmacy) GetPharmacyDoctorPage(c *gin.Context) { + req := requests.GetPharmacyDoctorPage{} + if err := c.ShouldBindJSON(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + pharmacyService := service.PharmacyService{} + result, err := pharmacyService.GetPharmacyDoctorPage(req) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.OkWithData(result, c) +} + +// GetPharmacyDoctorList 获取药房绑定的医生列表 +func (r *Pharmacy) GetPharmacyDoctorList(c *gin.Context) { + id := c.Param("pharmacy_id") + if id == "" { + id = c.Param("id") + } + if id == "" { + responses.FailWithMessage("缺少药房ID参数", c) + return + } + + pharmacyId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + pharmacyService := service.PharmacyService{} + list, err := pharmacyService.GetPharmacyDoctorList(pharmacyId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.OkWithData(list, c) +} diff --git a/api/dao/doctorPharmacy.go b/api/dao/doctorPharmacy.go index f37a28f..1abf340 100644 --- a/api/dao/doctorPharmacy.go +++ b/api/dao/doctorPharmacy.go @@ -96,3 +96,52 @@ func (r *DoctorPharmacyDao) SetDefaultPharmacyById(tx *gorm.DB, doctorPharmacyId } return nil } + +// GetPharmacyDoctorPageSearch 获取药房绑定的医生列表-分页 +func (r *DoctorPharmacyDao) GetPharmacyDoctorPageSearch(pharmacyId int64, req requests.GetPharmacyDoctorPage, page, pageSize int) (m []*model.DoctorPharmacy, total int64, err error) { + var totalRecords int64 + + query := global.Db.Model(&model.DoctorPharmacy{}). + Where("gdxz_doctor_pharmacy.pharmacy_id = ? AND gdxz_doctor_pharmacy.status = 1", pharmacyId) + + // 如果有医生姓名或手机号筛选,做表连接 + needJoinDoctor := req.DoctorName != "" || req.Mobile != "" + if needJoinDoctor { + query = query.Joins("JOIN gdxz_user_doctor ON gdxz_user_doctor.doctor_id = gdxz_doctor_pharmacy.doctor_id") + if req.DoctorName != "" { + query = query.Where("gdxz_user_doctor.user_name LIKE ?", "%"+req.DoctorName+"%") + } + if req.Mobile != "" { + query = query.Joins("JOIN gdxz_user ON gdxz_user.user_id = gdxz_user_doctor.user_id"). + Where("gdxz_user.mobile LIKE ?", "%"+req.Mobile+"%") + } + } + + if err := query.Count(&totalRecords).Error; err != nil { + return nil, 0, err + } + + err = query.Order("gdxz_doctor_pharmacy.is_default desc, gdxz_doctor_pharmacy.created_at desc"). + Preload("UserDoctor.User"). + Preload("UserDoctor.Hospital"). + Scopes(model.Paginate(page, pageSize)). + Find(&m).Error + if err != nil { + return nil, 0, err + } + + return m, totalRecords, nil +} + +// GetPharmacyDoctorListByPharmacyId 获取药房绑定的所有医生列表 +func (r *DoctorPharmacyDao) GetPharmacyDoctorListByPharmacyId(pharmacyId int64) (m []*model.DoctorPharmacy, err error) { + err = global.Db.Preload("UserDoctor.User"). + Preload("UserDoctor.Hospital"). + Where("pharmacy_id = ? AND status = 1", pharmacyId). + Order("is_default desc, created_at desc"). + Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} diff --git a/api/dto/PharmacyDoctor.go b/api/dto/PharmacyDoctor.go new file mode 100644 index 0000000..9f4f59e --- /dev/null +++ b/api/dto/PharmacyDoctor.go @@ -0,0 +1,78 @@ +package dto + +import ( + "fmt" + "hospital-admin-api/api/model" +) + +type PharmacyDoctorDto struct { + DoctorPharmacyId string `json:"doctor_pharmacy_id"` // 绑定关系id + DoctorId string `json:"doctor_id"` // 医生id + UserId string `json:"user_id"` // 用户id + UserName string `json:"user_name"` // 医生姓名 + Avatar string `json:"avatar"` // 头像 + DoctorTitle int `json:"doctor_title"` // 职称代码 + DoctorTitleName string `json:"doctor_title_name"` // 职称名称 + DepartmentCustomId string `json:"department_custom_id"` // 科室id + DepartmentCustomName string `json:"department_custom_name"` // 科室名称 + DepartmentCustomMobile string `json:"department_custom_mobile"` // 科室电话 + HospitalId string `json:"hospital_id"` // 医院id + HospitalName string `json:"hospital_name"` // 医院名称 + Mobile string `json:"mobile"` // 手机号 + IsDefault int `json:"is_default"` // 是否为默认药房(0:否 1:是) + Status int `json:"status"` // 状态(1:正常) + BindTime model.LocalTime `json:"bind_time"` // 绑定时间 +} + +var doctorTitleMap = map[int]string{ + 1: "主任医师", + 2: "主任中医师", + 3: "副主任医师", + 4: "副主任中医师", + 5: "主治医师", + 6: "住院医师", +} + +func GetPharmacyDoctorDto(m *model.DoctorPharmacy) *PharmacyDoctorDto { + if m == nil { + return nil + } + + dto := &PharmacyDoctorDto{ + DoctorPharmacyId: fmt.Sprintf("%d", m.DoctorPharmacyId), + DoctorId: fmt.Sprintf("%d", m.DoctorId), + IsDefault: m.IsDefault, + Status: m.Status, + BindTime: m.CreatedAt, + } + + if m.UserDoctor != nil { + dto.UserId = fmt.Sprintf("%d", m.UserDoctor.UserId) + dto.UserName = m.UserDoctor.UserName + dto.Avatar = m.UserDoctor.Avatar + dto.DoctorTitle = m.UserDoctor.DoctorTitle + dto.DoctorTitleName = doctorTitleMap[m.UserDoctor.DoctorTitle] + dto.DepartmentCustomId = fmt.Sprintf("%d", m.UserDoctor.DepartmentCustomId) + dto.DepartmentCustomName = m.UserDoctor.DepartmentCustomName + dto.DepartmentCustomMobile = m.UserDoctor.DepartmentCustomMobile + dto.HospitalId = fmt.Sprintf("%d", m.UserDoctor.HospitalID) + + if m.UserDoctor.Hospital != nil { + dto.HospitalName = m.UserDoctor.Hospital.HospitalName + } + + if m.UserDoctor.User != nil { + dto.Mobile = m.UserDoctor.User.Mobile + } + } + + return dto +} + +func GetPharmacyDoctorListDto(list []*model.DoctorPharmacy) []PharmacyDoctorDto { + res := make([]PharmacyDoctorDto, len(list)) + for i, v := range list { + res[i] = *GetPharmacyDoctorDto(v) + } + return res +} diff --git a/api/model/doctorPharmacy.go b/api/model/doctorPharmacy.go index ab35604..737aa90 100644 --- a/api/model/doctorPharmacy.go +++ b/api/model/doctorPharmacy.go @@ -14,7 +14,8 @@ type DoctorPharmacy struct { IsDefault int `gorm:"column:is_default;type:tinyint(1);default:0;comment:是否默认药房(0:否 1:是)" json:"is_default"` Status int `gorm:"column:status;type:tinyint(1);default:1;comment:状态(0:禁用 1:正常)" json:"status"` Model - Pharmacy *Pharmacy `gorm:"foreignKey:PharmacyId;references:pharmacy_id" json:"pharmacy"` + Pharmacy *Pharmacy `gorm:"foreignKey:PharmacyId;references:pharmacy_id" json:"pharmacy"` + UserDoctor *UserDoctor `gorm:"foreignKey:DoctorId;references:doctor_id" json:"user_doctor"` } func (m *DoctorPharmacy) TableName() string { diff --git a/api/requests/pharmacy.go b/api/requests/pharmacy.go index 65e6372..d51d6b3 100644 --- a/api/requests/pharmacy.go +++ b/api/requests/pharmacy.go @@ -1,11 +1,27 @@ package requests type PharmacyRequest struct { - GetPharmacyList // 获取药房列表 - GetPharmacyPage // 获取药房列表-分页 - AddPharmacy // 新增药房 - PutPharmacy // 修改药房 - PutPharmacyStatus // 修改药房状态 + GetPharmacyList // 获取药房列表 + GetPharmacyPage // 获取药房列表-分页 + AddPharmacy // 新增药房 + PutPharmacy // 修改药房 + PutPharmacyStatus // 修改药房状态 + GetPharmacyDoctorPage // 药房绑定的医生列表-分页 + GetPharmacyDoctorList // 药房绑定的医生列表 +} + +// GetPharmacyDoctorPage 药房绑定的医生列表-分页 +type GetPharmacyDoctorPage struct { + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"药房id" validate:"required"` + DoctorName string `json:"doctor_name" form:"doctor_name" label:"医生姓名"` + Mobile string `json:"mobile" form:"mobile" label:"手机号"` + Page int `json:"page" form:"page" label:"页码"` + PageSize int `json:"page_size" form:"page_size" label:"每页个数"` +} + +// GetPharmacyDoctorList 药房绑定的医生列表 +type GetPharmacyDoctorList struct { + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"药房id"` } // GetPharmacyList 获取药房列表 diff --git a/api/router/router.go b/api/router/router.go index 61defd7..62b3914 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -937,6 +937,12 @@ func privateRouter(r *gin.Engine, api controller.Api) { // 删除药房 pharmacyGroup.DELETE("/:pharmacy_id", api.Pharmacy.DeletePharmacy) + + // 药房绑定的医生列表-分页 + pharmacyGroup.POST("/doctor/page", api.Pharmacy.GetPharmacyDoctorPage) + + // 药房绑定的医生列表 + pharmacyGroup.GET("/doctor/:pharmacy_id", api.Pharmacy.GetPharmacyDoctorList) } // 科普分类管理 diff --git a/api/service/pharmacy.go b/api/service/pharmacy.go index 800b688..c9595a5 100644 --- a/api/service/pharmacy.go +++ b/api/service/pharmacy.go @@ -9,6 +9,7 @@ import ( "hospital-admin-api/api/model" "hospital-admin-api/api/requests" "hospital-admin-api/global" + "strconv" ) type PharmacyService struct{} @@ -259,3 +260,56 @@ func (r *PharmacyService) GetPharmacy(pharmacyId int64) (*dto.PharmacyDto, error return dto.GetPharmacyDto(pharmacy), nil } + +// GetPharmacyDoctorPage 获取药房绑定的医生列表-分页 +func (r *PharmacyService) GetPharmacyDoctorPage(req requests.GetPharmacyDoctorPage) (map[string]interface{}, error) { + pharmacyId, err := strconv.ParseInt(req.PharmacyId, 10, 64) + if err != nil || pharmacyId == 0 { + return nil, errors.New("药房id无效") + } + + pharmacyDao := dao.PharmacyDao{} + pharmacy, err := pharmacyDao.GetPharmacyById(pharmacyId) + if err != nil || pharmacy == nil { + return nil, errors.New("药房不存在或已被删除") + } + + if req.Page <= 0 { + req.Page = 1 + } + if req.PageSize <= 0 { + req.PageSize = 20 + } + + doctorPharmacyDao := dao.DoctorPharmacyDao{} + list, total, err := doctorPharmacyDao.GetPharmacyDoctorPageSearch(pharmacyId, req, req.Page, req.PageSize) + if err != nil { + return nil, err + } + + resList := dto.GetPharmacyDoctorListDto(list) + + result := make(map[string]interface{}) + result["page"] = req.Page + result["page_size"] = req.PageSize + result["total"] = total + result["data"] = resList + return result, nil +} + +// GetPharmacyDoctorList 获取药房绑定的全部医生列表 +func (r *PharmacyService) GetPharmacyDoctorList(pharmacyId int64) ([]dto.PharmacyDoctorDto, error) { + pharmacyDao := dao.PharmacyDao{} + pharmacy, err := pharmacyDao.GetPharmacyById(pharmacyId) + if err != nil || pharmacy == nil { + return nil, errors.New("药房不存在或已被删除") + } + + doctorPharmacyDao := dao.DoctorPharmacyDao{} + list, err := doctorPharmacyDao.GetPharmacyDoctorListByPharmacyId(pharmacyId) + if err != nil { + return nil, err + } + + return dto.GetPharmacyDoctorListDto(list), nil +} From 5f2baaace7cd3f8c251d205b11a93f4d14d1daf3 Mon Sep 17 00:00:00 2001 From: haomingming Date: Mon, 7 Sep 2026 15:27:45 +0800 Subject: [PATCH 05/16] 2 --- api/dao/doctorPharmacy.go | 1 + 1 file changed, 1 insertion(+) diff --git a/api/dao/doctorPharmacy.go b/api/dao/doctorPharmacy.go index 1abf340..23694de 100644 --- a/api/dao/doctorPharmacy.go +++ b/api/dao/doctorPharmacy.go @@ -3,6 +3,7 @@ package dao import ( "gorm.io/gorm" "hospital-admin-api/api/model" + "hospital-admin-api/api/requests" "hospital-admin-api/global" ) From 3205005b9a4f1361881acee9f68a5d6f277c9dd5 Mon Sep 17 00:00:00 2001 From: haomingming Date: Mon, 7 Sep 2026 16:25:04 +0800 Subject: [PATCH 06/16] =?UTF-8?q?=E8=8D=AF=E5=93=81=E3=80=81=E5=A4=84?= =?UTF-8?q?=E6=96=B9=E5=88=97=E8=A1=A8=E5=85=B3=E8=81=94=E8=8D=AF=E6=88=BF?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/dao/orderPrescription.go | 59 +++++++++++++++++++++++++++++++ api/dao/orderProduct.go | 28 +++++++++++++++ api/dto/OrderPrescription.go | 38 ++++++++++++++++++++ api/dto/OrderProduct.go | 38 ++++++++++++++++++++ api/model/orderPrescription.go | 4 +++ api/model/orderProduct.go | 4 +++ api/requests/orderPrescription.go | 6 ++++ api/requests/orderProduct.go | 6 ++++ api/service/export.go | 34 ++++++++++++++++++ api/service/order.go | 8 ++++- 10 files changed, 224 insertions(+), 1 deletion(-) diff --git a/api/dao/orderPrescription.go b/api/dao/orderPrescription.go index a95829b..d93616b 100644 --- a/api/dao/orderPrescription.go +++ b/api/dao/orderPrescription.go @@ -27,6 +27,9 @@ func (r *OrderPrescriptionDao) GetById(orderPrescriptionId int64) (m *model.Orde }) }) + // 药房 + query = query.Preload("Pharmacy") + err = query.First(&m, orderPrescriptionId).Error if err != nil { return nil, err @@ -100,6 +103,9 @@ func (r *OrderPrescriptionDao) GetOrderPrescriptionPageSearch(req requests.GetOr query = query.Where("gdxz_order_inquiry.annual_review_hide = ?", req.AnnualReviewHide) } + // 药房表 + query = query.Preload("Pharmacy") + // 患者表 query = query.Preload("UserPatient", func(db *gorm.DB) *gorm.DB { return db.Omit("open_id", "union_id", "wx_session_key") @@ -130,6 +136,17 @@ func (r *OrderPrescriptionDao) GetOrderPrescriptionPageSearch(req requests.GetOr // 患者家庭成员表 query = query.Preload("PatientFamily") + // 药房筛选 + if req.PharmacyId != "" { + query = query.Where("gdxz_order_prescription.pharmacy_id = ?", req.PharmacyId) + } + if req.PharmacyCode != "" { + query = query.Where("gdxz_order_prescription.pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") + } + if req.PharmacyName != "" { + query = query.Where("gdxz_order_prescription.pharmacy_name LIKE ?", "%"+req.PharmacyName+"%") + } + // 处方编号 if req.PrescriptionCode != "" { query = query.Where("prescription_code = ?", req.PrescriptionCode) @@ -311,6 +328,20 @@ func (r *OrderPrescriptionDao) GetOrderPrescriptionTransferPageSearch(req reques // 患者家庭成员表 query = query.Preload("PatientFamily") + // 药房表 + query = query.Preload("Pharmacy") + + // 药房筛选 + if req.PharmacyId != "" { + query = query.Where(prescriptionTable+".pharmacy_id = ?", req.PharmacyId) + } + if req.PharmacyCode != "" { + query = query.Where(prescriptionTable+".pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") + } + if req.PharmacyName != "" { + query = query.Where(prescriptionTable+".pharmacy_name LIKE ?", "%"+req.PharmacyName+"%") + } + // 处方编号 if req.PrescriptionCode != "" { query = query.Where(prescriptionTable+".prescription_code = ?", req.PrescriptionCode) @@ -504,8 +535,22 @@ func (r *OrderPrescriptionDao) GetOrderTransferPrescriptionExportListSearch(req // 患者家庭成员表 query = query.Preload("PatientFamily") + // 药房表 + query = query.Preload("Pharmacy") + // 当前搜索数据 if req.Type == 1 { + // 药房筛选 + if req.PharmacyId != "" { + query = query.Where(prescriptionTable+".pharmacy_id = ?", req.PharmacyId) + } + if req.PharmacyCode != "" { + query = query.Where(prescriptionTable+".pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") + } + if req.PharmacyName != "" { + query = query.Where(prescriptionTable+".pharmacy_name LIKE ?", "%"+req.PharmacyName+"%") + } + // 处方编号 if req.PrescriptionCode != "" { query = query.Where("prescription_code = ?", req.PrescriptionCode) @@ -687,8 +732,22 @@ func (r *OrderPrescriptionDao) GetOrderPrescriptionExportListSearch(req requests // 患者家庭成员表 query = query.Preload("PatientFamily") + // 药房表 + query = query.Preload("Pharmacy") + // 当前搜索数据 if req.Type == 1 { + // 药房筛选 + if req.PharmacyId != "" { + query = query.Where("gdxz_order_prescription.pharmacy_id = ?", req.PharmacyId) + } + if req.PharmacyCode != "" { + query = query.Where("gdxz_order_prescription.pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") + } + if req.PharmacyName != "" { + query = query.Where("gdxz_order_prescription.pharmacy_name LIKE ?", "%"+req.PharmacyName+"%") + } + // 处方编号 if req.PrescriptionCode != "" { query = query.Where("prescription_code = ?", req.PrescriptionCode) diff --git a/api/dao/orderProduct.go b/api/dao/orderProduct.go index 4d528b1..cc2b496 100644 --- a/api/dao/orderProduct.go +++ b/api/dao/orderProduct.go @@ -132,6 +132,20 @@ func (r *OrderProductDao) GetOrderProductPageSearch(req requests.GetOrderProduct // 药品数据 query = query.Preload("OrderProductItem") + // 药房数据 + query = query.Preload("Pharmacy") + + // 药房筛选 + if req.PharmacyId != "" { + query = query.Where("gdxz_order_product.pharmacy_id = ?", req.PharmacyId) + } + if req.PharmacyCode != "" { + query = query.Where("gdxz_order_product.pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") + } + if req.PharmacyName != "" { + query = query.Where("gdxz_order_product.pharmacy_name LIKE ?", "%"+req.PharmacyName+"%") + } + // 医生 query = query.Preload("UserDoctor", func(db *gorm.DB) *gorm.DB { return db.Omit("open_id", "union_id", "wx_session_key") @@ -463,8 +477,22 @@ func (r *OrderProductDao) GetOrderProductExportListSearch(req requests.OrderProd // 药品列表-药品 query = query.Preload("OrderProductItem.Product") + // 药房数据 + query = query.Preload("Pharmacy") + // 当前搜索数据 if req.Type == 1 { + // 药房筛选 + if req.PharmacyId != "" { + query = query.Where("gdxz_order_product.pharmacy_id = ?", req.PharmacyId) + } + if req.PharmacyCode != "" { + query = query.Where("gdxz_order_product.pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") + } + if req.PharmacyName != "" { + query = query.Where("gdxz_order_product.pharmacy_name LIKE ?", "%"+req.PharmacyName+"%") + } + // 医生姓名 - 同时查询原医生和抄方医生 if req.DoctorName != "" { // 原医生查询条件 diff --git a/api/dto/OrderPrescription.go b/api/dto/OrderPrescription.go index 52e5c85..b2fc8c1 100644 --- a/api/dto/OrderPrescription.go +++ b/api/dto/OrderPrescription.go @@ -40,11 +40,28 @@ type OrderPrescriptionDto struct { UserDoctor *UserDoctorDto `json:"user_doctor"` // 原始医生 InquiryDoctor *UserDoctorDto `json:"inquiry_doctor"` // 问诊医生信息 TransferUserDoctor *UserDoctorDto `json:"transfer_prescription_doctor"` // 接受抄方的医生(抄方处方医生信息) + PharmacyId string `json:"pharmacy_id"` // 药房id + PharmacyCode string `json:"pharmacy_code"` // 药房代码 + PharmacyName string `json:"pharmacy_name"` // 药房名称 + Pharmacy *PharmacyDto `json:"pharmacy"` // 药房详情 CreatedAt model.LocalTime `json:"created_at"` // 创建时间 UpdatedAt model.LocalTime `json:"updated_at"` // 修改时间 } func GetOrderPrescriptionDto(m *model.OrderPrescription) *OrderPrescriptionDto { + pharmacyName := m.PharmacyName + pharmacyCode := m.PharmacyCode + var pharmacyDto *PharmacyDto + if m.Pharmacy != nil { + pharmacyDto = GetPharmacyDto(m.Pharmacy) + if pharmacyName == "" { + pharmacyName = m.Pharmacy.PharmacyName + } + if pharmacyCode == "" { + pharmacyCode = m.Pharmacy.PharmacyCode + } + } + return &OrderPrescriptionDto{ OrderPrescriptionId: fmt.Sprintf("%d", m.OrderPrescriptionId), OrderInquiryId: fmt.Sprintf("%d", m.OrderInquiryId), @@ -69,6 +86,10 @@ func GetOrderPrescriptionDto(m *model.OrderPrescription) *OrderPrescriptionDto { PatientSex: m.PatientSex, PatientAge: m.PatientAge, DoctorAdvice: m.DoctorAdvice, + PharmacyId: fmt.Sprintf("%d", m.PharmacyId), + PharmacyCode: pharmacyCode, + PharmacyName: pharmacyName, + Pharmacy: pharmacyDto, CreatedAt: m.CreatedAt, UpdatedAt: m.UpdatedAt, } @@ -80,6 +101,19 @@ func GetOrderPrescriptionListDto(m []*model.OrderPrescription) []*OrderPrescript if len(m) > 0 { for i, v := range m { + pharmacyName := v.PharmacyName + pharmacyCode := v.PharmacyCode + var pharmacyDto *PharmacyDto + if v.Pharmacy != nil { + pharmacyDto = GetPharmacyDto(v.Pharmacy) + if pharmacyName == "" { + pharmacyName = v.Pharmacy.PharmacyName + } + if pharmacyCode == "" { + pharmacyCode = v.Pharmacy.PharmacyCode + } + } + response := &OrderPrescriptionDto{ OrderPrescriptionId: fmt.Sprintf("%d", v.OrderPrescriptionId), OrderInquiryId: fmt.Sprintf("%d", v.OrderInquiryId), @@ -104,6 +138,10 @@ func GetOrderPrescriptionListDto(m []*model.OrderPrescription) []*OrderPrescript PatientSex: v.PatientSex, PatientAge: v.PatientAge, DoctorAdvice: v.DoctorAdvice, + PharmacyId: fmt.Sprintf("%d", v.PharmacyId), + PharmacyCode: pharmacyCode, + PharmacyName: pharmacyName, + Pharmacy: pharmacyDto, CreatedAt: v.CreatedAt, UpdatedAt: v.UpdatedAt, } diff --git a/api/dto/OrderProduct.go b/api/dto/OrderProduct.go index 5a5c951..619b02a 100644 --- a/api/dto/OrderProduct.go +++ b/api/dto/OrderProduct.go @@ -65,6 +65,10 @@ type OrderProductDto struct { OrderProductCoupon *OrderProductCouponDto `json:"order_product_coupon"` // 优惠卷 ProductName string `json:"product_name"` // 药品数据 DiscountAmount float64 `json:"discount_amount"` // 优惠金额 + PharmacyId string `json:"pharmacy_id"` // 药房id + PharmacyCode string `json:"pharmacy_code"` // 药房代码 + PharmacyName string `json:"pharmacy_name"` // 药房名称 + Pharmacy *PharmacyDto `json:"pharmacy"` // 药房详情 } // OrderProductConsigneeDto 药品订单收货人数据 @@ -81,6 +85,19 @@ type OrderProductConsigneeDto struct { } func GetOrderProductDto(m *model.OrderProduct) *OrderProductDto { + pharmacyName := m.PharmacyName + pharmacyCode := m.PharmacyCode + var pharmacyDto *PharmacyDto + if m.Pharmacy != nil { + pharmacyDto = GetPharmacyDto(m.Pharmacy) + if pharmacyName == "" { + pharmacyName = m.Pharmacy.PharmacyName + } + if pharmacyCode == "" { + pharmacyCode = m.Pharmacy.PharmacyCode + } + } + return &OrderProductDto{ OrderProductId: fmt.Sprintf("%d", m.OrderProductId), OrderInquiryId: fmt.Sprintf("%d", m.OrderInquiryId), @@ -117,6 +134,10 @@ func GetOrderProductDto(m *model.OrderProduct) *OrderProductDto { AddressMask: m.AddressMask, ConsigneeNameMask: m.ConsigneeNameMask, ConsigneeTelMask: m.ConsigneeTelMask, + PharmacyId: fmt.Sprintf("%d", m.PharmacyId), + PharmacyCode: pharmacyCode, + PharmacyName: pharmacyName, + Pharmacy: pharmacyDto, CreatedAt: m.CreatedAt, UpdatedAt: m.UpdatedAt, } @@ -143,6 +164,19 @@ func GetOrderProductListDto(m []*model.OrderProduct) []*OrderProductDto { if len(m) > 0 { for i, v := range m { + pharmacyName := v.PharmacyName + pharmacyCode := v.PharmacyCode + var pharmacyDto *PharmacyDto + if v.Pharmacy != nil { + pharmacyDto = GetPharmacyDto(v.Pharmacy) + if pharmacyName == "" { + pharmacyName = v.Pharmacy.PharmacyName + } + if pharmacyCode == "" { + pharmacyCode = v.Pharmacy.PharmacyCode + } + } + response := &OrderProductDto{ OrderProductId: fmt.Sprintf("%d", v.OrderProductId), OrderInquiryId: fmt.Sprintf("%d", v.OrderInquiryId), @@ -169,6 +203,10 @@ func GetOrderProductListDto(m []*model.OrderProduct) []*OrderProductDto { ConsigneeNameMask: v.ConsigneeNameMask, ConsigneeTelMask: v.ConsigneeTelMask, PatientMobile: v.UserPatient.User.Mobile, + PharmacyId: fmt.Sprintf("%d", v.PharmacyId), + PharmacyCode: pharmacyCode, + PharmacyName: pharmacyName, + Pharmacy: pharmacyDto, CreatedAt: v.CreatedAt, UpdatedAt: v.UpdatedAt, } diff --git a/api/model/orderPrescription.go b/api/model/orderPrescription.go index d162ea8..8f1717c 100644 --- a/api/model/orderPrescription.go +++ b/api/model/orderPrescription.go @@ -31,12 +31,16 @@ type OrderPrescription struct { PatientSex int `gorm:"column:patient_sex;type:tinyint(1);comment:患者性别-就诊人(1:男 2:女)" json:"patient_sex"` PatientAge int `gorm:"column:patient_age;type:int(11);comment:患者年龄-就诊人" json:"patient_age"` DoctorAdvice string `gorm:"column:doctor_advice;type:varchar(255);comment:医嘱" json:"doctor_advice"` + PharmacyId int64 `gorm:"column:pharmacy_id;type:bigint(19);default:0;comment:开方药房id" json:"pharmacy_id"` + PharmacyCode string `gorm:"column:pharmacy_code;type:varchar(64);comment:开方药房代码快照" json:"pharmacy_code"` + PharmacyName string `gorm:"column:pharmacy_name;type:varchar(100);comment:开方药房名称快照" json:"pharmacy_name"` OrderInquiry *OrderInquiry `gorm:"foreignKey:OrderInquiryId;references:order_inquiry_id" json:"order_inquiry"` // 问诊订单 UserDoctor *UserDoctor `gorm:"foreignKey:DoctorId;references:doctor_id" json:"user_doctor"` // 医生 UserPharmacist *UserPharmacist `gorm:"foreignKey:PharmacistId;references:pharmacist_id" json:"user_pharmacist"` // 药师 UserPatient *UserPatient `gorm:"foreignKey:PatientId;references:patient_id" json:"user_patient"` // 患者 OrderPrescriptionIcd []*OrderPrescriptionIcd `gorm:"foreignKey:OrderPrescriptionId;references:order_prescription_id" json:"order_prescription_icd"` // 处方疾病 PatientFamily *PatientFamily `gorm:"foreignKey:FamilyId;references:family_id" json:"patient_family"` // 家庭成员 + Pharmacy *Pharmacy `gorm:"foreignKey:PharmacyId;references:pharmacy_id" json:"pharmacy"` // 药房 Model } diff --git a/api/model/orderProduct.go b/api/model/orderProduct.go index 836f1e8..c92d0c6 100644 --- a/api/model/orderProduct.go +++ b/api/model/orderProduct.go @@ -50,11 +50,15 @@ type OrderProduct struct { ConsigneeNameMask string `gorm:"column:consignee_name_mask;type:varchar(150);comment:收货人姓名(掩码)" json:"consignee_name_mask"` ConsigneeTel string `gorm:"column:consignee_tel;type:varchar(50);comment:收货人电话" json:"consignee_tel"` ConsigneeTelMask string `gorm:"column:consignee_tel_mask;type:varchar(50);comment:收货人电话(掩码)" json:"consignee_tel_mask"` + PharmacyId int64 `gorm:"column:pharmacy_id;type:bigint(19);default:0;comment:发货药房id" json:"pharmacy_id"` + PharmacyCode string `gorm:"column:pharmacy_code;type:varchar(64);comment:发货药房代码快照" json:"pharmacy_code"` + PharmacyName string `gorm:"column:pharmacy_name;type:varchar(100);comment:发货药房名称快照" json:"pharmacy_name"` UserDoctor *UserDoctor `gorm:"foreignKey:DoctorId;references:doctor_id" json:"user_doctor"` // 医生 OrderInquiry *OrderInquiry `gorm:"foreignKey:OrderInquiryId;references:order_inquiry_id" json:"order_inquiry"` // 问诊 UserPatient *UserPatient `gorm:"foreignKey:PatientId;references:patient_id" json:"user_patient"` // 患者 OrderPrescription *OrderPrescription `gorm:"foreignKey:OrderPrescriptionId;references:order_prescription_id" json:"order_prescription"` // 处方 OrderProductItem []*OrderProductItem `gorm:"foreignKey:OrderProductId;references:order_product_id" json:"order_product_item"` // 处方 + Pharmacy *Pharmacy `gorm:"foreignKey:PharmacyId;references:pharmacy_id" json:"pharmacy"` // 药房 Model } diff --git a/api/requests/orderPrescription.go b/api/requests/orderPrescription.go index f68256f..532cc01 100644 --- a/api/requests/orderPrescription.go +++ b/api/requests/orderPrescription.go @@ -20,6 +20,9 @@ type GetOrderPrescriptionPage struct { ExpiredTime string `json:"expired_time" form:"expired_time" label:"处方过期时间"` // 时间区间,数组形式,下标0为开始时间,下标1为结束时间 InquiryNo string `json:"inquiry_no" form:"inquiry_no" label:"问诊订单编号"` OrderProductNo string `json:"order_product_no" form:"order_product_no" label:"药品订单编号"` + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"药房id"` + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"药房代码"` + PharmacyName string `json:"pharmacy_name" form:"pharmacy_name" label:"药房名称"` AnnualReviewHide *int `json:"-" form:"-"` // 内部传递条件 } @@ -38,5 +41,8 @@ type OrderPrescriptionExportList struct { ExpiredTime string `json:"expired_time" form:"expired_time" label:"处方过期时间"` // 时间区间,数组形式,下标0为开始时间,下标1为结束时间 InquiryNo string `json:"inquiry_no" form:"inquiry_no" label:"问诊订单编号"` OrderProductNo string `json:"order_product_no" form:"order_product_no" label:"药品订单编号"` + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"药房id"` + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"药房代码"` + PharmacyName string `json:"pharmacy_name" form:"pharmacy_name" label:"药房名称"` AnnualReviewHide *int `json:"-" form:"-"` // 内部传递条件 } diff --git a/api/requests/orderProduct.go b/api/requests/orderProduct.go index 954602f..268be68 100644 --- a/api/requests/orderProduct.go +++ b/api/requests/orderProduct.go @@ -34,6 +34,9 @@ type GetOrderProductPage struct { ProductName string `json:"product_name" form:"product_name" label:"药品名称"` CommonName string `json:"common_name" form:"common_name" label:"药品通用名"` PrescriptionCode string `json:"prescription_code" form:"prescription_code" label:"处方编号"` + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"药房id"` + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"药房代码"` + PharmacyName string `json:"pharmacy_name" form:"pharmacy_name" label:"药房名称"` AnnualReviewHide *int `json:"-" form:"-"` // 内部传递条件 } @@ -67,5 +70,8 @@ type OrderProductExportList struct { ConsigneeTel string `json:"consignee_tel" form:"cancel_reason" label:"收货人电话"` PatientName string `json:"patient_name" form:"patient_name" label:"患者姓名-就诊人"` Mobile string `json:"mobile" form:"mobile" label:"手机号-医生/患者"` + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"药房id"` + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"药房代码"` + PharmacyName string `json:"pharmacy_name" form:"pharmacy_name" label:"药房名称"` AnnualReviewHide *int `json:"-" form:"-"` // 内部传递条件 } diff --git a/api/service/export.go b/api/service/export.go index eccc6bb..48e63e6 100644 --- a/api/service/export.go +++ b/api/service/export.go @@ -283,6 +283,8 @@ type OrderProductData struct { City string // 城市 County string // 区县 Address string // 详细地址 + PharmacyName string // 发货药房 + PharmacyCode string // 药房代码 } // OrderProductItemData 药品订单-药品列表 @@ -346,6 +348,8 @@ type OrderPrescriptionData struct { PatientMobile string // 患者电话 DoctorAdvice string // 医嘱 OrderPrescriptionIcd string // 处方诊断疾病 + PharmacyName string // 开方药房 + PharmacyCode string // 药房代码 CreatedAt string // 创建时间 } @@ -1497,6 +1501,8 @@ func (r *ExportService) OrderInquiry(d []*model.OrderInquiry) (string, error) { func (r *ExportService) OrderProduct(d []*model.OrderProduct) (string, error) { header := []utils.HeaderCellData{ {Value: "系统订单编号", CellType: "string", NumberFmt: "", ColWidth: 25, Colour: "#FFD700"}, + {Value: "发货药房", CellType: "string", NumberFmt: "", ColWidth: 25, Colour: "#FFD700"}, + {Value: "药房代码", CellType: "string", NumberFmt: "", ColWidth: 18, Colour: "#FFD700"}, {Value: "订单状态", CellType: "string", NumberFmt: "", ColWidth: 18, Colour: "#FFD700"}, {Value: "订单金额", CellType: "float64", NumberFmt: "0.0000", ColWidth: 18, Colour: "#FFD700"}, {Value: "优惠卷总金额", CellType: "float64", NumberFmt: "0.0000", ColWidth: 18, Colour: "#FFD700"}, @@ -1545,9 +1551,22 @@ func (r *ExportService) OrderProduct(d []*model.OrderProduct) (string, error) { var dataSlice []interface{} for _, v := range d { + pharmacyName := v.PharmacyName + pharmacyCode := v.PharmacyCode + if v.Pharmacy != nil { + if pharmacyName == "" { + pharmacyName = v.Pharmacy.PharmacyName + } + if pharmacyCode == "" { + pharmacyCode = v.Pharmacy.PharmacyCode + } + } + data := OrderProductData{ OrderProductNo: v.OrderProductNo, EscrowTradeNo: v.EscrowTradeNo, + PharmacyName: pharmacyName, + PharmacyCode: pharmacyCode, OrderProductStatus: utils.OrderProductStatusToString(v.OrderProductStatus), PayChannel: utils.PayChannelToString(v.PayChannel), PayStatus: utils.PayStatusToString(v.PayStatus), @@ -1789,6 +1808,8 @@ func (r *ExportService) OrderServicePackage(d []*model.OrderServicePackage) (str // OrderPrescription 处方 func (r *ExportService) OrderPrescription(d []*model.OrderPrescription) (string, error) { header := []utils.HeaderCellData{ + {Value: "开方药房", CellType: "string", NumberFmt: "", ColWidth: 25}, + {Value: "药房代码", CellType: "string", NumberFmt: "", ColWidth: 18}, {Value: "医生姓名", CellType: "string", NumberFmt: "", ColWidth: 18}, {Value: "药师姓名", CellType: "string", NumberFmt: "", ColWidth: 18}, {Value: "处方状态", CellType: "string", NumberFmt: "", ColWidth: 18}, @@ -1815,7 +1836,20 @@ func (r *ExportService) OrderPrescription(d []*model.OrderPrescription) (string, var dataSlice []interface{} for _, v := range d { + pharmacyName := v.PharmacyName + pharmacyCode := v.PharmacyCode + if v.Pharmacy != nil { + if pharmacyName == "" { + pharmacyName = v.Pharmacy.PharmacyName + } + if pharmacyCode == "" { + pharmacyCode = v.Pharmacy.PharmacyCode + } + } + data := OrderPrescriptionData{ + PharmacyName: pharmacyName, + PharmacyCode: pharmacyCode, PrescriptionStatus: utils.PrescriptionStatusToString(v.PrescriptionStatus), PharmacistAuditStatus: utils.PharmacistAuditStatusToString(v.PharmacistAuditStatus), PharmacistFailReason: v.PharmacistFailReason, diff --git a/api/service/order.go b/api/service/order.go index 8f96b21..23bdfd9 100644 --- a/api/service/order.go +++ b/api/service/order.go @@ -247,9 +247,15 @@ func (r *OrderService) ReportPreProduct(orderProductId, adminUserId int64) (bool presRequests[0] = presRequest + // 终端代码:优先使用订单关联药房的代码,未配置则使用全局配置 + terminalCode := config.C.Pre.PrePlatTerminalCode + if orderProduct.PharmacyCode != "" { + terminalCode = orderProduct.PharmacyCode + } + // 处理上传数据-基础数据 ReportPreRequest := prescription.ReportPreRequest{ - TerminalCode: config.C.Pre.PrePlatTerminalCode, + TerminalCode: terminalCode, OrderNo: orderProduct.OrderProductNo, // 订单编号 TransactNo: orderProduct.EscrowTradeNo, // 流水单号 PayDate: time.Time(orderProduct.PayTime).Format("2006-01-02 15:04:05"), // 支付时间 From b74a8aa89840599172d2e4f07b8f00bb3c51762d Mon Sep 17 00:00:00 2001 From: haomingming Date: Mon, 7 Sep 2026 16:44:34 +0800 Subject: [PATCH 07/16] 2 --- api/controller/doctorPharmacy.go | 4 ++-- api/service/doctorPharmacy.go | 10 +++++----- api/service/pharmacy.go | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/api/controller/doctorPharmacy.go b/api/controller/doctorPharmacy.go index 5821429..7a2873c 100644 --- a/api/controller/doctorPharmacy.go +++ b/api/controller/doctorPharmacy.go @@ -152,7 +152,7 @@ func (r *DoctorPharmacy) UnbindDoctorPharmacy(c *gin.Context) { pharmacyIdStr := c.Query("pharmacy_id") if pharmacyIdStr != "" { pharmacyId, err := strconv.ParseInt(pharmacyIdStr, 10, 64) - if err == nil && pharmacyId > 0 { + if err == nil && pharmacyId >= 0 { _, err = doctorPharmacyService.UnbindDoctorPharmacy(id, pharmacyId) if err != nil { responses.FailWithMessage(err.Error(), c) @@ -236,7 +236,7 @@ func (r *DoctorPharmacy) SetDefaultDoctorPharmacy(c *gin.Context) { pharmacyIdStr := c.Query("pharmacy_id") if pharmacyIdStr != "" { pharmacyId, err := strconv.ParseInt(pharmacyIdStr, 10, 64) - if err == nil && pharmacyId > 0 { + if err == nil && pharmacyId >= 0 { _, err = doctorPharmacyService.SetDefaultPharmacy(id, pharmacyId) if err != nil { responses.FailWithMessage(err.Error(), c) diff --git a/api/service/doctorPharmacy.go b/api/service/doctorPharmacy.go index 6d19038..9d3ca34 100644 --- a/api/service/doctorPharmacy.go +++ b/api/service/doctorPharmacy.go @@ -32,7 +32,7 @@ func (r *DoctorPharmacyService) BindDoctorPharmacies(doctorId int64, req request } pharmacyDao := dao.PharmacyDao{} - var defaultPharmacyId int64 + var defaultPharmacyId int64 = -1 if req.DefaultPharmacyId != "" { defaultPharmacyId, _ = strconv.ParseInt(req.DefaultPharmacyId, 10, 64) } @@ -56,7 +56,7 @@ func (r *DoctorPharmacyService) BindDoctorPharmacies(doctorId int64, req request // 遍历新增绑定 for i, v := range req.PharmacyIds { pharmacyId, err := strconv.ParseInt(v, 10, 64) - if err != nil || pharmacyId == 0 { + if err != nil || pharmacyId < 0 { continue } @@ -68,9 +68,9 @@ func (r *DoctorPharmacyService) BindDoctorPharmacies(doctorId int64, req request } isDefault := 0 - if defaultPharmacyId != 0 && pharmacyId == defaultPharmacyId { + if defaultPharmacyId >= 0 && pharmacyId == defaultPharmacyId { isDefault = 1 - } else if defaultPharmacyId == 0 && i == 0 { + } else if defaultPharmacyId < 0 && i == 0 { // 未指定默认药房时,默认第1个为默认药房 isDefault = 1 } @@ -103,7 +103,7 @@ func (r *DoctorPharmacyService) AddDoctorPharmacy(doctorId int64, req requests.A } pharmacyId, err := strconv.ParseInt(req.PharmacyId, 10, 64) - if err != nil || pharmacyId == 0 { + if err != nil || pharmacyId < 0 { return false, errors.New("药房id无效") } diff --git a/api/service/pharmacy.go b/api/service/pharmacy.go index c9595a5..c7290b7 100644 --- a/api/service/pharmacy.go +++ b/api/service/pharmacy.go @@ -264,7 +264,7 @@ func (r *PharmacyService) GetPharmacy(pharmacyId int64) (*dto.PharmacyDto, error // GetPharmacyDoctorPage 获取药房绑定的医生列表-分页 func (r *PharmacyService) GetPharmacyDoctorPage(req requests.GetPharmacyDoctorPage) (map[string]interface{}, error) { pharmacyId, err := strconv.ParseInt(req.PharmacyId, 10, 64) - if err != nil || pharmacyId == 0 { + if err != nil || pharmacyId < 0 { return nil, errors.New("药房id无效") } From 86f3cc2fbca7638b006af23c4b293d12f83084c5 Mon Sep 17 00:00:00 2001 From: haomingming Date: Tue, 8 Sep 2026 10:55:15 +0800 Subject: [PATCH 08/16] =?UTF-8?q?=E5=A4=84=E7=90=86=20GORM=200=20=E7=9A=84?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/dao/doctorPharmacy.go | 22 ++++++++++++ api/dao/product.go | 65 ++++++++++++++++++++++++++++++++---- api/dao/productPlatform.go | 10 ++++++ api/dto/DoctorPharmacy.go | 7 ++++ api/dto/Product.go | 22 +++++++++++- api/dto/ProductPlatform.go | 3 ++ api/model/product.go | 3 ++ api/model/productPlatform.go | 1 + api/requests/product.go | 10 ++++++ api/service/export.go | 15 +++++++++ api/service/product.go | 43 ++++++++++++++++++++++-- 11 files changed, 192 insertions(+), 9 deletions(-) diff --git a/api/dao/doctorPharmacy.go b/api/dao/doctorPharmacy.go index 23694de..968bed4 100644 --- a/api/dao/doctorPharmacy.go +++ b/api/dao/doctorPharmacy.go @@ -24,6 +24,28 @@ func (r *DoctorPharmacyDao) GetDoctorPharmacyListByDoctorId(doctorId int64) (m [ if err != nil { return nil, err } + + // GORM 在外键为 0 时会自动跳过 Preload,因此针对未能预加载的记录进行兜底补全 + var zeroPharmacy *model.Pharmacy + for _, dp := range m { + if dp.Pharmacy == nil { + if dp.PharmacyId == 0 { + if zeroPharmacy == nil { + var ph model.Pharmacy + if err := global.Db.Where("pharmacy_id = 0").First(&ph).Error; err == nil { + zeroPharmacy = &ph + } + } + dp.Pharmacy = zeroPharmacy + } else { + var ph model.Pharmacy + if err := global.Db.Where("pharmacy_id = ?", dp.PharmacyId).First(&ph).Error; err == nil { + dp.Pharmacy = &ph + } + } + } + } + return m, nil } diff --git a/api/dao/product.go b/api/dao/product.go index eac9694..664d1de 100644 --- a/api/dao/product.go +++ b/api/dao/product.go @@ -15,10 +15,16 @@ type ProductDao struct { // GetProductById 获取商品数据-商品id func (r *ProductDao) GetProductById(productId int64) (m *model.Product, err error) { - err = global.Db.First(&m, productId).Error + err = global.Db.Preload("Pharmacy").First(&m, productId).Error if err != nil { return nil, err } + if m != nil && m.Pharmacy == nil && m.PharmacyId == 0 { + var ph model.Pharmacy + if err := global.Db.Where("pharmacy_id = 0").First(&ph).Error; err == nil { + m.Pharmacy = &ph + } + } return m, nil } @@ -85,7 +91,7 @@ func (r *ProductDao) GetProductPageSearch(req requests.GetProductPage, page, pag // 库存表 query = query.Preload("ProductPlatformAmount", func(db *gorm.DB) *gorm.DB { return db.Select("amount_id", "product_platform_id", "product_platform_code", "stock") - }) + }).Preload("Pharmacy") // 商品名称 if req.ProductName != "" { @@ -132,6 +138,16 @@ func (r *ProductDao) GetProductPageSearch(req requests.GetProductPage, page, pag query = query.Where("product_pharmacy_code LIKE ?", "%"+req.ProductPharmacyCode+"%") } + // 所属药房ID + if req.PharmacyId != "" { + query = query.Where("gdxz_product.pharmacy_id = ?", req.PharmacyId) + } + + // 所属药房编码 + if req.PharmacyCode != "" { + query = query.Where("gdxz_product.pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") + } + // 批准文号 if req.LicenseNumber != "" { query = query.Where("license_number LIKE ?", "%"+req.LicenseNumber+"%") @@ -171,6 +187,7 @@ func (r *ProductDao) GetProductPageSearch(req requests.GetProductPage, page, pag if err != nil { return nil, 0, err } + fillZeroPharmacy(m) return m, totalRecords, nil } @@ -182,7 +199,7 @@ func (r *ProductDao) GetProductExportListSearch(req requests.ProductExportList) // 库存表 query = query.Preload("ProductPlatformAmount", func(db *gorm.DB) *gorm.DB { return db.Select("amount_id", "product_platform_id", "product_platform_code", "stock") - }) + }).Preload("Pharmacy") // 当前搜索数据 if req.Type == 1 { @@ -226,6 +243,16 @@ func (r *ProductDao) GetProductExportListSearch(req requests.ProductExportList) query = query.Where("product_pharmacy_code LIKE ?", "%"+req.ProductPharmacyCode+"%") } + // 所属药房ID + if req.PharmacyId != "" { + query = query.Where("gdxz_product.pharmacy_id = ?", req.PharmacyId) + } + + // 所属药房编码 + if req.PharmacyCode != "" { + query = query.Where("gdxz_product.pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") + } + // 批准文号 if req.LicenseNumber != "" { query = query.Where("license_number LIKE ?", "%"+req.LicenseNumber+"%") @@ -259,7 +286,7 @@ func (r *ProductDao) GetProductExportListSearch(req requests.ProductExportList) if err != nil { return nil, err } - + fillZeroPharmacy(m) return m, nil } @@ -271,7 +298,7 @@ func (r *ProductDao) GetProductListSearch(req requests.GetProductList) (m []*mod // 库存表 query = query.Preload("ProductPlatformAmount", func(db *gorm.DB) *gorm.DB { return db.Select("amount_id", "product_platform_id", "product_platform_code", "stock") - }) + }).Preload("Pharmacy") // 商品id if req.ProductId != "" { @@ -323,6 +350,16 @@ func (r *ProductDao) GetProductListSearch(req requests.GetProductList) (m []*mod query = query.Where("product_pharmacy_code LIKE ?", "%"+req.ProductPharmacyCode+"%") } + // 所属药房ID + if req.PharmacyId != "" { + query = query.Where("gdxz_product.pharmacy_id = ?", req.PharmacyId) + } + + // 所属药房编码 + if req.PharmacyCode != "" { + query = query.Where("gdxz_product.pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") + } + // 批准文号 if req.LicenseNumber != "" { query = query.Where("license_number LIKE ?", "%"+req.LicenseNumber+"%") @@ -348,6 +385,22 @@ func (r *ProductDao) GetProductListSearch(req requests.GetProductList) (m []*mod if err != nil { return nil, err } - + fillZeroPharmacy(m) return m, nil } + +// fillZeroPharmacy 补全因 GORM 零值跳过预加载的 pharmacy_id = 0 药房实体 +func fillZeroPharmacy(products []*model.Product) { + var zeroPharmacy *model.Pharmacy + for _, p := range products { + if p.Pharmacy == nil && p.PharmacyId == 0 { + if zeroPharmacy == nil { + var ph model.Pharmacy + if err := global.Db.Where("pharmacy_id = 0").First(&ph).Error; err == nil { + zeroPharmacy = &ph + } + } + p.Pharmacy = zeroPharmacy + } + } +} diff --git a/api/dao/productPlatform.go b/api/dao/productPlatform.go index bc9719b..bf410c5 100644 --- a/api/dao/productPlatform.go +++ b/api/dao/productPlatform.go @@ -90,6 +90,11 @@ func (r *ProductPlatformDao) GetPlatformProductPageSearch(req requests.GetPlatfo query = query.Where("product_pharmacy_code LIKE ?", "%"+req.ProductPharmacyCode+"%") } + // 第三方药房编码 + if req.PharmacyCode != "" { + query = query.Where("pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") + } + // 批准文号 if req.LicenseNumber != "" { query = query.Where("license_number LIKE ?", "%"+req.LicenseNumber+"%") @@ -140,6 +145,11 @@ func (r *ProductPlatformDao) GetPlatformProductListSearch(req requests.GetPlatfo query = query.Where("product_pharmacy_code LIKE ?", "%"+req.ProductPharmacyCode+"%") } + // 第三方药房编码 + if req.PharmacyCode != "" { + query = query.Where("pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") + } + // 批准文号 if req.LicenseNumber != "" { query = query.Where("license_number LIKE ?", "%"+req.LicenseNumber+"%") diff --git a/api/dto/DoctorPharmacy.go b/api/dto/DoctorPharmacy.go index 8490ade..2069fbf 100644 --- a/api/dto/DoctorPharmacy.go +++ b/api/dto/DoctorPharmacy.go @@ -3,6 +3,7 @@ package dto import ( "fmt" "hospital-admin-api/api/model" + "hospital-admin-api/global" ) type DoctorPharmacyDto struct { @@ -39,6 +40,12 @@ func GetDoctorPharmacyDto(m *model.DoctorPharmacy) *DoctorPharmacyDto { CreatedAt: m.CreatedAt, UpdatedAt: m.UpdatedAt, } + if m.Pharmacy == nil { + var ph model.Pharmacy + if err := global.Db.Where("pharmacy_id = ?", m.PharmacyId).First(&ph).Error; err == nil { + m.Pharmacy = &ph + } + } if m.Pharmacy != nil { dto.PharmacyName = m.Pharmacy.PharmacyName dto.PharmacyCode = m.Pharmacy.PharmacyCode diff --git a/api/dto/Product.go b/api/dto/Product.go index 3b31d18..fa1148b 100644 --- a/api/dto/Product.go +++ b/api/dto/Product.go @@ -9,6 +9,10 @@ import ( type ProductDto struct { ProductId string `json:"product_id"` // 主键id ProductPlatformId string `json:"product_platform_id"` // 处方平台商品id + PharmacyId string `json:"pharmacy_id"` // 所属药房ID + PharmacyCode string `json:"pharmacy_code"` // 所属药房编码 + PharmacyName string `json:"pharmacy_name"` // 所属药房名称 + Pharmacy *PharmacyDto `json:"pharmacy"` // 所属药房详情 ProductStatus int `json:"product_status"` // 商品状态(1:正常 2:下架) IsDelete int `json:"is_delete"` // 是否删除(0:否 1:是) PrescriptionNum int `json:"prescription_num"` // 处方可开具的数量 @@ -36,9 +40,11 @@ type ProductDto struct { // GetProductDto 商品详情 func GetProductDto(m *model.Product) *ProductDto { - return &ProductDto{ + dto := &ProductDto{ ProductId: fmt.Sprintf("%d", m.ProductId), ProductPlatformId: fmt.Sprintf("%d", m.ProductPlatformId), + PharmacyId: fmt.Sprintf("%d", m.PharmacyId), + PharmacyCode: m.PharmacyCode, ProductStatus: m.ProductStatus, IsDelete: m.IsDelete, PrescriptionNum: m.PrescriptionNum, @@ -62,6 +68,13 @@ func GetProductDto(m *model.Product) *ProductDto { CreatedAt: m.CreatedAt, UpdatedAt: m.UpdatedAt, } + + if m.Pharmacy != nil { + dto.Pharmacy = GetPharmacyDto(m.Pharmacy) + dto.PharmacyName = m.Pharmacy.PharmacyName + } + + return dto } // GetProductListDto 商品列表 @@ -74,6 +87,8 @@ func GetProductListDto(m []*model.Product) []*ProductDto { response := &ProductDto{ ProductId: fmt.Sprintf("%d", v.ProductId), ProductPlatformId: fmt.Sprintf("%d", v.ProductPlatformId), + PharmacyId: fmt.Sprintf("%d", v.PharmacyId), + PharmacyCode: v.PharmacyCode, ProductStatus: v.ProductStatus, IsDelete: v.IsDelete, PrescriptionNum: v.PrescriptionNum, @@ -98,6 +113,11 @@ func GetProductListDto(m []*model.Product) []*ProductDto { UpdatedAt: v.UpdatedAt, } + if v.Pharmacy != nil { + response.Pharmacy = GetPharmacyDto(v.Pharmacy) + response.PharmacyName = v.Pharmacy.PharmacyName + } + // 加载商品库存 if v.ProductPlatformAmount != nil { response = response.LoadProductAmount(v.ProductPlatformAmount) diff --git a/api/dto/ProductPlatform.go b/api/dto/ProductPlatform.go index aee13b2..3314657 100644 --- a/api/dto/ProductPlatform.go +++ b/api/dto/ProductPlatform.go @@ -12,6 +12,7 @@ type ProductPlatformDto struct { ProductType int `json:"product_type"` // 药品类型(0:未知 1:中成药 2:西药) ProductPlatformCode string `json:"product_platform_code"` // 处方平台商品编码 ProductPharmacyCode string `json:"product_pharmacy_code"` // 第三方药店商品编码 + PharmacyCode string `json:"pharmacy_code"` // 第三方药房编码 ProductSpec string `json:"product_spec"` // 商品规格 LicenseNumber string `json:"license_number"` // 批准文号 Manufacturer string `json:"manufacturer"` // 生产厂家 @@ -33,6 +34,7 @@ func GetProductPlatformDto(m *model.ProductPlatform) *ProductPlatformDto { ProductType: m.ProductType, ProductPlatformCode: m.ProductPlatformCode, ProductPharmacyCode: m.ProductPharmacyCode, + PharmacyCode: m.PharmacyCode, ProductSpec: m.ProductSpec, LicenseNumber: m.LicenseNumber, Manufacturer: m.Manufacturer, @@ -59,6 +61,7 @@ func GetProductPlatformListDto(m []*model.ProductPlatform) []*ProductPlatformDto ProductType: v.ProductType, ProductPlatformCode: v.ProductPlatformCode, ProductPharmacyCode: v.ProductPharmacyCode, + PharmacyCode: v.PharmacyCode, ProductSpec: v.ProductSpec, LicenseNumber: v.LicenseNumber, Manufacturer: v.Manufacturer, diff --git a/api/model/product.go b/api/model/product.go index 458c1b9..e1ecd49 100644 --- a/api/model/product.go +++ b/api/model/product.go @@ -10,6 +10,8 @@ import ( type Product struct { ProductId int64 `gorm:"column:product_id;type:bigint(19);primary_key;comment:主键id" json:"product_id"` ProductPlatformId int64 `gorm:"column:product_platform_id;type:bigint(19);comment:处方平台商品id" json:"product_platform_id"` + PharmacyId int64 `gorm:"column:pharmacy_id;type:bigint(20) unsigned;default:0;comment:所属药房ID" json:"pharmacy_id"` + PharmacyCode string `gorm:"column:pharmacy_code;type:varchar(64);default:'';comment:所属药房编码" json:"pharmacy_code"` ProductStatus int `gorm:"column:product_status;type:tinyint(1);default:1;comment:商品状态(1:正常 2:下架)" json:"product_status"` IsDelete int `gorm:"column:is_delete;type:tinyint(1);default:0;comment:是否删除(0:否 1:是)" json:"is_delete"` PrescriptionNum int `gorm:"column:prescription_num;type:int(11);default:5;comment:处方可开具的数量" json:"prescription_num"` @@ -32,6 +34,7 @@ type Product struct { AvailableDays float64 `gorm:"column:available_days;type:float(10,2);comment:可用天数(3)" json:"available_days"` ProductRemarks string `gorm:"column:product_remarks;type:varchar(255);comment:商品备注" json:"product_remarks"` ProductPlatformAmount *ProductPlatformAmount `gorm:"foreignKey:ProductPlatformId;references:product_platform_id" json:"product_platform_amount"` // 库存 + Pharmacy *Pharmacy `gorm:"foreignKey:PharmacyId;references:pharmacy_id" json:"pharmacy"` // 所属药房 Model } diff --git a/api/model/productPlatform.go b/api/model/productPlatform.go index acaa3c6..7d92060 100644 --- a/api/model/productPlatform.go +++ b/api/model/productPlatform.go @@ -14,6 +14,7 @@ type ProductPlatform struct { ProductType int `gorm:"column:product_type;type:tinyint(4);default:1;comment:药品类型(0:未知 1:中成药 2:西药)" json:"product_type"` ProductPlatformCode string `gorm:"column:product_platform_code;type:varchar(100);comment:处方平台商品编码" json:"product_platform_code"` ProductPharmacyCode string `gorm:"column:product_pharmacy_code;type:varchar(100);comment:第三方药店商品编码" json:"product_pharmacy_code"` + PharmacyCode string `gorm:"column:pharmacy_code;type:varchar(64);default:'';comment:第三方药房编码" json:"pharmacy_code"` ProductSpec string `gorm:"column:product_spec;type:varchar(255);comment:商品规格" json:"product_spec"` LicenseNumber string `gorm:"column:license_number;type:varchar(255);comment:批准文号" json:"license_number"` Manufacturer string `gorm:"column:manufacturer;type:varchar(255);comment:生产厂家" json:"manufacturer"` diff --git a/api/requests/product.go b/api/requests/product.go index 4e0a16a..70b7905 100644 --- a/api/requests/product.go +++ b/api/requests/product.go @@ -19,6 +19,7 @@ type GetPlatformProductPage struct { ProductType *int `json:"product_type" form:"product_type" label:"药品类型"` // 药品类型(0:未知 1:中成药 2:西药) ProductPlatformCode string `json:"product_platform_code" form:"product_platform_code" label:"处方平台编码"` // 处方平台商品编码 ProductPharmacyCode string `json:"product_pharmacy_code" form:"product_pharmacy_code" label:"药店编码"` // 第三方药店商品编码 + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"第三方药房编码"` // 第三方药房编码 LicenseNumber string `json:"license_number" form:"license_number" label:"批准文号"` // 批准文号 Manufacturer string `json:"manufacturer" form:"manufacturer" label:"生产厂家"` // 生产厂家 } @@ -29,6 +30,7 @@ type GetPlatformProductList struct { ProductType *int `json:"product_type" form:"product_type" label:"药品类型"` // 药品类型(0:未知 1:中成药 2:西药) ProductPlatformCode string `json:"product_platform_code" form:"product_platform_code" label:"处方平台编码"` // 处方平台商品编码 ProductPharmacyCode string `json:"product_pharmacy_code" form:"product_pharmacy_code" label:"药店编码"` // 第三方药店商品编码 + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"第三方药房编码"` // 第三方药房编码 LicenseNumber string `json:"license_number" form:"license_number" label:"批准文号"` // 批准文号 Manufacturer string `json:"manufacturer" form:"manufacturer" label:"生产厂家"` // 生产厂家 } @@ -45,6 +47,8 @@ type GetProductPage struct { ProductPlatformId string `json:"product_platform_id" form:"product_platform_id" label:"平台商品id"` // 处方平台商品id ProductPlatformCode string `json:"product_platform_code" form:"product_platform_code" label:"处方平台编码"` // 处方平台商品编码 ProductPharmacyCode string `json:"product_pharmacy_code" form:"product_pharmacy_code" label:"药店编码"` // 第三方药店商品编码 + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"所属药房ID"` // 所属药房ID + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"所属药房编码"` // 所属药房编码 LicenseNumber string `json:"license_number" form:"license_number" label:"批准文号"` // 批准文号 Manufacturer string `json:"manufacturer" form:"manufacturer" label:"生产厂家"` // 生产厂家 ProductRemarks string `json:"product_remarks" form:"product_remarks" label:"商品备注"` // 商品备注 @@ -63,6 +67,8 @@ type GetProductList struct { ProductPlatformId string `json:"product_platform_id" form:"product_platform_id" label:"平台商品id"` // 处方平台商品id ProductPlatformCode string `json:"product_platform_code" form:"product_platform_code" label:"处方平台编码"` // 处方平台商品编码 ProductPharmacyCode string `json:"product_pharmacy_code" form:"product_pharmacy_code" label:"药店编码"` // 第三方药店商品编码 + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"所属药房ID"` // 所属药房ID + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"所属药房编码"` // 所属药房编码 LicenseNumber string `json:"license_number" form:"license_number" label:"批准文号"` // 批准文号 Manufacturer string `json:"manufacturer" form:"manufacturer" label:"生产厂家"` // 生产厂家 ProductRemarks string `json:"product_remarks" form:"product_remarks" label:"商品备注"` // 商品备注 @@ -85,6 +91,8 @@ type AddProduct struct { IsMajing *int `json:"is_majing" form:"is_majing" label:"是否麻精药品"` // 是否麻精药品(0:否 1:是) ProductPlatformCode string `json:"product_platform_code" form:"product_platform_code" label:"处方平台商品编码" validate:"required"` // 处方平台商品编码 ProductPharmacyCode string `json:"product_pharmacy_code" form:"product_pharmacy_code" label:"第三方药店商品编码" validate:"required"` // 第三方药店商品编码 + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"所属药房ID"` // 所属药房ID + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"所属药房编码"` // 所属药房编码 ProductCoverImg string `json:"product_cover_img" form:"product_cover_img" label:"商品封面图"` // 商品封面图 ProductSpec string `json:"product_spec" form:"product_spec" label:"商品规格" validate:"required"` // 商品规格 LicenseNumber string `json:"license_number" form:"license_number" label:"批准文号" validate:"required"` // 批准文号 @@ -128,6 +136,8 @@ type ProductExportList struct { ProductPlatformId string `json:"product_platform_id" form:"product_platform_id" label:"平台商品id"` // 处方平台商品id ProductPlatformCode string `json:"product_platform_code" form:"product_platform_code" label:"处方平台编码"` // 处方平台商品编码 ProductPharmacyCode string `json:"product_pharmacy_code" form:"product_pharmacy_code" label:"药店编码"` // 第三方药店商品编码 + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"所属药房ID"` // 所属药房ID + PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"所属药房编码"` // 所属药房编码 LicenseNumber string `json:"license_number" form:"license_number" label:"批准文号"` // 批准文号 Manufacturer string `json:"manufacturer" form:"manufacturer" label:"生产厂家"` // 生产厂家 ProductRemarks string `json:"product_remarks" form:"product_remarks" label:"商品备注"` // 商品备注 diff --git a/api/service/export.go b/api/service/export.go index 48e63e6..a822d8b 100644 --- a/api/service/export.go +++ b/api/service/export.go @@ -375,6 +375,8 @@ type ProductData struct { FrequencyUse string // 使用频率(例:1天3次) AvailableDays float64 // 可用天数(3) ProductRemarks string // 商品备注 + PharmacyName string // 所属药房 + PharmacyCode string // 所属药房编码 CreatedAt string // 创建时间 } @@ -1974,11 +1976,22 @@ func (r *ExportService) Product(d []*model.Product) (string, error) { {Value: "使用频率(例:1天3次)", CellType: "string", NumberFmt: "", ColWidth: 18}, {Value: "可用天数(3)", CellType: "float64", NumberFmt: "0.0000", ColWidth: 18}, {Value: "商品备注", CellType: "string", NumberFmt: "", ColWidth: 40}, + {Value: "所属药房", CellType: "string", NumberFmt: "", ColWidth: 30}, + {Value: "所属药房编码", CellType: "string", NumberFmt: "", ColWidth: 30}, {Value: "创建时间", CellType: "date", NumberFmt: "yyyy-mm-dd hh:mm:ss", ColWidth: 30}, } var dataSlice []interface{} for _, v := range d { + pharmacyName := "" + pharmacyCode := v.PharmacyCode + if v.Pharmacy != nil { + pharmacyName = v.Pharmacy.PharmacyName + if pharmacyCode == "" { + pharmacyCode = v.Pharmacy.PharmacyCode + } + } + data := ProductData{ ProductName: v.ProductName, CommonName: v.CommonName, @@ -2000,6 +2013,8 @@ func (r *ExportService) Product(d []*model.Product) (string, error) { FrequencyUse: v.FrequencyUse, AvailableDays: v.AvailableDays, ProductRemarks: v.ProductRemarks, + PharmacyName: pharmacyName, + PharmacyCode: pharmacyCode, } if v.ProductPlatformAmount != nil { diff --git a/api/service/product.go b/api/service/product.go index 46ac523..69e2133 100644 --- a/api/service/product.go +++ b/api/service/product.go @@ -94,16 +94,53 @@ func (r *ProductService) AddProduct(userId string, req requests.AddProduct) (boo return false, errors.New("平台商品不存在") } - // 检测商品是否重复 + // 确定所属药房信息 + pharmacyDao := dao.PharmacyDao{} + var pharmacyId int64 = 0 + var pharmacyCode string = "" + + if req.PharmacyId != "" { + pId, err := strconv.ParseInt(req.PharmacyId, 10, 64) + if err == nil && pId >= 0 { + pharmacyId = pId + pharmacy, _ := pharmacyDao.GetPharmacyById(pharmacyId) + if pharmacy != nil { + pharmacyCode = pharmacy.PharmacyCode + } + } + } else if req.PharmacyCode != "" { + pharmacyCode = req.PharmacyCode + pharmacy, _ := pharmacyDao.GetPharmacyByCode(pharmacyCode) + if pharmacy != nil { + pharmacyId = pharmacy.PharmacyId + } + } else if productPlatform.PharmacyCode != "" { + pharmacyCode = productPlatform.PharmacyCode + pharmacy, _ := pharmacyDao.GetPharmacyByCode(pharmacyCode) + if pharmacy != nil { + pharmacyId = pharmacy.PharmacyId + } + } + + // 若仍无编码,查询对应药房编码(如默认药房 0) + if pharmacyCode == "" { + pharmacy, _ := pharmacyDao.GetPharmacyById(pharmacyId) + if pharmacy != nil { + pharmacyCode = pharmacy.PharmacyCode + } + } + + // 检测同一药房下商品是否重复 maps := make(map[string]interface{}) maps["product_platform_id"] = req.ProductPlatformId + maps["pharmacy_id"] = pharmacyId products, err := productDao.GetProductList(maps) if err != nil { return false, errors.New("商品重复添加") } if len(products) != 0 { - return false, errors.New("商品重复添加") + return false, errors.New("该药房已添加此商品,请勿重复添加") } // 处理图片 @@ -120,6 +157,8 @@ func (r *ProductService) AddProduct(userId string, req requests.AddProduct) (boo // 新增商品表 product := &model.Product{ ProductPlatformId: productPlatform.ProductPlatformId, + PharmacyId: pharmacyId, + PharmacyCode: pharmacyCode, ProductStatus: *req.ProductStatus, ProductName: req.ProductName, CommonName: req.CommonName, From f6f6845692df6dec524073e35a084eca09744580 Mon Sep 17 00:00:00 2001 From: haomingming Date: Tue, 8 Sep 2026 13:57:44 +0800 Subject: [PATCH 09/16] 2 --- api/service/product.go | 6 ++++-- extend/prescription/prescription.go | 7 ++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/api/service/product.go b/api/service/product.go index 69e2133..192ee9d 100644 --- a/api/service/product.go +++ b/api/service/product.go @@ -28,7 +28,8 @@ func (r *ProductService) GetProductPlatform(productPlatformId int64) (g *dto.Pro var quantity int ReportPreRequest := prescription.GetProdStockRequest{ - DrugCode: productPlatform.ProductPharmacyCode, + PharmacyCode: productPlatform.PharmacyCode, + DrugCode: productPlatform.ProductPharmacyCode, } result, err := ReportPreRequest.GetProdStock() @@ -188,7 +189,8 @@ func (r *ProductService) AddProduct(userId string, req requests.AddProduct) (boo // 获取商品库存 ReportPreRequest := prescription.GetProdStockRequest{ - DrugCode: product.ProductPharmacyCode, + PharmacyCode: product.PharmacyCode, + DrugCode: product.ProductPharmacyCode, } result, err := ReportPreRequest.GetProdStock() diff --git a/extend/prescription/prescription.go b/extend/prescription/prescription.go index 415bc91..5bf6201 100644 --- a/extend/prescription/prescription.go +++ b/extend/prescription/prescription.go @@ -409,7 +409,9 @@ func (r ReportPreRequest) ReportPre() (bool, error) { // GetProdStock 获取商品库存 func (r GetProdStockRequest) GetProdStock() (*GetProdStockDataResponse, error) { - r.PharmacyCode = config.C.Pre.PrePlatPharmacyCode + if r.PharmacyCode == "" { + r.PharmacyCode = config.C.Pre.PrePlatPharmacyCode + } jsonData, err := json.Marshal(r) if err != nil { utils.LogJsonErr("获取商品库存-序列化请求参数失败", err) @@ -483,5 +485,8 @@ func (r GetProdStockRequest) GetProdStock() (*GetProdStockDataResponse, error) { } utils.LogJsonInfo("获取商品库存-成功", response.Data) + if len(response.Data) == 0 { + return &GetProdStockDataResponse{Quantity: "0"}, nil + } return &response.Data[0], nil } From d95e2bc0ec5db0d7f69f4cbff8e8694f60a29d01 Mon Sep 17 00:00:00 2001 From: haomingming Date: Tue, 8 Sep 2026 14:20:13 +0800 Subject: [PATCH 10/16] =?UTF-8?q?=E8=8D=AF=E5=93=81=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8D=AF=E6=88=BF=E4=BF=A1=E6=81=AF=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=E5=8F=8A=E7=AD=9B=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/dao/productPlatform.go | 121 +++++++++++++++++++++++++++++++++++ api/dto/ProductPlatform.go | 40 ++++++------ api/model/productPlatform.go | 3 +- api/requests/product.go | 2 + api/service/product.go | 7 +- 5 files changed, 149 insertions(+), 24 deletions(-) diff --git a/api/dao/productPlatform.go b/api/dao/productPlatform.go index bf410c5..6a3ae9e 100644 --- a/api/dao/productPlatform.go +++ b/api/dao/productPlatform.go @@ -1,6 +1,8 @@ package dao import ( + "strconv" + "gorm.io/gorm" "hospital-admin-api/api/model" "hospital-admin-api/api/requests" @@ -16,6 +18,9 @@ func (r *ProductPlatformDao) GetProductPlatformById(productPlatformId int64) (m if err != nil { return nil, err } + if m != nil { + fillPlatformPharmacy([]*model.ProductPlatform{m}) + } return m, nil } @@ -25,6 +30,7 @@ func (r *ProductPlatformDao) GetProductPlatformList(maps interface{}) (m []*mode if err != nil { return nil, err } + fillPlatformPharmacy(m) return m, nil } @@ -90,6 +96,32 @@ func (r *ProductPlatformDao) GetPlatformProductPageSearch(req requests.GetPlatfo query = query.Where("product_pharmacy_code LIKE ?", "%"+req.ProductPharmacyCode+"%") } + // 所属药房ID + if req.PharmacyId != "" { + pId, err := strconv.ParseInt(req.PharmacyId, 10, 64) + if err == nil { + var ph model.Pharmacy + var dbErr error + if pId == 0 { + dbErr = global.Db.Where("pharmacy_id = 0").First(&ph).Error + } else { + dbErr = global.Db.Where("pharmacy_id = ? AND status != 2", pId).First(&ph).Error + } + if dbErr == nil { + if ph.PharmacyCode != "" { + query = query.Where("pharmacy_code = ?", ph.PharmacyCode) + } else { + query = query.Where("(pharmacy_code = '' OR pharmacy_code IS NULL)") + } + } else if pId == 0 { + // 兜底:若数据库暂无 pharmacy_id = 0 的记录,仍匹配 pharmacy_code 为空的默认商品 + query = query.Where("(pharmacy_code = '' OR pharmacy_code IS NULL)") + } else { + query = query.Where("1 = 0") + } + } + } + // 第三方药房编码 if req.PharmacyCode != "" { query = query.Where("pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") @@ -117,6 +149,7 @@ func (r *ProductPlatformDao) GetPlatformProductPageSearch(req requests.GetPlatfo if err != nil { return nil, 0, err } + fillPlatformPharmacy(m) return m, totalRecords, nil } @@ -145,6 +178,31 @@ func (r *ProductPlatformDao) GetPlatformProductListSearch(req requests.GetPlatfo query = query.Where("product_pharmacy_code LIKE ?", "%"+req.ProductPharmacyCode+"%") } + // 所属药房ID + if req.PharmacyId != "" { + pId, err := strconv.ParseInt(req.PharmacyId, 10, 64) + if err == nil { + var ph model.Pharmacy + var dbErr error + if pId == 0 { + dbErr = global.Db.Where("pharmacy_id = 0").First(&ph).Error + } else { + dbErr = global.Db.Where("pharmacy_id = ? AND status != 2", pId).First(&ph).Error + } + if dbErr == nil { + if ph.PharmacyCode != "" { + query = query.Where("pharmacy_code = ?", ph.PharmacyCode) + } else { + query = query.Where("(pharmacy_code = '' OR pharmacy_code IS NULL)") + } + } else if pId == 0 { + query = query.Where("(pharmacy_code = '' OR pharmacy_code IS NULL)") + } else { + query = query.Where("1 = 0") + } + } + } + // 第三方药房编码 if req.PharmacyCode != "" { query = query.Where("pharmacy_code LIKE ?", "%"+req.PharmacyCode+"%") @@ -167,5 +225,68 @@ func (r *ProductPlatformDao) GetPlatformProductListSearch(req requests.GetPlatfo if err != nil { return nil, err } + fillPlatformPharmacy(m) return m, nil } + +// fillPlatformPharmacy 批量补全平台商品的所属药房实体 +func fillPlatformPharmacy(list []*model.ProductPlatform) { + if len(list) == 0 { + return + } + + // 1. 收集非空的 pharmacy_code + var codes []string + codeMap := make(map[string]bool) + for _, item := range list { + if item.PharmacyCode != "" && !codeMap[item.PharmacyCode] { + codeMap[item.PharmacyCode] = true + codes = append(codes, item.PharmacyCode) + } + } + + // 2. 批量查出对应药房 + pharmacyByCode := make(map[string]*model.Pharmacy) + if len(codes) > 0 { + var pharmacies []*model.Pharmacy + if err := global.Db.Where("pharmacy_code IN ? AND status != 2", codes).Find(&pharmacies).Error; err == nil { + for _, ph := range pharmacies { + pharmacyByCode[ph.PharmacyCode] = ph + } + } + } + + // 3. 兜底获取默认药房 (pharmacy_id = 0) + var zeroPharmacy *model.Pharmacy + hasLoadedZero := false + getZeroPharmacy := func() *model.Pharmacy { + if !hasLoadedZero { + hasLoadedZero = true + var ph model.Pharmacy + if err := global.Db.Where("pharmacy_id = 0").First(&ph).Error; err == nil { + zeroPharmacy = &ph + } + } + return zeroPharmacy + } + + // 4. 回填 + for _, item := range list { + if item.PharmacyCode != "" { + if ph, ok := pharmacyByCode[item.PharmacyCode]; ok { + item.Pharmacy = ph + } else { + zPh := getZeroPharmacy() + if zPh != nil && zPh.PharmacyCode == item.PharmacyCode { + item.Pharmacy = zPh + } + } + } else { + // pharmacy_code 为空,默认归属到 pharmacy_id = 0 + zPh := getZeroPharmacy() + if zPh != nil { + item.Pharmacy = zPh + } + } + } +} diff --git a/api/dto/ProductPlatform.go b/api/dto/ProductPlatform.go index 3314657..2faffba 100644 --- a/api/dto/ProductPlatform.go +++ b/api/dto/ProductPlatform.go @@ -12,7 +12,10 @@ type ProductPlatformDto struct { ProductType int `json:"product_type"` // 药品类型(0:未知 1:中成药 2:西药) ProductPlatformCode string `json:"product_platform_code"` // 处方平台商品编码 ProductPharmacyCode string `json:"product_pharmacy_code"` // 第三方药店商品编码 + PharmacyId string `json:"pharmacy_id"` // 所属药房ID PharmacyCode string `json:"pharmacy_code"` // 第三方药房编码 + PharmacyName string `json:"pharmacy_name"` // 所属药房名称 + Pharmacy *PharmacyDto `json:"pharmacy"` // 所属药房详情 ProductSpec string `json:"product_spec"` // 商品规格 LicenseNumber string `json:"license_number"` // 批准文号 Manufacturer string `json:"manufacturer"` // 生产厂家 @@ -27,14 +30,16 @@ type ProductPlatformDto struct { // GetProductPlatformDto 平台商品详情 func GetProductPlatformDto(m *model.ProductPlatform) *ProductPlatformDto { - return &ProductPlatformDto{ + dto := &ProductPlatformDto{ ProductPlatformId: fmt.Sprintf("%d", m.ProductPlatformId), ProductName: m.ProductName, ProductPrice: m.ProductPrice, ProductType: m.ProductType, ProductPlatformCode: m.ProductPlatformCode, ProductPharmacyCode: m.ProductPharmacyCode, + PharmacyId: "0", PharmacyCode: m.PharmacyCode, + PharmacyName: "", ProductSpec: m.ProductSpec, LicenseNumber: m.LicenseNumber, Manufacturer: m.Manufacturer, @@ -45,6 +50,17 @@ func GetProductPlatformDto(m *model.ProductPlatform) *ProductPlatformDto { CreatedAt: m.CreatedAt, UpdatedAt: m.UpdatedAt, } + + if m.Pharmacy != nil { + dto.Pharmacy = GetPharmacyDto(m.Pharmacy) + dto.PharmacyId = fmt.Sprintf("%d", m.Pharmacy.PharmacyId) + dto.PharmacyName = m.Pharmacy.PharmacyName + if dto.PharmacyCode == "" { + dto.PharmacyCode = m.Pharmacy.PharmacyCode + } + } + + return dto } // GetProductPlatformListDto 平台商品列表 @@ -54,27 +70,7 @@ func GetProductPlatformListDto(m []*model.ProductPlatform) []*ProductPlatformDto if len(m) > 0 { for i, v := range m { - response := &ProductPlatformDto{ - ProductPlatformId: fmt.Sprintf("%d", v.ProductPlatformId), - ProductName: v.ProductName, - ProductPrice: v.ProductPrice, - ProductType: v.ProductType, - ProductPlatformCode: v.ProductPlatformCode, - ProductPharmacyCode: v.ProductPharmacyCode, - PharmacyCode: v.PharmacyCode, - ProductSpec: v.ProductSpec, - LicenseNumber: v.LicenseNumber, - Manufacturer: v.Manufacturer, - SingleUnit: v.SingleUnit, - PackagingUnit: v.PackagingUnit, - PackagingCount: v.PackagingCount, - RetailUnit: v.RetailUnit, - CreatedAt: v.CreatedAt, - UpdatedAt: v.UpdatedAt, - } - - // 将转换后的结构体添加到新切片中 - responses[i] = response + responses[i] = GetProductPlatformDto(v) } } diff --git a/api/model/productPlatform.go b/api/model/productPlatform.go index 7d92060..ffa7df4 100644 --- a/api/model/productPlatform.go +++ b/api/model/productPlatform.go @@ -21,8 +21,9 @@ type ProductPlatform struct { SingleUnit string `gorm:"column:single_unit;type:varchar(50);comment:单次剂量单位" json:"single_unit"` PackagingUnit string `gorm:"column:packaging_unit;type:varchar(20);comment:基本包装单位" json:"packaging_unit"` PackagingCount string `gorm:"column:packaging_count;type:varchar(20);comment:基本包装数量" json:"packaging_count"` - RetailUnit string `gorm:"column:retail_unit;type:varchar(20);comment:零售单位" json:"retail_unit"` + RetailUnit string `gorm:"column:retail_unit;type:varchar(20);comment:零售单位" json:"retail_unit"` Model + Pharmacy *Pharmacy `gorm:"foreignKey:PharmacyCode;references:pharmacy_code" json:"pharmacy,omitempty"` } func (m *ProductPlatform) TableName() string { diff --git a/api/requests/product.go b/api/requests/product.go index 70b7905..80d6c79 100644 --- a/api/requests/product.go +++ b/api/requests/product.go @@ -19,6 +19,7 @@ type GetPlatformProductPage struct { ProductType *int `json:"product_type" form:"product_type" label:"药品类型"` // 药品类型(0:未知 1:中成药 2:西药) ProductPlatformCode string `json:"product_platform_code" form:"product_platform_code" label:"处方平台编码"` // 处方平台商品编码 ProductPharmacyCode string `json:"product_pharmacy_code" form:"product_pharmacy_code" label:"药店编码"` // 第三方药店商品编码 + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"所属药房ID"` // 所属药房ID PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"第三方药房编码"` // 第三方药房编码 LicenseNumber string `json:"license_number" form:"license_number" label:"批准文号"` // 批准文号 Manufacturer string `json:"manufacturer" form:"manufacturer" label:"生产厂家"` // 生产厂家 @@ -30,6 +31,7 @@ type GetPlatformProductList struct { ProductType *int `json:"product_type" form:"product_type" label:"药品类型"` // 药品类型(0:未知 1:中成药 2:西药) ProductPlatformCode string `json:"product_platform_code" form:"product_platform_code" label:"处方平台编码"` // 处方平台商品编码 ProductPharmacyCode string `json:"product_pharmacy_code" form:"product_pharmacy_code" label:"药店编码"` // 第三方药店商品编码 + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"所属药房ID"` // 所属药房ID PharmacyCode string `json:"pharmacy_code" form:"pharmacy_code" label:"第三方药房编码"` // 第三方药房编码 LicenseNumber string `json:"license_number" form:"license_number" label:"批准文号"` // 批准文号 Manufacturer string `json:"manufacturer" form:"manufacturer" label:"生产厂家"` // 生产厂家 diff --git a/api/service/product.go b/api/service/product.go index 192ee9d..42f88da 100644 --- a/api/service/product.go +++ b/api/service/product.go @@ -27,8 +27,13 @@ func (r *ProductService) GetProductPlatform(productPlatformId int64) (g *dto.Pro // 获取商品库存 var quantity int + pharmacyCode := productPlatform.PharmacyCode + if pharmacyCode == "" && productPlatform.Pharmacy != nil { + pharmacyCode = productPlatform.Pharmacy.PharmacyCode + } + ReportPreRequest := prescription.GetProdStockRequest{ - PharmacyCode: productPlatform.PharmacyCode, + PharmacyCode: pharmacyCode, DrugCode: productPlatform.ProductPharmacyCode, } From da13b9dfafa4fab100ebe3d4396d5de987e809d9 Mon Sep 17 00:00:00 2001 From: haomingming Date: Tue, 8 Sep 2026 14:51:42 +0800 Subject: [PATCH 11/16] 3 --- config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config.yaml b/config.yaml index bbf338a..cd8004c 100644 --- a/config.yaml +++ b/config.yaml @@ -111,11 +111,11 @@ pre: # pre-plat-client-secret: 0baa5927164710b9f800bf33546b6da3 # pre-plat-app-url: http://49.233.3.200:6304/api/thridapi/ # pre-plat-pharmacy-code: JG-10009 - pre-plat-client-id: ZD-021 - pre-plat-client-secret: 4sdjas2387sjdasjhdas289 + pre-plat-client-id: ZD-004 + pre-plat-client-secret: 0baa5927164710b9f800bf33546b6da4 pre-plat-app-url: http://cf-thirdapi-test.yctang.net/api/thridapi/ pre-plat-pharmacy-code: ZD-10198 - pre-plat-terminal-code: ZD-10199 + pre-plat-terminal-code: ZD-10003 # [rabbitMq] amqp: From 3f5807aad2e18f53057f388e50ce60e8586fb546 Mon Sep 17 00:00:00 2001 From: haomingming Date: Tue, 15 Sep 2026 14:03:54 +0800 Subject: [PATCH 12/16] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AF=BC=E5=87=BA=20ex?= =?UTF-8?q?cel=20=E9=94=99=E4=B9=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/service/export.go | 14 +++++++---- utils/export.go | 58 ++++++++++++++++++++++++++++++++----------- 2 files changed, 52 insertions(+), 20 deletions(-) diff --git a/api/service/export.go b/api/service/export.go index a822d8b..eb9d9cf 100644 --- a/api/service/export.go +++ b/api/service/export.go @@ -246,6 +246,8 @@ type OrderInquiry struct { // OrderProductData 药品订单 type OrderProductData struct { OrderProductNo string // 订单编号 + PharmacyName string // 发货药房 + PharmacyCode string // 药房代码 OrderProductStatus string // 订单状态(1:待支付 2:待发货 3:已发货 4:已签收 5:已取消) AmountTotal float64 // 订单金额 CouponAmountTotal float64 // 优惠卷总金额 @@ -283,8 +285,6 @@ type OrderProductData struct { City string // 城市 County string // 区县 Address string // 详细地址 - PharmacyName string // 发货药房 - PharmacyCode string // 药房代码 } // OrderProductItemData 药品订单-药品列表 @@ -327,6 +327,8 @@ type OrderServicePackageDto struct { // OrderPrescriptionData 处方 type OrderPrescriptionData struct { + PharmacyName string // 开方药房 + PharmacyCode string // 药房代码 DoctorName string // 医生姓名 PharmacistName string // 药师姓名 PrescriptionStatus string // 处方状态(1:待审核 2:待使用 3:已失效 4:已使用) @@ -348,8 +350,6 @@ type OrderPrescriptionData struct { PatientMobile string // 患者电话 DoctorAdvice string // 医嘱 OrderPrescriptionIcd string // 处方诊断疾病 - PharmacyName string // 开方药房 - PharmacyCode string // 药房代码 CreatedAt string // 创建时间 } @@ -1662,11 +1662,15 @@ func (r *ExportService) OrderProduct(d []*model.OrderProduct) (string, error) { // 处理药品列表 for _, item := range v.OrderProductItem { + var availableDays float64 + if item.Product != nil { + availableDays = item.Product.AvailableDays + } productItem := OrderProductItemData{ ProductName: item.ProductName, ProductPlatformCode: item.ProductPlatformCode, ProductSpec: item.ProductSpec, - AvailableDays: item.Product.AvailableDays, + AvailableDays: availableDays, ProductAmount: fmt.Sprintf("%d", item.Amount), ProductPrice: item.ProductPrice, } diff --git a/utils/export.go b/utils/export.go index 299be6a..bd47b14 100644 --- a/utils/export.go +++ b/utils/export.go @@ -199,9 +199,11 @@ func fillDataWithMerge(f *excelize.File, sheetName string, header []HeaderCellDa } // 设置单元格样式 - err = setCellStyle(f, sheetName, axis, header[i], alignment) - if err != nil { - return 0, err + if colOffset < len(header) { + err = setCellStyle(f, sheetName, axis, header[colOffset], alignment) + if err != nil { + return 0, err + } } // 设置行高 35-第一行 @@ -214,23 +216,33 @@ func fillDataWithMerge(f *excelize.File, sheetName string, header []HeaderCellDa mergeNum = mergeNum + 1 mergeNumSlice = append(mergeNumSlice, colName) } else { - var sliceFieldNum int // 切片字段数量 - // 最大切片数量,此数量为其余需合并的数量 if filedNumSlice < field.Len() { filedNumSlice = field.Len() } + elemType := field.Type().Elem() + if elemType.Kind() == reflect.Ptr { + elemType = elemType.Elem() + } + numSliceFields := 0 + if elemType.Kind() == reflect.Struct { + numSliceFields = elemType.NumField() + } + for j := 0; j < field.Len(); j++ { item := field.Index(j).Interface() v1 := reflect.ValueOf(item) + if v1.Kind() == reflect.Ptr { + v1 = v1.Elem() + } - for i2 := 0; i2 < field.Index(j).NumField(); i2++ { + for i2 := 0; i2 < v1.NumField(); i2++ { // 获取字段值 cellValue := v1.Field(i2).Interface() // 获取列名 - colName, err := excelize.ColumnNumberToName(i + i2 + 1) + colName, err := excelize.ColumnNumberToName(colOffset + i2 + 1) if err != nil { return 0, err } @@ -245,9 +257,11 @@ func fillDataWithMerge(f *excelize.File, sheetName string, header []HeaderCellDa } // 设置单元格样式 - err = setCellStyle(f, sheetName, axis, header[i+i2], alignment) - if err != nil { - return row, err + if colOffset+i2 < len(header) { + err = setCellStyle(f, sheetName, axis, header[colOffset+i2], alignment) + if err != nil { + return row, err + } } // 设置行高 35-第一行 @@ -255,14 +269,28 @@ func fillDataWithMerge(f *excelize.File, sheetName string, header []HeaderCellDa if err != nil { return row, err } - - sliceFieldNum = i2 } } - // 列偏移量需增加上切片字段数量 - colOffset = colOffset + sliceFieldNum + if field.Len() == 0 { + for i2 := 0; i2 < numSliceFields; i2++ { + colName, err := excelize.ColumnNumberToName(colOffset + i2 + 1) + if err != nil { + return 0, err + } + axis = colName + fmt.Sprintf("%d", row+1) + if colOffset+i2 < len(header) { + _ = setCellStyle(f, sheetName, axis, header[colOffset+i2], alignment) + } + _ = f.SetRowHeight(sheetName, row+1, 35) + } + } + + // 列偏移量需增加上切片字段数量(减1是因为循环末尾有colOffset++) + if numSliceFields > 0 { + colOffset = colOffset + numSliceFields - 1 + } } colOffset++ @@ -325,7 +353,7 @@ func setCellStyle(f *excelize.File, sheetName, axis string, header HeaderCellDat } } - if header.CellType == "float" { + if header.CellType == "float" || header.CellType == "float64" { style.NumFmt = 2 customNumFmt := "0.000" style.CustomNumFmt = &customNumFmt From b349acb4b47ccd173f01978c238bc0fd54d03268 Mon Sep 17 00:00:00 2001 From: haomingming Date: Wed, 16 Sep 2026 17:21:31 +0800 Subject: [PATCH 13/16] =?UTF-8?q?1=E3=80=81=E5=A2=9E=E5=8A=A0=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E8=8D=AF=E6=88=BF=E5=85=B3=E8=81=94=E5=8C=BB=E7=94=9F?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E5=AF=BC=E5=87=BA=202=E3=80=81=E6=A3=80?= =?UTF-8?q?=E6=B5=8B=E5=88=B0=E6=9C=89=E7=BB=91=E5=AE=9A/=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=8C=BB=E7=94=9F=E6=97=B6=E7=9B=B4=E6=8E=A5=E6=8A=A5?= =?UTF-8?q?=E9=94=99=EF=BC=8C=E5=BC=BA=E5=88=B6=E8=A6=81=E6=B1=82=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=91=98=E5=85=88=E6=89=8B=E5=8A=A8=E5=A4=84=E7=90=86?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/controller/export.go | 48 ++++++++++++++++++++ api/dao/doctorPharmacy.go | 95 +++++++++++++++++++++++++++++++++++++++ api/requests/pharmacy.go | 24 +++++++--- api/router/router.go | 13 ++++++ api/service/export.go | 87 +++++++++++++++++++++++++++++++++++ api/service/pharmacy.go | 37 +++++++++++++++ 6 files changed, 297 insertions(+), 7 deletions(-) diff --git a/api/controller/export.go b/api/controller/export.go index b77099f..249d3ce 100644 --- a/api/controller/export.go +++ b/api/controller/export.go @@ -781,3 +781,51 @@ func (r *Export) OrderService(c *gin.Context) { responses.OkWithData(ossAddress, c) } + +// PharmacyDoctor 药房关联医生 +func (r *Export) PharmacyDoctor(c *gin.Context) { + pharmacyRequest := requests.PharmacyRequest{} + req := pharmacyRequest.PharmacyDoctorExportList + 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 + } + + // 获取数据 + doctorPharmacyDao := dao.DoctorPharmacyDao{} + list, err := doctorPharmacyDao.GetPharmacyDoctorExportListSearch(req) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 业务处理 + exportService := service.ExportService{} + ossAddress, err := exportService.PharmacyDoctor(list) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 获取当前登陆用户id + userId := c.GetInt64("UserId") + if userId != 0 { + // 记录日志 + logExport := &model.LogExport{ + AdminUserId: userId, + ExportModule: "药房关联医生", + ExportFile: utils.RemoveOssDomain(ossAddress), + } + + logExportDao := dao.LogExportDao{} + _, _ = logExportDao.AddLogExportUnTransaction(logExport) + } + + responses.OkWithData(ossAddress, c) +} diff --git a/api/dao/doctorPharmacy.go b/api/dao/doctorPharmacy.go index 968bed4..46a62ad 100644 --- a/api/dao/doctorPharmacy.go +++ b/api/dao/doctorPharmacy.go @@ -1,6 +1,10 @@ package dao import ( + "errors" + "strconv" + "strings" + "gorm.io/gorm" "hospital-admin-api/api/model" "hospital-admin-api/api/requests" @@ -168,3 +172,94 @@ func (r *DoctorPharmacyDao) GetPharmacyDoctorListByPharmacyId(pharmacyId int64) } return m, nil } + +// GetDoctorPharmacyCountsByPharmacyId 获取药房绑定的医生数量(有效绑定数、设为默认药房数) +func (r *DoctorPharmacyDao) GetDoctorPharmacyCountsByPharmacyId(pharmacyId int64) (totalCount int64, defaultCount int64, err error) { + err = global.Db.Model(&model.DoctorPharmacy{}). + Where("pharmacy_id = ? AND status = 1", pharmacyId). + Count(&totalCount).Error + if err != nil { + return 0, 0, err + } + + err = global.Db.Model(&model.DoctorPharmacy{}). + Where("pharmacy_id = ? AND status = 1 AND is_default = 1", pharmacyId). + Count(&defaultCount).Error + if err != nil { + return 0, 0, err + } + + return totalCount, defaultCount, nil +} + +// GetPharmacyDoctorExportListSearch 获取药房关联医生列表-导出 +func (r *DoctorPharmacyDao) GetPharmacyDoctorExportListSearch(req requests.PharmacyDoctorExportList) (m []*model.DoctorPharmacy, err error) { + query := global.Db.Model(&model.DoctorPharmacy{}). + Where("gdxz_doctor_pharmacy.status = 1") + + // 药房id过滤 + if req.PharmacyId != "" { + pharmacyId, _ := strconv.ParseInt(req.PharmacyId, 10, 64) + if pharmacyId >= 0 { + query = query.Where("gdxz_doctor_pharmacy.pharmacy_id = ?", pharmacyId) + } + } + + // 1:当前搜索数据 + if req.Type == 1 { + needJoinDoctor := req.DoctorName != "" || req.Mobile != "" + if needJoinDoctor { + query = query.Joins("JOIN gdxz_user_doctor ON gdxz_user_doctor.doctor_id = gdxz_doctor_pharmacy.doctor_id") + if req.DoctorName != "" { + query = query.Where("gdxz_user_doctor.user_name LIKE ?", "%"+req.DoctorName+"%") + } + if req.Mobile != "" { + query = query.Joins("JOIN gdxz_user ON gdxz_user.user_id = gdxz_user_doctor.user_id"). + Where("gdxz_user.mobile LIKE ?", "%"+req.Mobile+"%") + } + } + } + + // 2:当前选中数据 + if req.Type == 2 { + if req.Id == "" { + return nil, errors.New("未提供需导出数据编号") + } + id := strings.Split(req.Id, ",") + query = query.Where("gdxz_doctor_pharmacy.doctor_pharmacy_id IN (?) OR gdxz_doctor_pharmacy.doctor_id IN (?)", id, id) + } + + // 3:全部数据(无额外搜索条件) + + err = query.Order("gdxz_doctor_pharmacy.is_default desc, gdxz_doctor_pharmacy.created_at desc"). + Preload("Pharmacy"). + Preload("UserDoctor.User"). + Preload("UserDoctor.Hospital"). + Find(&m).Error + if err != nil { + return nil, err + } + + // GORM 在外键为 0 时会自动跳过 Preload,因此针对未能预加载的记录进行兜底补全 + var zeroPharmacy *model.Pharmacy + for _, dp := range m { + if dp.Pharmacy == nil { + if dp.PharmacyId == 0 { + if zeroPharmacy == nil { + var ph model.Pharmacy + if err := global.Db.Where("pharmacy_id = 0").First(&ph).Error; err == nil { + zeroPharmacy = &ph + } + } + dp.Pharmacy = zeroPharmacy + } else { + var ph model.Pharmacy + if err := global.Db.Where("pharmacy_id = ?", dp.PharmacyId).First(&ph).Error; err == nil { + dp.Pharmacy = &ph + } + } + } + } + + return m, nil +} diff --git a/api/requests/pharmacy.go b/api/requests/pharmacy.go index d51d6b3..0713e03 100644 --- a/api/requests/pharmacy.go +++ b/api/requests/pharmacy.go @@ -1,13 +1,23 @@ package requests type PharmacyRequest struct { - GetPharmacyList // 获取药房列表 - GetPharmacyPage // 获取药房列表-分页 - AddPharmacy // 新增药房 - PutPharmacy // 修改药房 - PutPharmacyStatus // 修改药房状态 - GetPharmacyDoctorPage // 药房绑定的医生列表-分页 - GetPharmacyDoctorList // 药房绑定的医生列表 + GetPharmacyList // 获取药房列表 + GetPharmacyPage // 获取药房列表-分页 + AddPharmacy // 新增药房 + PutPharmacy // 修改药房 + PutPharmacyStatus // 修改药房状态 + GetPharmacyDoctorPage // 药房绑定的医生列表-分页 + GetPharmacyDoctorList // 药房绑定的医生列表 + PharmacyDoctorExportList // 药房关联医生-导出 +} + +// PharmacyDoctorExportList 药房关联医生-导出 +type PharmacyDoctorExportList 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(doctor_pharmacy_id或doctor_id),逗号分隔 + PharmacyId string `json:"pharmacy_id" form:"pharmacy_id" label:"药房id"` // 药房id + DoctorName string `json:"doctor_name" form:"doctor_name" label:"医生姓名"` // 医生姓名 + Mobile string `json:"mobile" form:"mobile" label:"手机号"` // 手机号 } // GetPharmacyDoctorPage 药房绑定的医生列表-分页 diff --git a/api/router/router.go b/api/router/router.go index 62b3914..206cfe3 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -391,6 +391,9 @@ func privateRouter(r *gin.Engine, api controller.Api) { // 设置医生的默认药房 doctorPharmacyGroup.PUT("/default/:id", api.DoctorPharmacy.SetDefaultDoctorPharmacy) doctorPharmacyGroup.PUT("/default", api.DoctorPharmacy.SetDefaultDoctorPharmacyPut) + + // 药房关联医生-导出 + doctorPharmacyGroup.POST("/export", api.Export.PharmacyDoctor) } // 身份审核列表 @@ -809,6 +812,13 @@ func privateRouter(r *gin.Engine, api controller.Api) { // 系统药品 productGroup.POST("", api.Export.Product) } + + // 药房 + pharmacyGroup := exportGroup.Group("/pharmacy") + { + // 药房关联医生 + pharmacyGroup.POST("/doctor", api.Export.PharmacyDoctor) + } } // 商品管理 @@ -943,6 +953,9 @@ func privateRouter(r *gin.Engine, api controller.Api) { // 药房绑定的医生列表 pharmacyGroup.GET("/doctor/:pharmacy_id", api.Pharmacy.GetPharmacyDoctorList) + + // 药房关联医生-导出 + pharmacyGroup.POST("/doctor/export", api.Export.PharmacyDoctor) } // 科普分类管理 diff --git a/api/service/export.go b/api/service/export.go index eb9d9cf..af5cf09 100644 --- a/api/service/export.go +++ b/api/service/export.go @@ -380,6 +380,21 @@ type ProductData struct { CreatedAt string // 创建时间 } +// PharmacyDoctorData 药房关联医生 +type PharmacyDoctorData struct { + PharmacyName string // 药房名称 + PharmacyCode string // 药房代码 + DoctorName string // 医生姓名 + Mobile string // 手机号 + DoctorTitle string // 医生职称 + HospitalName string // 医院名称 + DepartmentCustomName string // 科室名称 + DepartmentCustomMobile string // 科室电话 + IsDefault string // 是否默认药房(0:否 1:是) + Status string // 状态(0:禁用 1:正常) + CreatedAt string // 关联时间 +} + // DoctorWithdrawal 提现记录 func (r *ExportService) DoctorWithdrawal(doctorWithdrawals []*model.DoctorWithdrawal) (string, error) { header := []utils.HeaderCellData{ @@ -2052,3 +2067,75 @@ func (r *ExportService) Product(d []*model.Product) (string, error) { ossPath = utils.AddOssDomain("/" + ossPath) return ossPath, nil } + +// PharmacyDoctor 药房关联医生 +func (r *ExportService) PharmacyDoctor(d []*model.DoctorPharmacy) (string, error) { + header := []utils.HeaderCellData{ + {Value: "药房名称", CellType: "string", NumberFmt: "", ColWidth: 25}, + {Value: "药房代码", CellType: "string", NumberFmt: "", ColWidth: 18}, + {Value: "医生姓名", CellType: "string", NumberFmt: "", ColWidth: 18}, + {Value: "手机号", CellType: "string", NumberFmt: "", ColWidth: 18}, + {Value: "医生职称", CellType: "string", NumberFmt: "", ColWidth: 18}, + {Value: "医院名称", CellType: "string", NumberFmt: "", ColWidth: 30}, + {Value: "科室名称", CellType: "string", NumberFmt: "", ColWidth: 20}, + {Value: "科室电话", CellType: "string", NumberFmt: "", ColWidth: 18}, + {Value: "是否默认药房", CellType: "string", NumberFmt: "", ColWidth: 18}, + {Value: "状态", CellType: "string", NumberFmt: "", ColWidth: 15}, + {Value: "关联时间", CellType: "date", NumberFmt: "yyyy-mm-dd hh:mm:ss", ColWidth: 30}, + } + + var dataSlice []interface{} + for _, v := range d { + data := PharmacyDoctorData{ + IsDefault: utils.IsDefaultToString(v.IsDefault), + Status: "正常", + } + if v.Status == 0 { + data.Status = "禁用" + } + + if v.Pharmacy != nil { + data.PharmacyName = v.Pharmacy.PharmacyName + data.PharmacyCode = v.Pharmacy.PharmacyCode + } + + if v.UserDoctor != nil { + data.DoctorName = v.UserDoctor.UserName + data.DoctorTitle = utils.DoctorTitleToString(v.UserDoctor.DoctorTitle) + data.DepartmentCustomName = v.UserDoctor.DepartmentCustomName + data.DepartmentCustomMobile = v.UserDoctor.DepartmentCustomMobile + if v.UserDoctor.Hospital != nil { + data.HospitalName = v.UserDoctor.Hospital.HospitalName + } + if v.UserDoctor.User != nil { + data.Mobile = v.UserDoctor.User.Mobile + } + } + + if v.CreatedAt != (model.LocalTime{}) { + data.CreatedAt = time.Time(v.CreatedAt).Format("2006-01-02 15:04:05") + } + + dataSlice = append(dataSlice, data) + } + + file, err := utils.Export(header, dataSlice) + if err != nil { + return "", err + } + + // 设置文件名字 + now := time.Now() + dateTimeString := now.Format("20060102150405") // 当前时间字符串 + rand.New(rand.NewSource(time.Now().UnixNano())) // 设置随机数 + ossPath := "admin/export/药房关联医生" + 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/pharmacy.go b/api/service/pharmacy.go index c7290b7..21a9334 100644 --- a/api/service/pharmacy.go +++ b/api/service/pharmacy.go @@ -109,6 +109,18 @@ func (r *PharmacyService) PutPharmacy(pharmacyId int64, req requests.PutPharmacy } } + // 若修改为禁用,校验是否有医生设为默认药房 + if req.Status != nil && *req.Status == 0 && pharmacy.Status == 1 { + doctorPharmacyDao := dao.DoctorPharmacyDao{} + totalCount, defaultCount, err := doctorPharmacyDao.GetDoctorPharmacyCountsByPharmacyId(pharmacyId) + if err != nil { + return false, errors.New("查询药房关联医生失败") + } + if defaultCount > 0 { + return false, fmt.Errorf("该药房已被 %d 位医生设为默认药房(共 %d 位医生绑定),无法禁用。请先在【药房关联医生】中调整默认药房或解除绑定后再试", defaultCount, totalCount) + } + } + tx := global.Db.Begin() defer func() { if rec := recover(); rec != nil { @@ -201,6 +213,18 @@ func (r *PharmacyService) PutPharmacyStatus(pharmacyId int64, req requests.PutPh return false, errors.New("药房不存在或已删除") } + // 若修改为禁用,校验是否有医生设为默认药房 + if req.Status != nil && *req.Status == 0 { + doctorPharmacyDao := dao.DoctorPharmacyDao{} + totalCount, defaultCount, err := doctorPharmacyDao.GetDoctorPharmacyCountsByPharmacyId(pharmacyId) + if err != nil { + return false, errors.New("查询药房关联医生失败") + } + if defaultCount > 0 { + return false, fmt.Errorf("该药房已被 %d 位医生设为默认药房(共 %d 位医生绑定),无法禁用。请先在【药房关联医生】中调整默认药房或解除绑定后再试", defaultCount, totalCount) + } + } + data := map[string]interface{}{ "status": *req.Status, } @@ -230,6 +254,19 @@ func (r *PharmacyService) DeletePharmacy(pharmacyId int64) (bool, error) { return false, errors.New("药房不存在或已删除") } + // 删除药房前校验:若有关联医生(特别是默认药房),拦截禁止删除 + doctorPharmacyDao := dao.DoctorPharmacyDao{} + totalCount, defaultCount, err := doctorPharmacyDao.GetDoctorPharmacyCountsByPharmacyId(pharmacyId) + if err != nil { + return false, errors.New("查询药房关联医生失败") + } + if defaultCount > 0 { + return false, fmt.Errorf("该药房已被 %d 位医生设为默认药房(共 %d 位医生绑定),无法删除。请先在【药房关联医生】中调整默认药房或解除绑定后再试", defaultCount, totalCount) + } + if totalCount > 0 { + return false, fmt.Errorf("该药房仍有 %d 位医生绑定,无法删除。请先在【药房关联医生】中解除绑定后再试", totalCount) + } + tx := global.Db.Begin() defer func() { if rec := recover(); rec != nil { From cfdac70e9466cd6ebe043358970b048dbc7a5888 Mon Sep 17 00:00:00 2001 From: haomingming Date: Thu, 17 Sep 2026 08:51:56 +0800 Subject: [PATCH 14/16] =?UTF-8?q?=E8=8D=AF=E6=88=BF=E4=B8=8B=E7=BA=BF?= =?UTF-8?q?=EF=BC=88=E7=A6=81=E7=94=A8/=E5=88=A0=E9=99=A4=EF=BC=89?= =?UTF-8?q?=E5=8C=BB=E7=94=9F=E5=88=86=E6=B5=81=E8=BF=81=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/controller/pharmacy.go | 51 ++++++++ api/dao/doctorPharmacy.go | 38 ++++++ api/dto/PharmacyDoctor.go | 40 ++++++ api/requests/pharmacy.go | 15 +++ api/router/router.go | 6 + api/service/pharmacy.go | 255 +++++++++++++++++++++++++++++++++++++ 6 files changed, 405 insertions(+) diff --git a/api/controller/pharmacy.go b/api/controller/pharmacy.go index 3d725ce..700a765 100644 --- a/api/controller/pharmacy.go +++ b/api/controller/pharmacy.go @@ -282,3 +282,54 @@ func (r *Pharmacy) GetPharmacyDoctorList(c *gin.Context) { responses.OkWithData(list, c) } + +// GetAffectedDoctors 获取药房下线受影响医生列表(预检接口) +func (r *Pharmacy) GetAffectedDoctors(c *gin.Context) { + id := c.Param("pharmacy_id") + if id == "" { + id = c.Param("id") + } + if id == "" { + responses.FailWithMessage("缺少药房ID参数", c) + return + } + + pharmacyId, err := strconv.ParseInt(id, 10, 64) + if err != nil { + responses.Fail(c) + return + } + + pharmacyService := service.PharmacyService{} + result, err := pharmacyService.GetAffectedDoctors(pharmacyId) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.OkWithData(result, c) +} + +// BatchTransferAndAction 批量迁移医生默认药房并执行药房操作(禁用/删除) +func (r *Pharmacy) BatchTransferAndAction(c *gin.Context) { + pharmacyRequest := requests.PharmacyRequest{} + req := pharmacyRequest.BatchTransferAndAction + if err := c.ShouldBindJSON(&req); err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + if err := global.Validate.Struct(req); err != nil { + responses.FailWithMessage(utils.Translate(err), c) + return + } + + pharmacyService := service.PharmacyService{} + _, err := pharmacyService.BatchTransferAndAction(req) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + responses.Ok(c) +} diff --git a/api/dao/doctorPharmacy.go b/api/dao/doctorPharmacy.go index 46a62ad..2b639c3 100644 --- a/api/dao/doctorPharmacy.go +++ b/api/dao/doctorPharmacy.go @@ -192,6 +192,44 @@ func (r *DoctorPharmacyDao) GetDoctorPharmacyCountsByPharmacyId(pharmacyId int64 return totalCount, defaultCount, nil } +// GetOtherPharmaciesByDoctorIds 批量获取一组医生绑定的其他有效药房 +func (r *DoctorPharmacyDao) GetOtherPharmaciesByDoctorIds(doctorIds []int64, excludePharmacyId int64) (m []*model.DoctorPharmacy, err error) { + if len(doctorIds) == 0 { + return nil, nil + } + + err = global.Db.Preload("Pharmacy"). + Where("doctor_id IN (?) AND status = 1 AND pharmacy_id != ?", doctorIds, excludePharmacyId). + Order("is_default desc, created_at desc"). + Find(&m).Error + if err != nil { + return nil, err + } + + // GORM 在外键为 0 时会自动跳过 Preload,因此针对未能预加载的记录进行兜底补全 + var zeroPharmacy *model.Pharmacy + for _, dp := range m { + if dp.Pharmacy == nil { + if dp.PharmacyId == 0 { + if zeroPharmacy == nil { + var ph model.Pharmacy + if err := global.Db.Where("pharmacy_id = 0").First(&ph).Error; err == nil { + zeroPharmacy = &ph + } + } + dp.Pharmacy = zeroPharmacy + } else { + var ph model.Pharmacy + if err := global.Db.Where("pharmacy_id = ?", dp.PharmacyId).First(&ph).Error; err == nil { + dp.Pharmacy = &ph + } + } + } + } + + return m, nil +} + // GetPharmacyDoctorExportListSearch 获取药房关联医生列表-导出 func (r *DoctorPharmacyDao) GetPharmacyDoctorExportListSearch(req requests.PharmacyDoctorExportList) (m []*model.DoctorPharmacy, err error) { query := global.Db.Model(&model.DoctorPharmacy{}). diff --git a/api/dto/PharmacyDoctor.go b/api/dto/PharmacyDoctor.go index 9f4f59e..f6d5201 100644 --- a/api/dto/PharmacyDoctor.go +++ b/api/dto/PharmacyDoctor.go @@ -76,3 +76,43 @@ func GetPharmacyDoctorListDto(list []*model.DoctorPharmacy) []PharmacyDoctorDto } return res } + +// GetDoctorTitleName 获取医生职称名称 +func GetDoctorTitleName(title int) string { + return doctorTitleMap[title] +} + +// BoundPharmacySimpleDto 医生绑定的药房简要信息 +type BoundPharmacySimpleDto struct { + PharmacyId string `json:"pharmacy_id"` + PharmacyName string `json:"pharmacy_name"` + PharmacyCode string `json:"pharmacy_code"` + IsDefault int `json:"is_default"` +} + +// AffectedDoctorItemDto 受影响的医生明细 +type AffectedDoctorItemDto struct { + DoctorId string `json:"doctor_id"` + DoctorPharmacyId string `json:"doctor_pharmacy_id"` + UserId string `json:"user_id"` + UserName string `json:"user_name"` + Mobile string `json:"mobile"` + DoctorTitleName string `json:"doctor_title_name"` + HospitalId string `json:"hospital_id"` + HospitalName string `json:"hospital_name"` + DepartmentCustomId string `json:"department_custom_id"` + DepartmentCustomName string `json:"department_custom_name"` + IsDefault int `json:"is_default"` // 在当前待下线药房是否为默认(1:是 0:否) + OtherBoundPharmacies []BoundPharmacySimpleDto `json:"other_bound_pharmacies"` // 该医生名下绑定的其他可用药房 +} + +// PharmacyAffectedDoctorsDto 下线预检受影响医生列表响应 +type PharmacyAffectedDoctorsDto struct { + PharmacyId string `json:"pharmacy_id"` + PharmacyName string `json:"pharmacy_name"` + PharmacyCode string `json:"pharmacy_code"` + Status int `json:"status"` + DefaultDoctorCount int64 `json:"default_doctor_count"` + TotalDoctorCount int64 `json:"total_doctor_count"` + DoctorList []AffectedDoctorItemDto `json:"doctor_list"` +} diff --git a/api/requests/pharmacy.go b/api/requests/pharmacy.go index 0713e03..ecacda0 100644 --- a/api/requests/pharmacy.go +++ b/api/requests/pharmacy.go @@ -9,6 +9,7 @@ type PharmacyRequest struct { GetPharmacyDoctorPage // 药房绑定的医生列表-分页 GetPharmacyDoctorList // 药房绑定的医生列表 PharmacyDoctorExportList // 药房关联医生-导出 + BatchTransferAndAction // 批量迁移医生默认药房并执行药房操作 } // PharmacyDoctorExportList 药房关联医生-导出 @@ -89,3 +90,17 @@ type PutPharmacy struct { type PutPharmacyStatus struct { Status *int `json:"status" form:"status" label:"状态" validate:"required,oneof=0 1"` } + +// BatchTransferDoctorItem 单个医生的迁移配置 +type BatchTransferDoctorItem struct { + DoctorId string `json:"doctor_id" form:"doctor_id" label:"医生id" validate:"required"` + TargetPharmacyId string `json:"target_pharmacy_id" form:"target_pharmacy_id" label:"目标药房id" validate:"required"` +} + +// BatchTransferAndAction 批量迁移医生默认药房并执行药房操作 +type BatchTransferAndAction struct { + SourcePharmacyId string `json:"source_pharmacy_id" form:"source_pharmacy_id" label:"原药房id" validate:"required"` + Action string `json:"action" form:"action" label:"操作类型" validate:"required,oneof=disable delete"` + UnbindSource *int `json:"unbind_source" form:"unbind_source" label:"是否解绑原药房"` // 1:是 0:否,若action为delete则强制解绑 + Transfers []BatchTransferDoctorItem `json:"transfers" form:"transfers" label:"迁移列表" validate:"required,dive"` +} diff --git a/api/router/router.go b/api/router/router.go index 206cfe3..7b59038 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -956,6 +956,12 @@ func privateRouter(r *gin.Engine, api controller.Api) { // 药房关联医生-导出 pharmacyGroup.POST("/doctor/export", api.Export.PharmacyDoctor) + + // 获取药房下线受影响医生列表(预检接口) + pharmacyGroup.GET("/affected-doctors/:pharmacy_id", api.Pharmacy.GetAffectedDoctors) + + // 批量迁移医生默认药房并执行药房操作(禁用/删除) + pharmacyGroup.POST("/batch-transfer-and-action", api.Pharmacy.BatchTransferAndAction) } // 科普分类管理 diff --git a/api/service/pharmacy.go b/api/service/pharmacy.go index 21a9334..c2cad4d 100644 --- a/api/service/pharmacy.go +++ b/api/service/pharmacy.go @@ -350,3 +350,258 @@ func (r *PharmacyService) GetPharmacyDoctorList(pharmacyId int64) ([]dto.Pharmac return dto.GetPharmacyDoctorListDto(list), nil } + +// GetAffectedDoctors 获取药房下线受影响医生列表(预检接口) +func (r *PharmacyService) GetAffectedDoctors(pharmacyId int64) (*dto.PharmacyAffectedDoctorsDto, error) { + pharmacyDao := dao.PharmacyDao{} + pharmacy, err := pharmacyDao.GetPharmacyById(pharmacyId) + if err != nil || pharmacy == nil { + return nil, errors.New("药房不存在或已删除") + } + + doctorPharmacyDao := dao.DoctorPharmacyDao{} + totalCount, defaultCount, err := doctorPharmacyDao.GetDoctorPharmacyCountsByPharmacyId(pharmacyId) + if err != nil { + return nil, errors.New("查询药房关联医生数量失败") + } + + // 获取当前药房绑定的所有医生 + list, err := doctorPharmacyDao.GetPharmacyDoctorListByPharmacyId(pharmacyId) + if err != nil { + return nil, errors.New("查询药房关联医生列表失败") + } + + // 收集所有医生ID + doctorIds := make([]int64, 0, len(list)) + for _, dp := range list { + doctorIds = append(doctorIds, dp.DoctorId) + } + + // 批量查询这些医生绑定的其他有效药房 + otherMap := make(map[int64][]dto.BoundPharmacySimpleDto) + if len(doctorIds) > 0 { + otherList, err := doctorPharmacyDao.GetOtherPharmaciesByDoctorIds(doctorIds, pharmacyId) + if err == nil { + for _, dp := range otherList { + if dp.Pharmacy != nil { + otherMap[dp.DoctorId] = append(otherMap[dp.DoctorId], dto.BoundPharmacySimpleDto{ + PharmacyId: strconv.FormatInt(dp.Pharmacy.PharmacyId, 10), + PharmacyName: dp.Pharmacy.PharmacyName, + PharmacyCode: dp.Pharmacy.PharmacyCode, + IsDefault: dp.IsDefault, + }) + } + } + } + } + + doctorItems := make([]dto.AffectedDoctorItemDto, 0, len(list)) + for _, dp := range list { + item := dto.AffectedDoctorItemDto{ + DoctorId: strconv.FormatInt(dp.DoctorId, 10), + DoctorPharmacyId: strconv.FormatInt(dp.DoctorPharmacyId, 10), + IsDefault: dp.IsDefault, + } + if dp.UserDoctor != nil { + item.UserId = strconv.FormatInt(dp.UserDoctor.UserId, 10) + item.UserName = dp.UserDoctor.UserName + item.DoctorTitleName = dto.GetDoctorTitleName(dp.UserDoctor.DoctorTitle) + item.HospitalId = strconv.FormatInt(dp.UserDoctor.HospitalID, 10) + if dp.UserDoctor.Hospital != nil { + item.HospitalName = dp.UserDoctor.Hospital.HospitalName + } + item.DepartmentCustomId = strconv.FormatInt(dp.UserDoctor.DepartmentCustomId, 10) + item.DepartmentCustomName = dp.UserDoctor.DepartmentCustomName + if dp.UserDoctor.User != nil { + item.Mobile = dp.UserDoctor.User.Mobile + } + } + if others, ok := otherMap[dp.DoctorId]; ok { + item.OtherBoundPharmacies = others + } else { + item.OtherBoundPharmacies = []dto.BoundPharmacySimpleDto{} + } + doctorItems = append(doctorItems, item) + } + + res := &dto.PharmacyAffectedDoctorsDto{ + PharmacyId: strconv.FormatInt(pharmacy.PharmacyId, 10), + PharmacyName: pharmacy.PharmacyName, + PharmacyCode: pharmacy.PharmacyCode, + Status: pharmacy.Status, + DefaultDoctorCount: defaultCount, + TotalDoctorCount: totalCount, + DoctorList: doctorItems, + } + return res, nil +} + +// BatchTransferAndAction 批量迁移医生默认药房并执行药房操作(禁用/删除) +func (r *PharmacyService) BatchTransferAndAction(req requests.BatchTransferAndAction) (bool, error) { + sourcePharmacyId, err := strconv.ParseInt(req.SourcePharmacyId, 10, 64) + if err != nil || sourcePharmacyId < 0 { + return false, errors.New("原药房id无效") + } + + if req.Action != "disable" && req.Action != "delete" { + return false, errors.New("操作类型仅支持 disable(禁用) 或 delete(删除)") + } + + pharmacyDao := dao.PharmacyDao{} + sourcePharmacy, err := pharmacyDao.GetPharmacyById(sourcePharmacyId) + if err != nil || sourcePharmacy == nil { + return false, errors.New("原药房不存在或已删除") + } + + // 查询当前以原药房为默认药房的所有医生 + doctorPharmacyDao := dao.DoctorPharmacyDao{} + var defaultDoctorPharmacies []*model.DoctorPharmacy + err = global.Db.Where("pharmacy_id = ? AND status = 1 AND is_default = 1", sourcePharmacyId).Find(&defaultDoctorPharmacies).Error + if err != nil { + return false, errors.New("查询受影响医生失败") + } + + defaultDoctorMap := make(map[int64]bool) + for _, dp := range defaultDoctorPharmacies { + defaultDoctorMap[dp.DoctorId] = true + } + + // 校验 transfers + transferDoctorMap := make(map[int64]int64) // doctorId -> targetPharmacyId + targetPharmacyIdSet := make(map[int64]bool) + + for _, item := range req.Transfers { + docId, err := strconv.ParseInt(item.DoctorId, 10, 64) + if err != nil || docId <= 0 { + return false, errors.New("迁移配置中包含无效的医生id: " + item.DoctorId) + } + targetPharId, err := strconv.ParseInt(item.TargetPharmacyId, 10, 64) + if err != nil || targetPharId < 0 { + return false, errors.New("迁移配置中包含无效的目标药房id: " + item.TargetPharmacyId) + } + if targetPharId == sourcePharmacyId { + return false, errors.New("目标药房不能是当前待下线的药房自身") + } + if _, exists := transferDoctorMap[docId]; exists { + return false, fmt.Errorf("医生(ID: %d)存在重复迁移配置,每位医生只能指定一个默认药房", docId) + } + transferDoctorMap[docId] = targetPharId + targetPharmacyIdSet[targetPharId] = true + } + + // 强校验:原药房名下所有默认医生必须全部指定了替代药房 + for docId := range defaultDoctorMap { + if _, ok := transferDoctorMap[docId]; !ok { + return false, fmt.Errorf("医生(ID: %d)当前以此药房为默认药房,必须为其指定替代药房", docId) + } + } + + // 校验所有目标药房必须存在且处于正常状态 (status = 1) + if len(targetPharmacyIdSet) > 0 { + var targetPharIds []int64 + for id := range targetPharmacyIdSet { + targetPharIds = append(targetPharIds, id) + } + + var targetPharmacies []*model.Pharmacy + err = global.Db.Where("pharmacy_id IN (?)", targetPharIds).Find(&targetPharmacies).Error + if err != nil { + return false, errors.New("查询目标药房信息失败") + } + + targetMap := make(map[int64]*model.Pharmacy) + for _, ph := range targetPharmacies { + targetMap[ph.PharmacyId] = ph + } + + for _, targetId := range targetPharIds { + ph, exists := targetMap[targetId] + if !exists || ph == nil { + return false, fmt.Errorf("目标药房(ID: %d)不存在或已被删除", targetId) + } + if ph.Status != 1 { + return false, fmt.Errorf("目标药房【%s】处于禁用状态,无法作为替代药房", ph.PharmacyName) + } + } + } + + // 开启事务执行迁移与药房操作 + tx := global.Db.Begin() + defer func() { + if rec := recover(); rec != nil { + tx.Rollback() + } + }() + + // 逐个医生处理目标药房绑定与默认设置 + for docId, targetPharId := range transferDoctorMap { + // 1. 重置该医生名下现有的所有药房为非默认 + if err := doctorPharmacyDao.ResetDoctorDefaultPharmacy(tx, docId); err != nil { + tx.Rollback() + return false, errors.New("重置医生默认药房失败") + } + + // 2. 检查该医生是否已绑定目标药房 + existTarget, _ := doctorPharmacyDao.GetDoctorPharmacyByDoctorAndPharmacy(docId, targetPharId) + if existTarget != nil { + // 更新为 status = 1, is_default = 1 + err = tx.Model(&model.DoctorPharmacy{}). + Where("doctor_pharmacy_id = ?", existTarget.DoctorPharmacyId). + Updates(map[string]interface{}{ + "is_default": 1, + "status": 1, + }).Error + if err != nil { + tx.Rollback() + return false, errors.New("更新目标药房绑定关系失败") + } + } else { + // 新增绑定记录 + newBinding := &model.DoctorPharmacy{ + DoctorId: docId, + PharmacyId: targetPharId, + IsDefault: 1, + Status: 1, + } + _, err = doctorPharmacyDao.AddDoctorPharmacy(tx, newBinding) + if err != nil { + tx.Rollback() + return false, errors.New("新增目标药房绑定关系失败: " + err.Error()) + } + } + + // 3. 处理医生与原药房关系 + if req.Action == "delete" || (req.UnbindSource != nil && *req.UnbindSource == 1) { + _ = doctorPharmacyDao.DeleteDoctorPharmacyByDoctorAndPharmacy(tx, docId, sourcePharmacyId) + } + } + + // 执行原药房下线操作 + if req.Action == "disable" { + // 若选择了解绑原药房,清空原药房所有绑定记录 + if req.UnbindSource != nil && *req.UnbindSource == 1 { + _ = doctorPharmacyDao.DeleteDoctorPharmacy(tx, map[string]interface{}{"pharmacy_id": sourcePharmacyId}) + } + + data := map[string]interface{}{ + "status": 0, + } + err = pharmacyDao.EditPharmacyById(tx, sourcePharmacyId, data) + if err != nil { + tx.Rollback() + return false, errors.New("修改药房状态失败: " + err.Error()) + } + } else if req.Action == "delete" { + // 删除药房必须清空所有关联记录,防止外键孤儿数据 + _ = doctorPharmacyDao.DeleteDoctorPharmacy(tx, map[string]interface{}{"pharmacy_id": sourcePharmacyId}) + + err = pharmacyDao.DeletePharmacyById(tx, sourcePharmacyId) + if err != nil { + tx.Rollback() + return false, errors.New("删除药房失败: " + err.Error()) + } + } + + tx.Commit() + return true, nil +} From 5d4fcf993eb74710b77fcb1f806653f2311644fc Mon Sep 17 00:00:00 2001 From: haomingming Date: Thu, 17 Sep 2026 09:04:12 +0800 Subject: [PATCH 15/16] 1 --- api/router/router.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/api/router/router.go b/api/router/router.go index 7b59038..45651ea 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -984,6 +984,16 @@ func privateRouter(r *gin.Engine, api controller.Api) { } } + // 药房兼容路由(兼容无 /basic 前缀的 /admin/pharmacy/*) + adminPharmacyGroup := adminGroup.Group("/pharmacy") + { + // 获取药房下线受影响医生列表(预检接口) + adminPharmacyGroup.GET("/affected-doctors/:pharmacy_id", api.Pharmacy.GetAffectedDoctors) + + // 批量迁移医生默认药房并执行药房操作(禁用/删除) + adminPharmacyGroup.POST("/batch-transfer-and-action", api.Pharmacy.BatchTransferAndAction) + } + // 文章管理 articleGroup := adminGroup.Group("/article") { From bb3dcd4e1da375b6b2c32389eaff9d1f5c02bb74 Mon Sep 17 00:00:00 2001 From: haomingming Date: Thu, 17 Sep 2026 09:18:24 +0800 Subject: [PATCH 16/16] 2 --- api/dao/doctorPharmacy.go | 14 ++++++++++++++ api/service/pharmacy.go | 8 ++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/api/dao/doctorPharmacy.go b/api/dao/doctorPharmacy.go index 2b639c3..61afca8 100644 --- a/api/dao/doctorPharmacy.go +++ b/api/dao/doctorPharmacy.go @@ -173,6 +173,20 @@ func (r *DoctorPharmacyDao) GetPharmacyDoctorListByPharmacyId(pharmacyId int64) return m, nil } +// GetDefaultPharmacyDoctorListByPharmacyId 获取将该药房设为默认药房的医生列表 +func (r *DoctorPharmacyDao) GetDefaultPharmacyDoctorListByPharmacyId(pharmacyId int64) (m []*model.DoctorPharmacy, err error) { + err = global.Db.Preload("UserDoctor"). + Preload("UserDoctor.User"). + Preload("UserDoctor.Hospital"). + Where("pharmacy_id = ? AND status = 1 AND is_default = 1", pharmacyId). + Order("created_at desc"). + Find(&m).Error + if err != nil { + return nil, err + } + return m, nil +} + // GetDoctorPharmacyCountsByPharmacyId 获取药房绑定的医生数量(有效绑定数、设为默认药房数) func (r *DoctorPharmacyDao) GetDoctorPharmacyCountsByPharmacyId(pharmacyId int64) (totalCount int64, defaultCount int64, err error) { err = global.Db.Model(&model.DoctorPharmacy{}). diff --git a/api/service/pharmacy.go b/api/service/pharmacy.go index c2cad4d..1a8428f 100644 --- a/api/service/pharmacy.go +++ b/api/service/pharmacy.go @@ -365,10 +365,10 @@ func (r *PharmacyService) GetAffectedDoctors(pharmacyId int64) (*dto.PharmacyAff return nil, errors.New("查询药房关联医生数量失败") } - // 获取当前药房绑定的所有医生 - list, err := doctorPharmacyDao.GetPharmacyDoctorListByPharmacyId(pharmacyId) + // 获取将当前药房设为默认药房的受影响医生列表(仅默认药房受影响的医生需要重新指定默认药房) + list, err := doctorPharmacyDao.GetDefaultPharmacyDoctorListByPharmacyId(pharmacyId) if err != nil { - return nil, errors.New("查询药房关联医生列表失败") + return nil, errors.New("查询受影响医生列表失败") } // 收集所有医生ID @@ -383,7 +383,7 @@ func (r *PharmacyService) GetAffectedDoctors(pharmacyId int64) (*dto.PharmacyAff otherList, err := doctorPharmacyDao.GetOtherPharmaciesByDoctorIds(doctorIds, pharmacyId) if err == nil { for _, dp := range otherList { - if dp.Pharmacy != nil { + if dp.Pharmacy != nil && dp.Pharmacy.Status == 1 { otherMap[dp.DoctorId] = append(otherMap[dp.DoctorId], dto.BoundPharmacySimpleDto{ PharmacyId: strconv.FormatInt(dp.Pharmacy.PharmacyId, 10), PharmacyName: dp.Pharmacy.PharmacyName,