Browse Source

fill out a lot of db functions.

master
Gisle Aune 2 years ago
parent
commit
dc0619ebdf
  1. 27
      entities/scope.go
  2. 5
      entities/sprint.go
  3. 1
      entities/stat.go
  4. 1
      models/item.go
  5. 5
      models/scope.go
  6. 16
      ports/httpapi/items.go
  7. 2
      ports/httpapi/scopes.go
  8. 37
      ports/mysql/db.go
  9. 76
      ports/mysql/items.go
  10. 140
      ports/mysql/mysqlcore/db.go
  11. 29
      ports/mysql/mysqlcore/items.sql.go
  12. 27
      ports/mysql/mysqlcore/projects.sql.go
  13. 12
      ports/mysql/mysqlcore/scopes.sql.go
  14. 247
      ports/mysql/mysqlcore/sprint.sql.go
  15. 9
      ports/mysql/mysqlcore/stats.sql.go
  16. 7
      ports/mysql/queries/items.sql
  17. 9
      ports/mysql/queries/projects.sql
  18. 4
      ports/mysql/queries/scopes.sql
  19. 40
      ports/mysql/queries/sprint.sql
  20. 3
      ports/mysql/queries/stats.sql
  21. 83
      ports/mysql/scopes.go
  22. 126
      ports/mysql/sprint.go
  23. 57
      ports/mysql/stats.go
  24. 25
      usecases/items/service.go
  25. 16
      usecases/projects/result.go
  26. 2
      usecases/scopes/context.go
  27. 32
      usecases/scopes/result.go
  28. 4
      usecases/scopes/service.go
  29. 17
      usecases/sprints/repository.go

27
entities/scope.go

@ -1,5 +1,9 @@
package entities
import (
"git.aiterp.net/stufflog3/stufflog3/models"
)
type Scope struct {
ID int `json:"id"`
Name string `json:"name"`
@ -7,6 +11,29 @@ type Scope struct {
CustomLabels map[string]string `json:"customLabels"`
}
func (scope *Scope) ApplyUpdate(update models.ScopeUpdate) {
if update.Name != nil {
scope.Name = *update.Name
}
if update.Abbreviation != nil {
scope.Abbreviation = *update.Abbreviation
}
if scope.CustomLabels == nil {
scope.CustomLabels = make(map[string]string)
}
for key, value := range update.CustomLabels {
if value == nil {
delete(scope.CustomLabels, key)
} else {
scope.CustomLabels[key] = *value
}
}
if len(scope.CustomLabels) == 0 {
scope.CustomLabels = nil
}
}
type ScopeMember struct {
ScopeID int `json:"scopeId"`
UserID string `json:"userId"`

5
entities/sprint.go

@ -19,9 +19,8 @@ type Sprint struct {
IsCoarse bool `json:"isCoarse"`
IsUnweighted bool `json:"isUnweighted"`
AggregateName string `json:"aggregateName"`
AggregateAcquired float64 `json:"aggregateAcquired"`
AggregateRequired int `json:"aggregateRequired"`
AggregateName string `json:"aggregateName"`
AggregateRequired int `json:"aggregateRequired"`
}
// SprintPart is not meant for the frontend, but it can be submitted.

1
entities/stat.go

@ -4,6 +4,7 @@ import "git.aiterp.net/stufflog3/stufflog3/models"
type Stat struct {
ID int `json:"id"`
ScopeID int `json:"scopeId"`
Name string `json:"name"`
Weight float64 `json:"weight"`
Description string `json:"description"`

1
models/item.go

@ -22,5 +22,6 @@ type ItemFilter struct {
ScopeIDs []int `json:"scopeIds,omitempty"`
ProjectIDs []int `json:"projectIds,omitempty"`
RequirementIDs []int `json:"requirementIds,omitempty"`
StatIDs []int `json:"statIds,omitempty"`
Loose bool `json:"loose,omitempty"`
}

5
models/scope.go

@ -1,6 +1,7 @@
package models
type ScopeUpdate struct {
Name *string
Abbreviation *string
Name *string `json:"name"`
Abbreviation *string `json:"abbreviation"`
CustomLabels map[string]*string `json:"customLabels"`
}

16
ports/httpapi/items.go

@ -154,6 +154,22 @@ func Items(g *gin.RouterGroup, items *items.Service) {
}
}
if statID := c.Query("statId"); statID != "" {
ids := strings.Split(statID, ",")
for _, id := range ids {
parsed, err := strconv.Atoi(id)
if err != nil {
return nil, models.BadInputError{
Object: "Query",
Field: fmt.Sprintf("statId[%d]", len(filter.StatIDs)),
Problem: "Invalid number",
}
}
filter.StatIDs = append(filter.StatIDs, parsed)
}
}
return items.ListScoped(c.Request.Context(), filter)
}))
}

2
ports/httpapi/scopes.go

@ -61,7 +61,7 @@ func ScopeMiddleware(scopes *scopes.Service, auth *auth.Service) gin.HandlerFunc
return
}
c.Request = c.Request.WithContext(scopes.CreateContext(c.Request.Context(), userID, *scope))
c.Request = c.Request.WithContext(scopes.CreateContext(c.Request.Context(), userID, *scope, members))
}
}

37
ports/mysql/db.go

@ -3,8 +3,11 @@ package mysql
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"git.aiterp.net/stufflog3/stufflog3/models"
"git.aiterp.net/stufflog3/stufflog3/ports/mysql/mysqlcore"
"git.aiterp.net/stufflog3/stufflog3/ports/mysql/sqltypes"
"git.aiterp.net/stufflog3/stufflog3/usecases/items"
"git.aiterp.net/stufflog3/stufflog3/usecases/projects"
"git.aiterp.net/stufflog3/stufflog3/usecases/scopes"
@ -88,3 +91,37 @@ func intPtr(nullInt32 sql.NullInt32) *int {
return nil
}
}
func sqlTimePtr(ptr *time.Time) sql.NullTime {
if ptr != nil {
return sql.NullTime{Time: *ptr, Valid: true}
} else {
return sql.NullTime{Valid: false}
}
}
func sqlDatePtr(ptr *models.Date) sqltypes.NullDate {
if ptr != nil {
return sqltypes.NullDate{Date: *ptr, Valid: true}
} else {
return sqltypes.NullDate{Valid: false}
}
}
func sqlIntPtr(ptr *int) sql.NullInt32 {
if ptr != nil {
return sql.NullInt32{Int32: int32(*ptr), Valid: true}
} else {
return sql.NullInt32{Valid: false}
}
}
func sqlJsonPtr(ptr interface{}) sqltypes.NullRawMessage {
if ptr != nil {
j, err := json.Marshal(ptr)
return sqltypes.NullRawMessage{RawMessage: j, Valid: err == nil}
} else {
return sqltypes.NullRawMessage{Valid: false}
}
}

76
ports/mysql/items.go

