Loggest thy stuff
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

273 lines
5.8 KiB

  1. package mysql
  2. import (
  3. "context"
  4. "database/sql"
  5. "encoding/json"
  6. "golang.org/x/sync/errgroup"
  7. "sort"
  8. "git.aiterp.net/stufflog3/stufflog3-api/internal/database/mysql/mysqlcore"
  9. "git.aiterp.net/stufflog3/stufflog3-api/internal/models"
  10. "git.aiterp.net/stufflog3/stufflog3-api/internal/slerrors"
  11. )
  12. type scopeRepository struct {
  13. db *sql.DB
  14. }
  15. func (r *scopeRepository) Find(ctx context.Context, id int) (*models.Scope, error) {
  16. q := mysqlcore.New(r.db)
  17. scope, err := q.GetScope(ctx, id)
  18. if err != nil {
  19. if err == sql.ErrNoRows {
  20. return nil, slerrors.NotFound("Scope")
  21. }
  22. return nil, err
  23. }
  24. res := &models.Scope{
  25. ScopeEntry: models.ScopeEntry{
  26. ID: scope.ID,
  27. Name: scope.Name,
  28. Abbreviation: scope.Abbreviation,
  29. },
  30. }
  31. eg, ctx := errgroup.WithContext(ctx)
  32. eg.Go(func() error {
  33. members, err := q.ListScopeMembers(ctx, id)
  34. if err != nil && err != sql.ErrNoRows {
  35. return err
  36. }
  37. for _, member := range members {
  38. res.Members = append(res.Members, models.ScopeMember{
  39. ID: member.UserID,
  40. Name: member.Name,
  41. Owner: member.Owner,
  42. })
  43. }
  44. return nil
  45. })
  46. eg.Go(func() error {
  47. projects, err := q.ListProjectEntries(ctx, id)
  48. if err != nil && err != sql.ErrNoRows {
  49. return err
  50. }
  51. for _, project := range projects {
  52. res.Projects = append(res.Projects, models.ProjectEntry{
  53. ID: project.ID,
  54. Name: project.Name,
  55. Status: models.Status(project.Status),
  56. })
  57. }
  58. return nil
  59. })
  60. eg.Go(func() error {
  61. stats, err := q.ListStats(ctx, id)
  62. if err != nil && err != sql.ErrNoRows {
  63. return err
  64. }
  65. for _, stat := range stats {
  66. var amounts map[string]int
  67. if stat.AllowedAmounts.Valid {
  68. amounts = make(map[string]int)
  69. err := json.Unmarshal(stat.AllowedAmounts.RawMessage, &amounts)
  70. if err != nil {
  71. return err
  72. }
  73. }
  74. res.Stats = append(res.Stats, models.Stat{
  75. StatEntry: models.StatEntry{
  76. ID: stat.ID,
  77. Name: stat.Name,
  78. Weight: stat.Weight,
  79. },
  80. Description: stat.Description,
  81. AllowedAmounts: amounts,
  82. })
  83. }
  84. return nil
  85. })
  86. err = eg.Wait()
  87. if err != nil {
  88. return nil, err
  89. }
  90. return res, nil
  91. }
  92. func (r *scopeRepository) List(ctx context.Context) ([]models.ScopeEntry, error) {
  93. q := mysqlcore.New(r.db)
  94. scopes, err := q.ListScopes(ctx)
  95. if err != nil {
  96. return nil, err
  97. }
  98. res := make([]models.ScopeEntry, 0, len(scopes))
  99. for _, scope := range scopes {
  100. res = append(res, models.ScopeEntry{
  101. ID: scope.ID,
  102. Name: scope.Name,
  103. Abbreviation: scope.Abbreviation,
  104. })
  105. }
  106. return res, nil
  107. }
  108. func (r *scopeRepository) ListByUser(ctx context.Context, userID string) ([]models.ScopeEntry, error) {
  109. q := mysqlcore.New(r.db)
  110. scopes, err := q.ListScopesByUser(ctx, userID)
  111. if err != nil {
  112. return nil, err
  113. }
  114. res := make([]models.ScopeEntry, 0, len(scopes))
  115. for _, scope := range scopes {
  116. res = append(res, models.ScopeEntry{
  117. ID: scope.ID,
  118. Name: scope.Name,
  119. Abbreviation: scope.Abbreviation,
  120. })
  121. }
  122. return res, nil
  123. }
  124. func (r *scopeRepository) Create(ctx context.Context, scope models.ScopeEntry, owner models.ScopeMember) (*models.Scope, error) {
  125. tx, err := r.db.BeginTx(ctx, nil)
  126. if err != nil {
  127. return nil, err
  128. }
  129. defer tx.Rollback()
  130. q := mysqlcore.New(tx)
  131. res, err := q.InsertScope(ctx, mysqlcore.InsertScopeParams(scope))
  132. if err != nil {
  133. return nil, err
  134. }
  135. id, err := res.LastInsertId()
  136. if err != nil {
  137. return nil, err
  138. }
  139. err = q.UpdateScopeMember(ctx, mysqlcore.UpdateScopeMemberParams{
  140. ScopeID: int(id),
  141. UserID: owner.ID,
  142. Name: owner.Name,
  143. Owner: true,
  144. })
  145. err = tx.Commit()
  146. if err != nil {
  147. return nil, err
  148. }
  149. return &models.Scope{
  150. ScopeEntry: models.ScopeEntry{
  151. ID: int(id),
  152. Name: scope.Name,
  153. Abbreviation: scope.Abbreviation,
  154. },
  155. DisplayName: owner.Name,
  156. Members: []models.ScopeMember{
  157. {
  158. ID: owner.ID,
  159. Name: owner.Name,
  160. Owner: true,
  161. },
  162. },
  163. Projects: []models.ProjectEntry{},
  164. Stats: []models.Stat{},
  165. }, nil
  166. }
  167. func (r *scopeRepository) Update(ctx context.Context, scope models.ScopeEntry) error {
  168. return mysqlcore.New(r.db).UpdateScope(ctx, mysqlcore.UpdateScopeParams{
  169. Name: scope.Name,
  170. Abbreviation: scope.Abbreviation,
  171. ID: scope.ID,
  172. })
  173. }
  174. func (r *scopeRepository) Delete(ctx context.Context, scope models.Scope) error {
  175. tx, err := r.db.BeginTx(ctx, nil)
  176. if err != nil {
  177. return err
  178. }
  179. defer tx.Rollback()
  180. q := mysqlcore.New(tx)
  181. err = q.DeleteAllScopeMembers(ctx, scope.ID)
  182. if err != nil {
  183. return err
  184. }
  185. err = q.DeleteScope(ctx, scope.ID)
  186. if err != nil {
  187. return err
  188. }
  189. return tx.Commit()
  190. }
  191. func (r *scopeRepository) UpdateMember(ctx context.Context, scope models.Scope, member models.ScopeMember) (*models.Scope, error) {
  192. err := mysqlcore.New(r.db).UpdateScopeMember(ctx, mysqlcore.UpdateScopeMemberParams{
  193. ScopeID: scope.ID,
  194. UserID: member.ID,
  195. Name: member.Name,
  196. Owner: member.Owner,
  197. })
  198. if err != nil {
  199. return nil, err
  200. }
  201. found := false
  202. scope.Members = append(scope.Members[:0:0], scope.Members...)
  203. for i, member2 := range scope.Members {
  204. if member2.ID == member.ID {
  205. scope.Members[i] = member2
  206. found = true
  207. }
  208. }
  209. if !found {
  210. scope.Members = append(scope.Members, member)
  211. sort.Slice(scope.Members, func(i, j int) bool {
  212. return scope.Members[i].Name < scope.Members[j].Name
  213. })
  214. }
  215. return &scope, nil
  216. }
  217. func (r *scopeRepository) DeleteMember(ctx context.Context, scope models.Scope, userID string) (*models.Scope, error) {
  218. err := mysqlcore.New(r.db).DeleteScopeMember(ctx, mysqlcore.DeleteScopeMemberParams{
  219. ScopeID: scope.ID,
  220. UserID: userID,
  221. })
  222. if err != nil {
  223. return nil, err
  224. }
  225. newMembers := make([]models.ScopeMember, 0, len(scope.Members)-1)
  226. for _, member := range scope.Members {
  227. if member.ID != userID {
  228. newMembers = append(newMembers, member)
  229. }
  230. }
  231. scope.Members = newMembers
  232. return &scope, nil
  233. }