change to GORM, add member and rank handlers

This commit is contained in:
2024-03-08 00:39:46 -08:00
parent 84424fdae9
commit 3b715cf331
36 changed files with 3491 additions and 230 deletions

110
api/db/award.go Normal file
View File

@@ -0,0 +1,110 @@
package db
/*
DDL
CREATE TABLE `awards` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) DEFAULT NULL,
`short_name` varchar(10) DEFAULT NULL,
`description` text DEFAULT NULL,
`type` varchar(100) DEFAULT NULL,
`footprint` varchar(50) DEFAULT NULL,
`created_at` datetime DEFAULT current_timestamp(),
`updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`image_url` varchar(250) DEFAULT NULL,
`deleted` tinytext DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=81 DEFAULT CHARSET=utf8mb4 COMMENT='Contains a list of Awards for the unit.';
*/
type Award struct {
ObjectBase
Name string `json:"name"`
ShortName string `json:"short_name"`
Description string `json:"description"`
Type string `json:"type"`
Footprint string `json:"footprint"`
ImageURL string `json:"image_url"`
Members []Member `json:"members" gorm:"many2many:member_awards;"`
}
// Get one by id
func (a *Award) GetByID(id int) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.First(a, id).Error
return err
}
// Get one by name
func (a *Award) GetByName(name string) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Where("name = ?", name).First(a).Error
return err
}
// Get all
func (a *Award) GetAll() ([]Award, error) {
db, err := GetDB()
if err != nil {
return nil, err
}
var awards []Award
err = db.Find(&awards).Error
return awards, err
}
// Create
func (a *Award) Create() error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Create(a).Error
return err
}
// Update
func (a *Award) Update() error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Save(a).Error
return err
}
// Delete
func (a *Award) Delete() error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Delete(a).Error
return err
}
// Get all holders of an award
func (a *Award) GetHolders() ([]Member, error) {
db, err := GetDB()
if err != nil {
return nil, err
}
var members []Member
err = db.Model(a).Association("Members").Find(&members)
return members, err
}

142
api/db/course.go Normal file
View File

@@ -0,0 +1,142 @@
package db
import "context"
/*
DDL
CREATE TABLE `courses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`short_name` varchar(10) NOT NULL,
`category` varchar(100) NOT NULL,
`description` varchar(1000) DEFAULT NULL,
`image_url` varchar(255) DEFAULT NULL,
`created_at` datetime NOT NULL DEFAULT current_timestamp(),
`updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`deleted` tinyint(4) DEFAULT 0,
`prereq_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
UNIQUE KEY `shortName` (`short_name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=39 DEFAULT CHARSET=utf8mb4;
*/
type Course struct {
ObjectBase
Name string `json:"name"`
ShortName string `json:"short_name"`
Category string `json:"category"`
Description string `json:"description"`
ImageURL string `json:"image_url"`
PassedMembers []Member `json:"passed_members" gorm:"many2many:member_courses_pass;"`
FailedMembers []Member `json:"failed_members" gorm:"many2many:member_courses_fail;"`
Prerequisites []*Course `json:"prerequisites" gorm:"many2many:course_prerequisites;"`
TrainingEvents []TrainingEvent `json:"training_events"`
}
// Get one by id
func (c *Course) GetByID(id int) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.First(c, id).Error
return err
}
// Get one by name
func (c *Course) GetByName(name string) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Where("name = ?", name).First(c).Error
return err
}
// Get all
func (c *Course) GetAll() ([]Course, error) {
db, err := GetDB()
if err != nil {
return nil, err
}
var courses []Course
err = db.Find(&courses).Error
return courses, err
}
// Get all training events for a course
func (c *Course) GetTrainingEvents(ctx context.Context, id int) ([]TrainingEvent, error) {
db, err := GetDB()
if err != nil {
return nil, err
}
var events []TrainingEvent
err = db.WithContext(ctx).Where("course_id = ?", id).Find(&events).Error
if err != nil {
return nil, err
}
return events, nil
}
// Get all prerequisites for a course
func (c *Course) GetPrerequisites(ctx context.Context, id int) ([]Course, error) {
var prereqs []Course
db, err := GetDB()
if err != nil {
return nil, err
}
err = db.WithContext(ctx).Model(c).Where("id = ?", id).Association("Prerequisites").Find(&prereqs)
if err != nil {
return nil, err
}
return prereqs, nil
}
// Create a new course
func (c *Course) Create(ctx context.Context, course Course) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).Create(course).Error
if err != nil {
return err
}
return nil
}
// Update a course
func (c *Course) Update(ctx context.Context, course Course) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).Save(course).Error
if err != nil {
return err
}
return nil
}
// Delete a course
func (c *Course) Delete(ctx context.Context, course Course) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).Delete(course).Error
if err != nil {
return err
}
return nil
}

View File

@@ -3,15 +3,43 @@ package db
import (
"database/sql"
"sync"
"time"
_ "github.com/go-sql-driver/mysql"
"github.com/spf13/viper"
"gopkg.in/guregu/null.v3"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var ActiveDB *sql.DB
var ActiveDB *gorm.DB
var activeSQL *sql.DB
var lock = new(sync.Mutex)
func GetDB() (*sql.DB, error) {
type ObjectBase struct {
ID int `json:"id" gorm:"primarykey"`
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime; not null"`
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime; not null"`
Deleted bool `json:"deleted" gorm:"default:false; index; not null"`
DeletedAt null.Time `json:"deleted_at"`
}
func AutoMigrate() error {
db, err := GetDB()
if err != nil {
return err
}
err = db.AutoMigrate(
&Award{},
&Course{},
&Member{},
&Rank{},
&TrainingEvent{},
)
return err
}
func GetDB() (*gorm.DB, error) {
if ActiveDB != nil {
return ActiveDB, nil
@@ -26,17 +54,22 @@ func GetDB() (*sql.DB, error) {
return db, nil
}
func ConnectDB() (*sql.DB, error) {
func ConnectDB() (*gorm.DB, error) {
lock.Lock()
defer lock.Unlock()
if ActiveDB != nil {
ActiveDB.Close()
ActiveDB = nil
if activeSQL != nil {
activeSQL.Close()
activeSQL = nil
}
cfg := viper.GetViper()
db, err := sql.Open("mysql", cfg.GetString("MARIADB_CONNSTRING"))
db, err := gorm.Open(mysql.Open(cfg.GetString("MARIADB_CONNSTRING")), &gorm.Config{
FullSaveAssociations: true,
PrepareStmt: true,
})
activeSQL, err = db.DB()
if err != nil {
return nil, err
}

219
api/db/member.go Normal file
View File

@@ -0,0 +1,219 @@
package db
import (
"context"
"github.com/labstack/echo/v4"
"gopkg.in/guregu/null.v3"
)
/*
DDL
CREATE TABLE `members` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`timezone` varchar(5) DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`website` varchar(240) DEFAULT NULL,
`guilded_id` varchar(10) DEFAULT NULL,
`steam_id_64` varchar(17) DEFAULT NULL,
`teamspeak_uid` varchar(32) DEFAULT NULL,
`steam_profile_name` varchar(32) DEFAULT NULL,
`discord_id` varchar(20) DEFAULT NULL,
`discord_username` varchar(32) DEFAULT NULL,
`aliases` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`aliases`)),
`created_at` datetime NOT NULL DEFAULT current_timestamp(),
`updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`deleted` tinyint(4) DEFAULT NULL,
`remarks` text DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
UNIQUE KEY `steamId64` (`steam_id_64`) USING BTREE,
UNIQUE KEY `discordId` (`discord_id`) USING BTREE,
UNIQUE KEY `guilded_id` (`guilded_id`)
) ENGINE=InnoDB AUTO_INCREMENT=186 DEFAULT CHARSET=utf8mb4;
*/
// Member is a struct that represents a member
type Member struct {
ObjectBase
Name string `json:"name"`
Company null.String `json:"company"`
Timezone null.String `json:"timezone"`
Email null.String `json:"email"`
Website null.String `json:"website"`
GuildedID null.String `json:"guilded_id"`
SteamID64 null.String `json:"steam_id_64"`
TeamspeakUID null.String `json:"teamspeak_uid"`
SteamProfileName null.String `json:"steam_profile_name"`
DiscordID null.String `json:"discord_id"`
DiscordUsername null.String `json:"discord_username"`
Aliases null.String `json:"aliases"`
Remarks null.String `json:"remarks"`
Rank Rank `json:"rank" gorm:"references:ID; foreignkey:RankID"`
RankID int `json:"rank_id"`
Awards []Award `json:"awards" gorm:"many2many:member_awards;"`
}
// Get one by id
func (m *Member) GetByID(ctx context.Context, id int) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).First(m, id).Error
if err != nil {
return err
}
return nil
}
// Get all
func (m *Member) GetAll(ctx context.Context) ([]Member, error) {
var members []Member
db, err := GetDB()
if err != nil {
return nil, err
}
// Search by provided struct
err = db.WithContext(ctx).
Model(m).Where(m).Find(&members).Error
if err != nil {
return nil, err
}
return members, nil
}
// Create a new member
func (m *Member) Create(ctx context.Context, c echo.Context) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).Create(m).Error
if err != nil {
return err
}
return nil
}
// Update a member
func (m *Member) Update(ctx context.Context, c echo.Context) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).Save(m).Error
if err != nil {
return err
}
return nil
}
// Delete a member
func (m *Member) Delete(ctx context.Context, c echo.Context) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).Delete(m).Error
if err != nil {
return err
}
return nil
}
// Get by name
func (m *Member) GetByName(ctx context.Context, name string) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).Where("name = ?", name).First(m).Error
if err != nil {
return err
}
return nil
}
// Get by steam id
func (m *Member) GetBySteamID(ctx context.Context, steamID string) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).Where("steam_id_64 = ?", steamID).First(m).Error
if err != nil {
return err
}
return nil
}
// Get by discord id
func (m *Member) GetByDiscordID(ctx context.Context, discordID string) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).Where("discord_id = ?", discordID).First(m).Error
if err != nil {
return err
}
return nil
}
// Get by guilded id
func (m *Member) GetByGuildedID(ctx context.Context, guildedID string) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).Where("guilded_id = ?", guildedID).First(m).Error
if err != nil {
return err
}
return nil
}
// Get by teamspeak uid
func (m *Member) GetByTeamspeakUID(ctx context.Context, teamspeakUID string) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).Where("teamspeak_uid = ?", teamspeakUID).First(m).Error
if err != nil {
return err
}
return nil
}
// Get by email
func (m *Member) GetByEmail(ctx context.Context, email string) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.WithContext(ctx).Where("email = ?", email).First(m).Error
if err != nil {
return err
}
return nil
}
// Get awards a member has
func (m *Member) GetAwards(ctx context.Context) ([]Award, error) {
db, err := GetDB()
if err != nil {
return nil, err
}
err = db.WithContext(ctx).Model(m).Association("Awards").Find(&m.Awards)
if err != nil {
return nil, err
}
return m.Awards, nil
}

109
api/db/rank.go Normal file
View File

@@ -0,0 +1,109 @@
package db
/*
DDL
CREATE TABLE `ranks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`short_name` varchar(70) NOT NULL,
`category` varchar(100) NOT NULL,
`sort_id` int(11) NOT NULL DEFAULT 0,
`image_url` varchar(240) DEFAULT NULL,
`created_at` datetime NOT NULL DEFAULT current_timestamp(),
`updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`deleted` tinyint(4) DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
UNIQUE KEY `shortName` (`short_name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8mb4;
*/
type Rank struct {
ObjectBase
Name string `json:"name"`
ShortName string `json:"short_name"`
Category string `json:"category"`
SortID int `json:"sort_id"`
ImageURL string `json:"image_url"`
Members []Member `json:"members" gorm:"references:ID; foreignkey:RankID"`
}
// Get one by id
func (r *Rank) GetByID(id int) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.First(r, id).Error
return err
}
// Get one by name
func (r *Rank) GetByName(name string) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Where("name = ?", name).First(r).Error
return err
}
// Get all
func (r *Rank) GetAll() ([]Rank, error) {
db, err := GetDB()
if err != nil {
return nil, err
}
var ranks []Rank
err = db.Find(&ranks).Error
return ranks, err
}
// Add a member to a rank
func (r *Rank) AddHolder(m *Member) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Model(r).Association("Members").Append(m)
return err
}
// Create
func (r *Rank) Create() error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Create(r).Error
return err
}
// Update
func (r *Rank) Update() error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Save(r).Error
return err
}
// Delete
func (r *Rank) Delete() error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Delete(r).Error
return err
}

