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.

194 lines
5.2 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
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. "github.com/lib/pq"
  10. "time"
  11. )
  12. type projectRepository struct {
  13. db *sqlx.DB
  14. }
  15. func (r *projectRepository) Find(ctx context.Context, id string) (*models.Project, error) {
  16. res := projectDBO{}
  17. err := r.db.GetContext(ctx, &res, "SELECT * FROM project WHERE project_id=$1", id)
  18. if err != nil {
  19. if err == sql.ErrNoRows {
  20. return nil, slerrors.NotFound("Project")
  21. }
  22. return nil, err
  23. }
  24. return res.ToProject(), nil
  25. }
  26. func (r *projectRepository) List(ctx context.Context, filter models.ProjectFilter) ([]*models.Project, error) {
  27. sq := squirrel.Select("*").From("project").PlaceholderFormat(squirrel.Dollar)
  28. sq = sq.Where(squirrel.Eq{"user_id": filter.UserID})
  29. if filter.IDs != nil {
  30. sq = sq.Where(squirrel.Eq{"project_id": filter.IDs})
  31. }
  32. if filter.Active != nil {
  33. if filter.IncludeSemiActive {
  34. sq = sq.Where(squirrel.Or{
  35. squirrel.Eq{"active": *filter.Active},
  36. squirrel.Eq{"status_tag": []string{
  37. "to do", "background", "on hold", "progress",
  38. }},
  39. })
  40. } else {
  41. sq = sq.Where(squirrel.Eq{"active": *filter.Active})
  42. }
  43. }
  44. if filter.Expiring {
  45. sq = sq.Where("end_time IS NOT NULL")
  46. }
  47. if filter.Favorite != nil {
  48. sq = sq.Where(squirrel.Eq{"favorite": *filter.Favorite})
  49. }
  50. sq = sq.OrderBy("active", "created_time DESC")
  51. query, args, err := sq.ToSql()
  52. if err != nil {
  53. return nil, err
  54. }
  55. res := make([]*projectDBO, 0, 8)
  56. err = r.db.SelectContext(ctx, &res, query, args...)
  57. if err != nil {
  58. if err == sql.ErrNoRows {
  59. return []*models.Project{}, nil
  60. }
  61. return nil, err
  62. }
  63. res2 := make([]*models.Project, len(res))
  64. for i, v := range res {
  65. res2[i] = v.ToProject()
  66. }
  67. return res2, nil
  68. }
  69. func (r *projectRepository) Insert(ctx context.Context, project models.Project) error {
  70. if project.Tags == nil {
  71. project.Tags = []string{}
  72. }
  73. _, err := r.db.NamedExecContext(ctx, `
  74. INSERT INTO project(
  75. project_id, user_id, name, description, icon, active, created_time, start_time, end_time, subtract_amount, status_tag, favorite, tags
  76. ) VALUES (
  77. :project_id, :user_id, :name, :description, :icon, :active, :created_time, :start_time, :end_time, :subtract_amount, :status_tag, :favorite, :tags
  78. )
  79. `, toProjectDBO(project))
  80. if err != nil {
  81. return err
  82. }
  83. return nil
  84. }
  85. func (r *projectRepository) Update(ctx context.Context, project models.Project) error {
  86. if project.Tags == nil {
  87. project.Tags = []string{}
  88. }
  89. _, err := r.db.NamedExecContext(ctx, `
  90. UPDATE project SET
  91. name = :name,
  92. description = :description,
  93. icon = :icon,
  94. active = :active,
  95. start_time = :start_time,
  96. end_time = :end_time,
  97. subtract_amount = :subtract_amount,
  98. status_tag = :status_tag,
  99. favorite = :favorite,
  100. tags = :tags
  101. WHERE project_id=:project_id
  102. `, toProjectDBO(project))
  103. if err != nil {
  104. return err
  105. }
  106. return nil
  107. }
  108. func (r *projectRepository) Delete(ctx context.Context, project models.Project) error {
  109. _, err := r.db.ExecContext(ctx, `DELETE FROM project WHERE project_id=$1`, project.ID)
  110. if err != nil {
  111. if err == sql.ErrNoRows {
  112. return slerrors.NotFound("Project")
  113. }
  114. return err
  115. }
  116. _, err = r.db.ExecContext(ctx, `DELETE FROM task_link WHERE project_id=$1`, project.ID)
  117. if err != nil && err != sql.ErrNoRows {
  118. return err
  119. }
  120. return nil
  121. }
  122. type projectDBO struct {
  123. ID string `json:"id" db:"project_id"`
  124. UserID string `json:"-" db:"user_id"`
  125. Name string `json:"name" db:"name"`
  126. Description string `json:"description" db:"description"`
  127. Icon string `json:"icon" db:"icon"`
  128. Active bool `json:"active" db:"active"`
  129. CreatedTime time.Time `json:"createdTime" db:"created_time"`
  130. StartTime *time.Time `json:"startTime" db:"start_time"`
  131. EndTime *time.Time `json:"endTime" db:"end_time"`
  132. SubtractAmount int `json:"subtractAmount" db:"subtract_amount"`
  133. StatusTag *string `json:"statusTag" db:"status_tag"`
  134. Favorite bool `json:"favorite" db:"favorite"`
  135. Tags pq.StringArray `json:"tags" db:"tags"`
  136. }
  137. func toProjectDBO(project models.Project) *projectDBO {
  138. return &projectDBO{
  139. ID: project.ID,
  140. UserID: project.UserID,
  141. Name: project.Name,
  142. Description: project.Description,
  143. Icon: project.Icon,
  144. Active: project.Active,
  145. CreatedTime: project.CreatedTime,
  146. StartTime: project.StartTime,
  147. EndTime: project.EndTime,
  148. SubtractAmount: project.SubtractAmount,
  149. StatusTag: project.StatusTag,
  150. Favorite: project.Favorite,
  151. Tags: project.Tags,
  152. }
  153. }
  154. func (d *projectDBO) ToProject() *models.Project {
  155. return &models.Project{
  156. ID: d.ID,
  157. UserID: d.UserID,
  158. Name: d.Name,
  159. Description: d.Description,
  160. Icon: d.Icon,
  161. Active: d.Active,
  162. CreatedTime: d.CreatedTime,
  163. StartTime: d.StartTime,
  164. EndTime: d.EndTime,
  165. SubtractAmount: d.SubtractAmount,
  166. StatusTag: d.StatusTag,
  167. Favorite: d.Favorite,
  168. Tags: d.Tags,
  169. }
  170. }