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.

202 lines
5.1 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package postgres
  2. import (
  3. "context"
  4. "database/sql"
  5. "github.com/Masterminds/squirrel"
  6. "github.com/gissleh/stufflog/internal/slerrors"
  7. "github.com/gissleh/stufflog/models"
  8. "github.com/jmoiron/sqlx"
  9. )
  10. type taskRepository struct {
  11. db *sqlx.DB
  12. }
  13. func (r *taskRepository) Find(ctx context.Context, id string) (*models.Task, error) {
  14. res := models.Task{}
  15. err := r.db.GetContext(ctx, &res, "SELECT task.*, p.icon FROM task INNER JOIN project AS p ON task.project_id = p.project_id WHERE task_id=$1", id)
  16. if err != nil {
  17. if err == sql.ErrNoRows {
  18. return nil, slerrors.NotFound("Task")
  19. }
  20. return nil, err
  21. }
  22. return &res, nil
  23. }
  24. func (r *taskRepository) List(ctx context.Context, filter models.TaskFilter) ([]*models.Task, error) {
  25. tasks, _, err := r.ListWithLinks(ctx, filter)
  26. return tasks, err
  27. }
  28. func (r *taskRepository) ListWithLinks(ctx context.Context, filter models.TaskFilter) ([]*models.Task, []*models.TaskLink, error) {
  29. type tasksWithLinks struct {
  30. models.Task
  31. LinkedProjectID *string `db:"tl_project_id"`
  32. }
  33. sq := squirrel.Select("task.*", "tl.project_id as tl_project_id", "p.icon").From("task").PlaceholderFormat(squirrel.Dollar)
  34. sq = sq.Where(squirrel.Eq{"task.user_id": filter.UserID})
  35. if filter.Active != nil {
  36. sq = sq.Where(squirrel.Eq{"task.active": *filter.Active})
  37. }
  38. if filter.Expiring != nil {
  39. if *filter.Expiring {
  40. sq = sq.Where("task.end_time IS NOT NULL")
  41. } else {
  42. sq = sq.Where("task.end_time IS NULL")
  43. }
  44. }
  45. if filter.IDs != nil {
  46. sq = sq.Where(squirrel.Eq{"task.task_id": filter.IDs})
  47. }
  48. if filter.ItemIDs != nil {
  49. sq = sq.Where(squirrel.Eq{"task.item_id": filter.ItemIDs})
  50. }
  51. if filter.ProjectIDs != nil {
  52. sq = sq.Where(squirrel.Or{
  53. squirrel.Eq{"task.project_id": filter.ProjectIDs},
  54. squirrel.Eq{"tl.project_id": filter.ProjectIDs},
  55. })
  56. }
  57. sq = sq.LeftJoin("task_link AS tl ON task.task_id = tl.task_id")
  58. sq = sq.InnerJoin("project AS p ON task.project_id = p.project_id")
  59. sq = sq.OrderBy("active DESC", "status_tag ASC", "created_time")
  60. query, args, err := sq.ToSql()
  61. if err != nil {
  62. return nil, nil, err
  63. }
  64. rows := make([]tasksWithLinks, 0, 8)
  65. err = r.db.SelectContext(ctx, &rows, query, args...)
  66. if err != nil {
  67. if err == sql.ErrNoRows {
  68. return []*models.Task{}, []*models.TaskLink{}, nil
  69. }
  70. return nil, nil, err
  71. }
  72. added := make(map[string]bool)
  73. tasks := make([]*models.Task, 0, len(rows))
  74. links := make([]*models.TaskLink, 0, len(rows))
  75. for _, row := range rows {
  76. if row.LinkedProjectID != nil {
  77. links = append(links, &models.TaskLink{
  78. TaskID: row.Task.ID,
  79. ProjectID: *row.LinkedProjectID,
  80. })
  81. }
  82. if !added[row.Task.ID] {
  83. task := row.Task
  84. tasks = append(tasks, &task)
  85. added[row.Task.ID] = true
  86. }
  87. }
  88. return tasks, links, nil
  89. }
  90. func (r *taskRepository) Insert(ctx context.Context, task models.Task) error {
  91. _, err := r.db.NamedExecContext(ctx, `
  92. INSERT INTO task (
  93. task_id, user_id, item_id, project_id, item_amount, name, description, active, created_time, end_time, status_tag
  94. ) VALUES (
  95. :task_id, :user_id, :item_id, :project_id, :item_amount, :name, :description, :active, :created_time, :end_time, :status_tag
  96. )
  97. `, &task)
  98. if err != nil {
  99. return err
  100. }
  101. return nil
  102. }
  103. func (r *taskRepository) Update(ctx context.Context, task models.Task) error {
  104. _, err := r.db.NamedExecContext(ctx, `
  105. UPDATE task SET
  106. item_id = :item_id,
  107. item_amount = :item_amount,
  108. name = :name,
  109. description = :description,
  110. active = :active,
  111. end_time = :end_time,
  112. status_tag = :status_tag,
  113. project_id = :project_id
  114. WHERE task_id=:task_id
  115. `, &task)
  116. if err != nil {
  117. return err
  118. }
  119. _, err = r.db.NamedExecContext(ctx, `UPDATE log SET item_id = :item_id WHERE task_id=:task_id`, &task)
  120. if err != nil {
  121. return err
  122. }
  123. return nil
  124. }
  125. func (r *taskRepository) CreateLink(ctx context.Context, link models.TaskLink) error {
  126. _, err := r.db.NamedExecContext(ctx, `
  127. INSERT INTO task_link (project_id, task_id) VALUES (:project_id, :task_id)
  128. ON CONFLICT DO NOTHING
  129. `, &link)
  130. return err
  131. }
  132. func (r *taskRepository) DeleteLink(ctx context.Context, link models.TaskLink) error {
  133. _, err := r.db.NamedExecContext(ctx, `
  134. DELETE FROM task_link WHERE task_id=:task_id AND project_id=:project_id
  135. `, &link)
  136. if err == sql.ErrNoRows {
  137. err = slerrors.NotFound("Link")
  138. }
  139. return err
  140. }
  141. func (r *taskRepository) UnlinkTask(ctx context.Context, task models.Task) error {
  142. _, err := r.db.ExecContext(ctx, `
  143. DELETE FROM task_link WHERE task_id=$1;
  144. `, task.ID)
  145. if err == sql.ErrNoRows {
  146. err = nil
  147. }
  148. return err
  149. }
  150. func (r *taskRepository) UnlinkProject(ctx context.Context, project models.Project) error {
  151. _, err := r.db.ExecContext(ctx, `
  152. DELETE FROM task_link WHERE task_id=$1;
  153. `, project.ID)
  154. if err == sql.ErrNoRows {
  155. err = nil
  156. }
  157. return err
  158. }
  159. func (r *taskRepository) Delete(ctx context.Context, task models.Task) error {
  160. _, err := r.db.ExecContext(ctx, `DELETE FROM task WHERE task_id=$1`, task.ID)
  161. if err != nil {
  162. if err == sql.ErrNoRows {
  163. return slerrors.NotFound("Task")
  164. }
  165. return err
  166. }
  167. _, err = r.db.ExecContext(ctx, `DELETE FROM task_link WHERE task_id=$1`, task.ID)
  168. if err != nil && err != sql.ErrNoRows {
  169. return err
  170. }
  171. return nil
  172. }