add stats repo.

This commit is contained in:
2022-04-30 14:12:30 +02:00
parent a249110622
commit 39bc4fe7e3
19 changed files with 1058 additions and 120 deletions
+3 -2
View File
@@ -9,6 +9,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http" "net/http"
"strconv" "strconv"
"strings"
) )
func handler(key string, callback func(c *gin.Context) (interface{}, error)) gin.HandlerFunc { func handler(key string, callback func(c *gin.Context) (interface{}, error)) gin.HandlerFunc {
@@ -26,7 +27,7 @@ func handler(key string, callback func(c *gin.Context) (interface{}, error)) gin
StatusLabels: models.StatusLabels, StatusLabels: models.StatusLabels,
} }
if s.Stats != nil { if s.Stats != nil && !strings.Contains(c.FullPath(), "/stats/") {
options.Stats = make(map[int]models.Stat) options.Stats = make(map[int]models.Stat)
for _, stat := range s.Stats { for _, stat := range s.Stats {
options.Stats[stat.ID] = stat options.Stats[stat.ID] = stat
@@ -73,7 +74,7 @@ func scopeIDMiddleware(db database.Database) gin.HandlerFunc {
return return
} }
scope, err := db.Scopes().Find(c.Request.Context(), scopeID, c.Request.Method != "GET") scope, err := db.Scopes().Find(c.Request.Context(), scopeID, strings.Contains(c.FullPath(), "/stats/") || c.Request.Method != "GET")
if err != nil || !scope.HasMember(auth.UserID(c)) { if err != nil || !scope.HasMember(auth.UserID(c)) {
c.AbortWithStatusJSON(http.StatusUnauthorized, slerrors.ErrorResponse{ c.AbortWithStatusJSON(http.StatusUnauthorized, slerrors.ErrorResponse{
Code: http.StatusNotFound, Code: http.StatusNotFound,
+138
View File
@@ -47,4 +47,142 @@ func Projects(g *gin.RouterGroup, db database.Database) {
return db.Projects(getScope(c).ID).Create(c.Request.Context(), *project) return db.Projects(getScope(c).ID).Create(c.Request.Context(), *project)
})) }))
g.PUT("/:id", handler("project", func(c *gin.Context) (interface{}, error) {
id, err := reqInt(c, "id")
if err != nil {
return nil, err
}
update := &models.ProjectUpdate{}
err = c.BindJSON(update)
if err != nil {
return nil, slerrors.BadRequest("Invalid JSON input: " + err.Error())
}
project, err := db.Projects(getScope(c).ID).Find(c.Request.Context(), id)
if err != nil {
return nil, err
}
return db.Projects(getScope(c).ID).Update(c.Request.Context(), *project, *update)
}))
g.POST("/:id/requirements", handler("project", func(c *gin.Context) (interface{}, error) {
id, err := reqInt(c, "id")
if err != nil {
return nil, err
}
requirement := &models.ProjectRequirement{}
err = c.BindJSON(requirement)
if err != nil {
return nil, slerrors.BadRequest("Invalid JSON input: " + err.Error())
}
if requirement.Name == "" {
return nil, slerrors.BadRequest("Requirement name cannot be empty.")
}
if !requirement.Status.Valid() {
return nil, slerrors.BadRequest("Bad requirement status.")
}
for _, stat := range requirement.Stats {
if getScope(c).Stat(stat.ID) == nil {
return nil, slerrors.Forbidden("One or more stats are not part of scope.")
}
if stat.Required < 0 {
return nil, slerrors.BadRequest("-1 stats are not allowed when creating project requirements.")
}
}
project, err := db.Projects(getScope(c).ID).Find(c.Request.Context(), id)
if err != nil {
return nil, err
}
return db.Projects(getScope(c).ID).AddRequirement(c.Request.Context(), project.ProjectEntry, *requirement)
}))
g.PUT("/:id/requirements/:rid", handler("project", func(c *gin.Context) (interface{}, error) {
id, err := reqInt(c, "id")
if err != nil {
return nil, err
}
rid, err := reqInt(c, "rid")
if err != nil {
return nil, err
}
update := &models.ProjectRequirementUpdate{}
err = c.BindJSON(update)
if err != nil {
return nil, slerrors.BadRequest("Invalid JSON input: " + err.Error())
}
if update.Name != nil && *update.Name == "" {
return nil, slerrors.BadRequest("Requirement name cannot be empty.")
}
if update.Status != nil && !update.Status.Valid() {
return nil, slerrors.BadRequest("Bad requirement status.")
}
for _, stat := range update.Stats {
if getScope(c).Stat(stat.ID) == nil {
return nil, slerrors.Forbidden("One or more stats are not part of scope.")
}
}
project, err := db.Projects(getScope(c).ID).Find(c.Request.Context(), id)
if err != nil {
return nil, err
}
requirement := project.Requirement(rid)
if requirement == nil {
return nil, slerrors.NotFound("Project requirement")
}
return db.Projects(getScope(c).ID).UpdateRequirement(c.Request.Context(), project.ProjectEntry, *requirement, *update)
}))
g.DELETE("/:id/requirements/:rid", handler("project", func(c *gin.Context) (interface{}, error) {
deleteItems := c.Query("deleteItems") == "true"
id, err := reqInt(c, "id")
if err != nil {
return nil, err
}
rid, err := reqInt(c, "rid")
if err != nil {
return nil, err
}
project, err := db.Projects(getScope(c).ID).Find(c.Request.Context(), id)
if err != nil {
return nil, err
}
requirement := project.Requirement(rid)
if requirement == nil {
return nil, slerrors.NotFound("Project requirement")
}
return db.Projects(getScope(c).ID).DeleteRequirement(c.Request.Context(), project.ProjectEntry, *requirement, deleteItems)
}))
g.DELETE("/:id", handler("project", func(c *gin.Context) (interface{}, error) {
deleteItems := c.Query("deleteItems") == "true"
id, err := reqInt(c, "id")
if err != nil {
return nil, err
}
project, err := db.Projects(getScope(c).ID).Find(c.Request.Context(), id)
if err != nil {
return nil, err
}
err = db.Projects(getScope(c).ID).Delete(c.Request.Context(), project.ProjectEntry, deleteItems)
if err != nil {
return nil, err
}
return project, nil
}))
} }
+98
View File
@@ -0,0 +1,98 @@
package api
import (
"git.aiterp.net/stufflog3/stufflog3-api/internal/database"
"git.aiterp.net/stufflog3/stufflog3-api/internal/models"
"git.aiterp.net/stufflog3/stufflog3-api/internal/slerrors"
"github.com/gin-gonic/gin"
)
func Stats(g *gin.RouterGroup, db database.Database) {
g.Use(scopeIDMiddleware(db))
g.GET("/", handler("stats", func(c *gin.Context) (interface{}, error) {
return getScope(c).Stats, nil
}))
g.GET("/:id", handler("stat", func(c *gin.Context) (interface{}, error) {
id, err := reqInt(c, "id")
if err != nil {
return nil, err
}
stat := getScope(c).Stat(id)
if stat == nil {
return nil, slerrors.NotFound("Stat")
}
return stat, nil
}))
g.POST("/", handler("stat", func(c *gin.Context) (interface{}, error) {
stat := &models.Stat{}
err := c.BindJSON(stat)
if err != nil {
return nil, slerrors.BadRequest("Invalid JSON input: " + err.Error())
}
if stat.Name == "" {
return nil, slerrors.BadRequest("Project name cannot be blank")
}
if stat.Weight < 0 {
return nil, slerrors.BadRequest("Negative weight not allowed")
}
for key, value := range stat.AllowedAmounts {
if value <= 0 {
return nil, slerrors.BadRequest("Invalid allowed amount: " + key + " (0/-1 only allowed when updating to delete them)")
}
}
return db.Stats(getScope(c).ID).Create(c.Request.Context(), *stat)
}))
g.PUT("/:id", handler("stat", func(c *gin.Context) (interface{}, error) {
id, err := reqInt(c, "id")
if err != nil {
return nil, err
}
update := &models.StatUpdate{}
err = c.BindJSON(update)
if err != nil {
return nil, slerrors.BadRequest("Invalid JSON input: " + err.Error())
}
stat := getScope(c).Stat(id)
if stat == nil {
return nil, slerrors.NotFound("Stat")
}
if update.Name != nil && *update.Name == "" {
return nil, slerrors.BadRequest("Project name cannot be blank")
}
if update.Weight != nil && *update.Weight < 0 {
return nil, slerrors.BadRequest("Negative weight not allowed")
}
return db.Stats(getScope(c).ID).Update(c.Request.Context(), *stat, *update)
}))
g.DELETE("/:id", handler("stat", func(c *gin.Context) (interface{}, error) {
id, err := reqInt(c, "id")
if err != nil {
return nil, err
}
stat := getScope(c).Stat(id)
if stat == nil {
return nil, slerrors.NotFound("Stat")
}
err = db.Stats(getScope(c).ID).Delete(c.Request.Context(), *stat)
if err != nil {
return nil, err
}
return stat, nil
}))
}
+1
View File
@@ -36,6 +36,7 @@ func main() {
api.Scopes(server.Group("/api/scopes"), db) api.Scopes(server.Group("/api/scopes"), db)
api.Items(server.Group("/api/scope/:scope_id/items"), db) api.Items(server.Group("/api/scope/:scope_id/items"), db)
api.Projects(server.Group("/api/scope/:scope_id/projects"), db) api.Projects(server.Group("/api/scope/:scope_id/projects"), db)
api.Stats(server.Group("/api/scope/:scope_id/stats"), db)
exitSignal := make(chan os.Signal) exitSignal := make(chan os.Signal)
signal.Notify(exitSignal, os.Interrupt, os.Kill, syscall.SIGTERM) signal.Notify(exitSignal, os.Interrupt, os.Kill, syscall.SIGTERM)
+6 -6
View File
@@ -29,7 +29,7 @@ type StatRepository interface {
Find(ctx context.Context, id int) (*models.Stat, error) Find(ctx context.Context, id int) (*models.Stat, error)
List(ctx context.Context) ([]models.Stat, error) List(ctx context.Context) ([]models.Stat, error)
Create(ctx context.Context, stat models.Stat) (*models.Stat, error) Create(ctx context.Context, stat models.Stat) (*models.Stat, error)
Update(ctx context.Context, stat models.Stat) error Update(ctx context.Context, stat models.Stat, update models.StatUpdate) (*models.Stat, error)
Delete(ctx context.Context, stat models.Stat) error Delete(ctx context.Context, stat models.Stat) error
} }
@@ -55,10 +55,10 @@ type ProjectRepository interface {
Find(ctx context.Context, id int) (*models.Project, error) Find(ctx context.Context, id int) (*models.Project, error)
List(ctx context.Context) ([]models.ProjectEntry, error) List(ctx context.Context) ([]models.ProjectEntry, error)
Create(ctx context.Context, project models.Project) (*models.Project, error) Create(ctx context.Context, project models.Project) (*models.Project, error)
Update(ctx context.Context, project models.Project) (*models.Project, error) Update(ctx context.Context, project models.Project, update models.ProjectUpdate) (*models.Project, error)
Delete(ctx context.Context, project models.ProjectEntry) error Delete(ctx context.Context, project models.ProjectEntry, deleteItems bool) error
AddRequirement(ctx context.Context, project models.ProjectEntry, requirement models.ProjectRequirement) AddRequirement(ctx context.Context, project models.ProjectEntry, requirement models.ProjectRequirement) (*models.Project, error)
UpdateRequirement(ctx context.Context, project models.ProjectEntry, requirement models.ProjectRequirement, update models.ProjectRequirementUpdate) UpdateRequirement(ctx context.Context, project models.ProjectEntry, requirement models.ProjectRequirement, update models.ProjectRequirementUpdate) (*models.Project, error)
DeleteRequirement(ctx context.Context, project models.ProjectEntry, requirement models.ProjectRequirement, deleteItems bool) DeleteRequirement(ctx context.Context, project models.ProjectEntry, requirement models.ProjectRequirement, deleteItems bool) (*models.Project, error)
} }
+4 -2
View File
@@ -21,8 +21,10 @@ func (d *Database) Scopes() database.ScopeRepository {
} }
func (d *Database) Stats(scopeID int) database.StatRepository { func (d *Database) Stats(scopeID int) database.StatRepository {
//TODO implement me return &statsRepository{
panic("implement me") db: d.db, q: d.q,
scopeID: scopeID,
}
} }
func (d *Database) Items(scopeID int) database.ItemRepository { func (d *Database) Items(scopeID int) database.ItemRepository {
+202 -92
View File
@@ -24,12 +24,27 @@ func New(db DBTX) *Queries {
func Prepare(ctx context.Context, db DBTX) (*Queries, error) { func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
q := Queries{db: db} q := Queries{db: db}
var err error var err error
if q.cLearItemStatProgressByStatStmt, err = db.PrepareContext(ctx, cLearItemStatProgressByStat); err != nil {
return nil, fmt.Errorf("error preparing query CLearItemStatProgressByStat: %w", err)
}
if q.clearItemProjectRequirementStmt, err = db.PrepareContext(ctx, clearItemProjectRequirement); err != nil { if q.clearItemProjectRequirementStmt, err = db.PrepareContext(ctx, clearItemProjectRequirement); err != nil {
return nil, fmt.Errorf("error preparing query ClearItemProjectRequirement: %w", err) return nil, fmt.Errorf("error preparing query ClearItemProjectRequirement: %w", err)
} }
if q.clearItemProjectRequirementByProjectIDStmt, err = db.PrepareContext(ctx, clearItemProjectRequirementByProjectID); err != nil {
return nil, fmt.Errorf("error preparing query ClearItemProjectRequirementByProjectID: %w", err)
}
if q.clearItemStatProgressStmt, err = db.PrepareContext(ctx, clearItemStatProgress); err != nil { if q.clearItemStatProgressStmt, err = db.PrepareContext(ctx, clearItemStatProgress); err != nil {
return nil, fmt.Errorf("error preparing query ClearItemStatProgress: %w", err) return nil, fmt.Errorf("error preparing query ClearItemStatProgress: %w", err)
} }
if q.deleteAllProjectRequirementStatsStmt, err = db.PrepareContext(ctx, deleteAllProjectRequirementStats); err != nil {
return nil, fmt.Errorf("error preparing query DeleteAllProjectRequirementStats: %w", err)
}
if q.deleteAllProjectRequirementStatsByStatStmt, err = db.PrepareContext(ctx, deleteAllProjectRequirementStatsByStat); err != nil {
return nil, fmt.Errorf("error preparing query DeleteAllProjectRequirementStatsByStat: %w", err)
}
if q.deleteAllProjectRequirementsStmt, err = db.PrepareContext(ctx, deleteAllProjectRequirements); err != nil {
return nil, fmt.Errorf("error preparing query DeleteAllProjectRequirements: %w", err)
}
if q.deleteAllScopeMembersStmt, err = db.PrepareContext(ctx, deleteAllScopeMembers); err != nil { if q.deleteAllScopeMembersStmt, err = db.PrepareContext(ctx, deleteAllScopeMembers); err != nil {
return nil, fmt.Errorf("error preparing query DeleteAllScopeMembers: %w", err) return nil, fmt.Errorf("error preparing query DeleteAllScopeMembers: %w", err)
} }
@@ -48,12 +63,18 @@ func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
if q.deleteProjectRequirementStmt, err = db.PrepareContext(ctx, deleteProjectRequirement); err != nil { if q.deleteProjectRequirementStmt, err = db.PrepareContext(ctx, deleteProjectRequirement); err != nil {
return nil, fmt.Errorf("error preparing query DeleteProjectRequirement: %w", err) return nil, fmt.Errorf("error preparing query DeleteProjectRequirement: %w", err)
} }
if q.deleteProjectRequirementStatStmt, err = db.PrepareContext(ctx, deleteProjectRequirementStat); err != nil {
return nil, fmt.Errorf("error preparing query DeleteProjectRequirementStat: %w", err)
}
if q.deleteScopeStmt, err = db.PrepareContext(ctx, deleteScope); err != nil { if q.deleteScopeStmt, err = db.PrepareContext(ctx, deleteScope); err != nil {
return nil, fmt.Errorf("error preparing query DeleteScope: %w", err) return nil, fmt.Errorf("error preparing query DeleteScope: %w", err)
} }
if q.deleteScopeMemberStmt, err = db.PrepareContext(ctx, deleteScopeMember); err != nil { if q.deleteScopeMemberStmt, err = db.PrepareContext(ctx, deleteScopeMember); err != nil {
return nil, fmt.Errorf("error preparing query DeleteScopeMember: %w", err) return nil, fmt.Errorf("error preparing query DeleteScopeMember: %w", err)
} }
if q.deleteStatStmt, err = db.PrepareContext(ctx, deleteStat); err != nil {
return nil, fmt.Errorf("error preparing query DeleteStat: %w", err)
}
if q.getItemStmt, err = db.PrepareContext(ctx, getItem); err != nil { if q.getItemStmt, err = db.PrepareContext(ctx, getItem); err != nil {
return nil, fmt.Errorf("error preparing query GetItem: %w", err) return nil, fmt.Errorf("error preparing query GetItem: %w", err)
} }
@@ -75,6 +96,9 @@ func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
if q.getScopeWithDisplayNameStmt, err = db.PrepareContext(ctx, getScopeWithDisplayName); err != nil { if q.getScopeWithDisplayNameStmt, err = db.PrepareContext(ctx, getScopeWithDisplayName); err != nil {
return nil, fmt.Errorf("error preparing query GetScopeWithDisplayName: %w", err) return nil, fmt.Errorf("error preparing query GetScopeWithDisplayName: %w", err)
} }
if q.getStatStmt, err = db.PrepareContext(ctx, getStat); err != nil {
return nil, fmt.Errorf("error preparing query GetStat: %w", err)
}
if q.insertItemStmt, err = db.PrepareContext(ctx, insertItem); err != nil { if q.insertItemStmt, err = db.PrepareContext(ctx, insertItem); err != nil {
return nil, fmt.Errorf("error preparing query InsertItem: %w", err) return nil, fmt.Errorf("error preparing query InsertItem: %w", err)
} }
@@ -87,6 +111,9 @@ func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
if q.insertScopeStmt, err = db.PrepareContext(ctx, insertScope); err != nil { if q.insertScopeStmt, err = db.PrepareContext(ctx, insertScope); err != nil {
return nil, fmt.Errorf("error preparing query InsertScope: %w", err) return nil, fmt.Errorf("error preparing query InsertScope: %w", err)
} }
if q.insertStatStmt, err = db.PrepareContext(ctx, insertStat); err != nil {
return nil, fmt.Errorf("error preparing query InsertStat: %w", err)
}
if q.listItemStatProgressStmt, err = db.PrepareContext(ctx, listItemStatProgress); err != nil { if q.listItemStatProgressStmt, err = db.PrepareContext(ctx, listItemStatProgress); err != nil {
return nil, fmt.Errorf("error preparing query ListItemStatProgress: %w", err) return nil, fmt.Errorf("error preparing query ListItemStatProgress: %w", err)
} }
@@ -141,6 +168,9 @@ func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
if q.replaceItemStatProgressStmt, err = db.PrepareContext(ctx, replaceItemStatProgress); err != nil { if q.replaceItemStatProgressStmt, err = db.PrepareContext(ctx, replaceItemStatProgress); err != nil {
return nil, fmt.Errorf("error preparing query ReplaceItemStatProgress: %w", err) return nil, fmt.Errorf("error preparing query ReplaceItemStatProgress: %w", err)
} }
if q.replaceProjectRequirementStatStmt, err = db.PrepareContext(ctx, replaceProjectRequirementStat); err != nil {
return nil, fmt.Errorf("error preparing query ReplaceProjectRequirementStat: %w", err)
}
if q.updateItemStmt, err = db.PrepareContext(ctx, updateItem); err != nil { if q.updateItemStmt, err = db.PrepareContext(ctx, updateItem); err != nil {
return nil, fmt.Errorf("error preparing query UpdateItem: %w", err) return nil, fmt.Errorf("error preparing query UpdateItem: %w", err)
} }
@@ -156,21 +186,49 @@ func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
if q.updateScopeMemberStmt, err = db.PrepareContext(ctx, updateScopeMember); err != nil { if q.updateScopeMemberStmt, err = db.PrepareContext(ctx, updateScopeMember); err != nil {
return nil, fmt.Errorf("error preparing query UpdateScopeMember: %w", err) return nil, fmt.Errorf("error preparing query UpdateScopeMember: %w", err)
} }
if q.updateStatStmt, err = db.PrepareContext(ctx, updateStat); err != nil {
return nil, fmt.Errorf("error preparing query UpdateStat: %w", err)
}
return &q, nil return &q, nil
} }
func (q *Queries) Close() error { func (q *Queries) Close() error {
var err error var err error
if q.cLearItemStatProgressByStatStmt != nil {
if cerr := q.cLearItemStatProgressByStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing cLearItemStatProgressByStatStmt: %w", cerr)
}
}
if q.clearItemProjectRequirementStmt != nil { if q.clearItemProjectRequirementStmt != nil {
if cerr := q.clearItemProjectRequirementStmt.Close(); cerr != nil { if cerr := q.clearItemProjectRequirementStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing clearItemProjectRequirementStmt: %w", cerr) err = fmt.Errorf("error closing clearItemProjectRequirementStmt: %w", cerr)
} }
} }
if q.clearItemProjectRequirementByProjectIDStmt != nil {
if cerr := q.clearItemProjectRequirementByProjectIDStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing clearItemProjectRequirementByProjectIDStmt: %w", cerr)
}
}
if q.clearItemStatProgressStmt != nil { if q.clearItemStatProgressStmt != nil {
if cerr := q.clearItemStatProgressStmt.Close(); cerr != nil { if cerr := q.clearItemStatProgressStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing clearItemStatProgressStmt: %w", cerr) err = fmt.Errorf("error closing clearItemStatProgressStmt: %w", cerr)
} }
} }
if q.deleteAllProjectRequirementStatsStmt != nil {
if cerr := q.deleteAllProjectRequirementStatsStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteAllProjectRequirementStatsStmt: %w", cerr)
}
}
if q.deleteAllProjectRequirementStatsByStatStmt != nil {
if cerr := q.deleteAllProjectRequirementStatsByStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteAllProjectRequirementStatsByStatStmt: %w", cerr)
}
}
if q.deleteAllProjectRequirementsStmt != nil {
if cerr := q.deleteAllProjectRequirementsStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteAllProjectRequirementsStmt: %w", cerr)
}
}
if q.deleteAllScopeMembersStmt != nil { if q.deleteAllScopeMembersStmt != nil {
if cerr := q.deleteAllScopeMembersStmt.Close(); cerr != nil { if cerr := q.deleteAllScopeMembersStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteAllScopeMembersStmt: %w", cerr) err = fmt.Errorf("error closing deleteAllScopeMembersStmt: %w", cerr)
@@ -201,6 +259,11 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing deleteProjectRequirementStmt: %w", cerr) err = fmt.Errorf("error closing deleteProjectRequirementStmt: %w", cerr)
} }
} }
if q.deleteProjectRequirementStatStmt != nil {
if cerr := q.deleteProjectRequirementStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteProjectRequirementStatStmt: %w", cerr)
}
}
if q.deleteScopeStmt != nil { if q.deleteScopeStmt != nil {
if cerr := q.deleteScopeStmt.Close(); cerr != nil { if cerr := q.deleteScopeStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteScopeStmt: %w", cerr) err = fmt.Errorf("error closing deleteScopeStmt: %w", cerr)
@@ -211,6 +274,11 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing deleteScopeMemberStmt: %w", cerr) err = fmt.Errorf("error closing deleteScopeMemberStmt: %w", cerr)
} }
} }
if q.deleteStatStmt != nil {
if cerr := q.deleteStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteStatStmt: %w", cerr)
}
}
if q.getItemStmt != nil { if q.getItemStmt != nil {
if cerr := q.getItemStmt.Close(); cerr != nil { if cerr := q.getItemStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing getItemStmt: %w", cerr) err = fmt.Errorf("error closing getItemStmt: %w", cerr)
@@ -246,6 +314,11 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing getScopeWithDisplayNameStmt: %w", cerr) err = fmt.Errorf("error closing getScopeWithDisplayNameStmt: %w", cerr)
} }
} }
if q.getStatStmt != nil {
if cerr := q.getStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing getStatStmt: %w", cerr)
}
}
if q.insertItemStmt != nil { if q.insertItemStmt != nil {
if cerr := q.insertItemStmt.Close(); cerr != nil { if cerr := q.insertItemStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing insertItemStmt: %w", cerr) err = fmt.Errorf("error closing insertItemStmt: %w", cerr)
@@ -266,6 +339,11 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing insertScopeStmt: %w", cerr) err = fmt.Errorf("error closing insertScopeStmt: %w", cerr)
} }
} }
if q.insertStatStmt != nil {
if cerr := q.insertStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing insertStatStmt: %w", cerr)
}
}
if q.listItemStatProgressStmt != nil { if q.listItemStatProgressStmt != nil {
if cerr := q.listItemStatProgressStmt.Close(); cerr != nil { if cerr := q.listItemStatProgressStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing listItemStatProgressStmt: %w", cerr) err = fmt.Errorf("error closing listItemStatProgressStmt: %w", cerr)
@@ -356,6 +434,11 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing replaceItemStatProgressStmt: %w", cerr) err = fmt.Errorf("error closing replaceItemStatProgressStmt: %w", cerr)
} }
} }
if q.replaceProjectRequirementStatStmt != nil {
if cerr := q.replaceProjectRequirementStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing replaceProjectRequirementStatStmt: %w", cerr)
}
}
if q.updateItemStmt != nil { if q.updateItemStmt != nil {
if cerr := q.updateItemStmt.Close(); cerr != nil { if cerr := q.updateItemStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing updateItemStmt: %w", cerr) err = fmt.Errorf("error closing updateItemStmt: %w", cerr)
@@ -381,6 +464,11 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing updateScopeMemberStmt: %w", cerr) err = fmt.Errorf("error closing updateScopeMemberStmt: %w", cerr)
} }
} }
if q.updateStatStmt != nil {
if cerr := q.updateStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing updateStatStmt: %w", cerr)
}
}
return err return err
} }
@@ -418,101 +506,123 @@ func (q *Queries) queryRow(ctx context.Context, stmt *sql.Stmt, query string, ar
} }
type Queries struct { type Queries struct {
db DBTX db DBTX
tx *sql.Tx tx *sql.Tx
clearItemProjectRequirementStmt *sql.Stmt cLearItemStatProgressByStatStmt *sql.Stmt
clearItemStatProgressStmt *sql.Stmt clearItemProjectRequirementStmt *sql.Stmt
deleteAllScopeMembersStmt *sql.Stmt clearItemProjectRequirementByProjectIDStmt *sql.Stmt
deleteItemStmt *sql.Stmt clearItemStatProgressStmt *sql.Stmt
deleteItemForRequirementStmt *sql.Stmt deleteAllProjectRequirementStatsStmt *sql.Stmt
deleteItemStatProgressStmt *sql.Stmt deleteAllProjectRequirementStatsByStatStmt *sql.Stmt
deleteProjectStmt *sql.Stmt deleteAllProjectRequirementsStmt *sql.Stmt
deleteProjectRequirementStmt *sql.Stmt deleteAllScopeMembersStmt *sql.Stmt
deleteScopeStmt *sql.Stmt deleteItemStmt *sql.Stmt
deleteScopeMemberStmt *sql.Stmt deleteItemForRequirementStmt *sql.Stmt
getItemStmt *sql.Stmt deleteItemStatProgressStmt *sql.Stmt
getItemStatProgressBetweenStmt *sql.Stmt deleteProjectStmt *sql.Stmt
getProjectStmt *sql.Stmt deleteProjectRequirementStmt *sql.Stmt
getProjectRequirementStmt *sql.Stmt deleteProjectRequirementStatStmt *sql.Stmt
getScopeStmt *sql.Stmt deleteScopeStmt *sql.Stmt
getScopeDisplayNameStmt *sql.Stmt deleteScopeMemberStmt *sql.Stmt
getScopeWithDisplayNameStmt *sql.Stmt deleteStatStmt *sql.Stmt
insertItemStmt *sql.Stmt getItemStmt *sql.Stmt
insertProjectStmt *sql.Stmt getItemStatProgressBetweenStmt *sql.Stmt
insertProjectRequirementStmt *sql.Stmt getProjectStmt *sql.Stmt
insertScopeStmt *sql.Stmt getProjectRequirementStmt *sql.Stmt
listItemStatProgressStmt *sql.Stmt getScopeStmt *sql.Stmt
listItemStatProgressMultiStmt *sql.Stmt getScopeDisplayNameStmt *sql.Stmt
listItemsAcquiredBetweenStmt *sql.Stmt getScopeWithDisplayNameStmt *sql.Stmt
listItemsByProjectStmt *sql.Stmt getStatStmt *sql.Stmt
listItemsCreatedBetweenStmt *sql.Stmt insertItemStmt *sql.Stmt
listItemsCreatedBetweenNoScopeStmt *sql.Stmt insertProjectStmt *sql.Stmt
listItemsLooseBetweenStmt *sql.Stmt insertProjectRequirementStmt *sql.Stmt
listItemsLooseBetweenNoScopeStmt *sql.Stmt insertScopeStmt *sql.Stmt
listItemsScheduledBetweenStmt *sql.Stmt insertStatStmt *sql.Stmt
listItemsScheduledBetweenNoScopeStmt *sql.Stmt listItemStatProgressStmt *sql.Stmt
listProjectEntriesStmt *sql.Stmt listItemStatProgressMultiStmt *sql.Stmt
listProjectRequirementStatsStmt *sql.Stmt listItemsAcquiredBetweenStmt *sql.Stmt
listProjectRequirementsByProjectIDStmt *sql.Stmt listItemsByProjectStmt *sql.Stmt
listScopeMembersStmt *sql.Stmt listItemsCreatedBetweenStmt *sql.Stmt
listScopesStmt *sql.Stmt listItemsCreatedBetweenNoScopeStmt *sql.Stmt
listScopesByUserStmt *sql.Stmt listItemsLooseBetweenStmt *sql.Stmt
listStatsStmt *sql.Stmt listItemsLooseBetweenNoScopeStmt *sql.Stmt
replaceItemStatProgressStmt *sql.Stmt listItemsScheduledBetweenStmt *sql.Stmt
updateItemStmt *sql.Stmt listItemsScheduledBetweenNoScopeStmt *sql.Stmt
updateProjectStmt *sql.Stmt listProjectEntriesStmt *sql.Stmt
updateProjectRequirementStmt *sql.Stmt listProjectRequirementStatsStmt *sql.Stmt
updateScopeStmt *sql.Stmt listProjectRequirementsByProjectIDStmt *sql.Stmt
updateScopeMemberStmt *sql.Stmt listScopeMembersStmt *sql.Stmt
listScopesStmt *sql.Stmt
listScopesByUserStmt *sql.Stmt
listStatsStmt *sql.Stmt
replaceItemStatProgressStmt *sql.Stmt
replaceProjectRequirementStatStmt *sql.Stmt
updateItemStmt *sql.Stmt
updateProjectStmt *sql.Stmt
updateProjectRequirementStmt *sql.Stmt
updateScopeStmt *sql.Stmt
updateScopeMemberStmt *sql.Stmt
updateStatStmt *sql.Stmt
} }
func (q *Queries) WithTx(tx *sql.Tx) *Queries { func (q *Queries) WithTx(tx *sql.Tx) *Queries {
return &Queries{ return &Queries{
db: tx, db: tx,
tx: tx, tx: tx,
clearItemProjectRequirementStmt: q.clearItemProjectRequirementStmt, cLearItemStatProgressByStatStmt: q.cLearItemStatProgressByStatStmt,
clearItemStatProgressStmt: q.clearItemStatProgressStmt, clearItemProjectRequirementStmt: q.clearItemProjectRequirementStmt,
deleteAllScopeMembersStmt: q.deleteAllScopeMembersStmt, clearItemProjectRequirementByProjectIDStmt: q.clearItemProjectRequirementByProjectIDStmt,
deleteItemStmt: q.deleteItemStmt, clearItemStatProgressStmt: q.clearItemStatProgressStmt,
deleteItemForRequirementStmt: q.deleteItemForRequirementStmt, deleteAllProjectRequirementStatsStmt: q.deleteAllProjectRequirementStatsStmt,
deleteItemStatProgressStmt: q.deleteItemStatProgressStmt, deleteAllProjectRequirementStatsByStatStmt: q.deleteAllProjectRequirementStatsByStatStmt,
deleteProjectStmt: q.deleteProjectStmt, deleteAllProjectRequirementsStmt: q.deleteAllProjectRequirementsStmt,
deleteProjectRequirementStmt: q.deleteProjectRequirementStmt, deleteAllScopeMembersStmt: q.deleteAllScopeMembersStmt,
deleteScopeStmt: q.deleteScopeStmt, deleteItemStmt: q.deleteItemStmt,
deleteScopeMemberStmt: q.deleteScopeMemberStmt, deleteItemForRequirementStmt: q.deleteItemForRequirementStmt,
getItemStmt: q.getItemStmt, deleteItemStatProgressStmt: q.deleteItemStatProgressStmt,
getItemStatProgressBetweenStmt: q.getItemStatProgressBetweenStmt, deleteProjectStmt: q.deleteProjectStmt,
getProjectStmt: q.getProjectStmt, deleteProjectRequirementStmt: q.deleteProjectRequirementStmt,
getProjectRequirementStmt: q.getProjectRequirementStmt, deleteProjectRequirementStatStmt: q.deleteProjectRequirementStatStmt,
getScopeStmt: q.getScopeStmt, deleteScopeStmt: q.deleteScopeStmt,
getScopeDisplayNameStmt: q.getScopeDisplayNameStmt, deleteScopeMemberStmt: q.deleteScopeMemberStmt,
getScopeWithDisplayNameStmt: q.getScopeWithDisplayNameStmt, deleteStatStmt: q.deleteStatStmt,
insertItemStmt: q.insertItemStmt, getItemStmt: q.getItemStmt,
insertProjectStmt: q.insertProjectStmt, getItemStatProgressBetweenStmt: q.getItemStatProgressBetweenStmt,
insertProjectRequirementStmt: q.insertProjectRequirementStmt, getProjectStmt: q.getProjectStmt,
insertScopeStmt: q.insertScopeStmt, getProjectRequirementStmt: q.getProjectRequirementStmt,
listItemStatProgressStmt: q.listItemStatProgressStmt, getScopeStmt: q.getScopeStmt,
listItemStatProgressMultiStmt: q.listItemStatProgressMultiStmt, getScopeDisplayNameStmt: q.getScopeDisplayNameStmt,
listItemsAcquiredBetweenStmt: q.listItemsAcquiredBetweenStmt, getScopeWithDisplayNameStmt: q.getScopeWithDisplayNameStmt,
listItemsByProjectStmt: q.listItemsByProjectStmt, getStatStmt: q.getStatStmt,
listItemsCreatedBetweenStmt: q.listItemsCreatedBetweenStmt, insertItemStmt: q.insertItemStmt,
listItemsCreatedBetweenNoScopeStmt: q.listItemsCreatedBetweenNoScopeStmt, insertProjectStmt: q.insertProjectStmt,
listItemsLooseBetweenStmt: q.listItemsLooseBetweenStmt, insertProjectRequirementStmt: q.insertProjectRequirementStmt,
listItemsLooseBetweenNoScopeStmt: q.listItemsLooseBetweenNoScopeStmt, insertScopeStmt: q.insertScopeStmt,
listItemsScheduledBetweenStmt: q.listItemsScheduledBetweenStmt, insertStatStmt: q.insertStatStmt,
listItemsScheduledBetweenNoScopeStmt: q.listItemsScheduledBetweenNoScopeStmt, listItemStatProgressStmt: q.listItemStatProgressStmt,
listProjectEntriesStmt: q.listProjectEntriesStmt, listItemStatProgressMultiStmt: q.listItemStatProgressMultiStmt,
listProjectRequirementStatsStmt: q.listProjectRequirementStatsStmt, listItemsAcquiredBetweenStmt: q.listItemsAcquiredBetweenStmt,
listProjectRequirementsByProjectIDStmt: q.listProjectRequirementsByProjectIDStmt, listItemsByProjectStmt: q.listItemsByProjectStmt,
listScopeMembersStmt: q.listScopeMembersStmt, listItemsCreatedBetweenStmt: q.listItemsCreatedBetweenStmt,
listScopesStmt: q.listScopesStmt, listItemsCreatedBetweenNoScopeStmt: q.listItemsCreatedBetweenNoScopeStmt,
listScopesByUserStmt: q.listScopesByUserStmt, listItemsLooseBetweenStmt: q.listItemsLooseBetweenStmt,
listStatsStmt: q.listStatsStmt, listItemsLooseBetweenNoScopeStmt: q.listItemsLooseBetweenNoScopeStmt,
replaceItemStatProgressStmt: q.replaceItemStatProgressStmt, listItemsScheduledBetweenStmt: q.listItemsScheduledBetweenStmt,
updateItemStmt: q.updateItemStmt, listItemsScheduledBetweenNoScopeStmt: q.listItemsScheduledBetweenNoScopeStmt,
updateProjectStmt: q.updateProjectStmt, listProjectEntriesStmt: q.listProjectEntriesStmt,
updateProjectRequirementStmt: q.updateProjectRequirementStmt, listProjectRequirementStatsStmt: q.listProjectRequirementStatsStmt,
updateScopeStmt: q.updateScopeStmt, listProjectRequirementsByProjectIDStmt: q.listProjectRequirementsByProjectIDStmt,
updateScopeMemberStmt: q.updateScopeMemberStmt, listScopeMembersStmt: q.listScopeMembersStmt,
listScopesStmt: q.listScopesStmt,
listScopesByUserStmt: q.listScopesByUserStmt,
listStatsStmt: q.listStatsStmt,
replaceItemStatProgressStmt: q.replaceItemStatProgressStmt,
replaceProjectRequirementStatStmt: q.replaceProjectRequirementStatStmt,
updateItemStmt: q.updateItemStmt,
updateProjectStmt: q.updateProjectStmt,
updateProjectRequirementStmt: q.updateProjectRequirementStmt,
updateScopeStmt: q.updateScopeStmt,
updateScopeMemberStmt: q.updateScopeMemberStmt,
updateStatStmt: q.updateStatStmt,
} }
} }
@@ -13,6 +13,15 @@ import (
"git.aiterp.net/stufflog3/stufflog3-api/internal/sqltypes" "git.aiterp.net/stufflog3/stufflog3-api/internal/sqltypes"
) )
const cLearItemStatProgressByStat = `-- name: CLearItemStatProgressByStat :exec
DELETE FROM item_stat_progress WHERE stat_id = ?
`
func (q *Queries) CLearItemStatProgressByStat(ctx context.Context, statID int) error {
_, err := q.exec(ctx, q.cLearItemStatProgressByStatStmt, cLearItemStatProgressByStat, statID)
return err
}
const clearItemProjectRequirement = `-- name: ClearItemProjectRequirement :exec const clearItemProjectRequirement = `-- name: ClearItemProjectRequirement :exec
UPDATE item SET project_requirement_id = NULL WHERE project_requirement_id = ? UPDATE item SET project_requirement_id = NULL WHERE project_requirement_id = ?
` `
@@ -22,6 +31,18 @@ func (q *Queries) ClearItemProjectRequirement(ctx context.Context, projectRequir
return err return err
} }
const clearItemProjectRequirementByProjectID = `-- name: ClearItemProjectRequirementByProjectID :exec
UPDATE item i
LEFT JOIN project_requirement pr ON pr.id = i.project_requirement_id
SET i.project_requirement_id = NULL
WHERE pr.project_id = ?
`
func (q *Queries) ClearItemProjectRequirementByProjectID(ctx context.Context, projectID int) error {
_, err := q.exec(ctx, q.clearItemProjectRequirementByProjectIDStmt, clearItemProjectRequirementByProjectID, projectID)
return err
}
const clearItemStatProgress = `-- name: ClearItemStatProgress :exec const clearItemStatProgress = `-- name: ClearItemStatProgress :exec
DELETE FROM item_stat_progress WHERE item_id = ? DELETE FROM item_stat_progress WHERE item_id = ?
` `
@@ -11,6 +11,33 @@ import (
"time" "time"
) )
const deleteAllProjectRequirementStats = `-- name: DeleteAllProjectRequirementStats :exec
DELETE FROM project_requirement_stat WHERE project_requirement_id = ?
`
func (q *Queries) DeleteAllProjectRequirementStats(ctx context.Context, projectRequirementID int) error {
_, err := q.exec(ctx, q.deleteAllProjectRequirementStatsStmt, deleteAllProjectRequirementStats, projectRequirementID)
return err
}
const deleteAllProjectRequirementStatsByStat = `-- name: DeleteAllProjectRequirementStatsByStat :exec
DELETE FROM project_requirement_stat WHERE stat_id = ?
`
func (q *Queries) DeleteAllProjectRequirementStatsByStat(ctx context.Context, statID int) error {
_, err := q.exec(ctx, q.deleteAllProjectRequirementStatsByStatStmt, deleteAllProjectRequirementStatsByStat, statID)
return err
}
const deleteAllProjectRequirements = `-- name: DeleteAllProjectRequirements :exec
DELETE FROM project_requirement WHERE project_id = ?
`
func (q *Queries) DeleteAllProjectRequirements(ctx context.Context, projectID int) error {
_, err := q.exec(ctx, q.deleteAllProjectRequirementsStmt, deleteAllProjectRequirements, projectID)
return err
}
const deleteProject = `-- name: DeleteProject :exec const deleteProject = `-- name: DeleteProject :exec
DELETE FROM project WHERE id = ? DELETE FROM project WHERE id = ?
` `
@@ -29,6 +56,20 @@ func (q *Queries) DeleteProjectRequirement(ctx context.Context, id int) error {
return err return err
} }
const deleteProjectRequirementStat = `-- name: DeleteProjectRequirementStat :exec
DELETE FROM project_requirement_stat WHERE project_requirement_id = ? AND stat_id = ?
`
type DeleteProjectRequirementStatParams struct {
ProjectRequirementID int
StatID int
}
func (q *Queries) DeleteProjectRequirementStat(ctx context.Context, arg DeleteProjectRequirementStatParams) error {
_, err := q.exec(ctx, q.deleteProjectRequirementStatStmt, deleteProjectRequirementStat, arg.ProjectRequirementID, arg.StatID)
return err
}
const getProject = `-- name: GetProject :one const getProject = `-- name: GetProject :one
SELECT id, scope_id, author_id, name, status, description, created_time FROM project WHERE id = ? SELECT id, scope_id, author_id, name, status, description, created_time FROM project WHERE id = ?
` `
@@ -232,6 +273,22 @@ func (q *Queries) ListProjectRequirementsByProjectID(ctx context.Context, projec
return items, nil return items, nil
} }
const replaceProjectRequirementStat = `-- name: ReplaceProjectRequirementStat :exec
REPLACE INTO project_requirement_stat (project_requirement_id, stat_id, required)
VALUES (?, ?, ?)
`
type ReplaceProjectRequirementStatParams struct {
ProjectRequirementID int
StatID int
Required int
}
func (q *Queries) ReplaceProjectRequirementStat(ctx context.Context, arg ReplaceProjectRequirementStatParams) error {
_, err := q.exec(ctx, q.replaceProjectRequirementStatStmt, replaceProjectRequirementStat, arg.ProjectRequirementID, arg.StatID, arg.Required)
return err
}
const updateProject = `-- name: UpdateProject :exec const updateProject = `-- name: UpdateProject :exec
UPDATE project UPDATE project
SET name = ?, SET name = ?,
@@ -7,10 +7,79 @@ package mysqlcore
import ( import (
"context" "context"
"database/sql"
"git.aiterp.net/stufflog3/stufflog3-api/internal/sqltypes" "git.aiterp.net/stufflog3/stufflog3-api/internal/sqltypes"
) )
const deleteStat = `-- name: DeleteStat :exec
DELETE FROM stat WHERE id = ? AND scope_id = ?
`
type DeleteStatParams struct {
ID int
ScopeID int
}
func (q *Queries) DeleteStat(ctx context.Context, arg DeleteStatParams) error {
_, err := q.exec(ctx, q.deleteStatStmt, deleteStat, arg.ID, arg.ScopeID)
return err
}
const getStat = `-- name: GetStat :one
SELECT id, name, description, weight, allowed_amounts FROM stat
WHERE scope_id = ? AND id = ?
`
type GetStatParams struct {
ScopeID int
ID int
}
type GetStatRow struct {
ID int
Name string
Description string
Weight float64
AllowedAmounts sqltypes.NullRawMessage
}
func (q *Queries) GetStat(ctx context.Context, arg GetStatParams) (GetStatRow, error) {
row := q.queryRow(ctx, q.getStatStmt, getStat, arg.ScopeID, arg.ID)
var i GetStatRow
err := row.Scan(
&i.ID,
&i.Name,
&i.Description,
&i.Weight,
&i.AllowedAmounts,
)
return i, err
}
const insertStat = `-- name: InsertStat :execresult
INSERT INTO stat (scope_id, name, description, weight, allowed_amounts)
VALUES (?, ?, ?, ?, ?)
`
type InsertStatParams struct {
ScopeID int
Name string
Description string
Weight float64
AllowedAmounts sqltypes.NullRawMessage
}
func (q *Queries) InsertStat(ctx context.Context, arg InsertStatParams) (sql.Result, error) {
return q.exec(ctx, q.insertStatStmt, insertStat,
arg.ScopeID,
arg.Name,
arg.Description,
arg.Weight,
arg.AllowedAmounts,
)
}
const listStats = `-- name: ListStats :many const listStats = `-- name: ListStats :many
SELECT id, name, description, weight, allowed_amounts FROM stat SELECT id, name, description, weight, allowed_amounts FROM stat
WHERE scope_id = ? WHERE scope_id = ?
@@ -52,3 +121,33 @@ func (q *Queries) ListStats(ctx context.Context, scopeID int) ([]ListStatsRow, e
} }
return items, nil return items, nil
} }
const updateStat = `-- name: UpdateStat :exec
UPDATE stat SET
name = ?,
description = ?,
weight = ?,
allowed_amounts = ?
WHERE id = ? AND scope_id = ?
`
type UpdateStatParams struct {
Name string
Description string
Weight float64
AllowedAmounts sqltypes.NullRawMessage
ID int
ScopeID int
}
func (q *Queries) UpdateStat(ctx context.Context, arg UpdateStatParams) error {
_, err := q.exec(ctx, q.updateStatStmt, updateStat,
arg.Name,
arg.Description,
arg.Weight,
arg.AllowedAmounts,
arg.ID,
arg.ScopeID,
)
return err
}
+175 -15
View File
@@ -154,27 +154,187 @@ func (r *projectRepository) Create(ctx context.Context, project models.Project)
return r.Find(ctx, int(id)) return r.Find(ctx, int(id))
} }
func (r *projectRepository) Update(ctx context.Context, project models.Project) (*models.Project, error) { func (r *projectRepository) Update(ctx context.Context, project models.Project, update models.ProjectUpdate) (*models.Project, error) {
//TODO implement me project.Update(update)
panic("implement me")
err := r.q.UpdateProject(ctx, mysqlcore.UpdateProjectParams{
Name: project.Name,
Status: int(project.Status),
Description: project.Description,
ID: project.ID,
})
if err != nil {
return nil, err
}
return r.Find(ctx, project.ID)
} }
func (r *projectRepository) Delete(ctx context.Context, project models.ProjectEntry) error { func (r *projectRepository) Delete(ctx context.Context, project models.ProjectEntry, deleteItems bool) error {
//TODO implement me tx, err := r.db.BeginTx(ctx, nil)
panic("implement me") if err != nil {
return err
}
defer tx.Rollback()
q := r.q.WithTx(tx)
err = q.DeleteProject(ctx, project.ID)
if err != nil {
return err
}
if deleteItems {
reqs, err := q.ListProjectRequirementsByProjectID(ctx, project.ID)
if err != nil {
return err
}
for _, req := range reqs {
err = q.DeleteItemForRequirement(ctx, sql.NullInt32{Valid: true, Int32: int32(req.ID)})
if err != nil {
return err
}
err = q.DeleteAllProjectRequirementStats(ctx, req.ID)
if err != nil {
return err
}
}
} else {
err = q.ClearItemProjectRequirementByProjectID(ctx, project.ID)
if err != nil {
return err
}
}
return tx.Commit()
} }
func (r *projectRepository) AddRequirement(ctx context.Context, project models.ProjectEntry, requirement models.ProjectRequirement) { func (r *projectRepository) AddRequirement(ctx context.Context, project models.ProjectEntry, requirement models.ProjectRequirement) (*models.Project, error) {
//TODO implement me tx, err := r.db.BeginTx(ctx, nil)
panic("implement me") if err != nil {
return nil, err
}
defer tx.Rollback()
q := r.q.WithTx(tx)
res, err := q.InsertProjectRequirement(ctx, mysqlcore.InsertProjectRequirementParams{
ScopeID: r.scopeID,
ProjectID: project.ID,
Name: requirement.Name,
Status: int(requirement.Status),
Description: requirement.Description,
})
if err != nil {
return nil, err
}
id, err := res.LastInsertId()
if err != nil {
return nil, err
}
for _, stat := range requirement.Stats {
err = q.ReplaceProjectRequirementStat(ctx, mysqlcore.ReplaceProjectRequirementStatParams{
ProjectRequirementID: int(id),
StatID: stat.ID,
Required: stat.Required,
})
if err != nil {
return nil, err
}
}
err = tx.Commit()
if err != nil {
return nil, err
}
return r.Find(ctx, project.ID)
} }
func (r *projectRepository) UpdateRequirement(ctx context.Context, project models.ProjectEntry, requirement models.ProjectRequirement, update models.ProjectRequirementUpdate) { func (r *projectRepository) UpdateRequirement(ctx context.Context, project models.ProjectEntry, requirement models.ProjectRequirement, update models.ProjectRequirementUpdate) (*models.Project, error) {
//TODO implement me tx, err := r.db.BeginTx(ctx, nil)
panic("implement me") if err != nil {
return nil, err
}
defer tx.Rollback()
q := r.q.WithTx(tx)
requirement.Update(update)
err = q.UpdateProjectRequirement(ctx, mysqlcore.UpdateProjectRequirementParams{
Name: requirement.Name,
Status: int(requirement.Status),
Description: requirement.Description,
ID: requirement.ID,
})
if err != nil {
return nil, err
}
for _, stat := range requirement.Stats {
if stat.Required < 0 {
err = q.DeleteProjectRequirementStat(ctx, mysqlcore.DeleteProjectRequirementStatParams{
ProjectRequirementID: requirement.ID,
StatID: stat.ID,
})
} else {
err = q.ReplaceProjectRequirementStat(ctx, mysqlcore.ReplaceProjectRequirementStatParams{
ProjectRequirementID: requirement.ID,
StatID: stat.ID,
Required: stat.Required,
})
}
if err != nil {
return nil, err
}
}
err = tx.Commit()
if err != nil {
return nil, err
}
return r.Find(ctx, project.ID)
} }
func (r *projectRepository) DeleteRequirement(ctx context.Context, project models.ProjectEntry, requirement models.ProjectRequirement, deleteItems bool) { func (r *projectRepository) DeleteRequirement(ctx context.Context, project models.ProjectEntry, requirement models.ProjectRequirement, deleteItems bool) (*models.Project, error) {
//TODO implement me tx, err := r.db.BeginTx(ctx, nil)
panic("implement me") if err != nil {
return nil, err
}
defer tx.Rollback()
q := r.q.WithTx(tx)
err = q.DeleteProjectRequirement(ctx, requirement.ID)
if err != nil {
if err == sql.ErrNoRows {
return nil, slerrors.NotFound("Project requirement")
}
return nil, err
}
if deleteItems {
err = q.DeleteItemForRequirement(ctx, sql.NullInt32{Valid: true, Int32: int32(requirement.ID)})
if err != nil {
return nil, err
}
} else {
err = q.ClearItemProjectRequirement(ctx, sql.NullInt32{Valid: true, Int32: int32(requirement.ID)})
if err != nil {
return nil, err
}
err = q.DeleteAllProjectRequirementStats(ctx, requirement.ID)
if err != nil {
return nil, err
}
}
err = tx.Commit()
if err != nil {
return nil, err
}
return r.Find(ctx, project.ID)
} }
+9
View File
@@ -105,6 +105,12 @@ DELETE FROM item WHERE project_requirement_id = ?;
-- name: ClearItemProjectRequirement :exec -- name: ClearItemProjectRequirement :exec
UPDATE item SET project_requirement_id = NULL WHERE project_requirement_id = ?; UPDATE item SET project_requirement_id = NULL WHERE project_requirement_id = ?;
-- name: ClearItemProjectRequirementByProjectID :exec
UPDATE item i
LEFT JOIN project_requirement pr ON pr.id = i.project_requirement_id
SET i.project_requirement_id = NULL
WHERE pr.project_id = ?;
-- name: ReplaceItemStatProgress :exec -- name: ReplaceItemStatProgress :exec
REPLACE INTO item_stat_progress (item_id, stat_id, acquired, required) REPLACE INTO item_stat_progress (item_id, stat_id, acquired, required)
VALUES (?, ?, ?, ?); VALUES (?, ?, ?, ?);
@@ -114,3 +120,6 @@ DELETE FROM item_stat_progress WHERE item_id = ? AND stat_id = ?;
-- name: ClearItemStatProgress :exec -- name: ClearItemStatProgress :exec
DELETE FROM item_stat_progress WHERE item_id = ?; DELETE FROM item_stat_progress WHERE item_id = ?;
-- name: CLearItemStatProgressByStat :exec
DELETE FROM item_stat_progress WHERE stat_id = ?;
@@ -45,4 +45,19 @@ WHERE id = ?;
-- name: DeleteProjectRequirement :exec -- name: DeleteProjectRequirement :exec
DELETE FROM project_requirement WHERE id = ?; DELETE FROM project_requirement WHERE id = ?;
-- name: DeleteAllProjectRequirements :exec
DELETE FROM project_requirement WHERE project_id = ?;
-- name: ReplaceProjectRequirementStat :exec
REPLACE INTO project_requirement_stat (project_requirement_id, stat_id, required)
VALUES (?, ?, ?);
-- name: DeleteProjectRequirementStat :exec
DELETE FROM project_requirement_stat WHERE project_requirement_id = ? AND stat_id = ?;
-- name: DeleteAllProjectRequirementStats :exec
DELETE FROM project_requirement_stat WHERE project_requirement_id = ?;
-- name: DeleteAllProjectRequirementStatsByStat :exec
DELETE FROM project_requirement_stat WHERE stat_id = ?;
+20 -1
View File
@@ -1,3 +1,22 @@
-- name: ListStats :many -- name: ListStats :many
SELECT id, name, description, weight, allowed_amounts FROM stat SELECT id, name, description, weight, allowed_amounts FROM stat
WHERE scope_id = ?; WHERE scope_id = ?;
-- name: GetStat :one
SELECT id, name, description, weight, allowed_amounts FROM stat
WHERE scope_id = ? AND id = ?;
-- name: InsertStat :execresult
INSERT INTO stat (scope_id, name, description, weight, allowed_amounts)
VALUES (?, ?, ?, ?, ?);
-- name: UpdateStat :exec
UPDATE stat SET
name = ?,
description = ?,
weight = ?,
allowed_amounts = ?
WHERE id = ? AND scope_id = ?;
-- name: DeleteStat :exec
DELETE FROM stat WHERE id = ? AND scope_id = ?;
+144
View File
@@ -0,0 +1,144 @@
package mysql
import (
"context"
"database/sql"
"encoding/json"
"git.aiterp.net/stufflog3/stufflog3-api/internal/database/mysql/mysqlcore"
"git.aiterp.net/stufflog3/stufflog3-api/internal/models"
"git.aiterp.net/stufflog3/stufflog3-api/internal/slerrors"
"git.aiterp.net/stufflog3/stufflog3-api/internal/sqltypes"
)
type statsRepository struct {
db *sql.DB
q *mysqlcore.Queries
scopeID int
}
func (r *statsRepository) Find(ctx context.Context, id int) (*models.Stat, error) {
row, err := r.q.GetStat(ctx, mysqlcore.GetStatParams{ScopeID: r.scopeID, ID: id})
if err != nil {
if err == sql.ErrNoRows {
return nil, slerrors.NotFound("Stat")
}
return nil, err
}
return r.rowToStat(row), nil
}
func (r *statsRepository) List(ctx context.Context) ([]models.Stat, error) {
rows, err := r.q.ListStats(ctx, r.scopeID)
if err != nil && err != sql.ErrNoRows {
return nil, err
}
stats := make([]models.Stat, 0, len(rows))
for _, row := range rows {
stats = append(stats, *r.rowToStat(mysqlcore.GetStatRow(row)))
}
return stats, nil
}
func (r *statsRepository) Create(ctx context.Context, stat models.Stat) (*models.Stat, error) {
allowedAmounts := sqltypes.NullRawMessage{}
if stat.AllowedAmounts != nil && len(stat.AllowedAmounts) > 0 {
allowedAmounts.Valid = true
allowedAmounts.RawMessage, _ = json.Marshal(stat.AllowedAmounts)
}
res, err := r.q.InsertStat(ctx, mysqlcore.InsertStatParams{
ScopeID: r.scopeID,
Name: stat.Name,
Description: stat.Description,
Weight: stat.Weight,
AllowedAmounts: allowedAmounts,
})
if err != nil {
return nil, err
}
id, err := res.LastInsertId()
if err != nil {
return nil, err
}
return r.Find(ctx, int(id))
}
func (r *statsRepository) Update(ctx context.Context, stat models.Stat, update models.StatUpdate) (*models.Stat, error) {
stat.Update(update)
allowedAmounts := sqltypes.NullRawMessage{}
if stat.AllowedAmounts != nil && len(stat.AllowedAmounts) > 0 {
allowedAmounts.Valid = true
allowedAmounts.RawMessage, _ = json.Marshal(stat.AllowedAmounts)
}
err := r.q.UpdateStat(ctx, mysqlcore.UpdateStatParams{
Name: stat.Name,
Description: stat.Description,
Weight: stat.Weight,
AllowedAmounts: allowedAmounts,
ID: stat.ID,
ScopeID: r.scopeID,
})
if err != nil {
return nil, err
}
return &stat, nil
}
func (r *statsRepository) Delete(ctx context.Context, stat models.Stat) error {
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer tx.Rollback()
q := r.q.WithTx(tx)
err = q.DeleteStat(ctx, mysqlcore.DeleteStatParams{ScopeID: r.scopeID, ID: stat.ID})
if err == sql.ErrNoRows {
return slerrors.NotFound("Stat")
}
if err != nil {
return err
}
err = q.CLearItemStatProgressByStat(ctx, stat.ID)
if err != nil {
return err
}
err = q.DeleteAllProjectRequirementStatsByStat(ctx, stat.ID)
if err != nil {
return err
}
// TODO: delete from Sprints
return tx.Commit()
}
func (r *statsRepository) rowToStat(row mysqlcore.GetStatRow) *models.Stat {
stat := models.Stat{
StatEntry: models.StatEntry{
ID: row.ID,
Name: row.Name,
Weight: row.Weight,
},
Description: row.Description,
AllowedAmounts: nil,
}
if row.AllowedAmounts.Valid {
stat.AllowedAmounts = make(map[string]int)
_ = json.Unmarshal(row.AllowedAmounts.RawMessage, &stat)
if len(stat.AllowedAmounts) == 0 {
stat.AllowedAmounts = nil
}
}
return &stat
}
+32
View File
@@ -64,3 +64,35 @@ type Project struct {
Description string `json:"description"` Description string `json:"description"`
Requirements []ProjectRequirement `json:"requirements"` Requirements []ProjectRequirement `json:"requirements"`
} }
func (project *Project) Update(update ProjectUpdate) {
if update.OwnerID != nil {
project.OwnerID = *update.OwnerID
}
if update.Name != nil {
project.Name = *update.Name
}
if update.Description != nil {
project.Description = *update.Description
}
if update.Status != nil {
project.Status = *update.Status
}
}
func (project *Project) Requirement(id int) *ProjectRequirement {
for i, requirement := range project.Requirements {
if requirement.ID == id {
return &project.Requirements[i]
}
}
return nil
}
type ProjectUpdate struct {
Name *string `json:"name,omitempty"`
OwnerID *string `json:"ownerId,omitempty"`
Status *Status `json:"status,omitempty"`
Description *string `json:"description,omitempty"`
}
+33 -1
View File
@@ -20,6 +20,38 @@ type Stat struct {
AllowedAmounts map[string]int `json:"allowedAmounts"` AllowedAmounts map[string]int `json:"allowedAmounts"`
} }
func (stat *Stat) Update(update StatUpdate) {
if update.Name != nil {
stat.Name = *update.Name
}
if update.Description != nil {
stat.Description = *update.Description
}
if update.Weight != nil {
stat.Weight = *update.Weight
}
for key, value := range update.AllowedAmounts {
if stat.AllowedAmounts == nil {
stat.AllowedAmounts = make(map[string]int, len(update.AllowedAmounts))
}
if value <= 0 {
delete(stat.AllowedAmounts, key)
} else {
stat.AllowedAmounts[key] = value
}
}
if len(stat.AllowedAmounts) == 0 {
stat.AllowedAmounts = nil
}
}
type StatUpdate struct {
Name *string `json:"name"`
Description *string `json:"description"`
Weight *float64 `json:"weight"`
AllowedAmounts map[string]int `json:"allowedAmounts"`
}
func (stat *Stat) AllowsAmount(amount int) bool { func (stat *Stat) AllowsAmount(amount int) bool {
if stat == nil { if stat == nil {
return false return false
@@ -35,4 +67,4 @@ func (stat *Stat) AllowsAmount(amount int) bool {
} }
return false return false
} }
+1 -1
View File
@@ -32,5 +32,5 @@ func (n NullRawMessage) Value() (driver.Value, error) {
return nil, nil return nil, nil
} }
return n.RawMessage, nil return []byte(n.RawMessage), nil
} }