feat: 完善小组绩效与有效端统计并修复审查问题
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
package business
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"kra/internal/biz/business"
|
||||
)
|
||||
|
||||
type teamRepo struct{ data Provider }
|
||||
|
||||
func NewTeamRepo(data Provider) business.TeamRepo { return &teamRepo{data: data} }
|
||||
|
||||
func (r *teamRepo) Members(ctx context.Context, scope business.UserScope) ([]*business.BusinessMember, error) {
|
||||
db := r.data.DB().WithContext(ctx)
|
||||
var rows []struct {
|
||||
Account accountPO `gorm:"embedded"`
|
||||
HireDate, Employment string
|
||||
GroupID uint64
|
||||
}
|
||||
q := applyUserScope(db.Table("sys_users u").Where("u.deleted_at IS NULL AND u.level BETWEEN 1 AND 3"), scope, "u.")
|
||||
if err := q.Select("u.*,p.username AS parent_user_name,mp.hire_date,mp.employment,gm.group_id").Joins("LEFT JOIN sys_users p ON p.id=u.parent_id AND p.deleted_at IS NULL").Joins("LEFT JOIN sys_business_member_profiles mp ON mp.user_id=u.id").Joins("LEFT JOIN sys_business_group_members gm ON gm.user_id=u.id").Order("u.id").Scan(&rows).Error; err != nil {
|
||||
return nil, business.ErrStorage
|
||||
}
|
||||
ids := make([]uint, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
ids = append(ids, row.Account.ID)
|
||||
}
|
||||
counts, err := (&accountRepo{data: r.data}).DirectCounts(ctx, ids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := make([]*business.BusinessMember, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
a := toBizAccount(row.Account)
|
||||
a.Password = ""
|
||||
a.PromoteCount = counts[a.ID].PromoteCount
|
||||
a.BindCount = counts[a.ID].BindCount
|
||||
employment := row.Employment
|
||||
if employment == "" {
|
||||
employment = "employed"
|
||||
if a.Status != 0 {
|
||||
employment = "departed"
|
||||
}
|
||||
}
|
||||
a.HireDate, a.Employment = row.HireDate, employment
|
||||
out = append(out, &business.BusinessMember{Account: *a, GroupID: row.GroupID})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
func readTeamCatalog(db *gorm.DB) (*business.TeamCatalog, error) {
|
||||
var state businessGroupStatePO
|
||||
if err := db.First(&state, "id=1").Error; err != nil {
|
||||
return nil, business.ErrStorage
|
||||
}
|
||||
var groups []businessGroupPO
|
||||
if err := db.Order("sort,id").Find(&groups).Error; err != nil {
|
||||
return nil, business.ErrStorage
|
||||
}
|
||||
var members []businessGroupMemberPO
|
||||
if err := db.Order("user_id").Find(&members).Error; err != nil {
|
||||
return nil, business.ErrStorage
|
||||
}
|
||||
byGroup := map[uint64][]uint{}
|
||||
for _, m := range members {
|
||||
byGroup[m.GroupID] = append(byGroup[m.GroupID], m.UserID)
|
||||
}
|
||||
out := &business.TeamCatalog{Revision: state.Revision, Groups: []*business.BusinessGroup{}}
|
||||
for _, g := range groups {
|
||||
out.Groups = append(out.Groups, &business.BusinessGroup{ID: g.ID, Name: g.Name, OwnerID: g.OwnerID, Sort: g.Sort, MemberIDs: append([]uint{}, byGroup[g.ID]...)})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
func (r *teamRepo) Catalog(ctx context.Context) (*business.TeamCatalog, error) {
|
||||
var value *business.TeamCatalog
|
||||
err := r.data.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error { var err error; value, err = readTeamCatalog(tx); return err })
|
||||
return value, storageError(err)
|
||||
}
|
||||
func (r *teamRepo) SaveCatalog(ctx context.Context, revision uint64, groups []*business.BusinessGroup) (*business.TeamCatalog, error) {
|
||||
db := r.data.DB().WithContext(ctx)
|
||||
err := db.Transaction(func(tx *gorm.DB) error {
|
||||
updated := tx.Model(&businessGroupStatePO{}).Where("id=1 AND revision=?", revision).Update("revision", gorm.Expr("revision+1"))
|
||||
if updated.Error != nil {
|
||||
return updated.Error
|
||||
}
|
||||
if updated.RowsAffected != 1 {
|
||||
return business.ErrTeamConflict
|
||||
}
|
||||
var current []businessGroupPO
|
||||
if err := tx.Find(¤t).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
byID := map[uint64]businessGroupPO{}
|
||||
for _, g := range current {
|
||||
byID[g.ID] = g
|
||||
}
|
||||
ids := []uint64{}
|
||||
members := []businessGroupMemberPO{}
|
||||
for _, g := range groups {
|
||||
po := businessGroupPO{ID: g.ID, Name: g.Name, OwnerID: g.OwnerID, Sort: g.Sort}
|
||||
if g.ID == 0 {
|
||||
if err := tx.Create(&po).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
old, exists := byID[g.ID]
|
||||
if !exists {
|
||||
return business.ErrTeamConflict
|
||||
}
|
||||
if old.Name != g.Name || old.Sort != g.Sort {
|
||||
if err := tx.Model(&businessGroupPO{}).Where("id=?", g.ID).Updates(map[string]any{"name": g.Name, "sort": g.Sort, "updated_at": time.Now()}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
ids = append(ids, po.ID)
|
||||
for _, id := range g.MemberIDs {
|
||||
members = append(members, businessGroupMemberPO{UserID: id, GroupID: po.ID})
|
||||
}
|
||||
}
|
||||
deleted := tx.Model(&businessGroupPO{})
|
||||
if len(ids) > 0 {
|
||||
deleted = deleted.Where("id NOT IN ?", ids)
|
||||
} else {
|
||||
deleted = deleted.Where("1=1")
|
||||
}
|
||||
if err := deleted.Delete(&businessGroupPO{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Where("1=1").Delete(&businessGroupMemberPO{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if len(members) > 0 {
|
||||
if err := tx.CreateInBatches(&members, 300).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, storageError(err)
|
||||
}
|
||||
return r.Catalog(ctx)
|
||||
}
|
||||
func (r *teamRepo) UpdateProfile(ctx context.Context, p business.MemberProfile) error {
|
||||
return storageError(r.data.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
var account accountPO
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&account, p.ID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
domain := toBizAccount(account)
|
||||
domain.Phone = p.Phone
|
||||
if err := checkAccountUnique(tx, domain); err != nil {
|
||||
return err
|
||||
}
|
||||
status, enable := 0, 1
|
||||
if p.Employment == "departed" {
|
||||
status, enable = 1, 0
|
||||
}
|
||||
values := map[string]any{"real_name": p.RealName, "phone": p.Phone, "business_status": status, "enable": enable, "updated_at": time.Now()}
|
||||
if p.Password != "" {
|
||||
values["password"] = p.Password
|
||||
values["password_updated_at"] = time.Now()
|
||||
}
|
||||
if err := tx.Model(&accountPO{}).Where("id=?", p.ID).Updates(values).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "user_id"}}, DoUpdates: clause.AssignmentColumns([]string{"hire_date", "employment", "updated_at"})}).Create(&businessMemberProfilePO{UserID: p.ID, HireDate: p.HireDate, Employment: p.Employment, UpdatedAt: time.Now()}).Error
|
||||
}))
|
||||
}
|
||||
Reference in New Issue
Block a user