Loggest thine 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.

243 lines
6.4 KiB

  1. package mysql
  2. import (
  3. "context"
  4. "database/sql"
  5. "git.aiterp.net/stufflog3/stufflog3/entities"
  6. "git.aiterp.net/stufflog3/stufflog3/internal/genutils"
  7. "git.aiterp.net/stufflog3/stufflog3/models"
  8. "git.aiterp.net/stufflog3/stufflog3/ports/mysql/mysqlcore"
  9. "github.com/Masterminds/squirrel"
  10. "time"
  11. )
  12. type sprintRepository struct {
  13. db *sql.DB
  14. q *mysqlcore.Queries
  15. }
  16. func (r *sprintRepository) Find(ctx context.Context, scopeID, sprintID int) (*entities.Sprint, error) {
  17. row, err := r.q.GetSprint(ctx, mysqlcore.GetSprintParams{ScopeID: scopeID, ID: sprintID})
  18. if err != nil {
  19. if err == sql.ErrNoRows {
  20. return nil, models.NotFoundError("Sprint")
  21. }
  22. return nil, err
  23. }
  24. return &entities.Sprint{
  25. ID: row.ID,
  26. ScopeID: row.ScopeID,
  27. Name: row.Name,
  28. Description: row.Description,
  29. Kind: models.SprintKind(row.Kind),
  30. FromTime: row.FromTime,
  31. ToTime: row.ToTime,
  32. IsTimed: row.IsTimed,
  33. IsCoarse: row.IsCoarse,
  34. IsUnweighted: row.IsUnweighted,
  35. AggregateName: row.AggregateName,
  36. AggregateRequired: row.AggregateRequired,
  37. }, nil
  38. }
  39. func (r *sprintRepository) ListAt(ctx context.Context, scopeID int, at time.Time) ([]entities.Sprint, error) {
  40. rows, err := r.q.ListSprintsAt(ctx, mysqlcore.ListSprintsAtParams{ScopeID: scopeID, Time: at})
  41. if err != nil {
  42. if err == sql.ErrNoRows {
  43. return nil, models.NotFoundError("Sprint")
  44. }
  45. return nil, err
  46. }
  47. sprints := make([]entities.Sprint, 0, len(rows))
  48. for _, row := range rows {
  49. sprints = append(sprints, entities.Sprint{
  50. ID: row.ID,
  51. ScopeID: row.ScopeID,
  52. Name: row.Name,
  53. Description: row.Description,
  54. Kind: models.SprintKind(row.Kind),
  55. FromTime: row.FromTime,
  56. ToTime: row.ToTime,
  57. IsTimed: row.IsTimed,
  58. IsCoarse: row.IsCoarse,
  59. IsUnweighted: row.IsUnweighted,
  60. AggregateName: row.AggregateName,
  61. AggregateRequired: row.AggregateRequired,
  62. })
  63. }
  64. return sprints, nil
  65. }
  66. func (r *sprintRepository) ListBetween(ctx context.Context, scopeID int, from, to time.Time) ([]entities.Sprint, error) {
  67. rows, err := r.q.ListSprintsBetween(ctx, mysqlcore.ListSprintsBetweenParams{
  68. ScopeID: scopeID,
  69. FromTime: from,
  70. ToTime: from,
  71. FromTime_2: to,
  72. ToTime_2: to,
  73. FromTime_3: from,
  74. ToTime_3: to,
  75. })
  76. if err != nil {
  77. if err == sql.ErrNoRows {
  78. return nil, models.NotFoundError("Sprint")
  79. }
  80. return nil, err
  81. }
  82. sprints := make([]entities.Sprint, 0, len(rows))
  83. for _, row := range rows {
  84. sprints = append(sprints, entities.Sprint{
  85. ID: row.ID,
  86. ScopeID: row.ScopeID,
  87. Name: row.Name,
  88. Description: row.Description,
  89. Kind: models.SprintKind(row.Kind),
  90. FromTime: row.FromTime,
  91. ToTime: row.ToTime,
  92. IsTimed: row.IsTimed,
  93. IsCoarse: row.IsCoarse,
  94. IsUnweighted: row.IsUnweighted,
  95. AggregateName: row.AggregateName,
  96. AggregateRequired: row.AggregateRequired,
  97. })
  98. }
  99. return sprints, nil
  100. }
  101. func (r *sprintRepository) Insert(ctx context.Context, sprint entities.Sprint) (*entities.Sprint, error) {
  102. res, err := r.q.InsertSprint(ctx, mysqlcore.InsertSprintParams{
  103. ScopeID: sprint.ScopeID,
  104. Name: sprint.Name,
  105. Description: sprint.Description,
  106. Kind: int(sprint.Kind),
  107. FromTime: sprint.FromTime,
  108. ToTime: sprint.ToTime,
  109. IsTimed: sprint.IsTimed,
  110. IsCoarse: sprint.IsCoarse,
  111. AggregateName: sprint.AggregateName,
  112. AggregateRequired: sprint.AggregateRequired,
  113. IsUnweighted: sprint.IsUnweighted,
  114. })
  115. if err != nil {
  116. return nil, err
  117. }
  118. id, err := res.LastInsertId()
  119. if err != nil {
  120. return nil, err
  121. }
  122. sprint.ID = int(id)
  123. return &sprint, nil
  124. }
  125. func (r *sprintRepository) Update(ctx context.Context, sprint entities.Sprint, update models.SprintUpdate) error {
  126. sprint.ApplyUpdate(update)
  127. return r.q.UpdateSprint(ctx, mysqlcore.UpdateSprintParams{
  128. Name: sprint.Name,
  129. Description: sprint.Description,
  130. FromTime: sprint.FromTime,
  131. ToTime: sprint.ToTime,
  132. IsTimed: sprint.IsTimed,
  133. IsCoarse: sprint.IsCoarse,
  134. IsUnweighted: sprint.IsUnweighted,
  135. AggregateName: sprint.AggregateName,
  136. AggregateRequired: sprint.AggregateRequired,
  137. ID: sprint.ID,
  138. })
  139. }
  140. func (r *sprintRepository) Delete(ctx context.Context, sprint entities.Sprint) error {
  141. tx, err := r.db.BeginTx(ctx, nil)
  142. if err != nil {
  143. return err
  144. }
  145. defer tx.Rollback()
  146. q := r.q.WithTx(tx)
  147. err = q.DeleteAllSprintParts(ctx, sprint.ID)
  148. if err != nil {
  149. return err
  150. }
  151. err = q.DeleteSprint(ctx, sprint.ID)
  152. if err != nil {
  153. return err
  154. }
  155. return tx.Commit()
  156. }
  157. func (r *sprintRepository) ListParts(ctx context.Context, sprints ...entities.Sprint) ([]entities.SprintPart, error) {
  158. if len(sprints) == 0 {
  159. return []entities.SprintPart{}, nil
  160. } else if len(sprints) == 1 {
  161. rows, err := r.q.ListSprintParts(ctx, sprints[0].ID)
  162. if err != nil {
  163. return nil, err
  164. }
  165. return genutils.Map(rows, func(row mysqlcore.SprintPart) entities.SprintPart {
  166. return entities.SprintPart{
  167. SprintID: row.SprintID,
  168. PartID: row.ObjectID,
  169. Required: row.Required,
  170. }
  171. }), nil
  172. }
  173. ids := make([]int, 0, len(sprints))
  174. for _, sprint := range sprints {
  175. ids = append(ids, sprint.ID)
  176. }
  177. query, args, err := squirrel.Select("sprint_id, object_id, required").
  178. From("sprint_part").
  179. Where(squirrel.Eq{"sprint_id": ids}).
  180. ToSql()
  181. if err != nil {
  182. return nil, err
  183. }
  184. rows, err := r.db.QueryContext(ctx, query, args...)
  185. if err != nil {
  186. return nil, err
  187. }
  188. res := make([]entities.SprintPart, 0, 16)
  189. for rows.Next() {
  190. part := entities.SprintPart{}
  191. err = rows.Scan(&part.SprintID, &part.PartID, &part.Required)
  192. if err != nil {
  193. return nil, err
  194. }
  195. res = append(res, part)
  196. }
  197. return res, nil
  198. }
  199. func (r *sprintRepository) UpdatePart(ctx context.Context, part entities.SprintPart) error {
  200. return r.q.ReplaceSprintPart(ctx, mysqlcore.ReplaceSprintPartParams{
  201. SprintID: part.SprintID,
  202. ObjectID: part.PartID,
  203. Required: part.Required,
  204. })
  205. }
  206. func (r *sprintRepository) DeletePart(ctx context.Context, part entities.SprintPart) error {
  207. return r.q.DeleteSprintPart(ctx, mysqlcore.DeleteSprintPartParams{
  208. SprintID: part.SprintID,
  209. ObjectID: part.PartID,
  210. })
  211. }