package system import ( "context" "errors" "time" "kra/app/system/internal/biz" "gorm.io/gorm" ) type positionRepo struct{ data Provider } func NewPositionRepo(data Provider) biz.PositionRepo { return &positionRepo{data: data} } type positionPO struct { ID uint `gorm:"primaryKey"` CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` Name string `gorm:"index"` Code string Sort int Status *bool `gorm:"default:true"` Remark string } func (positionPO) TableName() string { return "sys_positions" } type userPositionPO struct { // The reference implementation does not declare a key on this explicit join model. Do not let a // database uniqueness constraint change duplicate-assignment behavior. UserID uint `gorm:"column:sys_user_id"` PositionID uint `gorm:"column:sys_position_id"` } func (userPositionPO) TableName() string { return "sys_user_positions" } func posFromPO(po positionPO) *biz.Position { return &biz.Position{ID: po.ID, CreatedAt: po.CreatedAt, UpdatedAt: po.UpdatedAt, Name: po.Name, Code: po.Code, Sort: po.Sort, Status: po.Status, Remark: po.Remark} } func (r *positionRepo) CreatePosition(ctx context.Context, v *biz.Position) error { return r.data.DB().WithContext(ctx).Create(&positionPO{Name: v.Name, Code: v.Code, Sort: v.Sort, Status: v.Status, Remark: v.Remark}).Error } func (r *positionRepo) UpdatePosition(ctx context.Context, v *biz.Position) error { return r.data.DB().WithContext(ctx).Model(&positionPO{}).Where("id = ?", v.ID).Updates(map[string]any{"name": v.Name, "code": v.Code, "sort": v.Sort, "status": v.Status, "remark": v.Remark}).Error } func (r *positionRepo) DeletePosition(ctx context.Context, id uint) error { if id == 0 { return errors.New("岗位ID不能为空") } var count int64 if err := r.data.DB().WithContext(ctx).Model(&userPositionPO{}).Where("sys_position_id = ?", id).Count(&count).Error; err != nil { return err } if count > 0 { return errors.New("该岗位下存在用户,不允许删除") } return r.data.DB().WithContext(ctx).Delete(&positionPO{}, id).Error } func (r *positionRepo) FindPosition(ctx context.Context, id uint) (*biz.Position, error) { var po positionPO if err := r.data.DB().WithContext(ctx).First(&po, id).Error; err != nil { return nil, err } return posFromPO(po), nil } func (r *positionRepo) ListPositions(ctx context.Context, page, size int, q *biz.PositionListFilter) ([]*biz.Position, int64, error) { db := r.data.DB().WithContext(ctx).Model(&positionPO{}) if q != nil { if q.Name != "" { db = db.Where("name LIKE ?", "%"+q.Name+"%") } if q.Code != "" { db = db.Where("code LIKE ?", "%"+q.Code+"%") } if q.Status != nil { db = db.Where("status = ?", *q.Status) } } var total int64 if err := db.Count(&total).Error; err != nil { return nil, 0, err } var pos []positionPO // The compatible position endpoint applies the supplied LIMIT/OFFSET // directly (it does not normalize missing page values through the shared // pagination helper). if err := db.Order("sort").Limit(size).Offset(size * (page - 1)).Find(&pos).Error; err != nil { return nil, 0, err } out := make([]*biz.Position, 0, len(pos)) for _, po := range pos { out = append(out, posFromPO(po)) } return out, total, nil } func (r *positionRepo) PositionUserIDs(ctx context.Context, id uint) ([]uint, error) { var ids []uint err := r.data.DB().WithContext(ctx).Model(&userPositionPO{}).Where("sys_position_id = ?", id).Pluck("sys_user_id", &ids).Error return ids, err } func (r *positionRepo) SetPositionUsers(ctx context.Context, id uint, ids []uint) error { if id == 0 { return errors.New("岗位ID不能为空") } return r.data.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error { if err := tx.Where("sys_position_id = ?", id).Delete(&userPositionPO{}).Error; err != nil { return err } links := make([]userPositionPO, 0, len(ids)) for _, uid := range ids { links = append(links, userPositionPO{UserID: uid, PositionID: id}) } if len(links) > 0 { return tx.Create(&links).Error } return nil }) } func (r *positionRepo) SetUserPositions(ctx context.Context, uid uint, ids []uint) error { return r.data.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error { if err := tx.Where("sys_user_id = ?", uid).Delete(&userPositionPO{}).Error; err != nil { return err } links := make([]userPositionPO, 0, len(ids)) for _, id := range ids { links = append(links, userPositionPO{UserID: uid, PositionID: id}) } if len(links) > 0 { return tx.Create(&links).Error } return nil }) }