@ -17,8 +17,23 @@ type itemRepository struct {
}
func (r *itemRepository) Find(ctx context.Context, scopeID, itemID int) (*entities.Item, error) {
//TODO implement me
panic("implement me")
row, err := r.q.GetItem(ctx, mysqlcore.GetItemParams{ScopeID: scopeID, ID: itemID})
if err != nil {
return nil, err
}
return &entities.Item{
ID: row.ID,
ScopeID: row.ScopeID,
OwnerID: row.OwnerID,
ProjectID: intPtr(row.ProjectID),
ProjectRequirementID: intPtr(row.ProjectRequirementID),
Name: row.Name,
Description: row.Description,
CreatedTime: row.CreatedTime,
AcquiredTime: timePtr(row.AcquiredTime),
ScheduledDate: row.ScheduledDate.AsPtr(),
}, nil
}
func (r *itemRepository) Fetch(ctx context.Context, filter models.ItemFilter) ([]entities.Item, error) {
@ -32,6 +47,9 @@ func (r *itemRepository) Fetch(ctx context.Context, filter models.ItemFilter) ([
if filter.RequirementIDs != nil && len(filter.RequirementIDs) == 0 {
return []entities.Item{}, nil
}
if filter.StatIDs != nil && len(filter.StatIDs) == 0 {
return []entities.Item{}, nil
}
sq := squirrel.Select(
"i.id, i.scope_id, i.project_requirement_id, pr.project_id, i.owner_id, i.name," +
@ -70,6 +88,10 @@ func (r *itemRepository) Fetch(ctx context.Context, filter models.ItemFilter) ([
if len(filter.ProjectIDs) > 0 {
sq = sq.Where(squirrel.Eq{"pr.project_id": filter.ProjectIDs})
}
if len(filter.StatIDs) > 0 {
sq = sq.RightJoin("item_stat_progress isp ON isp.item_id = i.id")
sq = sq.Where(squirrel.Eq{"isp.stat_id": filter.StatIDs})
}
if filter.OwnerID != nil {
sq = sq.Where(squirrel.Eq{"i.owner_id": filter.OwnerID})
}
@ -131,18 +153,44 @@ func (r *itemRepository) Fetch(ctx context.Context, filter models.ItemFilter) ([
}
func (r *itemRepository) Insert(ctx context.Context, item entities.Item) (*entities.Item, error) {
//TODO implement me
panic("implement me")
res, err := r.q.InsertItem(ctx, mysqlcore.InsertItemParams{
ScopeID: item.ScopeID,
ProjectRequirementID: sql.NullInt32{},
Name: item.Name,
Description: item.Description,
CreatedTime: item.CreatedTime,
OwnerID: item.OwnerID,
AcquiredTime: sqlTimePtr(item.AcquiredTime),
ScheduledDate: sqlDatePtr(item.ScheduledDate),
})
if err != nil {
return nil, err
}
id, err := res.LastInsertId()
if err != nil {
return nil, err
}
item.ID = int(id)
return &item, nil
}
func (r *itemRepository) Update(ctx context.Context, item entities.Item, update models.ItemUpdate) error {
//TODO implement me
panic("implement me")
item.ApplyUpdate(update)
return r.q.UpdateItem(ctx, mysqlcore.UpdateItemParams{
ProjectRequirementID: sqlIntPtr(item.ProjectRequirementID),
Name: item.Name,
Description: item.Description,
AcquiredTime: sqlTimePtr(item.AcquiredTime),
ScheduledDate: sqlDatePtr(item.ScheduledDate),
OwnerID: item.OwnerID,
ID: item.ID,
})
}
func (r *itemRepository) Delete(ctx context.Context, item entities.Item) error {
//TODO implement me
panic("implement me")
return r.q.DeleteItem(ctx, item.ID)
}
func (r *itemRepository) ListProgress(ctx context.Context, items ...entities.Item) ([]entities.ItemProgress, error) {
@ -185,6 +233,14 @@ func (r *itemRepository) ListProgress(ctx context.Context, items ...entities.Ite
}
func (r *itemRepository) UpdateProgress(ctx context.Context, item entities.ItemProgress) error {
//TODO implement me
panic("implement me")
if item.Required <= 0 {
return r.q.DeleteItemStatProgress(ctx, mysqlcore.DeleteItemStatProgressParams{ItemID: item.ItemID, StatID: item.StatID})
}
return r.q.ReplaceItemStatProgress(ctx, mysqlcore.ReplaceItemStatProgressParams{
ItemID: item.ItemID,
StatID: item.StatID,
Acquired: item.Required,
Required: item.Acquired,
})
}

140
ports/mysql/mysqlcore/db.go

@ -30,6 +30,12 @@ func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
if q.clearItemStatProgressStmt, err = db.PrepareContext(ctx, clearItemStatProgress); err != nil {
return nil, fmt.Errorf("error preparing query ClearItemStatProgress: %w", err)
}
if q.clearItemStatProgressByStatStmt, err = db.PrepareContext(ctx, clearItemStatProgressByStat); err != nil {
return nil, fmt.Errorf("error preparing query ClearItemStatProgressByStat: %w", err)
}
if q.clearProjectRequirementStatsByStatStmt, err = db.PrepareContext(ctx, clearProjectRequirementStatsByStat); err != nil {
return nil, fmt.Errorf("error preparing query ClearProjectRequirementStatsByStat: %w", err)
}
if q.deleteAllItemStatProgressByStatIdStmt, err = db.PrepareContext(ctx, deleteAllItemStatProgressByStatId); err != nil {
return nil, fmt.Errorf("error preparing query DeleteAllItemStatProgressByStatId: %w", err)
}
@ -42,9 +48,24 @@ func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
if q.deleteAllProjectRequirementsStmt, err = db.PrepareContext(ctx, deleteAllProjectRequirements); err != nil {
return nil, fmt.Errorf("error preparing query DeleteAllProjectRequirements: %w", err)
}
if q.deleteAllScopeItemsStmt, err = db.PrepareContext(ctx, deleteAllScopeItems); err != nil {
return nil, fmt.Errorf("error preparing query DeleteAllScopeItems: %w", err)
}
if q.deleteAllScopeMembersStmt, err = db.PrepareContext(ctx, deleteAllScopeMembers); err != nil {
return nil, fmt.Errorf("error preparing query DeleteAllScopeMembers: %w", err)
}
if q.deleteAllScopeProjectRequirementsStmt, err = db.PrepareContext(ctx, deleteAllScopeProjectRequirements); err != nil {
return nil, fmt.Errorf("error preparing query DeleteAllScopeProjectRequirements: %w", err)
}
if q.deleteAllScopeProjectsStmt, err = db.PrepareContext(ctx, deleteAllScopeProjects); err != nil {
return nil, fmt.Errorf("error preparing query DeleteAllScopeProjects: %w", err)
}
if q.deleteAllScopeSprintsStmt, err = db.PrepareContext(ctx, deleteAllScopeSprints); err != nil {
return nil, fmt.Errorf("error preparing query DeleteAllScopeSprints: %w", err)
}
if q.deleteAllScopeStatsStmt, err = db.PrepareContext(ctx, deleteAllScopeStats); err != nil {
return nil, fmt.Errorf("error preparing query DeleteAllScopeStats: %w", err)
}
if q.deleteItemStmt, err = db.PrepareContext(ctx, deleteItem); err != nil {
return nil, fmt.Errorf("error preparing query DeleteItem: %w", err)
}
@ -69,6 +90,9 @@ func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
if q.deleteScopeMemberStmt, err = db.PrepareContext(ctx, deleteScopeMember); err != nil {
return nil, fmt.Errorf("error preparing query DeleteScopeMember: %w", err)
}
if q.deleteSprintStmt, err = db.PrepareContext(ctx, deleteSprint); err != nil {
return nil, fmt.Errorf("error preparing query DeleteSprint: %w", err)
}
if q.deleteStatStmt, err = db.PrepareContext(ctx, deleteStat); err != nil {
return nil, fmt.Errorf("error preparing query DeleteStat: %w", err)
}
@ -84,6 +108,9 @@ func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
if q.getScopeStmt, err = db.PrepareContext(ctx, getScope); err != nil {
return nil, fmt.Errorf("error preparing query GetScope: %w", err)
}
if q.getSprintStmt, err = db.PrepareContext(ctx, getSprint); err != nil {
return nil, fmt.Errorf("error preparing query GetSprint: %w", err)
}
if q.getStatStmt, err = db.PrepareContext(ctx, getStat); err != nil {
return nil, fmt.Errorf("error preparing query GetStat: %w", err)
}
@ -99,6 +126,9 @@ func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
if q.insertScopeStmt, err = db.PrepareContext(ctx, insertScope); err != nil {
return nil, fmt.Errorf("error preparing query InsertScope: %w", err)
}
if q.insertSprintStmt, err = db.PrepareContext(ctx, insertSprint); err != nil {
return nil, fmt.Errorf("error preparing query InsertSprint: %w", err)
}
if q.insertStatStmt, err = db.PrepareContext(ctx, insertStat); err != nil {
return nil, fmt.Errorf("error preparing query InsertStat: %w", err)
}
@ -153,6 +183,12 @@ func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
if q.listScopesByUserStmt, err = db.PrepareContext(ctx, listScopesByUser); err != nil {
return nil, fmt.Errorf("error preparing query ListScopesByUser: %w", err)
}
if q.listSprintsAtStmt, err = db.PrepareContext(ctx, listSprintsAt); err != nil {
return nil, fmt.Errorf("error preparing query ListSprintsAt: %w", err)
}
if q.listSprintsBetweenStmt, err = db.PrepareContext(ctx, listSprintsBetween); err != nil {
return nil, fmt.Errorf("error preparing query ListSprintsBetween: %w", err)
}
if q.listStatsStmt, err = db.PrepareContext(ctx, listStats); err != nil {
return nil, fmt.Errorf("error preparing query ListStats: %w", err)
}
@ -177,6 +213,9 @@ func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
if q.updateScopeStmt, err = db.PrepareContext(ctx, updateScope); err != nil {
return nil, fmt.Errorf("error preparing query UpdateScope: %w", err)
}
if q.updateSprintStmt, err = db.PrepareContext(ctx, updateSprint); err != nil {
return nil, fmt.Errorf("error preparing query UpdateSprint: %w", err)
}
if q.updateStatStmt, err = db.PrepareContext(ctx, updateStat); err != nil {
return nil, fmt.Errorf("error preparing query UpdateStat: %w", err)
}
@ -195,6 +234,16 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing clearItemStatProgressStmt: %w", cerr)
}
}
if q.clearItemStatProgressByStatStmt != nil {
if cerr := q.clearItemStatProgressByStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing clearItemStatProgressByStatStmt: %w", cerr)
}
}
if q.clearProjectRequirementStatsByStatStmt != nil {
if cerr := q.clearProjectRequirementStatsByStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing clearProjectRequirementStatsByStatStmt: %w", cerr)
}
}
if q.deleteAllItemStatProgressByStatIdStmt != nil {
if cerr := q.deleteAllItemStatProgressByStatIdStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteAllItemStatProgressByStatIdStmt: %w", cerr)
@ -215,11 +264,36 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing deleteAllProjectRequirementsStmt: %w", cerr)
}
}
if q.deleteAllScopeItemsStmt != nil {
if cerr := q.deleteAllScopeItemsStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteAllScopeItemsStmt: %w", cerr)
}
}
if q.deleteAllScopeMembersStmt != nil {
if cerr := q.deleteAllScopeMembersStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteAllScopeMembersStmt: %w", cerr)
}
}
if q.deleteAllScopeProjectRequirementsStmt != nil {
if cerr := q.deleteAllScopeProjectRequirementsStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteAllScopeProjectRequirementsStmt: %w", cerr)
}
}
if q.deleteAllScopeProjectsStmt != nil {
if cerr := q.deleteAllScopeProjectsStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteAllScopeProjectsStmt: %w", cerr)
}
}
if q.deleteAllScopeSprintsStmt != nil {
if cerr := q.deleteAllScopeSprintsStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteAllScopeSprintsStmt: %w", cerr)
}
}
if q.deleteAllScopeStatsStmt != nil {
if cerr := q.deleteAllScopeStatsStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteAllScopeStatsStmt: %w", cerr)
}
}
if q.deleteItemStmt != nil {
if cerr := q.deleteItemStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteItemStmt: %w", cerr)
@ -260,6 +334,11 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing deleteScopeMemberStmt: %w", cerr)
}
}
if q.deleteSprintStmt != nil {
if cerr := q.deleteSprintStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteSprintStmt: %w", cerr)
}
}
if q.deleteStatStmt != nil {
if cerr := q.deleteStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteStatStmt: %w", cerr)
@ -285,6 +364,11 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing getScopeStmt: %w", cerr)
}
}
if q.getSprintStmt != nil {
if cerr := q.getSprintStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing getSprintStmt: %w", cerr)
}
}
if q.getStatStmt != nil {
if cerr := q.getStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing getStatStmt: %w", cerr)
@ -310,6 +394,11 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing insertScopeStmt: %w", cerr)
}
}
if q.insertSprintStmt != nil {
if cerr := q.insertSprintStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing insertSprintStmt: %w", cerr)
}
}
if q.insertStatStmt != nil {
if cerr := q.insertStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing insertStatStmt: %w", cerr)
@ -400,6 +489,16 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing listScopesByUserStmt: %w", cerr)
}
}
if q.listSprintsAtStmt != nil {
if cerr := q.listSprintsAtStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing listSprintsAtStmt: %w", cerr)
}
}
if q.listSprintsBetweenStmt != nil {
if cerr := q.listSprintsBetweenStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing listSprintsBetweenStmt: %w", cerr)
}
}
if q.listStatsStmt != nil {
if cerr := q.listStatsStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing listStatsStmt: %w", cerr)
@ -440,6 +539,11 @@ func (q *Queries) Close() error {
err = fmt.Errorf("error closing updateScopeStmt: %w", cerr)
}
}
if q.updateSprintStmt != nil {
if cerr := q.updateSprintStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing updateSprintStmt: %w", cerr)
}
}
if q.updateStatStmt != nil {
if cerr := q.updateStatStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing updateStatStmt: %w", cerr)
@ -486,11 +590,18 @@ type Queries struct {
tx *sql.Tx
clearItemProjectRequirementStmt *sql.Stmt
clearItemStatProgressStmt *sql.Stmt
clearItemStatProgressByStatStmt *sql.Stmt
clearProjectRequirementStatsByStatStmt *sql.Stmt
deleteAllItemStatProgressByStatIdStmt *sql.Stmt
deleteAllProjectRequirementStatByStatIdStmt *sql.Stmt
deleteAllProjectRequirementStatsStmt *sql.Stmt
deleteAllProjectRequirementsStmt *sql.Stmt
deleteAllScopeItemsStmt *sql.Stmt
deleteAllScopeMembersStmt *sql.Stmt
deleteAllScopeProjectRequirementsStmt *sql.Stmt
deleteAllScopeProjectsStmt *sql.Stmt
deleteAllScopeSprintsStmt *sql.Stmt
deleteAllScopeStatsStmt *sql.Stmt
deleteItemStmt *sql.Stmt
deleteItemForRequirementStmt *sql.Stmt
deleteItemStatProgressStmt *sql.Stmt
@ -499,16 +610,19 @@ type Queries struct {
deleteProjectRequirementStatStmt *sql.Stmt
deleteScopeStmt *sql.Stmt
deleteScopeMemberStmt *sql.Stmt
deleteSprintStmt *sql.Stmt
deleteStatStmt *sql.Stmt
getItemStmt *sql.Stmt
getItemStatProgressBetweenStmt *sql.Stmt
getProjectStmt *sql.Stmt
getScopeStmt *sql.Stmt
getSprintStmt *sql.Stmt
getStatStmt *sql.Stmt
insertItemStmt *sql.Stmt
insertProjectStmt *sql.Stmt
insertProjectRequirementStmt *sql.Stmt
insertScopeStmt *sql.Stmt
insertSprintStmt *sql.Stmt
insertStatStmt *sql.Stmt
listItemStatProgressStmt *sql.Stmt
listItemStatProgressMultiStmt *sql.Stmt
@ -527,6 +641,8 @@ type Queries struct {
listScopeMembersMultiStmt *sql.Stmt
listScopesStmt *sql.Stmt
listScopesByUserStmt *sql.Stmt
listSprintsAtStmt *sql.Stmt
listSprintsBetweenStmt *sql.Stmt
listStatsStmt *sql.Stmt
replaceItemStatProgressStmt *sql.Stmt
replaceProjectRequirementStatStmt *sql.Stmt
@ -535,20 +651,28 @@ type Queries struct {
updateProjectStmt *sql.Stmt
updateProjectRequirementStmt *sql.Stmt
updateScopeStmt *sql.Stmt
updateSprintStmt *sql.Stmt
updateStatStmt *sql.Stmt
}
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
return &Queries{
db: tx,
tx: tx,
clearItemProjectRequirementStmt: q.clearItemProjectRequirementStmt,
clearItemStatProgressStmt: q.clearItemStatProgressStmt,
deleteAllItemStatProgressByStatIdStmt: q.deleteAllItemStatProgressByStatIdStmt,
db: tx,
tx: tx,
clearItemProjectRequirementStmt: q.clearItemProjectRequirementStmt,
clearItemStatProgressStmt: q.clearItemStatProgressStmt,
clearItemStatProgressByStatStmt: q.clearItemStatProgressByStatStmt,
clearProjectRequirementStatsByStatStmt: q.clearProjectRequirementStatsByStatStmt,
deleteAllItemStatProgressByStatIdStmt: q.deleteAllItemStatProgressByStatIdStmt,
deleteAllProjectRequirementStatByStatIdStmt: q.deleteAllProjectRequirementStatByStatIdStmt,
deleteAllProjectRequirementStatsStmt: q.deleteAllProjectRequirementStatsStmt,
deleteAllProjectRequirementsStmt: q.deleteAllProjectRequirementsStmt,
deleteAllScopeItemsStmt: q.deleteAllScopeItemsStmt,
deleteAllScopeMembersStmt: q.deleteAllScopeMembersStmt,
deleteAllScopeProjectRequirementsStmt: q.deleteAllScopeProjectRequirementsStmt,
deleteAllScopeProjectsStmt: q.deleteAllScopeProjectsStmt,
deleteAllScopeSprintsStmt: q.deleteAllScopeSprintsStmt,
deleteAllScopeStatsStmt: q.deleteAllScopeStatsStmt,
deleteItemStmt: q.deleteItemStmt,
deleteItemForRequirementStmt: q.deleteItemForRequirementStmt,
deleteItemStatProgressStmt: q.deleteItemStatProgressStmt,
@ -557,16 +681,19 @@ func (q *Queries) WithTx(tx *sql.Tx) *Queries {
deleteProjectRequirementStatStmt: q.deleteProjectRequirementStatStmt,
deleteScopeStmt: q.deleteScopeStmt,
deleteScopeMemberStmt: q.deleteScopeMemberStmt,
deleteSprintStmt: q.deleteSprintStmt,
deleteStatStmt: q.deleteStatStmt,
getItemStmt: q.getItemStmt,
getItemStatProgressBetweenStmt: q.getItemStatProgressBetweenStmt,
getProjectStmt: q.getProjectStmt,
getScopeStmt: q.getScopeStmt,
getSprintStmt: q.getSprintStmt,
getStatStmt: q.getStatStmt,
insertItemStmt: q.insertItemStmt,
insertProjectStmt: q.insertProjectStmt,
insertProjectRequirementStmt: q.insertProjectRequirementStmt,
insertScopeStmt: q.insertScopeStmt,
insertSprintStmt: q.insertSprintStmt,
insertStatStmt: q.insertStatStmt,
listItemStatProgressStmt: q.listItemStatProgressStmt,
listItemStatProgressMultiStmt: q.listItemStatProgressMultiStmt,
@ -585,6 +712,8 @@ func (q *Queries) WithTx(tx *sql.Tx) *Queries {
listScopeMembersMultiStmt: q.listScopeMembersMultiStmt,
listScopesStmt: q.listScopesStmt,
listScopesByUserStmt: q.listScopesByUserStmt,
listSprintsAtStmt: q.listSprintsAtStmt,
listSprintsBetweenStmt: q.listSprintsBetweenStmt,
listStatsStmt: q.listStatsStmt,
replaceItemStatProgressStmt: q.replaceItemStatProgressStmt,
replaceProjectRequirementStatStmt: q.replaceProjectRequirementStatStmt,
@ -593,6 +722,7 @@ func (q *Queries) WithTx(tx *sql.Tx) *Queries {
updateProjectStmt: q.updateProjectStmt,
updateProjectRequirementStmt: q.updateProjectRequirementStmt,
updateScopeStmt: q.updateScopeStmt,
updateSprintStmt: q.updateSprintStmt,
updateStatStmt: q.updateStatStmt,
}
}

29
ports/mysql/mysqlcore/items.sql.go

@ -22,6 +22,24 @@ func (q *Queries) ClearItemStatProgress(ctx context.Context, itemID int) error {
return err
}
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 deleteAllScopeItems = `-- name: DeleteAllScopeItems :exec
DELETE FROM item WHERE scope_id = ?
`
func (q *Queries) DeleteAllScopeItems(ctx context.Context, scopeID int) error {
_, err := q.exec(ctx, q.deleteAllScopeItemsStmt, deleteAllScopeItems, scopeID)
return err
}
const deleteItem = `-- name: DeleteItem :exec
DELETE FROM item WHERE id = ?
`
@ -57,9 +75,14 @@ func (q *Queries) DeleteItemStatProgress(ctx context.Context, arg DeleteItemStat
const getItem = `-- name: GetItem :one
SELECT i.id, i.scope_id, i.project_requirement_id, i.owner_id, i.name, i.description, i.created_time, i.acquired_time, i.scheduled_date, pr.project_id FROM item i
LEFT JOIN project_requirement pr ON pr.id = i.project_requirement_id
WHERE i.id = ?
WHERE i.id = ? and i.scope_id = ?
`
type GetItemParams struct {
ID int
ScopeID int
}
type GetItemRow struct {
ID int
ScopeID int
@ -73,8 +96,8 @@ type GetItemRow struct {
ProjectID sql.NullInt32
}
func (q *Queries) GetItem(ctx context.Context, id int) (GetItemRow, error) {
row := q.queryRow(ctx, q.getItemStmt, getItem, id)
func (q *Queries) GetItem(ctx context.Context, arg GetItemParams) (GetItemRow, error) {
row := q.queryRow(ctx, q.getItemStmt, getItem, arg.ID, arg.ScopeID)
var i GetItemRow
err := row.Scan(
&i.ID,

27
ports/mysql/mysqlcore/projects.sql.go

@ -21,6 +21,15 @@ func (q *Queries) ClearItemProjectRequirement(ctx context.Context, projectRequir
return err
}
const clearProjectRequirementStatsByStat = `-- name: ClearProjectRequirementStatsByStat :exec
DELETE FROM project_requirement_stat WHERE stat_id = ?
`
func (q *Queries) ClearProjectRequirementStatsByStat(ctx context.Context, statID int) error {
_, err := q.exec(ctx, q.clearProjectRequirementStatsByStatStmt, clearProjectRequirementStatsByStat, statID)
return err
}
const deleteAllProjectRequirementStats = `-- name: DeleteAllProjectRequirementStats :exec
DELETE FROM project_requirement_stat WHERE project_requirement_id = ?
`
@ -39,6 +48,24 @@ func (q *Queries) DeleteAllProjectRequirements(ctx context.Context, projectID in
return err
}
const deleteAllScopeProjectRequirements = `-- name: DeleteAllScopeProjectRequirements :exec
DELETE FROM project_requirement WHERE scope_id = ?
`
func (q *Queries) DeleteAllScopeProjectRequirements(ctx context.Context, scopeID int) error {
_, err := q.exec(ctx, q.deleteAllScopeProjectRequirementsStmt, deleteAllScopeProjectRequirements, scopeID)
return err
}
const deleteAllScopeProjects = `-- name: DeleteAllScopeProjects :exec
DELETE FROM project WHERE scope_id = ?
`
func (q *Queries) DeleteAllScopeProjects(ctx context.Context, scopeID int) error {
_, err := q.exec(ctx, q.deleteAllScopeProjectsStmt, deleteAllScopeProjects, scopeID)
return err
}
const deleteProject = `-- name: DeleteProject :exec
DELETE FROM project WHERE id = ? AND scope_id = ?
`

12
ports/mysql/mysqlcore/scopes.sql.go

@ -62,24 +62,18 @@ func (q *Queries) GetScope(ctx context.Context, id int) (Scope, error) {
}
const insertScope = `-- name: InsertScope :execresult
INSERT INTO scope (id, name, abbreviation, custom_labels)
VALUES (?, ?, ?, ?)
INSERT INTO scope (name, abbreviation, custom_labels)
VALUES (?, ?, ?)
`
type InsertScopeParams struct {
ID int
Name string
Abbreviation string
CustomLabels sqltypes.NullRawMessage
}
func (q *Queries) InsertScope(ctx context.Context, arg InsertScopeParams) (sql.Result, error) {
return q.exec(ctx, q.insertScopeStmt, insertScope,
arg.ID,
arg.Name,
arg.Abbreviation,
arg.CustomLabels,
)
return q.exec(ctx, q.insertScopeStmt, insertScope, arg.Name, arg.Abbreviation, arg.CustomLabels)
}
const listScopeMembers = `-- name: ListScopeMembers :many

247
ports/mysql/mysqlcore/sprint.sql.go

@ -0,0 +1,247 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.13.0
// source: sprint.sql
package mysqlcore
import (
"context"
"database/sql"
"time"
)
const deleteAllScopeSprints = `-- name: DeleteAllScopeSprints :exec
DELETE FROM sprint WHERE scope_id = ?
`
func (q *Queries) DeleteAllScopeSprints(ctx context.Context, scopeID int) error {
_, err := q.exec(ctx, q.deleteAllScopeSprintsStmt, deleteAllScopeSprints, scopeID)
return err
}
const deleteSprint = `-- name: DeleteSprint :exec
DELETE FROM sprint WHERE id = ?
`
func (q *Queries) DeleteSprint(ctx context.Context, id int) error {
_, err := q.exec(ctx, q.deleteSprintStmt, deleteSprint, id)
return err
}
const getSprint = `-- name: GetSprint :one
SELECT id, scope_id, name, description, from_time, to_time, is_timed, is_coarse, is_unweighted, kind, aggregate_name, aggregate_required FROM sprint WHERE id = ? AND scope_id = ?
`
type GetSprintParams struct {
ID int
ScopeID int
}
func (q *Queries) GetSprint(ctx context.Context, arg GetSprintParams) (Sprint, error) {
row := q.queryRow(ctx, q.getSprintStmt, getSprint, arg.ID, arg.ScopeID)
var i Sprint
err := row.Scan(
&i.ID,
&i.ScopeID,
&i.Name,
&i.Description,
&i.FromTime,
&i.ToTime,
&i.IsTimed,
&i.IsCoarse,
&i.IsUnweighted,
&i.Kind,
&i.AggregateName,
&i.AggregateRequired,
)
return i, err
}
const insertSprint = `-- name: InsertSprint :execresult
INSERT INTO sprint (
scope_id, name, description, kind, from_time, to_time,
is_timed, is_coarse, aggregate_name, aggregate_required, is_unweighted
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`
type InsertSprintParams struct {
ScopeID int
Name string
Description string
Kind int
FromTime time.Time
ToTime time.Time
IsTimed bool
IsCoarse bool
AggregateName string
AggregateRequired int
IsUnweighted bool
}
func (q *Queries) InsertSprint(ctx context.Context, arg InsertSprintParams) (sql.Result, error) {
return q.exec(ctx, q.insertSprintStmt, insertSprint,
arg.ScopeID,
arg.Name,
arg.Description,
arg.Kind,
arg.FromTime,
arg.ToTime,
arg.IsTimed,
arg.IsCoarse,
arg.AggregateName,
arg.AggregateRequired,
arg.IsUnweighted,
)
}
const listSprintsAt = `-- name: ListSprintsAt :many
SELECT id, scope_id, name, description, from_time, to_time, is_timed, is_coarse, is_unweighted, kind, aggregate_name, aggregate_required FROM sprint WHERE scope_id = ? AND from_time <= ? AND to_time > ?
`
type ListSprintsAtParams struct {
ScopeID int
Time time.Time
}
func (q *Queries) ListSprintsAt(ctx context.Context, arg ListSprintsAtParams) ([]Sprint, error) {
rows, err := q.query(ctx, q.listSprintsAtStmt, listSprintsAt, arg.ScopeID, arg.Time, arg.Time)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Sprint{}
for rows.Next() {
var i Sprint
if err := rows.Scan(
&i.ID,
&i.ScopeID,
&i.Name,
&i.Description,
&i.FromTime,
&i.ToTime,
&i.IsTimed,
&i.IsCoarse,
&i.IsUnweighted,
&i.Kind,
&i.AggregateName,
&i.AggregateRequired,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listSprintsBetween = `-- name: ListSprintsBetween :many
SELECT id, scope_id, name, description, from_time, to_time, is_timed, is_coarse, is_unweighted, kind, aggregate_name, aggregate_required FROM sprint WHERE scope_id = ?
AND (
-- from time is within from..to
(from_time <= ? AND to_time > ?)
-- or to time is within from..to
OR (from_time <= ? AND to_time > ?)
-- or from and to time are on each their side of from..to
OR (from_time < ? AND to_time >= ?)
)
`
type ListSprintsBetweenParams struct {
ScopeID int
FromTime time.Time
ToTime time.Time
FromTime_2 time.Time
ToTime_2 time.Time
FromTime_3 time.Time
ToTime_3 time.Time
}
func (q *Queries) ListSprintsBetween(ctx context.Context, arg ListSprintsBetweenParams) ([]Sprint, error) {
rows, err := q.query(ctx, q.listSprintsBetweenStmt, listSprintsBetween,
arg.ScopeID,
arg.FromTime,
arg.ToTime,
arg.FromTime_2,
arg.ToTime_2,
arg.FromTime_3,
arg.ToTime_3,
)
if err != nil {
return nil, err
}
defer rows.Close()
items := []Sprint{}
for rows.Next() {
var i Sprint
if err := rows.Scan(
&i.ID,
&i.ScopeID,
&i.Name,
&i.Description,
&i.FromTime,
&i.ToTime,
&i.IsTimed,
&i.IsCoarse,
&i.IsUnweighted,
&i.Kind,
&i.AggregateName,
&i.AggregateRequired,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const updateSprint = `-- name: UpdateSprint :exec
UPDATE sprint
SET name = ?,
description = ?,
from_time = ?,
to_time = ?,
is_timed = ?,
is_coarse = ?,
aggregate_name = ?,
aggregate_required = ?
WHERE id = ?
`
type UpdateSprintParams struct {
Name string
Description string
FromTime time.Time
ToTime time.Time
IsTimed bool
IsCoarse bool
AggregateName string
AggregateRequired int
ID int
}
func (q *Queries) UpdateSprint(ctx context.Context, arg UpdateSprintParams) error {
_, err := q.exec(ctx, q.updateSprintStmt, updateSprint,
arg.Name,
arg.Description,
arg.FromTime,
arg.ToTime,
arg.IsTimed,
arg.IsCoarse,
arg.AggregateName,
arg.AggregateRequired,
arg.ID,
)
return err
}

9
ports/mysql/mysqlcore/stats.sql.go

@ -30,6 +30,15 @@ func (q *Queries) DeleteAllProjectRequirementStatByStatId(ctx context.Context, s
return err
}
const deleteAllScopeStats = `-- name: DeleteAllScopeStats :exec
DELETE FROM stat WHERE scope_id = ?
`
func (q *Queries) DeleteAllScopeStats(ctx context.Context, scopeID int) error {
_, err := q.exec(ctx, q.deleteAllScopeStatsStmt, deleteAllScopeStats, scopeID)
return err
}
const deleteStat = `-- name: DeleteStat :exec
DELETE FROM stat WHERE id = ? AND scope_id = ?
`

7
ports/mysql/queries/items.sql

@ -1,7 +1,7 @@
-- name: GetItem :one
SELECT i.*, pr.project_id FROM item i
LEFT JOIN project_requirement pr ON pr.id = i.project_requirement_id
WHERE i.id = ?;
WHERE i.id = ? and i.scope_id = ?;
-- name: ListItemsByProject :many
SELECT i.*, pr.project_id FROM item i
@ -112,3 +112,8 @@ DELETE FROM item_stat_progress WHERE item_id = ? AND stat_id = ?;
-- name: ClearItemStatProgress :exec
DELETE FROM item_stat_progress WHERE item_id = ?;
-- name: ClearItemStatProgressByStat :exec
DELETE FROM item_stat_progress WHERE stat_id = ?;
-- name: DeleteAllScopeItems :exec
DELETE FROM item WHERE scope_id = ?;

9
ports/mysql/queries/projects.sql

@ -58,3 +58,12 @@ DELETE FROM project_requirement_stat WHERE project_requirement_id = ? AND stat_i
-- name: DeleteAllProjectRequirementStats :exec
DELETE FROM project_requirement_stat WHERE project_requirement_id = ?;
-- name: ClearProjectRequirementStatsByStat :exec
DELETE FROM project_requirement_stat WHERE stat_id = ?;
-- name: DeleteAllScopeProjects :exec
DELETE FROM project WHERE scope_id = ?;
-- name: DeleteAllScopeProjectRequirements :exec
DELETE FROM project_requirement WHERE scope_id = ?;

4
ports/mysql/queries/scopes.sql

@ -23,8 +23,8 @@ WHERE scope_id IN (?, ?, ?, ?, ?, ?)
ORDER BY name;
-- name: InsertScope :execresult
INSERT INTO scope (id, name, abbreviation, custom_labels)
VALUES (?, ?, ?, ?);
INSERT INTO scope (name, abbreviation, custom_labels)
VALUES (?, ?, ?);
-- name: UpdateScope :exec
UPDATE scope SET name = ?, abbreviation = ?, custom_labels = ? WHERE id = ?;

40
ports/mysql/queries/sprint.sql

@ -0,0 +1,40 @@
-- name: ListSprintsAt :many
SELECT * FROM sprint WHERE scope_id = ? AND from_time <= sqlc.arg(time) AND to_time > sqlc.arg(time);
-- name: ListSprintsBetween :many
SELECT * FROM sprint WHERE scope_id = ?
AND (
-- from time is within from..to
(from_time <= ? AND to_time > ?)
-- or to time is within from..to
OR (from_time <= ? AND to_time > ?)
-- or from and to time are on each their side of from..to
OR (from_time < ? AND to_time >= ?)
);
-- name: GetSprint :one
SELECT * FROM sprint WHERE id = ? AND scope_id = ?;
-- name: InsertSprint :execresult
INSERT INTO sprint (
scope_id, name, description, kind, from_time, to_time,
is_timed, is_coarse, aggregate_name, aggregate_required, is_unweighted
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
-- name: UpdateSprint :exec
UPDATE sprint
SET name = ?,
description = ?,
from_time = ?,
to_time = ?,
is_timed = ?,
is_coarse = ?,
aggregate_name = ?,
aggregate_required = ?
WHERE id = ?;
-- name: DeleteSprint :exec
DELETE FROM sprint WHERE id = ?;
-- name: DeleteAllScopeSprints :exec
DELETE FROM sprint WHERE scope_id = ?;

3
ports/mysql/queries/stats.sql

@ -24,3 +24,6 @@ DELETE FROM item_stat_progress WHERE stat_id = ?;
-- name: DeleteAllProjectRequirementStatByStatId :exec
DELETE FROM project_requirement_stat WHERE stat_id = ?;
-- name: DeleteAllScopeStats :exec
DELETE FROM stat WHERE scope_id = ?;

83
ports/mysql/scopes.go

@ -94,13 +94,49 @@ func (r *scopeRepository) ListUser(ctx context.Context, userID string) ([]entiti
}
func (r *scopeRepository) Create(ctx context.Context, scope entities.Scope, ownerID string) (*entities.Scope, error) {
//TODO implement me
panic("implement me")
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return nil, err
}
defer tx.Rollback()
q := r.q.WithTx(tx)
if len(scope.CustomLabels) == 0 {
scope.CustomLabels = nil
}
res, err := q.InsertScope(ctx, mysqlcore.InsertScopeParams{
Name: scope.Name,
Abbreviation: scope.Abbreviation,
CustomLabels: sqlJsonPtr(scope.CustomLabels),
})
if err != nil {
return nil, err
}
id, err := res.LastInsertId()
if err != nil {
return nil, err
}
err = tx.Commit()
if err != nil {
return nil, err
}
scope.ID = int(id)
return &scope, nil
}
func (r *scopeRepository) Update(ctx context.Context, scope entities.Scope, update models.ScopeUpdate) error {
//TODO implement me
panic("implement me")
scope.ApplyUpdate(update)
return r.q.UpdateScope(ctx, mysqlcore.UpdateScopeParams{
Name: scope.Name,
Abbreviation: scope.Abbreviation,
CustomLabels: sqlJsonPtr(scope.CustomLabels),
ID: scope.ID,
})
}
func (r *scopeRepository) Delete(ctx context.Context, scope entities.Scope) error {
@ -111,17 +147,52 @@ func (r *scopeRepository) Delete(ctx context.Context, scope entities.Scope) erro
defer tx.Rollback()
q := r.q.WithTx(tx)
// Wipe all progress
stats, err := q.ListStats(ctx, scope.ID)
if err != nil {
return err
}
for _, stat := range stats {
err = q.ClearProjectRequirementStatsByStat(ctx, stat.ID)
if err != nil {
return err
}
err = q.ClearItemStatProgressByStat(ctx, stat.ID)
if err != nil {
return err
}
}
// Clean up scoped data
err = q.DeleteAllScopeMembers(ctx, scope.ID)
if err != nil {
return err
}
err = q.DeleteAllScopeItems(ctx, scope.ID)
if err != nil {
return err
}
err = q.DeleteAllScopeProjectRequirements(ctx, scope.ID)
if err != nil {
return err
}
err = q.DeleteAllScopeProjects(ctx, scope.ID)
if err != nil {
return err
}
err = q.DeleteAllScopeSprints(ctx, scope.ID)
if err != nil {
return err
}
err = q.DeleteAllScopeStats(ctx, scope.ID)
if err != nil {
return err
}
err = q.DeleteScope(ctx, scope.ID)
if err != nil {
return err
}
// TODO: Wipe everything
return tx.Commit()
}

126
ports/mysql/sprint.go

@ -0,0 +1,126 @@
package mysql
import (
"context"
"database/sql"
"git.aiterp.net/stufflog3/stufflog3/entities"
"git.aiterp.net/stufflog3/stufflog3/models"
"git.aiterp.net/stufflog3/stufflog3/ports/mysql/mysqlcore"
"time"
)
type sprintRepository struct {
db *sql.DB
q *mysqlcore.Queries
}
func (r *sprintRepository) Find(ctx context.Context, scopeID, sprintID int) (*entities.Sprint, error) {
row, err := r.q.GetSprint(ctx, mysqlcore.GetSprintParams{ScopeID: scopeID, ID: sprintID})
if err != nil {
if err == sql.ErrNoRows {
return nil, models.NotFoundError("Sprint")
}
return nil, err
}
return &entities.Sprint{
ID: row.ID,
ScopeID: row.ScopeID,
Name: row.Name,
Description: row.Description,
Kind: models.SprintKind(row.Kind),
FromTime: row.FromTime,
ToTime: row.ToTime,
IsTimed: row.IsTimed,
IsCoarse: row.IsCoarse,
IsUnweighted: row.IsUnweighted,
AggregateName: row.AggregateName,
AggregateRequired: row.AggregateRequired,
}, nil
}
func (r *sprintRepository) ListAt(ctx context.Context, scopeID int, at time.Time) ([]entities.Sprint, error) {
rows, err := r.q.ListSprintsAt(ctx, mysqlcore.ListSprintsAtParams{ScopeID: scopeID, Time: at})
if err != nil {
if err == sql.ErrNoRows {
return nil, models.NotFoundError("Sprint")
}
return nil, err
}
sprints := make([]entities.Sprint, 0, len(rows))
for _, row := range rows {
sprints = append(sprints, entities.Sprint{
ID: row.ID,
ScopeID: row.ScopeID,
Name: row.Name,
Description: row.Description,
Kind: models.SprintKind(row.Kind),
FromTime: row.FromTime,
ToTime: row.ToTime,
IsTimed: row.IsTimed,
IsCoarse: row.IsCoarse,
IsUnweighted: row.IsUnweighted,
AggregateName: row.AggregateName,
AggregateRequired: row.AggregateRequired,
})
}
return sprints, nil
}
func (r *sprintRepository) ListBetween(ctx context.Context, scopeID int, from, to time.Time) ([]entities.Sprint, error) {
rows, err := r.q.ListSprintsBetween(ctx, mysqlcore.ListSprintsBetweenParams{
ScopeID: scopeID,
FromTime: from,
ToTime: from,
FromTime_2: to,
ToTime_2: to,
FromTime_3: from,
ToTime_3: to,
})
if err != nil {
if err == sql.ErrNoRows {
return nil, models.NotFoundError("Sprint")
}
return nil, err
}
sprints := make([]entities.Sprint, 0, len(rows))
for _, row := range rows {
sprints = append(sprints, entities.Sprint{
ID: row.ID,
ScopeID: row.ScopeID,
Name: row.Name,
Description: row.Description,
Kind: models.SprintKind(row.Kind),
FromTime: row.FromTime,
ToTime: row.ToTime,
IsTimed: row.IsTimed,
IsCoarse: row.IsCoarse,
IsUnweighted: row.IsUnweighted,
AggregateName: row.AggregateName,
AggregateRequired: row.AggregateRequired,
})
}
return sprints, nil
}
func (r *sprintRepository) Create(ctx context.Context, sprint entities.Sprint) (*entities.Sprint, error) {
//TODO implement me
panic("implement me")
}
func (r *sprintRepository) Update(ctx context.Context, sprint entities.Sprint, update models.SprintUpdate) error {
//TODO implement me
panic("implement me")
}
func (r *sprintRepository) Delete(ctx context.Context, sprint entities.Sprint) error {
//TODO implement me
panic("implement me")
}

57
ports/mysql/stats.go

@ -35,6 +35,7 @@ func (r *statsRepository) Find(ctx context.Context, scopeID, statID int) (*entit
return &entities.Stat{
ID: row.ID,
ScopeID: row.ScopeID,
Name: row.Name,
Weight: row.Weight,
Description: row.Description,
@ -65,6 +66,7 @@ func (r *statsRepository) List(ctx context.Context, scopeID int) ([]entities.Sta
res = append(res, entities.Stat{
ID: row.ID,
ScopeID: row.ScopeID,
Name: row.Name,
Weight: row.Weight,
Description: row.Description,
@ -76,16 +78,59 @@ func (r *statsRepository) List(ctx context.Context, scopeID int) ([]entities.Sta
}
func (r *statsRepository) Insert(ctx context.Context, stat entities.Stat) (*entities.Stat, error) {
//TODO implement me
panic("implement me")
res, err := r.q.InsertStat(ctx, mysqlcore.InsertStatParams{
ScopeID: stat.ScopeID,
Name: stat.Name,
Description: stat.Description,
Weight: stat.Weight,
AllowedAmounts: sqlJsonPtr(stat.AllowedAmounts),
})
if err != nil {
return nil, err
}
id, err := res.LastInsertId()
if err != nil {
return nil, err
}
stat.ID = int(id)
return &stat, nil
}
func (r *statsRepository) Update(ctx context.Context, stat entities.Stat, update models.StatUpdate) error {
//TODO implement me
panic("implement me")
stat.Update(update)
return r.q.UpdateStat(ctx, mysqlcore.UpdateStatParams{
Name: stat.Name,
Description: stat.Description,
Weight: stat.Weight,
AllowedAmounts: sqlJsonPtr(stat.AllowedAmounts),
ID: stat.ID,
ScopeID: stat.ScopeID,
})
}
func (r *statsRepository) Delete(ctx context.Context, stat entities.Stat) error {
//TODO implement me
panic("implement me")
tx, err := r.db.BeginTx(ctx, nil)
if err != nil {
return err
}
defer tx.Rollback()
q := r.q.WithTx(tx)
err = q.ClearItemStatProgressByStat(ctx, stat.ID)
if err != nil {
return err
}
err = q.ClearProjectRequirementStatsByStat(ctx, stat.ID)
if err != nil {
return err
}
err = q.DeleteStat(ctx, mysqlcore.DeleteStatParams{ScopeID: stat.ScopeID, ID: stat.ID})
if err != nil {
return err
}
return tx.Commit()
}

25
usecases/items/service.go

@ -13,6 +13,31 @@ type Service struct {
Repository Repository
}
func (s *Service) Find(ctx context.Context, id int) (*Result, error) {
sc := s.Scopes.Context(ctx)
if sc == nil {
return nil, models.PermissionDeniedError{}
}
item, err := s.Repository.Find(ctx, sc.ID, id)
if err != nil {
return nil, err
}
progresses, err := s.Repository.ListProgress(ctx, *item)
if err != nil {
return nil, err
}
scopeStats, err := sc.Stats(ctx)
if err != nil {
return nil, err
}
result := generateResult(*item, progresses, scopeStats)
return &result, nil
}
func (s *Service) ListScoped(ctx context.Context, filter models.ItemFilter) ([]Result, error) {
sc := s.Scopes.Context(ctx)
if sc == nil {

16
usecases/projects/result.go

@ -27,19 +27,19 @@ func generateEntry(project entities.Project) Entry {
type Result struct {
entities.Project
Requirements []ResultRequirement `json:"requirements"`
Requirements []RequirementResult `json:"requirements"`
}
type ResultRequirement struct {
type RequirementResult struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Status models.Status `json:"status"`
Stats []ResultRequirementStat `json:"stats"`
Stats []RequirementResultStat `json:"stats"`
Items []items.Result `json:"items"`
}
type ResultRequirementStat struct {
type RequirementResultStat struct {
ID int `json:"id"`
Name string `json:"name"`
Weight float64 `json:"weight"`
@ -57,7 +57,7 @@ func generateResult(
) Result {
res := Result{
Project: project,
Requirements: make([]ResultRequirement, 0, 8),
Requirements: make([]RequirementResult, 0, 8),
}
for _, req := range requirement {
@ -65,12 +65,12 @@ func generateResult(
continue
}
resReq := ResultRequirement{
resReq := RequirementResult{
ID: req.ID,
Name: req.Name,
Description: req.Description,
Status: req.Status,
Stats: make([]ResultRequirementStat, 0, 8),
Stats: make([]RequirementResultStat, 0, 8),
Items: make([]items.Result, 0, 8),
}
statIndices := make(map[int]int)
@ -79,7 +79,7 @@ func generateResult(
continue
}
resStat := ResultRequirementStat{
resStat := RequirementResultStat{
ID: reqStat.StatID,
Required: reqStat.Required,
}

2
usecases/scopes/context.go

@ -12,7 +12,7 @@ type Context struct {
userID string
ID int
Scope entities.Scope
Scope Result
statsOnce sync.Once
stats []entities.Stat

32
usecases/scopes/result.go

@ -0,0 +1,32 @@
package scopes
import "git.aiterp.net/stufflog3/stufflog3/entities"
type Result struct {
entities.Scope
Members []ResultMember `json:"members"`
}
type ResultMember struct {
ID string `json:"id"`
Name string `json:"name"`
Owner bool `json:"owner"`
}
func generateResult(scope entities.Scope, members []entities.ScopeMember) Result {
res := Result{Scope: scope, Members: make([]ResultMember, 0, 2)}
for _, member := range members {
if member.ScopeID != scope.ID {
continue
}
res.Members = append(res.Members, ResultMember{
ID: member.UserID,
Name: member.Name,
Owner: member.Owner,
})
}
return res
}

4
usecases/scopes/service.go

@ -15,14 +15,14 @@ type Service struct {
contextKey struct{}
}
func (s *Service) CreateContext(ctx context.Context, userID string, scope entities.Scope) context.Context {
func (s *Service) CreateContext(ctx context.Context, userID string, scope entities.Scope, members []entities.ScopeMember) context.Context {
return context.WithValue(ctx, &s.contextKey, &Context{
scopesRepo: s.Repository,
statsRepo: s.StatsLister,
userID: userID,
ID: scope.ID,
Scope: scope,
Scope: generateResult(scope, members),
})
}

17
usecases/sprints/repository.go

@ -0,0 +1,17 @@
package sprints
import (
"context"
"git.aiterp.net/stufflog3/stufflog3/entities"
"git.aiterp.net/stufflog3/stufflog3/models"
"time"
)
type Repository interface {
Find(ctx context.Context, scopeID, sprintID int) (*entities.Sprint, error)
ListAt(ctx context.Context, scopeID int, at time.Time) ([]entities.Sprint, error)
ListBetween(ctx context.Context, scopeID int, from, to time.Time) ([]entities.Sprint, error)
Create(ctx context.Context, sprint entities.Sprint) (*entities.Sprint, error)
Update(ctx context.Context, sprint entities.Sprint, update models.SprintUpdate) error
Delete(ctx context.Context, sprint entities.Sprint) error
}
Loading…
Cancel
Save