server/libfic/todo.go

445 lines
13 KiB
Go
Raw Normal View History

2018-01-17 00:21:32 +00:00
package fic
import (
"database/sql"
"fmt"
"path"
2018-01-17 00:21:32 +00:00
"time"
)
2018-03-09 18:07:08 +00:00
// Claim represents an issue, a bug or a ToDo item.
2018-01-17 00:21:32 +00:00
type Claim struct {
Id int64 `json:"id"`
Subject string `json:"subject"`
IdTeam *int64 `json:"id_team"`
IdExercice *int64 `json:"id_exercice"`
IdAssignee *int64 `json:"id_assignee"`
Creation time.Time `json:"creation"`
State string `json:"state"`
Priority string `json:"priority"`
2018-01-17 00:21:32 +00:00
}
2018-03-09 18:07:08 +00:00
// GetClaim retrieves the claim with the given identifier.
2021-11-22 14:35:07 +00:00
func GetClaim(id int64) (c *Claim, err error) {
c = &Claim{}
2020-01-20 08:24:24 +00:00
err = DBQueryRow("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims WHERE id_claim = ?", id).Scan(&c.Id, &c.Subject, &c.IdTeam, &c.IdExercice, &c.IdAssignee, &c.Creation, &c.State, &c.Priority)
2018-01-17 00:21:32 +00:00
return
}
2018-03-09 18:07:08 +00:00
// GetClaims returns a list of all Claim registered in the database.
2021-11-22 14:35:07 +00:00
func GetClaims() (res []*Claim, err error) {
2018-01-17 00:21:32 +00:00
var rows *sql.Rows
2020-01-20 08:24:24 +00:00
if rows, err = DBQuery("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims"); err != nil {
2018-01-17 00:21:32 +00:00
return
}
defer rows.Close()
for rows.Next() {
2021-11-22 14:35:07 +00:00
c := &Claim{}
2020-01-20 08:24:24 +00:00
if err = rows.Scan(&c.Id, &c.Subject, &c.IdTeam, &c.IdExercice, &c.IdAssignee, &c.Creation, &c.State, &c.Priority); err != nil {
2018-01-17 00:21:32 +00:00
return
}
res = append(res, c)
}
err = rows.Err()
return
}
// GetClaim retrieves the claim with the given identifier and registered for the given Team.
2021-11-22 14:35:07 +00:00
func (t *Team) GetClaim(id int64) (c *Claim, err error) {
c = &Claim{}
err = DBQueryRow("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims WHERE id_claim = ? AND id_team = ?", id, t.Id).Scan(&c.Id, &c.Subject, &c.IdTeam, &c.IdExercice, &c.IdAssignee, &c.Creation, &c.State, &c.Priority)
return
}
2018-03-09 18:07:08 +00:00
// GetClaims returns a list of all Claim registered for the Team.
2021-11-22 14:35:07 +00:00
func (t *Team) GetClaims() (res []*Claim, err error) {
2018-01-17 00:21:32 +00:00
var rows *sql.Rows
if rows, err = DBQuery("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims WHERE id_team = ?", t.Id); err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
2021-11-22 14:35:07 +00:00
c := &Claim{}
if err = rows.Scan(&c.Id, &c.Subject, &c.IdTeam, &c.IdExercice, &c.IdAssignee, &c.Creation, &c.State, &c.Priority); err != nil {
return
}
res = append(res, c)
}
err = rows.Err()
return
}
// GetExercices returns a list of all Claim registered for the Exercice.
2021-11-22 14:35:07 +00:00
func (e *Exercice) GetClaims() (res []*Claim, err error) {
var rows *sql.Rows
if rows, err = DBQuery("SELECT id_claim, subject, id_team, id_exercice, id_assignee, creation, state, priority FROM claims WHERE id_exercice = ?", e.Id); err != nil {
2018-01-17 00:21:32 +00:00
return nil, err
}
defer rows.Close()
for rows.Next() {
2021-11-22 14:35:07 +00:00
c := &Claim{}
2020-01-20 08:24:24 +00:00
if err = rows.Scan(&c.Id, &c.Subject, &c.IdTeam, &c.IdExercice, &c.IdAssignee, &c.Creation, &c.State, &c.Priority); err != nil {
2018-01-17 00:21:32 +00:00
return
}
res = append(res, c)
}
err = rows.Err()
return
}
2018-03-09 18:07:08 +00:00
// NewClaim creates and fills a new struct Claim and registers it into the database.
2021-11-22 14:35:07 +00:00
func NewClaim(subject string, team *Team, exercice *Exercice, assignee *ClaimAssignee, priority string) (*Claim, error) {
2018-01-17 00:21:32 +00:00
var tid *int64
if team == nil {
tid = nil
} else {
tid = &team.Id
}
2020-01-20 08:24:24 +00:00
var eid *int64
if exercice == nil {
eid = nil
} else {
eid = &exercice.Id
}
2018-01-17 00:21:32 +00:00
var aid *int64
if assignee == nil {
aid = nil
} else {
aid = &assignee.Id
}
2020-01-20 08:24:24 +00:00
if res, err := DBExec("INSERT INTO claims (subject, id_team, id_exercice, id_assignee, creation, state, priority) VALUES (?, ?, ?, ?, ?, ?, ?)", subject, tid, eid, aid, time.Now(), "new", priority); err != nil {
2021-11-22 14:35:07 +00:00
return nil, err
2018-01-17 00:21:32 +00:00
} else if cid, err := res.LastInsertId(); err != nil {
2021-11-22 14:35:07 +00:00
return nil, err
2018-01-17 00:21:32 +00:00
} else {
2021-11-22 14:35:07 +00:00
return &Claim{cid, subject, tid, eid, aid, time.Now(), "new", priority}, nil
2018-01-17 00:21:32 +00:00
}
}
2018-03-09 18:07:08 +00:00
// GetTeam returns the Team linked to the issue, if any.
2021-11-22 14:35:07 +00:00
func (c *Claim) GetTeam() (*Team, error) {
2018-01-17 00:21:32 +00:00
if c.IdTeam == nil {
return nil, nil
2018-01-21 13:18:26 +00:00
} else if t, err := GetTeam(*c.IdTeam); err != nil {
2018-01-17 00:21:32 +00:00
return nil, err
} else {
2021-11-22 14:35:07 +00:00
return t, nil
2018-01-17 00:21:32 +00:00
}
}
2018-03-09 18:07:08 +00:00
// SetTeam defines the Team that is linked to this issue.
2021-11-22 14:35:07 +00:00
func (c *Claim) SetTeam(t Team) {
2018-01-17 00:21:32 +00:00
c.IdTeam = &t.Id
}
2020-01-20 08:24:24 +00:00
// GetExercice returns the Exercice linked to the issue, if any.
2021-11-22 14:35:07 +00:00
func (c *Claim) GetExercice() (*Exercice, error) {
2020-01-20 08:24:24 +00:00
if c.IdExercice == nil {
return nil, nil
} else if e, err := GetExercice(*c.IdExercice); err != nil {
return nil, err
} else {
2021-11-22 14:35:07 +00:00
return e, nil
2020-01-20 08:24:24 +00:00
}
}
// SetExercice defines the Exercice that is linked to this issue.
2021-11-22 14:35:07 +00:00
func (c *Claim) SetExercice(e Exercice) {
2020-01-20 08:24:24 +00:00
c.IdExercice = &e.Id
}
2018-03-09 18:07:08 +00:00
// Update applies modifications back to the database.
2021-11-22 14:35:07 +00:00
func (c *Claim) Update() (int64, error) {
2020-01-20 08:24:24 +00:00
if res, err := DBExec("UPDATE claims SET subject = ?, id_team = ?, id_exercice = ?, id_assignee = ?, creation = ?, state = ?, priority = ? WHERE id_claim = ?", c.Subject, c.IdTeam, c.IdExercice, c.IdAssignee, c.Creation, c.State, c.Priority, c.Id); err != nil {
2018-01-17 00:21:32 +00:00
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
2018-03-09 18:07:08 +00:00
// Delete the issue from the database.
2021-11-22 14:35:07 +00:00
func (c *Claim) Delete() (int64, error) {
2018-01-17 00:21:32 +00:00
if res, err := DBExec("DELETE FROM claims WHERE id_claim = ?", c.Id); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
2018-03-09 18:07:08 +00:00
// ClearClaims removes all issues from database.
2018-01-17 00:21:32 +00:00
func ClearClaims() (int64, error) {
if res, err := DBExec("DELETE FROM claims"); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
2018-03-09 18:07:08 +00:00
// ClaimDescription represents some text describing an issue.
2018-01-17 00:21:32 +00:00
type ClaimDescription struct {
Id int64 `json:"id"`
2018-03-09 18:07:08 +00:00
// IdAssignee stores the user who handle the claim (or 0 if nobody handles it).
IdAssignee int64 `json:"id_assignee"`
2018-03-09 18:07:08 +00:00
// Content is the raw description.
Content string `json:"content"`
2018-03-09 18:07:08 +00:00
// Date is the timestamp when the description was written.
Date time.Time `json:"date"`
// Publish indicates wether it is shown back to the team.
Publish bool `json:"publish"`
2018-01-17 00:21:32 +00:00
}
2020-01-24 17:24:20 +00:00
// GetLastUpdate returns the date of the latest message written for the given Claim.
2021-11-22 14:35:07 +00:00
func (c *Claim) GetLastUpdate() (res *time.Time, err error) {
2020-01-24 17:24:20 +00:00
err = DBQueryRow("SELECT MAX(date) FROM claim_descriptions WHERE id_claim = ? GROUP BY id_claim", c.Id).Scan(&res)
return
}
2018-03-09 18:07:08 +00:00
// GetDescriptions returns a list of all descriptions stored in the database for the Claim.
2021-11-22 14:35:07 +00:00
func (c *Claim) GetDescriptions() (res []*ClaimDescription, err error) {
2018-01-17 00:21:32 +00:00
var rows *sql.Rows
if rows, err = DBQuery("SELECT id_description, id_assignee, content, date, publish FROM claim_descriptions WHERE id_claim = ?", c.Id); err != nil {
2018-01-17 00:21:32 +00:00
return nil, err
}
defer rows.Close()
for rows.Next() {
2021-11-22 14:35:07 +00:00
d := &ClaimDescription{}
if err = rows.Scan(&d.Id, &d.IdAssignee, &d.Content, &d.Date, &d.Publish); err != nil {
2018-01-17 00:21:32 +00:00
return
}
res = append(res, d)
}
err = rows.Err()
return
}
2018-03-09 18:07:08 +00:00
// AddDescription append in the database a new description; then returns the corresponding structure.
2021-11-22 14:35:07 +00:00
func (c *Claim) AddDescription(content string, assignee *ClaimAssignee, publish bool) (*ClaimDescription, error) {
var assignee_id *int64
if assignee != nil {
assignee_id = &assignee.Id
}
if res, err := DBExec("INSERT INTO claim_descriptions (id_claim, id_assignee, content, date, publish) VALUES (?, ?, ?, ?, ?)", c.Id, assignee_id, content, time.Now(), publish); err != nil {
return nil, err
2018-01-17 00:21:32 +00:00
} else if did, err := res.LastInsertId(); err != nil {
2021-11-22 14:35:07 +00:00
return nil, err
2018-01-17 00:21:32 +00:00
} else {
2021-11-22 14:35:07 +00:00
return &ClaimDescription{did, assignee.Id, content, time.Now(), publish}, nil
2018-01-17 00:21:32 +00:00
}
}
// GetAssignee retrieves an assignee from its identifier.
2021-11-22 14:35:07 +00:00
func (d *ClaimDescription) GetAssignee() (a *ClaimAssignee, err error) {
a = &ClaimAssignee{}
err = DBQueryRow("SELECT id_assignee, name FROM claim_assignees WHERE id_assignee = ?", d.IdAssignee).Scan(&a.Id, &a.Name)
return
}
2018-03-09 18:07:08 +00:00
// Update applies modifications back to the database
2021-11-22 14:35:07 +00:00
func (d *ClaimDescription) Update() (int64, error) {
if res, err := DBExec("UPDATE claim_descriptions SET id_assignee = ?, content = ?, date = ?, publish = ? WHERE id_description = ?", d.IdAssignee, d.Content, d.Date, d.Publish, d.Id); err != nil {
2018-01-17 00:21:32 +00:00
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
2018-03-09 18:07:08 +00:00
// Delete the description in the database.
2021-11-22 14:35:07 +00:00
func (d *ClaimDescription) Delete() (int64, error) {
2018-01-17 00:21:32 +00:00
if res, err := DBExec("DELETE FROM claim_descriptions WHERE id_description = ?", d.Id); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
2018-03-09 18:07:08 +00:00
// ClaimAssignee represents a user that can handle claims.
2018-01-17 00:21:32 +00:00
type ClaimAssignee struct {
Id int64 `json:"id"`
Name string `json:"name"`
}
2018-03-09 18:07:08 +00:00
// GetAssignee retrieves an assignee from its identifier.
2021-11-22 14:35:07 +00:00
func GetAssignee(id int64) (a *ClaimAssignee, err error) {
a = &ClaimAssignee{}
2018-01-17 00:21:32 +00:00
err = DBQueryRow("SELECT id_assignee, name FROM claim_assignees WHERE id_assignee = ?", id).Scan(&a.Id, &a.Name)
return
}
2018-03-09 18:07:08 +00:00
// GetAssignees returns a list of all assignees found in the database.
2021-11-22 14:35:07 +00:00
func GetAssignees() (res []*ClaimAssignee, err error) {
2018-01-17 00:21:32 +00:00
var rows *sql.Rows
if rows, err = DBQuery("SELECT id_assignee, name FROM claim_assignees"); err != nil {
return
}
defer rows.Close()
for rows.Next() {
2021-11-22 14:35:07 +00:00
a := &ClaimAssignee{}
2018-01-17 00:21:32 +00:00
if err = rows.Scan(&a.Id, &a.Name); err != nil {
return
}
res = append(res, a)
}
err = rows.Err()
return
}
2018-03-09 18:07:08 +00:00
// NewClaimAssignee creates and fills a new struct ClaimAssignee and registers it into the database.
2021-11-22 14:35:07 +00:00
func NewClaimAssignee(name string) (*ClaimAssignee, error) {
2018-01-17 00:21:32 +00:00
if res, err := DBExec("INSERT INTO claim_assignees (name) VALUES (?)", name); err != nil {
2021-11-22 14:35:07 +00:00
return nil, err
2018-01-17 00:21:32 +00:00
} else if aid, err := res.LastInsertId(); err != nil {
2021-11-22 14:35:07 +00:00
return nil, err
2018-01-17 00:21:32 +00:00
} else {
2021-11-22 14:35:07 +00:00
return &ClaimAssignee{aid, name}, nil
2018-01-17 00:21:32 +00:00
}
}
2018-03-09 18:07:08 +00:00
// Update applies modifications back to the database
2021-11-22 14:35:07 +00:00
func (a *ClaimAssignee) Update() (int64, error) {
2018-01-17 00:21:32 +00:00
if res, err := DBExec("UPDATE claim_assignees SET name = ? WHERE id_assignee = ?", a.Name, a.Id); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
2018-03-09 18:07:08 +00:00
// Delete the assignee in the database.
2021-11-22 14:35:07 +00:00
func (a *ClaimAssignee) Delete() (int64, error) {
2018-01-17 00:21:32 +00:00
if res, err := DBExec("DELETE FROM claim_assignees WHERE id_assignee = ?", a.Id); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
2018-03-09 18:07:08 +00:00
// ClearAssignees removes all assignees from database.
2018-01-17 00:21:32 +00:00
func ClearAssignees() (int64, error) {
if res, err := DBExec("DELETE FROM claim_assignees"); err != nil {
return 0, err
} else if nb, err := res.RowsAffected(); err != nil {
return 0, err
} else {
return nb, err
}
}
2018-03-09 18:07:08 +00:00
// GetAssignee returns the assignee assigned to the claim.
2021-11-22 14:35:07 +00:00
func (c *Claim) GetAssignee() (*ClaimAssignee, error) {
2018-01-17 00:21:32 +00:00
if c.IdAssignee == nil {
return nil, nil
} else if a, err := GetAssignee(*c.IdAssignee); err != nil {
return nil, err
} else {
2021-11-22 14:35:07 +00:00
return a, nil
2018-01-17 00:21:32 +00:00
}
}
2018-03-09 18:07:08 +00:00
// SetAssignee defines the assignee that'll handle the claim.
2021-11-22 14:35:07 +00:00
func (c *Claim) SetAssignee(a ClaimAssignee) {
2018-01-17 00:21:32 +00:00
c.IdAssignee = &a.Id
}
type teamIssueText struct {
Content string `json:"cnt"`
Assignee string `json:"assignee"`
Date time.Time `json:"date"`
}
type teamIssueFile struct {
Id int64 `json:"id"`
Subject string `json:"subject"`
Exercice *string `json:"exercice,omitempty"`
ExerciceURL string `json:"url,omitempty"`
Assignee *string `json:"assignee,omitempty"`
State string `json:"state"`
Priority string `json:"priority"`
Texts []teamIssueText `json:"texts"`
}
2021-11-22 14:35:07 +00:00
func (t *Team) MyIssueFile() (ret []teamIssueFile, err error) {
var claims []*Claim
if claims, err = t.GetClaims(); err == nil {
for _, claim := range claims {
var exercice *string = nil
var url string
if exo, err := claim.GetExercice(); err == nil && exo != nil {
exercice = &exo.Title
if exo.IdTheme == nil {
url = path.Join("_", exo.URLId)
} else if theme, err := GetTheme(*exo.IdTheme); err == nil {
url = path.Join(theme.URLId, exo.URLId)
}
}
var assignee *string = nil
if a, err := claim.GetAssignee(); err == nil && a != nil {
assignee = &a.Name
}
if descriptions, err := claim.GetDescriptions(); err != nil {
2021-11-22 14:35:07 +00:00
return nil, fmt.Errorf("error occurs during description retrieval (cid=%d): %w", claim.Id, err)
} else {
tif := teamIssueFile{
Id: claim.Id,
Subject: claim.Subject,
Exercice: exercice,
ExerciceURL: url,
Assignee: assignee,
State: claim.State,
Priority: claim.Priority,
Texts: []teamIssueText{},
}
for _, description := range descriptions {
if description.Publish {
if people, err := description.GetAssignee(); err != nil {
2021-11-22 14:35:07 +00:00
return nil, fmt.Errorf("error ocurs during assignee retrieval (aid=%d): %w", description.IdAssignee, err)
} else {
tif.Texts = append(tif.Texts, teamIssueText{
Content: description.Content,
Assignee: people.Name,
Date: description.Date,
})
}
}
}
ret = append(ret, tif)
}
}
} else {
2021-11-22 14:35:07 +00:00
err = fmt.Errorf("error occurs during claim retrieval: %w", err)
}
return
}