Gisle Aune
3 years ago
23 changed files with 1831 additions and 348 deletions
-
39api/common.go
-
72api/items.go
-
2api/scope.go
-
1cmd/stufflog3-server.go
-
30internal/database/database.go
-
4internal/database/mysql/database.go
-
354internal/database/mysql/items.go
-
191internal/database/mysql/mysqlcore/db.go
-
791internal/database/mysql/mysqlcore/item.sql.go
-
84internal/database/mysql/mysqlcore/models.go
-
61internal/database/mysql/mysqlcore/project.sql.go
-
78internal/database/mysql/mysqlcore/scope.sql.go
-
12internal/database/mysql/mysqlcore/stats.sql.go
-
105internal/database/mysql/queries/item.sql
-
6internal/database/mysql/queries/project.sql
-
98internal/database/mysql/scopes.go
-
46internal/models/common.go
-
92internal/models/item.go
-
14internal/models/project.go
-
26internal/models/scope.go
-
17internal/models/stat.go
-
46internal/sqltypes/nulldate.go
-
10sqlc.yaml
@ -0,0 +1,72 @@ |
|||
package api |
|||
|
|||
import ( |
|||
"git.aiterp.net/stufflog3/stufflog3-api/internal/auth" |
|||
"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" |
|||
"time" |
|||
) |
|||
|
|||
func Items(g *gin.RouterGroup, db database.Database) { |
|||
g.Use(scopeIDMiddleware(db)) |
|||
|
|||
g.GET("/:id", handler("item", func(c *gin.Context) (interface{}, error) { |
|||
id, err := reqInt(c, "id") |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
item, err := db.Items(getScope(c).ID).Find(c.Request.Context(), id) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
for _, member := range getScope(c).Members { |
|||
if member.ID == item.OwnerID { |
|||
item.Owner = &member |
|||
} |
|||
} |
|||
|
|||
return item, nil |
|||
})) |
|||
|
|||
g.POST("/", handler("item", func(c *gin.Context) (interface{}, error) { |
|||
item := &models.Item{} |
|||
err := c.BindJSON(item) |
|||
if err != nil { |
|||
return nil, slerrors.BadRequest("Invalid JSON input: " + err.Error()) |
|||
} |
|||
|
|||
item.CreatedTime = time.Now() |
|||
|
|||
if item.Name == "" { |
|||
return nil, slerrors.BadRequest("Blank item name not allowed") |
|||
} |
|||
if item.OwnerID == "" { |
|||
item.OwnerID = auth.UserID(c) |
|||
} else if getScope(c).HasMember(item.OwnerID) { |
|||
return nil, slerrors.Forbidden("Owner is not part of scope.") |
|||
} |
|||
if item.ProjectRequirementID != nil { |
|||
// TODO: Ensure project requirement exists in scope.
|
|||
return nil, slerrors.Forbidden("TODO: check project requirement ID.") |
|||
} |
|||
for _, stat := range item.Stats { |
|||
if getScope(c).Stat(stat.ID) == nil { |
|||
return nil, slerrors.Forbidden("One or more stats are not part of scope.") |
|||
} |
|||
if stat.Acquired == 0 && stat.Required == 0 { |
|||
return nil, slerrors.BadRequest("0/0 stats are not allowed when creating items.") |
|||
} |
|||
} |
|||
|
|||
item, err = db.Items(getScope(c).ID).Create(c.Request.Context(), *item) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
item.Owner = getScope(c).Member(item.OwnerID) |
|||
|
|||
return item, err |
|||
})) |
|||
} |
@ -0,0 +1,354 @@ |
|||
package mysql |
|||
|
|||
import ( |
|||
"context" |
|||
"database/sql" |
|||
"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" |
|||
"strings" |
|||
"time" |
|||
) |
|||
|
|||
type itemRepository struct { |
|||
db *sql.DB |
|||
scopeID int |
|||
} |
|||
|
|||
func (r *itemRepository) Find(ctx context.Context, id int) (*models.Item, error) { |
|||
res, err := mysqlcore.New(r.db).GetItem(ctx, id) |
|||
if err != nil { |
|||
if err == sql.ErrNoRows { |
|||
return nil, slerrors.NotFound("Item") |
|||
} |
|||
return nil, err |
|||
} |
|||
if res.ScopeID != r.scopeID { |
|||
return nil, slerrors.NotFound("Item") |
|||
} |
|||
|
|||
item := r.resToItem(mysqlcore.ListItemsAcquiredBetweenRow(res)) |
|||
|
|||
stats, _ := mysqlcore.New(r.db).ListItemStatProgress(ctx, id) |
|||
for _, stat := range stats { |
|||
item.Stats = append(item.Stats, models.StatProgressEntry{ |
|||
StatEntry: models.StatEntry{ |
|||
ID: int(stat.ID.Int32), |
|||
Name: stat.Name.String, |
|||
Weight: stat.Weight, |
|||
}, |
|||
Acquired: stat.Acquired, |
|||
Required: stat.Required, |
|||
}) |
|||
} |
|||
|
|||
return &item, nil |
|||
} |
|||
|
|||
func (r *itemRepository) ListCreated(ctx context.Context, from, to time.Time) ([]models.Item, error) { |
|||
rows, err := mysqlcore.New(r.db).ListItemsCreatedBetween(ctx, mysqlcore.ListItemsCreatedBetweenParams{ |
|||
CreatedTime: from, |
|||
CreatedTime_2: to, |
|||
ScopeID: r.scopeID, |
|||
}) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
items := make([]models.Item, 0, len(rows)) |
|||
for _, row := range rows { |
|||
items = append(items, r.resToItem(mysqlcore.ListItemsAcquiredBetweenRow(row))) |
|||
} |
|||
|
|||
err = r.fillStats(ctx, items) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
return items, nil |
|||
} |
|||
|
|||
func (r *itemRepository) ListAcquired(ctx context.Context, from, to time.Time) ([]models.Item, error) { |
|||
rows, err := mysqlcore.New(r.db).ListItemsAcquiredBetween(ctx, mysqlcore.ListItemsAcquiredBetweenParams{ |
|||
AcquiredTime: sql.NullTime{Valid: true, Time: from}, |
|||
AcquiredTime_2: sql.NullTime{Valid: true, Time: to}, |
|||
ScopeID: r.scopeID, |
|||
}) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
items := make([]models.Item, 0, len(rows)) |
|||
for _, row := range rows { |
|||
items = append(items, r.resToItem(row)) |
|||
} |
|||
|
|||
err = r.fillStats(ctx, items) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
return items, nil |
|||
} |
|||
|
|||
func (r *itemRepository) ListScheduled(ctx context.Context, from, to models.Date) ([]models.Item, error) { |
|||
rows, err := mysqlcore.New(r.db).ListItemsScheduledBetween(ctx, mysqlcore.ListItemsScheduledBetweenParams{ |
|||
ScheduledDate: sqltypes.NullDate{Valid: true, Date: from}, |
|||
ScheduledDate_2: sqltypes.NullDate{Valid: true, Date: to}, |
|||
ScopeID: r.scopeID, |
|||
}) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
items := make([]models.Item, 0, len(rows)) |
|||
for _, row := range rows { |
|||
items = append(items, r.resToItem(mysqlcore.ListItemsAcquiredBetweenRow(row))) |
|||
} |
|||
|
|||
err = r.fillStats(ctx, items) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
return items, nil |
|||
} |
|||
|
|||
func (r *itemRepository) ListLoose(ctx context.Context, from, to time.Time) ([]models.Item, error) { |
|||
rows, err := mysqlcore.New(r.db).ListItemsLooseBetween(ctx, mysqlcore.ListItemsLooseBetweenParams{ |
|||
CreatedTime: from, |
|||
CreatedTime_2: to, |
|||
ScopeID: r.scopeID, |
|||
}) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
items := make([]models.Item, 0, len(rows)) |
|||
for _, row := range rows { |
|||
items = append(items, r.resToItem(mysqlcore.ListItemsAcquiredBetweenRow(row))) |
|||
} |
|||
|
|||
err = r.fillStats(ctx, items) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
return items, nil |
|||
} |
|||
|
|||
func (r *itemRepository) Create(ctx context.Context, item models.Item) (*models.Item, error) { |
|||
item.Stats = append(item.Stats[:0:0], item.Stats...) |
|||
|
|||
tx, err := r.db.BeginTx(ctx, nil) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
defer tx.Rollback() |
|||
q := mysqlcore.New(tx) |
|||
|
|||
prID, acqTime, schDate := r.generateNullables(item) |
|||
|
|||
res, err := q.InsertItem(ctx, mysqlcore.InsertItemParams{ |
|||
ScopeID: r.scopeID, |
|||
ProjectRequirementID: prID, |
|||
Name: item.Name, |
|||
Description: item.Description, |
|||
CreatedTime: time.Now(), |
|||
CreatedUserID: item.OwnerID, |
|||
AcquiredTime: acqTime, |
|||
ScheduledDate: schDate, |
|||
}) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
id, err := res.LastInsertId() |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
for _, stat := range item.Stats { |
|||
err = q.ReplaceItemStatProgress(ctx, mysqlcore.ReplaceItemStatProgressParams{ |
|||
ItemID: int(id), |
|||
StatID: stat.ID, |
|||
Acquired: stat.Acquired, |
|||
Required: stat.Required, |
|||
}) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
} |
|||
|
|||
err = tx.Commit() |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
return r.Find(ctx, int(id)) |
|||
} |
|||
|
|||
func (r *itemRepository) generateNullables(item models.Item) (prID sql.NullInt32, acqTime sql.NullTime, schDate sqltypes.NullDate) { |
|||
if item.ProjectRequirementID != nil { |
|||
prID.Valid = true |
|||
prID.Int32 = int32(*item.ProjectRequirementID) |
|||
} |
|||
if item.AcquiredTime != nil { |
|||
acqTime.Valid = true |
|||
acqTime.Time = *item.AcquiredTime |
|||
} |
|||
if item.ScheduledDate != nil { |
|||
schDate.Valid = true |
|||
schDate.Date = *item.ScheduledDate |
|||
} |
|||
|
|||
return |
|||
} |
|||
|
|||
func (r *itemRepository) Update(ctx context.Context, item models.Item, update models.ItemUpdate) (*models.Item, error) { |
|||
tx, err := r.db.BeginTx(ctx, nil) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
defer tx.Rollback() |
|||
q := mysqlcore.New(r.db) |
|||
|
|||
item.ApplyUpdate(update) |
|||
|
|||
prID, acqTime, schDate := r.generateNullables(item) |
|||
|
|||
err = q.UpdateItem(ctx, mysqlcore.UpdateItemParams{ |
|||
ID: item.ID, |
|||
|
|||
ProjectRequirementID: prID, |
|||
Name: item.Name, |
|||
Description: item.Description, |
|||
AcquiredTime: acqTime, |
|||
ScheduledDate: schDate, |
|||
CreatedUserID: item.OwnerID, |
|||
}) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
for _, stat := range update.Stats { |
|||
if stat.Acquired == 0 && stat.Required == 0 { |
|||
err = q.DeleteItemStatProgress(ctx, mysqlcore.DeleteItemStatProgressParams{ |
|||
ItemID: item.ID, |
|||
StatID: stat.ID, |
|||
}) |
|||
} else { |
|||
err = q.ReplaceItemStatProgress(ctx, mysqlcore.ReplaceItemStatProgressParams{ |
|||
ItemID: item.ID, |
|||
StatID: stat.ID, |
|||
Acquired: stat.Acquired, |
|||
Required: stat.Required, |
|||
}) |
|||
} |
|||
|
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
} |
|||
|
|||
err = tx.Commit() |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
|
|||
return r.Find(ctx, item.ID) |
|||
} |
|||
|
|||
func (r *itemRepository) Delete(ctx context.Context, item models.Item) error { |
|||
tx, err := r.db.BeginTx(ctx, nil) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
defer tx.Rollback() |
|||
q := mysqlcore.New(r.db) |
|||
|
|||
err = q.DeleteItem(ctx, item.ID) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
err = q.ClearItemStatProgress(ctx, item.ID) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
return tx.Commit() |
|||
} |
|||
|
|||
func (r *itemRepository) resToItem(res mysqlcore.ListItemsAcquiredBetweenRow) models.Item { |
|||
item := models.Item{ |
|||
ID: res.ID, |
|||
ScopeID: res.ScopeID, |
|||
OwnerID: res.CreatedUserID, |
|||
Name: res.Name, |
|||
Description: res.Description, |
|||
CreatedTime: res.CreatedTime.UTC(), |
|||
} |
|||
if res.ProjectRequirementID.Valid { |
|||
projectRequirementID := int(res.ProjectRequirementID.Int32) |
|||
projectID := int(res.ProjectID.Int32) |
|||
item.ProjectRequirementID = &projectRequirementID |
|||
item.ProjectID = &projectID |
|||
} |
|||
if res.ScheduledDate.Valid { |
|||
item.ScheduledDate = &res.ScheduledDate.Date |
|||
} |
|||
if res.AcquiredTime.Valid { |
|||
item.AcquiredTime = &res.AcquiredTime.Time |
|||
} |
|||
|
|||
return item |
|||
} |
|||
|
|||
func (r *itemRepository) fillStats(ctx context.Context, items []models.Item) error { |
|||
if len(items) == 0 { |
|||
return nil |
|||
} |
|||
|
|||
ids := make([]interface{}, 0, len(items)) |
|||
for _, item := range items { |
|||
ids = append(ids, item.ID) |
|||
} |
|||
query := ` |
|||
SELECT isp.item_id, isp.required, isp.acquired, s.id, s.name, s.weight FROM item_stat_progress isp |
|||
LEFT JOIN stat s ON s.id = isp.stat_id |
|||
WHERE item_id IN (?` + strings.Repeat(",?", len(ids)-1) + `); |
|||
` |
|||
|
|||
rows, err := r.db.QueryContext(ctx, query, ids...) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
for rows.Next() { |
|||
var itemID, required, acquired, statID int |
|||
var statName string |
|||
var statWeight float64 |
|||
|
|||
err = rows.Scan(&itemID, &required, &acquired, &statID, &statName, &statWeight) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
for i := range items { |
|||
if items[i].ID == itemID { |
|||
items[i].Stats = append(items[i].Stats, models.StatProgressEntry{ |
|||
StatEntry: models.StatEntry{ |
|||
ID: statID, |
|||
Name: statName, |
|||
Weight: statWeight, |
|||
}, |
|||
Acquired: acquired, |
|||
Required: required, |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
|
|||
return nil |
|||
} |
@ -0,0 +1,791 @@ |
|||
// Code generated by sqlc. DO NOT EDIT.
|
|||
// versions:
|
|||
// sqlc v1.13.0
|
|||
// source: item.sql
|
|||
|
|||
package mysqlcore |
|||
|
|||
import ( |
|||
"context" |
|||
"database/sql" |
|||
"time" |
|||
|
|||
"git.aiterp.net/stufflog3/stufflog3-api/internal/sqltypes" |
|||
) |
|||
|
|||
const clearItemStatProgress = `-- name: ClearItemStatProgress :exec |
|||
DELETE FROM item_stat_progress WHERE item_id = ? |
|||
` |
|||
|
|||
func (q *Queries) ClearItemStatProgress(ctx context.Context, itemID int) error { |
|||
_, err := q.db.ExecContext(ctx, clearItemStatProgress, itemID) |
|||
return err |
|||
} |
|||
|
|||
const deleteItem = `-- name: DeleteItem :exec |
|||
DELETE FROM item WHERE id = ? |
|||
` |
|||
|
|||
func (q *Queries) DeleteItem(ctx context.Context, id int) error { |
|||
_, err := q.db.ExecContext(ctx, deleteItem, id) |
|||
return err |
|||
} |
|||
|
|||
const deleteItemStatProgress = `-- name: DeleteItemStatProgress :exec |
|||
DELETE FROM item_stat_progress WHERE item_id = ? AND stat_id = ? |
|||
` |
|||
|
|||
type DeleteItemStatProgressParams struct { |
|||
ItemID int |
|||
StatID int |
|||
} |
|||
|
|||
func (q *Queries) DeleteItemStatProgress(ctx context.Context, arg DeleteItemStatProgressParams) error { |
|||
_, err := q.db.ExecContext(ctx, deleteItemStatProgress, arg.ItemID, arg.StatID) |
|||
return err |
|||
} |
|||
|
|||
const getItem = `-- name: GetItem :one |
|||
SELECT i.id, i.scope_id, i.project_requirement_id, i.name, i.description, i.created_time, i.created_user_id, 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 = ? |
|||
` |
|||
|
|||
type GetItemRow struct { |
|||
ID int |
|||
ScopeID int |
|||
ProjectRequirementID sql.NullInt32 |
|||
Name string |
|||
Description string |
|||
CreatedTime time.Time |
|||
CreatedUserID string |
|||
AcquiredTime sql.NullTime |
|||
ScheduledDate sqltypes.NullDate |
|||
ProjectID sql.NullInt32 |
|||
} |
|||
|
|||
func (q *Queries) GetItem(ctx context.Context, id int) (GetItemRow, error) { |
|||
row := q.db.QueryRowContext(ctx, getItem, id) |
|||
var i GetItemRow |
|||
err := row.Scan( |
|||
&i.ID, |
|||
&i.ScopeID, |
|||
&i.ProjectRequirementID, |
|||
&i.Name, |
|||
&i.Description, |
|||
&i.CreatedTime, |
|||
&i.CreatedUserID, |
|||
&i.AcquiredTime, |
|||
&i.ScheduledDate, |
|||
&i.ProjectID, |
|||
) |
|||
return i, err |
|||
} |
|||
|
|||
const getItemStatProgressBetween = `-- name: GetItemStatProgressBetween :one |
|||
SELECT s.id, s.name, s.weight, SUM(isp.acquired), SUM(isp.required) FROM item i |
|||
LEFT JOIN item_stat_progress isp on i.id = isp.item_id |
|||
LEFT JOIN stat s on isp.stat_id = s.id |
|||
WHERE i.acquired_time >= ? |
|||
AND i.acquired_time < ? |
|||
AND i.scope_id = ? |
|||
GROUP BY stat_id |
|||
` |
|||
|
|||
type GetItemStatProgressBetweenParams struct { |
|||
AcquiredTime sql.NullTime |
|||
AcquiredTime_2 sql.NullTime |
|||
ScopeID int |
|||
} |
|||
|
|||
type GetItemStatProgressBetweenRow struct { |
|||
ID sql.NullInt32 |
|||
Name sql.NullString |
|||
Weight float64 |
|||
Sum interface{} |
|||
Sum_2 interface{} |
|||
} |
|||
|
|||
func (q *Queries) GetItemStatProgressBetween(ctx context.Context, arg GetItemStatProgressBetweenParams) (GetItemStatProgressBetweenRow, error) { |
|||
row := q.db.QueryRowContext(ctx, getItemStatProgressBetween, arg.AcquiredTime, arg.AcquiredTime_2, arg.ScopeID) |
|||
var i GetItemStatProgressBetweenRow |
|||
err := row.Scan( |
|||
&i.ID, |
|||
&i.Name, |
|||
&i.Weight, |
|||
&i.Sum, |
|||
&i.Sum_2, |
|||
) |
|||
return i, err |
|||
} |
|||
|
|||
const insertItem = `-- name: InsertItem :execresult |
|||
INSERT INTO item (scope_id, project_requirement_id, name, description, created_time, created_user_id, acquired_time, scheduled_date) |
|||
VALUES (?, ?, ?, ?, ?, ?, ?, ?) |
|||
` |
|||
|
|||
type InsertItemParams struct { |
|||
ScopeID int |
|||
ProjectRequirementID sql.NullInt32 |
|||
Name string |
|||
Description string |
|||
CreatedTime time.Time |
|||
CreatedUserID string |
|||
AcquiredTime sql.NullTime |
|||
ScheduledDate sqltypes.NullDate |
|||
} |
|||
|
|||
func (q *Queries) InsertItem(ctx context.Context, arg InsertItemParams) (sql.Result, error) { |
|||
return q.db.ExecContext(ctx, insertItem, |
|||
arg.ScopeID, |
|||
arg.ProjectRequirementID, |
|||
arg.Name, |
|||
arg.Description, |
|||
arg.CreatedTime, |
|||
arg.CreatedUserID, |
|||
arg.AcquiredTime, |
|||
arg.ScheduledDate, |
|||
) |
|||
} |
|||
|
|||
const listItemStatProgress = `-- name: ListItemStatProgress :many |
|||
SELECT isp.required, isp.acquired, s.id, s.name, s.weight FROM item_stat_progress isp |
|||
LEFT JOIN stat s ON s.id = isp.stat_id |
|||
WHERE item_id = ? |
|||
` |
|||
|
|||
type ListItemStatProgressRow struct { |
|||
Required int |
|||
Acquired int |
|||
ID sql.NullInt32 |
|||
Name sql.NullString |
|||
Weight float64 |
|||
} |
|||
|
|||
func (q *Queries) ListItemStatProgress(ctx context.Context, itemID int) ([]ListItemStatProgressRow, error) { |
|||
rows, err := q.db.QueryContext(ctx, listItemStatProgress, itemID) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
defer rows.Close() |
|||
items := []ListItemStatProgressRow{} |
|||
for rows.Next() { |
|||
var i ListItemStatProgressRow |
|||
if err := rows.Scan( |
|||
&i.Required, |
|||
&i.Acquired, |
|||
&i.ID, |
|||
&i.Name, |
|||
&i.Weight, |
|||
); 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 listItemStatProgressMulti = `-- name: ListItemStatProgressMulti :many |
|||
SELECT isp.item_id, isp.required, isp.acquired, s.id, s.name, s.weight FROM item_stat_progress isp |
|||
LEFT JOIN stat s ON s.id = isp.stat_id |
|||
WHERE item_id IN (?, ?, ?, ?, ?, ?, ?, ?) |
|||
` |
|||
|
|||
type ListItemStatProgressMultiParams struct { |
|||
ItemID int |
|||
ItemID_2 int |
|||
ItemID_3 int |
|||
ItemID_4 int |
|||
ItemID_5 int |
|||
ItemID_6 int |
|||
ItemID_7 int |
|||
ItemID_8 int |
|||
} |
|||
|
|||
type ListItemStatProgressMultiRow struct { |
|||
ItemID int |
|||
Required int |
|||
Acquired int |
|||
ID sql.NullInt32 |
|||
Name sql.NullString |
|||
Weight float64 |
|||
} |
|||
|
|||
func (q *Queries) ListItemStatProgressMulti(ctx context.Context, arg ListItemStatProgressMultiParams) ([]ListItemStatProgressMultiRow, error) { |
|||
rows, err := q.db.QueryContext(ctx, listItemStatProgressMulti, |
|||
arg.ItemID, |
|||
arg.ItemID_2, |
|||
arg.ItemID_3, |
|||
arg.ItemID_4, |
|||
arg.ItemID_5, |
|||
arg.ItemID_6, |
|||
arg.ItemID_7, |
|||
arg.ItemID_8, |
|||
) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
defer rows.Close() |
|||
items := []ListItemStatProgressMultiRow{} |
|||
for rows.Next() { |
|||
var i ListItemStatProgressMultiRow |
|||
if err := rows.Scan( |
|||
&i.ItemID, |
|||
&i.Required, |
|||
&i.Acquired, |
|||
&i.ID, |
|||
&i.Name, |
|||
&i.Weight, |
|||
); 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 listItemsAcquiredBetween = `-- name: ListItemsAcquiredBetween :many |
|||
SELECT i.id, i.scope_id, i.project_requirement_id, i.name, i.description, i.created_time, i.created_user_id, 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.acquired_time >= ? |
|||
AND i.acquired_time < ? |
|||
AND i.scope_id = ? |
|||
` |
|||
|
|||
type ListItemsAcquiredBetweenParams struct { |
|||
AcquiredTime sql.NullTime |
|||
AcquiredTime_2 sql.NullTime |
|||
ScopeID int |
|||
} |
|||
|
|||
type ListItemsAcquiredBetweenRow struct { |
|||
ID int |
|||
ScopeID int |
|||
ProjectRequirementID sql.NullInt32 |
|||
Name string |
|||
Description string |
|||
CreatedTime time.Time |
|||
CreatedUserID string |
|||
AcquiredTime sql.NullTime |
|||
ScheduledDate sqltypes.NullDate |
|||
ProjectID sql.NullInt32 |
|||
} |
|||
|
|||
func (q *Queries) ListItemsAcquiredBetween(ctx context.Context, arg ListItemsAcquiredBetweenParams) ([]ListItemsAcquiredBetweenRow, error) { |
|||
rows, err := q.db.QueryContext(ctx, listItemsAcquiredBetween, arg.AcquiredTime, arg.AcquiredTime_2, arg.ScopeID) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
defer rows.Close() |
|||
items := []ListItemsAcquiredBetweenRow{} |
|||
for rows.Next() { |
|||
var i ListItemsAcquiredBetweenRow |
|||
if err := rows.Scan( |
|||
&i.ID, |
|||
&i.ScopeID, |
|||
&i.ProjectRequirementID, |
|||
&i.Name, |
|||
&i.Description, |
|||
&i.CreatedTime, |
|||
&i.CreatedUserID, |
|||
&i.AcquiredTime, |
|||
&i.ScheduledDate, |
|||
&i.ProjectID, |
|||
); 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 listItemsByProject = `-- name: ListItemsByProject :many |
|||
SELECT i.id, i.scope_id, i.project_requirement_id, i.name, i.description, i.created_time, i.created_user_id, 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 pr.project_id = ? |
|||
` |
|||
|
|||
type ListItemsByProjectRow struct { |
|||
ID int |
|||
ScopeID int |
|||
ProjectRequirementID sql.NullInt32 |
|||
Name string |
|||
Description string |
|||
CreatedTime time.Time |
|||
CreatedUserID string |
|||
AcquiredTime sql.NullTime |
|||
ScheduledDate sqltypes.NullDate |
|||
ProjectID sql.NullInt32 |
|||
} |
|||
|
|||
func (q *Queries) ListItemsByProject(ctx context.Context, projectID int) ([]ListItemsByProjectRow, error) { |
|||
rows, err := q.db.QueryContext(ctx, listItemsByProject, projectID) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
defer rows.Close() |
|||
items := []ListItemsByProjectRow{} |
|||
for rows.Next() { |
|||
var i ListItemsByProjectRow |
|||
if err := rows.Scan( |
|||
&i.ID, |
|||
&i.ScopeID, |
|||
&i.ProjectRequirementID, |
|||
&i.Name, |
|||
&i.Description, |
|||
&i.CreatedTime, |
|||
&i.CreatedUserID, |
|||
&i.AcquiredTime, |
|||
&i.ScheduledDate, |
|||
&i.ProjectID, |
|||
); 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 listItemsCreatedBetween = `-- name: ListItemsCreatedBetween :many |
|||
SELECT i.id, i.scope_id, i.project_requirement_id, i.name, i.description, i.created_time, i.created_user_id, 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.created_time >= ? |
|||
AND i.created_time < ? |
|||
AND i.scope_id = ? |
|||
` |
|||
|
|||
type ListItemsCreatedBetweenParams struct { |
|||
CreatedTime time.Time |
|||
CreatedTime_2 time.Time |
|||
ScopeID int |
|||
} |
|||
|
|||
type ListItemsCreatedBetweenRow struct { |
|||
ID int |
|||
ScopeID int |
|||
ProjectRequirementID sql.NullInt32 |
|||
Name string |
|||
Description string |
|||
CreatedTime time.Time |
|||
CreatedUserID string |
|||
AcquiredTime sql.NullTime |
|||
ScheduledDate sqltypes.NullDate |
|||
ProjectID sql.NullInt32 |
|||
} |
|||
|
|||
func (q *Queries) ListItemsCreatedBetween(ctx context.Context, arg ListItemsCreatedBetweenParams) ([]ListItemsCreatedBetweenRow, error) { |
|||
rows, err := q.db.QueryContext(ctx, listItemsCreatedBetween, arg.CreatedTime, arg.CreatedTime_2, arg.ScopeID) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
defer rows.Close() |
|||
items := []ListItemsCreatedBetweenRow{} |
|||
for rows.Next() { |
|||
var i ListItemsCreatedBetweenRow |
|||
if err := rows.Scan( |
|||
&i.ID, |
|||
&i.ScopeID, |
|||
&i.ProjectRequirementID, |
|||
&i.Name, |
|||
&i.Description, |
|||
&i.CreatedTime, |
|||
&i.CreatedUserID, |
|||
&i.AcquiredTime, |
|||
&i.ScheduledDate, |
|||
&i.ProjectID, |
|||
); 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 listItemsCreatedBetweenNoScope = `-- name: ListItemsCreatedBetweenNoScope :many |
|||
SELECT i.id, i.scope_id, i.project_requirement_id, i.name, i.description, i.created_time, i.created_user_id, 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.created_time >= ? |
|||
AND i.created_time < ? |
|||
` |
|||
|
|||
type ListItemsCreatedBetweenNoScopeParams struct { |
|||
CreatedTime time.Time |
|||
CreatedTime_2 time.Time |
|||
} |
|||
|
|||
type ListItemsCreatedBetweenNoScopeRow struct { |
|||
ID int |
|||
ScopeID int |
|||
ProjectRequirementID sql.NullInt32 |
|||
Name string |
|||
Description string |
|||
CreatedTime time.Time |
|||
CreatedUserID string |
|||
AcquiredTime sql.NullTime |
|||
ScheduledDate sqltypes.NullDate |
|||
ProjectID sql.NullInt32 |
|||
} |
|||
|
|||
func (q *Queries) ListItemsCreatedBetweenNoScope(ctx context.Context, arg ListItemsCreatedBetweenNoScopeParams) ([]ListItemsCreatedBetweenNoScopeRow, error) { |
|||
rows, err := q.db.QueryContext(ctx, listItemsCreatedBetweenNoScope, arg.CreatedTime, arg.CreatedTime_2) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
defer rows.Close() |
|||
items := []ListItemsCreatedBetweenNoScopeRow{} |
|||
for rows.Next() { |
|||
var i ListItemsCreatedBetweenNoScopeRow |
|||
if err := rows.Scan( |
|||
&i.ID, |
|||
&i.ScopeID, |
|||
&i.ProjectRequirementID, |
|||
&i.Name, |
|||
&i.Description, |
|||
&i.CreatedTime, |
|||
&i.CreatedUserID, |
|||
&i.AcquiredTime, |
|||
&i.ScheduledDate, |
|||
&i.ProjectID, |
|||
); 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 listItemsLooseBetween = `-- name: ListItemsLooseBetween :many |
|||
SELECT i.id, i.scope_id, i.project_requirement_id, i.name, i.description, i.created_time, i.created_user_id, 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.created_time >= ? |
|||
AND i.created_time < ? |
|||
AND i.scope_id = ? |
|||
AND i.scheduled_date IS NULL |
|||
AND i.acquired_time IS NULL |
|||
` |
|||
|
|||
type ListItemsLooseBetweenParams struct { |
|||
CreatedTime time.Time |
|||
CreatedTime_2 time.Time |
|||
ScopeID int |
|||
} |
|||
|
|||
type ListItemsLooseBetweenRow struct { |
|||
ID int |
|||
ScopeID int |
|||
ProjectRequirementID sql.NullInt32 |
|||
Name string |
|||
Description string |
|||
CreatedTime time.Time |
|||
CreatedUserID string |
|||
AcquiredTime sql.NullTime |
|||
ScheduledDate sqltypes.NullDate |
|||
ProjectID sql.NullInt32 |
|||
} |
|||
|
|||
func (q *Queries) ListItemsLooseBetween(ctx context.Context, arg ListItemsLooseBetweenParams) ([]ListItemsLooseBetweenRow, error) { |
|||
rows, err := q.db.QueryContext(ctx, listItemsLooseBetween, arg.CreatedTime, arg.CreatedTime_2, arg.ScopeID) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
defer rows.Close() |
|||
items := []ListItemsLooseBetweenRow{} |
|||
for rows.Next() { |
|||
var i ListItemsLooseBetweenRow |
|||
if err := rows.Scan( |
|||
&i.ID, |
|||
&i.ScopeID, |
|||
&i.ProjectRequirementID, |
|||
&i.Name, |
|||
&i.Description, |
|||
&i.CreatedTime, |
|||
&i.CreatedUserID, |
|||
&i.AcquiredTime, |
|||
&i.ScheduledDate, |
|||
&i.ProjectID, |
|||
); 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 listItemsLooseBetweenNoScope = `-- name: ListItemsLooseBetweenNoScope :many |
|||
SELECT i.id, i.scope_id, i.project_requirement_id, i.name, i.description, i.created_time, i.created_user_id, 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.created_time >= ? |
|||
AND i.created_time < ? |
|||
AND i.scheduled_date IS NULL |
|||
AND i.acquired_time IS NULL |
|||
` |
|||
|
|||
type ListItemsLooseBetweenNoScopeParams struct { |
|||
CreatedTime time.Time |
|||
CreatedTime_2 time.Time |
|||
} |
|||
|
|||
type ListItemsLooseBetweenNoScopeRow struct { |
|||
ID int |
|||
ScopeID int |
|||
ProjectRequirementID sql.NullInt32 |
|||
Name string |
|||
Description string |
|||
CreatedTime time.Time |
|||
CreatedUserID string |
|||
AcquiredTime sql.NullTime |
|||
ScheduledDate sqltypes.NullDate |
|||
ProjectID sql.NullInt32 |
|||
} |
|||
|
|||
func (q *Queries) ListItemsLooseBetweenNoScope(ctx context.Context, arg ListItemsLooseBetweenNoScopeParams) ([]ListItemsLooseBetweenNoScopeRow, error) { |
|||
rows, err := q.db.QueryContext(ctx, listItemsLooseBetweenNoScope, arg.CreatedTime, arg.CreatedTime_2) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
defer rows.Close() |
|||
items := []ListItemsLooseBetweenNoScopeRow{} |
|||
for rows.Next() { |
|||
var i ListItemsLooseBetweenNoScopeRow |
|||
if err := rows.Scan( |
|||
&i.ID, |
|||
&i.ScopeID, |
|||
&i.ProjectRequirementID, |
|||
&i.Name, |
|||
&i.Description, |
|||
&i.CreatedTime, |
|||
&i.CreatedUserID, |
|||
&i.AcquiredTime, |
|||
&i.ScheduledDate, |
|||
&i.ProjectID, |
|||
); 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 listItemsScheduledBetween = `-- name: ListItemsScheduledBetween :many |
|||
SELECT i.id, i.scope_id, i.project_requirement_id, i.name, i.description, i.created_time, i.created_user_id, 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.scheduled_date >= ? |
|||
AND i.scheduled_date < ? |
|||
AND i.scope_id = ? |
|||
` |
|||
|
|||
type ListItemsScheduledBetweenParams struct { |
|||
ScheduledDate sqltypes.NullDate |
|||
ScheduledDate_2 sqltypes.NullDate |
|||
ScopeID int |
|||
} |
|||
|
|||
type ListItemsScheduledBetweenRow struct { |
|||
ID int |
|||
ScopeID int |
|||
ProjectRequirementID sql.NullInt32 |
|||
Name string |
|||
Description string |
|||
CreatedTime time.Time |
|||
CreatedUserID string |
|||
AcquiredTime sql.NullTime |
|||
ScheduledDate sqltypes.NullDate |
|||
ProjectID sql.NullInt32 |
|||
} |
|||
|
|||
func (q *Queries) ListItemsScheduledBetween(ctx context.Context, arg ListItemsScheduledBetweenParams) ([]ListItemsScheduledBetweenRow, error) { |
|||
rows, err := q.db.QueryContext(ctx, listItemsScheduledBetween, arg.ScheduledDate, arg.ScheduledDate_2, arg.ScopeID) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
defer rows.Close() |
|||
items := []ListItemsScheduledBetweenRow{} |
|||
for rows.Next() { |
|||
var i ListItemsScheduledBetweenRow |
|||
if err := rows.Scan( |
|||
&i.ID, |
|||
&i.ScopeID, |
|||
&i.ProjectRequirementID, |
|||
&i.Name, |
|||
&i.Description, |
|||
&i.CreatedTime, |
|||
&i.CreatedUserID, |
|||
&i.AcquiredTime, |
|||
&i.ScheduledDate, |
|||
&i.ProjectID, |
|||
); 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 listItemsScheduledBetweenNoScope = `-- name: ListItemsScheduledBetweenNoScope :many |
|||
SELECT i.id, i.scope_id, i.project_requirement_id, i.name, i.description, i.created_time, i.created_user_id, 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.scheduled_date >= ? |
|||
AND i.scheduled_date < ? |
|||
` |
|||
|
|||
type ListItemsScheduledBetweenNoScopeParams struct { |
|||
ScheduledDate sqltypes.NullDate |
|||
ScheduledDate_2 sqltypes.NullDate |
|||
} |
|||
|
|||
type ListItemsScheduledBetweenNoScopeRow struct { |
|||
ID int |
|||
ScopeID int |
|||
ProjectRequirementID sql.NullInt32 |
|||
Name string |
|||
Description string |
|||
CreatedTime time.Time |
|||
CreatedUserID string |
|||
AcquiredTime sql.NullTime |
|||
ScheduledDate sqltypes.NullDate |
|||
ProjectID sql.NullInt32 |
|||
} |
|||
|
|||
func (q *Queries) ListItemsScheduledBetweenNoScope(ctx context.Context, arg ListItemsScheduledBetweenNoScopeParams) ([]ListItemsScheduledBetweenNoScopeRow, error) { |
|||
rows, err := q.db.QueryContext(ctx, listItemsScheduledBetweenNoScope, arg.ScheduledDate, arg.ScheduledDate_2) |
|||
if err != nil { |
|||
return nil, err |
|||
} |
|||
defer rows.Close() |
|||
items := []ListItemsScheduledBetweenNoScopeRow{} |
|||
for rows.Next() { |
|||
var i ListItemsScheduledBetweenNoScopeRow |
|||
if err := rows.Scan( |
|||
&i.ID, |
|||
&i.ScopeID, |
|||
&i.ProjectRequirementID, |
|||
&i.Name, |
|||
&i.Description, |
|||
&i.CreatedTime, |
|||
&i.CreatedUserID, |
|||
&i.AcquiredTime, |
|||
&i.ScheduledDate, |
|||
&i.ProjectID, |
|||
); 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 replaceItemStatProgress = `-- name: ReplaceItemStatProgress :exec |
|||
REPLACE INTO item_stat_progress (item_id, stat_id, acquired, required) |
|||
VALUES (?, ?, ?, ?) |
|||
` |
|||
|
|||
type ReplaceItemStatProgressParams struct { |
|||
ItemID int |
|||
StatID int |
|||
Acquired int |
|||
Required int |
|||
} |
|||
|
|||
func (q *Queries) ReplaceItemStatProgress(ctx context.Context, arg ReplaceItemStatProgressParams) error { |
|||
_, err := q.db.ExecContext(ctx, replaceItemStatProgress, |
|||
arg.ItemID, |
|||
arg.StatID, |
|||
arg.Acquired, |
|||
arg.Required, |
|||
) |
|||
return err |
|||
} |
|||
|
|||
const updateItem = `-- name: UpdateItem :exec |
|||
UPDATE item |
|||
SET project_requirement_id = ?, |
|||
name = ?, |
|||
description = ?, |
|||
acquired_time = ?, |
|||
scheduled_date = ?, |
|||
created_user_id = ? |
|||
WHERE id = ? |
|||
` |
|||
|
|||
type UpdateItemParams struct { |
|||
ProjectRequirementID sql.NullInt32 |
|||
Name string |
|||
Description string |
|||
AcquiredTime sql.NullTime |
|||
ScheduledDate sqltypes.NullDate |
|||
CreatedUserID string |
|||
ID int |
|||
} |
|||
|
|||
func (q *Queries) UpdateItem(ctx context.Context, arg UpdateItemParams) error { |
|||
_, err := q.db.ExecContext(ctx, updateItem, |
|||
arg.ProjectRequirementID, |
|||
arg.Name, |
|||
arg.Description, |
|||
arg.AcquiredTime, |
|||
arg.ScheduledDate, |
|||
arg.CreatedUserID, |
|||
arg.ID, |
|||
) |
|||
return err |
|||
} |
@ -0,0 +1,105 @@ |
|||
-- 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 = ?; |
|||
|
|||
-- name: ListItemsByProject :many |
|||
SELECT i.*, pr.project_id FROM item i |
|||
LEFT JOIN project_requirement pr ON pr.id = i.project_requirement_id |
|||
WHERE pr.project_id = ?; |
|||
|
|||
-- name: ListItemsAcquiredBetween :many |
|||
SELECT i.*, pr.project_id FROM item i |
|||
LEFT JOIN project_requirement pr ON pr.id = i.project_requirement_id |
|||
WHERE i.acquired_time >= ? |
|||
AND i.acquired_time < ? |
|||
AND i.scope_id = ?; |
|||
|
|||
-- name: ListItemsScheduledBetween :many |
|||
SELECT i.*, pr.project_id FROM item i |
|||
LEFT JOIN project_requirement pr ON pr.id = i.project_requirement_id |
|||
WHERE i.scheduled_date >= ? |
|||
AND i.scheduled_date < ? |
|||
AND i.scope_id = ?; |
|||
|
|||
-- name: ListItemsCreatedBetween :many |
|||
SELECT i.*, pr.project_id FROM item i |
|||
LEFT JOIN project_requirement pr ON pr.id = i.project_requirement_id |
|||
WHERE i.created_time >= ? |
|||
AND i.created_time < ? |
|||
AND i.scope_id = ?; |
|||
|
|||
-- name: ListItemsLooseBetween :many |
|||
SELECT i.*, pr.project_id FROM item i |
|||
LEFT JOIN project_requirement pr ON pr.id = i.project_requirement_id |
|||
WHERE i.created_time >= ? |
|||
AND i.created_time < ? |
|||
AND i.scope_id = ? |
|||
AND i.scheduled_date IS NULL |
|||
AND i.acquired_time IS NULL; |
|||
|
|||
-- name: ListItemsScheduledBetweenNoScope :many |
|||
SELECT i.*, pr.project_id FROM item i |
|||
LEFT JOIN project_requirement pr ON pr.id = i.project_requirement_id |
|||
WHERE i.scheduled_date >= ? |
|||
AND i.scheduled_date < ?; |
|||
|
|||
-- name: ListItemsCreatedBetweenNoScope :many |
|||
SELECT i.*, pr.project_id FROM item i |
|||
LEFT JOIN project_requirement pr ON pr.id = i.project_requirement_id |
|||
WHERE i.created_time >= ? |
|||
AND i.created_time < ?; |
|||
|
|||
-- name: ListItemsLooseBetweenNoScope :many |
|||
SELECT i.*, pr.project_id FROM item i |
|||
LEFT JOIN project_requirement pr ON pr.id = i.project_requirement_id |
|||
WHERE i.created_time >= ? |
|||
AND i.created_time < ? |
|||
AND i.scheduled_date IS NULL |
|||
AND i.acquired_time IS NULL; |
|||
|
|||
-- name: GetItemStatProgressBetween :one |
|||
SELECT s.id, s.name, s.weight, SUM(isp.acquired), SUM(isp.required) FROM item i |
|||
LEFT JOIN item_stat_progress isp on i.id = isp.item_id |
|||
LEFT JOIN stat s on isp.stat_id = s.id |
|||
WHERE i.acquired_time >= ? |
|||
AND i.acquired_time < ? |
|||
AND i.scope_id = ? |
|||
GROUP BY stat_id; |
|||
|
|||
-- name: ListItemStatProgress :many |
|||
SELECT isp.required, isp.acquired, s.id, s.name, s.weight FROM item_stat_progress isp |
|||
LEFT JOIN stat s ON s.id = isp.stat_id |
|||
WHERE item_id = ?; |
|||
|
|||
-- name: ListItemStatProgressMulti :many |
|||
SELECT isp.item_id, isp.required, isp.acquired, s.id, s.name, s.weight FROM item_stat_progress isp |
|||
LEFT JOIN stat s ON s.id = isp.stat_id |
|||
WHERE item_id IN (?, ?, ?, ?, ?, ?, ?, ?); |
|||
|
|||
-- name: InsertItem :execresult |
|||
INSERT INTO item (scope_id, project_requirement_id, name, description, created_time, created_user_id, acquired_time, scheduled_date) |
|||
VALUES (?, ?, ?, ?, ?, ?, ?, ?); |
|||
|
|||
-- name: UpdateItem :exec |
|||
UPDATE item |
|||
SET project_requirement_id = ?, |
|||
name = ?, |
|||
description = ?, |
|||
acquired_time = ?, |
|||
scheduled_date = ?, |
|||
created_user_id = ? |
|||
WHERE id = ?; |
|||
|
|||
-- name: DeleteItem :exec |
|||
DELETE FROM item WHERE id = ?; |
|||
|
|||
-- name: ReplaceItemStatProgress :exec |
|||
REPLACE INTO item_stat_progress (item_id, stat_id, acquired, required) |
|||
VALUES (?, ?, ?, ?); |
|||
|
|||
-- name: DeleteItemStatProgress :exec |
|||
DELETE FROM item_stat_progress WHERE item_id = ? AND stat_id = ?; |
|||
|
|||
-- name: ClearItemStatProgress :exec |
|||
DELETE FROM item_stat_progress WHERE item_id = ?; |
@ -0,0 +1,46 @@ |
|||
package models |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"fmt" |
|||
"time" |
|||
) |
|||
|
|||
type Date [3]int |
|||
|
|||
func ParseDate(s string) (Date, error) { |
|||
date, err := time.ParseInLocation("2006-01-02", s, time.UTC) |
|||
if err != nil { |
|||
return [3]int{}, err |
|||
} |
|||
|
|||
y, m, d := date.Date() |
|||
return Date{y, int(m), d}, nil |
|||
} |
|||
|
|||
func (d *Date) UnmarshalJSON(b []byte) error { |
|||
var str string |
|||
err := json.Unmarshal(b, &str) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
*d, err = ParseDate(str) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func (d Date) String() string { |
|||
return fmt.Sprintf("%04d-%02d-%02d", d[0], d[1], d[2]) |
|||
} |
|||
|
|||
func (d Date) MarshalJSON() ([]byte, error) { |
|||
return []byte("\"" + d.String() + "\""), nil |
|||
} |
|||
|
|||
func (d Date) ToTime() time.Time { |
|||
return time.Date(d[0], time.Month(d[1]), d[2], 0, 0, 0, 0, time.UTC) |
|||
} |
@ -0,0 +1,46 @@ |
|||
package sqltypes |
|||
|
|||
import ( |
|||
"database/sql/driver" |
|||
"errors" |
|||
"git.aiterp.net/stufflog3/stufflog3-api/internal/models" |
|||
"time" |
|||
) |
|||
|
|||
type NullDate struct { |
|||
Date models.Date |
|||
Valid bool |
|||
} |
|||
|
|||
func (n *NullDate) Scan(value interface{}) error { |
|||
if value == nil { |
|||
n.Valid = false |
|||
return nil |
|||
} |
|||
|
|||
switch value := value.(type) { |
|||
case string: |
|||
date, err := models.ParseDate(value) |
|||
if err != nil { |
|||
return err |
|||
} |
|||
|
|||
n.Date = date |
|||
n.Valid = true |
|||
case time.Time: |
|||
n.Date = models.Date{value.Year(), int(value.Month()), value.Day()} |
|||
n.Valid = true |
|||
default: |
|||
return errors.New("invalid type") |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func (n NullDate) Value() (driver.Value, error) { |
|||
if !n.Valid { |
|||
return nil, nil |
|||
} |
|||
|
|||
return n.Date.String(), nil |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue