package sys import ( "context" "hotgo/internal/consts" "hotgo/internal/dao" "hotgo/internal/library/contexts" "hotgo/internal/library/dict" "hotgo/internal/library/hgorm/handler" "hotgo/internal/library/hgorm/hook" "hotgo/internal/model" "hotgo/internal/model/entity" "hotgo/internal/model/input/sysin" "hotgo/internal/service" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/util/gconv" ) type sSysTaskHall struct{} func NewSysTaskHall() *sSysTaskHall { return &sSysTaskHall{} } func init() { service.RegisterSysTaskHall(NewSysTaskHall()) dict.RegisterFunc("taskHallOption", "任务大厅选项", service.SysTaskHall().Option, true) } func (s *sSysTaskHall) model(ctx context.Context) *gdb.Model { return handler.Model(dao.TaskHall.Ctx(ctx), &handler.Option{FilterTenant: true}) } func (s *sSysTaskHall) relationModel(ctx context.Context) *gdb.Model { return handler.Model(dao.TaskHallLevel.Ctx(ctx), &handler.Option{FilterTenant: true}) } func (s *sSysTaskHall) List(ctx context.Context, in *sysin.TaskHallListInp) (list []*sysin.TaskHallListModel, total int, err error) { c := dao.TaskHall.Columns() mod := s.model(ctx).Fields(c.Id, c.HallCode, c.Name, c.IconUrl, c.Summary, c.CommissionRate, c.RateUnit, c.ClientRoute, c.PublishStatus, c.Sort, c.Version, c.CreatedAt) if in.Name != "" { mod = mod.WhereLike(c.Name, "%"+in.Name+"%") } if in.PublishStatus > 0 { mod = mod.Where(c.PublishStatus, in.PublishStatus) } err = mod.Page(in.Page, in.PerPage).OrderAsc(c.Sort).OrderDesc(c.Id).ScanAndCount(&list, &total, false) if err != nil { return nil, 0, gerror.Wrap(err, "获取任务大厅列表失败") } for _, row := range list { if err = s.loadLevels(ctx, row); err != nil { return nil, 0, err } } return } func (s *sSysTaskHall) View(ctx context.Context, in *sysin.TaskHallViewInp) (res *sysin.TaskHallListModel, err error) { c := dao.TaskHall.Columns() if err = s.model(ctx).Fields(c.Id, c.HallCode, c.Name, c.IconAttachmentId, c.IconUrl, c.Summary, c.CommissionRate, c.RateUnit, c.ClientRoute, c.PublishStatus, c.Sort, c.Version, c.Remark, c.CreatedAt).WherePri(in.Id).Scan(&res); err != nil { return nil, gerror.Wrap(err, "获取任务大厅详情失败") } if res == nil { return nil, gerror.New("任务大厅不存在") } err = s.loadLevels(ctx, res) return } func (s *sSysTaskHall) loadLevels(ctx context.Context, row *sysin.TaskHallListModel) error { rc, lc := dao.TaskHallLevel.Columns(), dao.AppMemberLevel.Columns() type levelRow struct { Id uint64 `json:"id"` Name string `json:"name"` } var rows []*levelRow err := s.relationModel(ctx).As("r").LeftJoin(dao.AppMemberLevel.Table()+" l", col("l", lc.Id)+"="+col("r", rc.LevelId)).Fields(col("l", lc.Id), col("l", lc.Name)).Where(col("r", rc.HallId), row.Id).OrderAsc(col("l", lc.Sort)).Scan(&rows) if err != nil { return gerror.Wrap(err, "获取大厅可用等级失败") } for _, v := range rows { row.LevelIds = append(row.LevelIds, v.Id) row.LevelNames = append(row.LevelNames, v.Name) } if row.LevelIds == nil { row.LevelIds = []uint64{} row.LevelNames = []string{} } return nil } func (s *sSysTaskHall) Edit(ctx context.Context, in *sysin.TaskHallEditInp) error { return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { c := dao.TaskHall.Columns() var before *entity.TaskHall if in.Id > 0 { if err := s.model(ctx).WherePri(in.Id).LockUpdate().Scan(&before); err != nil { return err } if before == nil { return gerror.New("任务大厅不存在") } if before.Version != in.Version { return gerror.New("大厅数据已更新,请刷新后重试") } } count, err := s.model(ctx).Where(c.HallCode, in.HallCode).WhereNot(c.Id, in.Id).Count() if err != nil { return err } if count > 0 { return gerror.New("大厅编码已存在") } count, err = s.model(ctx).Where(c.Name, in.Name).WhereNot(c.Id, in.Id).Count() if err != nil { return err } if count > 0 { return gerror.New("大厅名称已存在") } levelColumns := dao.AppMemberLevel.Columns() var memberLevel *entity.AppMemberLevel if err = handler.Model(dao.AppMemberLevel.Ctx(ctx), &handler.Option{FilterTenant: true}).WherePri(in.LevelIds[0]).Where(levelColumns.Status, consts.StatusEnabled).WhereGT(levelColumns.CurrentVersionId, 0).Scan(&memberLevel); err != nil { return gerror.Wrap(err, "获取会员等级失败") } if memberLevel == nil { return gerror.New("所选会员等级不存在、未发布或已停用") } var levelVersion *entity.AppMemberLevelVersion if err = handler.Model(dao.AppMemberLevelVersion.Ctx(ctx), &handler.Option{FilterTenant: true}).WherePri(memberLevel.CurrentVersionId).Scan(&levelVersion); err != nil { return gerror.Wrap(err, "获取会员等级比例失败") } if levelVersion == nil { return gerror.New("所选会员等级没有已发布规则") } in.CommissionRate = levelVersion.CommissionRate userId := contexts.GetUserId(ctx) data := g.Map{c.HallCode: in.HallCode, c.Name: in.Name, c.IconAttachmentId: in.IconAttachmentId, c.IconUrl: in.IconUrl, c.Summary: in.Summary, c.CommissionRate: in.CommissionRate, c.RateUnit: "basis_point", c.ClientRoute: in.ClientRoute, c.Sort: in.Sort, c.Remark: in.Remark, c.UpdatedBy: userId} if in.Id > 0 { data[c.Version] = gdb.Raw(c.Version + "+1") result, err := s.model(ctx).WherePri(in.Id).Where(c.Version, in.Version).Data(data).Update() if err != nil { return gerror.Wrap(err, "更新任务大厅失败") } rows, _ := result.RowsAffected() if rows != 1 { return gerror.New("大厅数据已更新,请刷新后重试") } } else { data[c.PublishStatus] = consts.BizPublishPublished data[c.CreatedBy] = userId result, err := s.model(ctx).Fields(c.HallCode, c.Name, c.IconAttachmentId, c.IconUrl, c.Summary, c.CommissionRate, c.RateUnit, c.ClientRoute, c.PublishStatus, c.Sort, c.Remark, c.CreatedBy, c.UpdatedBy).Hook(hook.SaveTenant).Data(data).Insert() if err != nil { return gerror.Wrap(err, "创建任务大厅失败") } last, _ := result.LastInsertId() in.Id = uint64(last) } rc := dao.TaskHallLevel.Columns() if _, err = s.relationModel(ctx).Where(rc.HallId, in.Id).Delete(); err != nil { return gerror.Wrap(err, "更新大厅等级关系失败") } for _, levelId := range in.LevelIds { if _, err = dao.TaskHallLevel.Ctx(ctx).Fields(rc.HallId, rc.LevelId).Hook(hook.SaveTenant).Data(g.Map{rc.HallId: in.Id, rc.LevelId: levelId}).Insert(); err != nil { return gerror.Wrap(err, "保存大厅等级关系失败") } } _ = dict.ClearFuncCache("taskHallOption") return service.SysBizAudit().Record(ctx, &sysin.BizAuditRecordInp{Module: "task_hall", Action: "task_hall.edit", TargetType: "task_hall", TargetId: in.Id, Before: before, After: g.Map{"name": in.Name, "commissionRate": in.CommissionRate, "levelIds": in.LevelIds, "clientRoute": in.ClientRoute}, Reason: in.Remark}) }) } func (s *sSysTaskHall) Status(ctx context.Context, in *sysin.TaskHallStatusInp) error { c := dao.TaskHall.Columns() var row *entity.TaskHall if err := s.model(ctx).WherePri(in.Id).Scan(&row); err != nil { return err } if row == nil { return gerror.New("任务大厅不存在") } if row.Version != in.Version { return gerror.New("大厅数据已更新,请刷新后重试") } if in.PublishStatus == consts.BizPublishPublished { count, err := s.relationModel(ctx).Where(dao.TaskHallLevel.Columns().HallId, in.Id).Count() if err != nil { return err } if count == 0 { return gerror.New("任务大厅至少绑定一个会员等级后才能发布") } } result, err := s.model(ctx).WherePri(in.Id).Where(c.Version, in.Version).Data(g.Map{c.PublishStatus: in.PublishStatus, c.UpdatedBy: contexts.GetUserId(ctx), c.Version: gdb.Raw(c.Version + "+1")}).Update() if err != nil { return gerror.Wrap(err, "更新任务大厅状态失败") } rows, _ := result.RowsAffected() if rows != 1 { return gerror.New("大厅数据已更新,请刷新后重试") } _ = dict.ClearFuncCache("taskHallOption") return service.SysBizAudit().Record(ctx, &sysin.BizAuditRecordInp{Module: "task_hall", Action: "task_hall.status", TargetType: "task_hall", TargetId: in.Id, Before: g.Map{"publishStatus": row.PublishStatus}, After: g.Map{"publishStatus": in.PublishStatus}}) } func (s *sSysTaskHall) Delete(ctx context.Context, in *sysin.TaskHallDeleteInp) error { return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { c := dao.TaskHall.Columns() var row *entity.TaskHall if err := s.model(ctx).WherePri(in.Id).LockUpdate().Scan(&row); err != nil { return err } if row == nil { return gerror.New("任务大厅不存在") } rc := dao.TaskHallLevel.Columns() if _, err := s.relationModel(ctx).Where(rc.HallId, in.Id).Delete(); err != nil { return err } if _, err := s.model(ctx).WherePri(in.Id).Data(g.Map{c.DeletedAt: gtime.Now(), c.DeletedBy: contexts.GetUserId(ctx), c.UpdatedBy: contexts.GetUserId(ctx)}).Update(); err != nil { return gerror.Wrap(err, "删除任务大厅失败") } _ = dict.ClearFuncCache("taskHallOption") return service.SysBizAudit().Record(ctx, &sysin.BizAuditRecordInp{Module: "task_hall", Action: "task_hall.delete", TargetType: "task_hall", TargetId: in.Id, Before: row, Reason: in.Reason}) }) } func (s *sSysTaskHall) Option(ctx context.Context) (opts []*model.Option, err error) { var rows []*entity.TaskHall c := dao.TaskHall.Columns() if err = s.model(ctx).Fields(c.Id, c.Name).Where(c.PublishStatus, consts.BizPublishPublished).OrderAsc(c.Sort).OrderAsc(c.Id).Scan(&rows); err != nil { return nil, gerror.Wrap(err, "获取任务大厅选项失败") } opts = make([]*model.Option, len(rows)) for i, row := range rows { opts[i] = dict.GenHashOption(row.Id, gconv.String(row.Name)) } return }