113
api/db/trainingEvent.go Normal file
View File

@@ -0,0 +1,113 @@
package db
/*
DDL
CREATE TABLE `course_events` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`course_id` int(11) DEFAULT NULL,
`event_type` int(11) DEFAULT NULL,
`event_date` datetime NOT NULL,
`guilded_event_id` int(11) DEFAULT NULL,
`created_at` datetime NOT NULL DEFAULT current_timestamp(),
`updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`deleted` tinyint(4) DEFAULT 0,
`report_url` varchar(2048) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_course_events_event_type_id` (`event_type`) USING BTREE,
KEY `courseId` (`course_id`) USING BTREE,
CONSTRAINT `fk_coures_events_course_id` FOREIGN KEY (`course_id`) REFERENCES `courses` (`id`) ON UPDATE CASCADE,
CONSTRAINT `fk_course_events_event_type_id` FOREIGN KEY (`event_type`) REFERENCES `event_types` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;
*/
type TrainingEvent struct {
ObjectBase
EventType int `json:"event_type"`
EventDate string `json:"event_date"`
GuildedEventID int `json:"guilded_event_id"`
ReportURL string `json:"report_url"`
Course Course `json:"course" gorm:"references:ID; foreignkey:CourseID"`
CourseID int `json:"course_id"`
}
// Get one by id
func (te *TrainingEvent) GetByID(id int) error {
db, err := GetDB()
if err != nil {
return err
}
err = db.First(te, id).Error
return err
}
// Get all
func (te *TrainingEvent) GetAll() ([]TrainingEvent, error) {
db, err := GetDB()
if err != nil {
return nil, err
}
var tes []TrainingEvent
err = db.Find(&tes).Error
return tes, err
}
// Get all by course
func (te *TrainingEvent) GetAllByCourse(courseID int) ([]TrainingEvent, error) {
db, err := GetDB()
if err != nil {
return nil, err
}
var tes []TrainingEvent
err = db.Where("course_id = ?", courseID).Find(&tes).Error
return tes, err
}
// Create
func (te *TrainingEvent) Create() error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Create(te).Error
return err
}
// Update
func (te *TrainingEvent) Update() error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Save(te).Error
return err
}
// Delete
func (te *TrainingEvent) Delete() error {
db, err := GetDB()
if err != nil {
return err
}
err = db.Delete(te).Error
return err
}
// Get all by date range
func (te *TrainingEvent) GetByDateRange(start string, end string) ([]TrainingEvent, error) {
db, err := GetDB()
if err != nil {
return nil, err
}
var tes []TrainingEvent
err = db.Where("event_date BETWEEN ? AND ?", start, end).Find(&tes).Error
return tes, err
}