From ead7ca0f97b060c6684290dd9fb0d901328aa166 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 7 Feb 2026 01:30:52 -0800 Subject: [PATCH 01/56] event repository --- internal/domain/announcements.go | 11 ++++ internal/domain/event.go | 12 ++++ internal/domain/officer.go | 9 +++ internal/repository/event.go | 108 +++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 internal/domain/announcements.go create mode 100644 internal/domain/event.go create mode 100644 internal/domain/officer.go create mode 100644 internal/repository/event.go diff --git a/internal/domain/announcements.go b/internal/domain/announcements.go new file mode 100644 index 0000000..0c9b499 --- /dev/null +++ b/internal/domain/announcements.go @@ -0,0 +1,11 @@ +package domain + +import "time" + +type Announcements struct { + Uuid string + Visibility string + AnnounceAt time.Time + DiscordChannelID string + DiscordMessageID string +} diff --git a/internal/domain/event.go b/internal/domain/event.go new file mode 100644 index 0000000..3e56484 --- /dev/null +++ b/internal/domain/event.go @@ -0,0 +1,12 @@ +package domain + +import "time" + +type Event struct { + Uuid string + Location string + StartAt time.Time + EndAt time.Time + IsAllDay bool + Host string +} diff --git a/internal/domain/officer.go b/internal/domain/officer.go new file mode 100644 index 0000000..23c47ca --- /dev/null +++ b/internal/domain/officer.go @@ -0,0 +1,9 @@ +package domain + +type Officer struct { + Uuid string + FullName string + Picture string + Github string + Discord string +} diff --git a/internal/repository/event.go b/internal/repository/event.go new file mode 100644 index 0000000..6d995a3 --- /dev/null +++ b/internal/repository/event.go @@ -0,0 +1,108 @@ +package repository + +import ( + "context" + "database/sql" + "time" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + +type EventRepository interface { + GetAllEvents(ctx context.Context) ([]*domain.Event, error) + + GetEventByID(ctx context.Context, id string) (*domain.Event, error) + Delete(ctx context.Context, id string) error + + Create(ctx context.Context, args domain.Event) error + Update(ctx context.Context, args domain.Event) error +} + +type eventRepository struct { + db *dbmodels.Queries +} + +func NewEventRepository(db *dbmodels.Queries) EventRepository { + return &eventRepository{db: db} +} + +func (r *eventRepository) GetEventByID(ctx context.Context, id string) (*domain.Event, error) { + dbEvent, err := r.db.GetEvent(ctx, id) + if err != nil { + return nil, err + } + + return convertDBEventToDomain(&dbEvent), nil +} + +func (r *eventRepository) GetAllEvents(ctx context.Context) ([]*domain.Event, error) { + dbEvent, err := r.db.GetEvents(ctx) + if err != nil { + return nil, err + } + + var eventSlice []*domain.Event + for _, elm := range dbEvent { + eventSlice = append(eventSlice, convertDBEventToDomain(&elm)) + } + return eventSlice, nil +} + +func (r *eventRepository) Delete(ctx context.Context, id string) error { + err := r.db.DeleteEvent(ctx, id) + if err != nil { + return err + } + return nil +} + +func (r *eventRepository) Create(ctx context.Context, args domain.Event) error { + err := r.db.CreateEvent(ctx, *convertDomaintoCreateDBEvent(&args)) + if err != nil { + return err + } + return nil +} + +func (r *eventRepository) Update(ctx context.Context, args domain.Event) error { + err := r.db.UpdateEvent(ctx, *convertDomaintoUpdateDBEvent(&args)) + if err != nil { + return err + } + return nil +} + +// ---- Helper func ---- +func convertDBEventToDomain(dbEvent *dbmodels.Event) *domain.Event { + return &domain.Event{ + Uuid: dbEvent.Uuid, + Location: dbEvent.Location, + StartAt: time.Unix(dbEvent.StartAt, 0), + EndAt: time.Unix(dbEvent.EndAt, 0), + IsAllDay: dbEvent.IsAllDay, + Host: dbEvent.Host, + } +} + +func convertDomaintoCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventParams { + return &dbmodels.CreateEventParams{ + Uuid: dEvent.Uuid, + Location: dEvent.Location, + StartAt: dEvent.StartAt.Unix(), + EndAt: dEvent.EndAt.Unix(), + IsAllDay: dEvent.IsAllDay, + Host: dEvent.Host, + } +} + +func convertDomaintoUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventParams { + return &dbmodels.UpdateEventParams{ + Uuid: dEvent.Uuid, + Location: sql.NullString{String: dEvent.Location, Valid: true}, + StartAt: sql.NullInt64{Int64: dEvent.StartAt.Unix(), Valid: true}, + EndAt: sql.NullInt64{Int64: dEvent.EndAt.Unix(), Valid: true}, + IsAllDay: sql.NullBool{Bool: dEvent.IsAllDay, Valid: true}, + Host: sql.NullString{String: dEvent.Host, Valid: true}, + } +} From bb7a753e57eacb6405aed531ca6bbef48f28ef29 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 7 Feb 2026 02:00:16 -0800 Subject: [PATCH 02/56] officer repository --- internal/repository/announcements.go | 0 internal/repository/helpers.go | 74 ++++++++++++++++++++++++++ internal/repository/officer.go | 79 ++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 internal/repository/announcements.go create mode 100644 internal/repository/helpers.go create mode 100644 internal/repository/officer.go diff --git a/internal/repository/announcements.go b/internal/repository/announcements.go new file mode 100644 index 0000000..e69de29 diff --git a/internal/repository/helpers.go b/internal/repository/helpers.go new file mode 100644 index 0000000..8d68903 --- /dev/null +++ b/internal/repository/helpers.go @@ -0,0 +1,74 @@ +package repository + +import ( + "database/sql" + "time" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + +// ---- Event Helper ---- +func convertDBEventToDomain(dbEvent *dbmodels.Event) *domain.Event { + return &domain.Event{ + Uuid: dbEvent.Uuid, + Location: dbEvent.Location, + StartAt: time.Unix(dbEvent.StartAt, 0), + EndAt: time.Unix(dbEvent.EndAt, 0), + IsAllDay: dbEvent.IsAllDay, + Host: dbEvent.Host, + } +} + +func convertDomaintoCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventParams { + return &dbmodels.CreateEventParams{ + Uuid: dEvent.Uuid, + Location: dEvent.Location, + StartAt: dEvent.StartAt.Unix(), + EndAt: dEvent.EndAt.Unix(), + IsAllDay: dEvent.IsAllDay, + Host: dEvent.Host, + } +} + +func convertDomaintoUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventParams { + return &dbmodels.UpdateEventParams{ + Uuid: dEvent.Uuid, + Location: sql.NullString{String: dEvent.Location, Valid: true}, + StartAt: sql.NullInt64{Int64: dEvent.StartAt.Unix(), Valid: true}, + EndAt: sql.NullInt64{Int64: dEvent.EndAt.Unix(), Valid: true}, + IsAllDay: sql.NullBool{Bool: dEvent.IsAllDay, Valid: true}, + Host: sql.NullString{String: dEvent.Host, Valid: true}, + } +} + +// ---- Officer Helper ---- +func convertDBOfficerToDomain(dbOfficer *dbmodels.Officer) *domain.Officer { + return &domain.Officer{ + Uuid: dbOfficer.Uuid, + FullName: dbOfficer.FullName, + Picture: dbOfficer.Picture.String, + Github: dbOfficer.Github.String, + Discord: dbOfficer.Discord.String, + } +} + +func convertDomaintoCreateDBOfficer(dOfficer *domain.Officer) *dbmodels.CreateOfficerParams { + return &dbmodels.CreateOfficerParams{ + Uuid: dOfficer.Uuid, + FullName: dOfficer.FullName, + Picture: sql.NullString{String: dOfficer.Picture, Valid: true}, + Github: sql.NullString{String: dOfficer.Github, Valid: true}, + Discord: sql.NullString{String: dOfficer.Discord, Valid: true}, + } +} + +func convertDomaintoUpdateDBOfficer(dOfficer *domain.Officer) *dbmodels.UpdateOfficerParams { + return &dbmodels.UpdateOfficerParams{ + Uuid: dOfficer.Uuid, + FullName: dOfficer.FullName, + Picture: sql.NullString{String: dOfficer.Picture, Valid: true}, + Github: sql.NullString{String: dOfficer.Github, Valid: true}, + Discord: sql.NullString{String: dOfficer.Discord, Valid: true}, + } +} diff --git a/internal/repository/officer.go b/internal/repository/officer.go new file mode 100644 index 0000000..33f55d4 --- /dev/null +++ b/internal/repository/officer.go @@ -0,0 +1,79 @@ +package repository + +import ( + "context" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + +type OfficerRepository interface { + GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) + GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) + Create(ctx context.Context, args domain.Officer) error + Update(ctx context.Context, args domain.Officer) error + Delete(ctx context.Context, id string) error +} + +type officerRepository struct { + db *dbmodels.Queries +} + +func NewOfficerRepository(db *dbmodels.Queries) OfficerRepository { + return &officerRepository{db: db} +} + +func (r *officerRepository) GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) { + dbOfficers, err := r.db.GetOfficers(ctx) + if err != nil { + return nil, err + } + + var officers []*domain.Officer + for _, dbOfficer := range dbOfficers { + officers = append(officers, convertDBOfficerToDomain(&dbOfficer)) + } + return officers, nil +} + +func (r *officerRepository) GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) { + row, err := r.db.GetOfficer(ctx, id) // Get officers and get officers return completly different things? + + if err != nil { + return nil, err + } + + dbOfficer := dbmodels.Officer{ + Uuid: id, + FullName: row.FullName, + Picture: row.Picture, + Github: row.Github, + Discord: row.Discord, + } + + return convertDBOfficerToDomain(&dbOfficer), nil +} + +func (r *officerRepository) Delete(ctx context.Context, id string) error { + err := r.db.DeleteOfficer(ctx, id) + if err != nil { + return err + } + return nil +} + +func (r *officerRepository) Create(ctx context.Context, args domain.Officer) error { + _, err := r.db.CreateOfficer(ctx, *convertDomaintoCreateDBOfficer(&args)) + if err != nil { + return err + } + return nil +} + +func (r *officerRepository) Update(ctx context.Context, args domain.Officer) error { + err := r.db.UpdateOfficer(ctx, *convertDomaintoUpdateDBOfficer(&args)) + if err != nil { + return err + } + return nil +} From c8768b75f3202b0a4258476f9f16978f1a6181ec Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 7 Feb 2026 02:17:07 -0800 Subject: [PATCH 03/56] announcement repository --- internal/domain/announcements.go | 2 +- internal/repository/announcements.go | 72 ++++++++++++++++++++++++++++ internal/repository/helpers.go | 31 ++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/internal/domain/announcements.go b/internal/domain/announcements.go index 0c9b499..5019dfb 100644 --- a/internal/domain/announcements.go +++ b/internal/domain/announcements.go @@ -2,7 +2,7 @@ package domain import "time" -type Announcements struct { +type Announcement struct { Uuid string Visibility string AnnounceAt time.Time diff --git a/internal/repository/announcements.go b/internal/repository/announcements.go index e69de29..7ffd248 100644 --- a/internal/repository/announcements.go +++ b/internal/repository/announcements.go @@ -0,0 +1,72 @@ +package repository + +import ( + "context" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + +type AnnouncementRepository interface { + GetAllAnnouncements(ctx context.Context) ([]*domain.Announcement, error) + + GetAnnouncementByID(ctx context.Context, id string) (*domain.Announcement, error) + Delete(ctx context.Context, id string) error + + Create(ctx context.Context, args domain.Announcement) error + Update(ctx context.Context, args domain.Announcement) error +} + +type announcementRepository struct { + db *dbmodels.Queries +} + +func NewAnnouncementRepository(db *dbmodels.Queries) AnnouncementRepository { + return &announcementRepository{db: db} +} + +func (r *announcementRepository) GetAnnouncementByID(ctx context.Context, id string) (*domain.Announcement, error) { + dbAnnouncement, err := r.db.GetAnnouncement(ctx, id) + if err != nil { + return nil, err + } + + return convertDBAnnouncementToDomain(&dbAnnouncement), nil +} + +func (r *announcementRepository) GetAllAnnouncements(ctx context.Context) ([]*domain.Announcement, error) { + dbAnnouncement, err := r.db.GetAnnouncements(ctx) + if err != nil { + return nil, err + } + + var eventSlice []*domain.Announcement + for _, elm := range dbAnnouncement { + eventSlice = append(eventSlice, convertDBAnnouncementToDomain(&elm)) + } + return eventSlice, nil +} + +func (r *announcementRepository) Delete(ctx context.Context, id string) error { + err := r.db.DeleteAnnouncement(ctx, id) + if err != nil { + return err + } + return nil +} + +func (r *announcementRepository) Create(ctx context.Context, args domain.Announcement) error { + err := r.db.CreateAnnouncement(ctx, *convertDomaintoCreateDBAnnouncement(&args)) + if err != nil { + return err + } + return nil +} + +func (r *announcementRepository) Update(ctx context.Context, args domain.Announcement) error { + err := r.db.UpdateAnnouncement(ctx, *convertDomaintoUpdateDBAnnouncement(&args)) + if err != nil { + return err + } + return nil +} diff --git a/internal/repository/helpers.go b/internal/repository/helpers.go index 8d68903..723096b 100644 --- a/internal/repository/helpers.go +++ b/internal/repository/helpers.go @@ -72,3 +72,34 @@ func convertDomaintoUpdateDBOfficer(dOfficer *domain.Officer) *dbmodels.UpdateOf Discord: sql.NullString{String: dOfficer.Discord, Valid: true}, } } + +// ---- Announcement Helper ---- +func convertDBAnnouncementToDomain(dbAnnouncement *dbmodels.Announcement) *domain.Announcement { + return &domain.Announcement{ + Uuid: dbAnnouncement.Uuid, + Visibility: dbAnnouncement.Visibility, + AnnounceAt: time.Unix(dbAnnouncement.AnnounceAt, 0), + DiscordChannelID: dbAnnouncement.DiscordChannelID.String, + DiscordMessageID: dbAnnouncement.DiscordMessageID.String, + } +} + +func convertDomaintoCreateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.CreateAnnouncementParams { + return &dbmodels.CreateAnnouncementParams{ + Uuid: dAnnouncement.Uuid, + Visibility: dAnnouncement.Visibility, + AnnounceAt: dAnnouncement.AnnounceAt.Unix(), + DiscordChannelID: sql.NullString{String: dAnnouncement.DiscordChannelID, Valid: true}, + DiscordMessageID: sql.NullString{String: dAnnouncement.DiscordMessageID, Valid: true}, + } +} + +func convertDomaintoUpdateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.UpdateAnnouncementParams { + return &dbmodels.UpdateAnnouncementParams{ + Uuid: dAnnouncement.Uuid, + Visibility: sql.NullString{String: dAnnouncement.Visibility, Valid: true}, + AnnounceAt: sql.NullInt64{Int64: dAnnouncement.AnnounceAt.Unix(), Valid: true}, + DiscordChannelID: sql.NullString{String: dAnnouncement.DiscordChannelID, Valid: true}, + DiscordMessageID: sql.NullString{String: dAnnouncement.DiscordMessageID, Valid: true}, + } +} From b6dc46fbc25f46aeb9f8901d7801aa21231fa393 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 7 Feb 2026 12:44:18 -0800 Subject: [PATCH 04/56] Tiers repository --- internal/domain/tier.go | 8 ++ internal/repository/{helpers.go => conv.go} | 73 ++++++++++++++++--- internal/repository/event.go | 40 +--------- internal/repository/officer.go | 4 +- internal/repository/position.go | 81 +++++++++++++++++++++ internal/repository/tier.go | 71 ++++++++++++++++++ 6 files changed, 228 insertions(+), 49 deletions(-) create mode 100644 internal/domain/tier.go rename internal/repository/{helpers.go => conv.go} (60%) create mode 100644 internal/repository/position.go create mode 100644 internal/repository/tier.go diff --git a/internal/domain/tier.go b/internal/domain/tier.go new file mode 100644 index 0000000..fadefeb --- /dev/null +++ b/internal/domain/tier.go @@ -0,0 +1,8 @@ +package domain + +type Tier struct { + Tier int + Title string + Tindex int + Team string +} diff --git a/internal/repository/helpers.go b/internal/repository/conv.go similarity index 60% rename from internal/repository/helpers.go rename to internal/repository/conv.go index 723096b..f0625a0 100644 --- a/internal/repository/helpers.go +++ b/internal/repository/conv.go @@ -8,7 +8,9 @@ import ( "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" ) -// ---- Event Helper ---- +// File for converting Database models into Doamin models + +// ---- Event Converter ---- func convertDBEventToDomain(dbEvent *dbmodels.Event) *domain.Event { return &domain.Event{ Uuid: dbEvent.Uuid, @@ -20,7 +22,7 @@ func convertDBEventToDomain(dbEvent *dbmodels.Event) *domain.Event { } } -func convertDomaintoCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventParams { +func convertDomainToCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventParams { return &dbmodels.CreateEventParams{ Uuid: dEvent.Uuid, Location: dEvent.Location, @@ -31,7 +33,7 @@ func convertDomaintoCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventPar } } -func convertDomaintoUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventParams { +func convertDomainToUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventParams { return &dbmodels.UpdateEventParams{ Uuid: dEvent.Uuid, Location: sql.NullString{String: dEvent.Location, Valid: true}, @@ -42,7 +44,7 @@ func convertDomaintoUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventPar } } -// ---- Officer Helper ---- +// ---- Officer Converter ---- func convertDBOfficerToDomain(dbOfficer *dbmodels.Officer) *domain.Officer { return &domain.Officer{ Uuid: dbOfficer.Uuid, @@ -53,7 +55,7 @@ func convertDBOfficerToDomain(dbOfficer *dbmodels.Officer) *domain.Officer { } } -func convertDomaintoCreateDBOfficer(dOfficer *domain.Officer) *dbmodels.CreateOfficerParams { +func convertDomainToCreateDBOfficer(dOfficer *domain.Officer) *dbmodels.CreateOfficerParams { return &dbmodels.CreateOfficerParams{ Uuid: dOfficer.Uuid, FullName: dOfficer.FullName, @@ -63,7 +65,7 @@ func convertDomaintoCreateDBOfficer(dOfficer *domain.Officer) *dbmodels.CreateOf } } -func convertDomaintoUpdateDBOfficer(dOfficer *domain.Officer) *dbmodels.UpdateOfficerParams { +func convertDomainToUpdateDBOfficer(dOfficer *domain.Officer) *dbmodels.UpdateOfficerParams { return &dbmodels.UpdateOfficerParams{ Uuid: dOfficer.Uuid, FullName: dOfficer.FullName, @@ -73,7 +75,7 @@ func convertDomaintoUpdateDBOfficer(dOfficer *domain.Officer) *dbmodels.UpdateOf } } -// ---- Announcement Helper ---- +// ---- Announcement Converter ---- func convertDBAnnouncementToDomain(dbAnnouncement *dbmodels.Announcement) *domain.Announcement { return &domain.Announcement{ Uuid: dbAnnouncement.Uuid, @@ -84,7 +86,7 @@ func convertDBAnnouncementToDomain(dbAnnouncement *dbmodels.Announcement) *domai } } -func convertDomaintoCreateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.CreateAnnouncementParams { +func convertDomainToCreateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.CreateAnnouncementParams { return &dbmodels.CreateAnnouncementParams{ Uuid: dAnnouncement.Uuid, Visibility: dAnnouncement.Visibility, @@ -94,7 +96,7 @@ func convertDomaintoCreateDBAnnouncement(dAnnouncement *domain.Announcement) *db } } -func convertDomaintoUpdateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.UpdateAnnouncementParams { +func convertDomainToUpdateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.UpdateAnnouncementParams { return &dbmodels.UpdateAnnouncementParams{ Uuid: dAnnouncement.Uuid, Visibility: sql.NullString{String: dAnnouncement.Visibility, Valid: true}, @@ -103,3 +105,56 @@ func convertDomaintoUpdateDBAnnouncement(dAnnouncement *domain.Announcement) *db DiscordMessageID: sql.NullString{String: dAnnouncement.DiscordMessageID, Valid: true}, } } + +// ---- Tier Converter ---- +func convertDBTierToDomain(dbTier *dbmodels.Tier) *domain.Tier { + return &domain.Tier{ + Tier: int(dbTier.Tier), + Title: dbTier.Title.String, + Tindex: int(dbTier.TIndex.Int64), + Team: dbTier.Team.String, + } +} + +func convertDomainToCreateDBTier(dTier *domain.Tier) *dbmodels.CreateTierParams { + return &dbmodels.CreateTierParams{ + Tier: int64(dTier.Tier), + Title: sql.NullString{String: dTier.Title, Valid: true}, + TIndex: sql.NullInt64{Int64: int64(dTier.Tindex), Valid: true}, + Team: sql.NullString{String: dTier.Team, Valid: true}, + } +} + +func convertDomainToUpdateDBTier(dTier *domain.Tier) *dbmodels.UpdateTierParams { + return &dbmodels.UpdateTierParams{ + Tier: int64(dTier.Tier), + Title: sql.NullString{String: dTier.Title, Valid: true}, + TIndex: sql.NullInt64{Int64: int64(dTier.Tindex), Valid: true}, + Team: sql.NullString{String: dTier.Team, Valid: true}, + } +} + +// ---- Position Converter ---- +func convertDBPositionToDomain(dbPosition *dbmodels.Position) *domain.Position { + return &domain.Position{ + Oid: dbPosition.Oid, + Semester: dbPosition.Semester, + Tier: int(dbPosition.Tier), + } +} + +func convertDomainToCreateDBPosition(dPositon *domain.Position) *dbmodels.CreatePositionParams { + return &dbmodels.CreatePositionParams{ + Oid: dPositon.Oid, + Semester: dPositon.Semester, + Tier: int64(dPositon.Tier), + } +} + +func convertDomainToUpdateDBPosition(dPositon *domain.Position) *dbmodels.UpdatePositionParams { + return &dbmodels.UpdatePositionParams{ + Oid: dPositon.Oid, + Semester: dPositon.Semester, + Tier: int64(dPositon.Tier), + } +} diff --git a/internal/repository/event.go b/internal/repository/event.go index 6d995a3..b435f5f 100644 --- a/internal/repository/event.go +++ b/internal/repository/event.go @@ -2,8 +2,6 @@ package repository import ( "context" - "database/sql" - "time" "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" @@ -58,7 +56,7 @@ func (r *eventRepository) Delete(ctx context.Context, id string) error { } func (r *eventRepository) Create(ctx context.Context, args domain.Event) error { - err := r.db.CreateEvent(ctx, *convertDomaintoCreateDBEvent(&args)) + err := r.db.CreateEvent(ctx, *convertDomainToCreateDBEvent(&args)) if err != nil { return err } @@ -66,43 +64,9 @@ func (r *eventRepository) Create(ctx context.Context, args domain.Event) error { } func (r *eventRepository) Update(ctx context.Context, args domain.Event) error { - err := r.db.UpdateEvent(ctx, *convertDomaintoUpdateDBEvent(&args)) + err := r.db.UpdateEvent(ctx, *convertDomainToUpdateDBEvent(&args)) if err != nil { return err } return nil } - -// ---- Helper func ---- -func convertDBEventToDomain(dbEvent *dbmodels.Event) *domain.Event { - return &domain.Event{ - Uuid: dbEvent.Uuid, - Location: dbEvent.Location, - StartAt: time.Unix(dbEvent.StartAt, 0), - EndAt: time.Unix(dbEvent.EndAt, 0), - IsAllDay: dbEvent.IsAllDay, - Host: dbEvent.Host, - } -} - -func convertDomaintoCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventParams { - return &dbmodels.CreateEventParams{ - Uuid: dEvent.Uuid, - Location: dEvent.Location, - StartAt: dEvent.StartAt.Unix(), - EndAt: dEvent.EndAt.Unix(), - IsAllDay: dEvent.IsAllDay, - Host: dEvent.Host, - } -} - -func convertDomaintoUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventParams { - return &dbmodels.UpdateEventParams{ - Uuid: dEvent.Uuid, - Location: sql.NullString{String: dEvent.Location, Valid: true}, - StartAt: sql.NullInt64{Int64: dEvent.StartAt.Unix(), Valid: true}, - EndAt: sql.NullInt64{Int64: dEvent.EndAt.Unix(), Valid: true}, - IsAllDay: sql.NullBool{Bool: dEvent.IsAllDay, Valid: true}, - Host: sql.NullString{String: dEvent.Host, Valid: true}, - } -} diff --git a/internal/repository/officer.go b/internal/repository/officer.go index 33f55d4..bc8abbb 100644 --- a/internal/repository/officer.go +++ b/internal/repository/officer.go @@ -63,7 +63,7 @@ func (r *officerRepository) Delete(ctx context.Context, id string) error { } func (r *officerRepository) Create(ctx context.Context, args domain.Officer) error { - _, err := r.db.CreateOfficer(ctx, *convertDomaintoCreateDBOfficer(&args)) + _, err := r.db.CreateOfficer(ctx, *convertDomainToCreateDBOfficer(&args)) if err != nil { return err } @@ -71,7 +71,7 @@ func (r *officerRepository) Create(ctx context.Context, args domain.Officer) err } func (r *officerRepository) Update(ctx context.Context, args domain.Officer) error { - err := r.db.UpdateOfficer(ctx, *convertDomaintoUpdateDBOfficer(&args)) + err := r.db.UpdateOfficer(ctx, *convertDomainToUpdateDBOfficer(&args)) if err != nil { return err } diff --git a/internal/repository/position.go b/internal/repository/position.go new file mode 100644 index 0000000..84c1e63 --- /dev/null +++ b/internal/repository/position.go @@ -0,0 +1,81 @@ +/* +package repository + +import ( + "context" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + +type OfficerRepository interface { + GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) + GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) + Create(ctx context.Context, args domain.Officer) error + Update(ctx context.Context, args domain.Officer) error + Delete(ctx context.Context, id string) error +} + +type officerRepository struct { + db *dbmodels.Queries +} + +func NewOfficerRepository(db *dbmodels.Queries) OfficerRepository { + return &officerRepository{db: db} +} + +func (r *officerRepository) GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) { + dbOfficers, err := r.db.GetOfficers(ctx) + if err != nil { + return nil, err + } + + var officers []*domain.Officer + for _, dbOfficer := range dbOfficers { + officers = append(officers, convertDBOfficerToDomain(&dbOfficer)) + } + return officers, nil +} + +func (r *officerRepository) GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) { + row, err := r.db.GetOfficer(ctx, id) // Get officers and get officers return completly different things? + + if err != nil { + return nil, err + } + + dbOfficer := dbmodels.Officer{ + Uuid: id, + FullName: row.FullName, + Picture: row.Picture, + Github: row.Github, + Discord: row.Discord, + } + + return convertDBOfficerToDomain(&dbOfficer), nil +} + +func (r *officerRepository) Delete(ctx context.Context, id string) error { + err := r.db.DeleteOfficer(ctx, id) + if err != nil { + return err + } + return nil +} + +func (r *officerRepository) Create(ctx context.Context, args domain.Officer) error { + _, err := r.db.CreateOfficer(ctx, *convertDomaintoCreateDBOfficer(&args)) + if err != nil { + return err + } + return nil +} + +func (r *officerRepository) Update(ctx context.Context, args domain.Officer) error { + err := r.db.UpdateOfficer(ctx, *convertDomaintoUpdateDBOfficer(&args)) + if err != nil { + return err + } + return nil +} +*/ \ No newline at end of file diff --git a/internal/repository/tier.go b/internal/repository/tier.go new file mode 100644 index 0000000..b1de681 --- /dev/null +++ b/internal/repository/tier.go @@ -0,0 +1,71 @@ +package repository + +import ( + "context" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + +type TierRepository interface { + GetAllTiers(ctx context.Context) ([]*domain.Tier, error) + GetTierByID(ctx context.Context, id int64) (*domain.Tier, error) + Create(ctx context.Context, args domain.Tier) error + Update(ctx context.Context, args domain.Tier) error + Delete(ctx context.Context, id int64) error +} + +type tierRepository struct { + db *dbmodels.Queries +} + +func NewTierRepository(db *dbmodels.Queries) TierRepository { + return &tierRepository{db: db} +} + +func (r *tierRepository) GetAllTiers(ctx context.Context) ([]*domain.Tier, error) { + dbTiers, err := r.db.GetTiers(ctx) + if err != nil { + return nil, err + } + + var Tiers []*domain.Tier + for _, dbTier := range dbTiers { + Tiers = append(Tiers, convertDBTierToDomain(&dbTier)) + } + return Tiers, nil +} + +func (r *tierRepository) GetTierByID(ctx context.Context, id int64) (*domain.Tier, error) { + dbTier, err := r.db.GetTier(ctx, id) + + if err != nil { + return nil, err + } + + return convertDBTierToDomain(&dbTier), nil +} + +func (r *tierRepository) Delete(ctx context.Context, id int64) error { + err := r.db.DeleteTier(ctx, id) + if err != nil { + return err + } + return nil +} + +func (r *tierRepository) Create(ctx context.Context, args domain.Tier) error { + _, err := r.db.CreateTier(ctx, *convertDomainToCreateDBTier(&args)) + if err != nil { + return err + } + return nil +} + +func (r *tierRepository) Update(ctx context.Context, args domain.Tier) error { + err := r.db.UpdateTier(ctx, *convertDomainToUpdateDBTier(&args)) + if err != nil { + return err + } + return nil +} From 95c4edf9d8d0a5bc7acc052f2d4c394b78f18875 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 7 Feb 2026 12:56:55 -0800 Subject: [PATCH 05/56] Positions repository --- internal/domain/position.go | 7 ++++ internal/repository/conv.go | 8 +++++ internal/repository/position.go | 59 ++++++++++++++------------------- 3 files changed, 39 insertions(+), 35 deletions(-) create mode 100644 internal/domain/position.go diff --git a/internal/domain/position.go b/internal/domain/position.go new file mode 100644 index 0000000..9c0978a --- /dev/null +++ b/internal/domain/position.go @@ -0,0 +1,7 @@ +package domain + +type Position struct { + Oid string + Semester string + Tier int +} diff --git a/internal/repository/conv.go b/internal/repository/conv.go index f0625a0..43e4cba 100644 --- a/internal/repository/conv.go +++ b/internal/repository/conv.go @@ -158,3 +158,11 @@ func convertDomainToUpdateDBPosition(dPositon *domain.Position) *dbmodels.Update Tier: int64(dPositon.Tier), } } + +func convertDomainToDeleteDBPosition(dPositon *domain.Position) *dbmodels.DeletePositionParams { + return &dbmodels.DeletePositionParams{ + Oid: dPositon.Oid, + Semester: dPositon.Semester, + Tier: int64(dPositon.Tier), + } +} diff --git a/internal/repository/position.go b/internal/repository/position.go index 84c1e63..4b78358 100644 --- a/internal/repository/position.go +++ b/internal/repository/position.go @@ -1,4 +1,3 @@ -/* package repository import ( @@ -8,74 +7,64 @@ import ( "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" ) -type OfficerRepository interface { - GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) - GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) - Create(ctx context.Context, args domain.Officer) error - Update(ctx context.Context, args domain.Officer) error - Delete(ctx context.Context, id string) error +type PositionRepository interface { + GetAllpositions(ctx context.Context) ([]*domain.Officer, error) + GetpositionByID(ctx context.Context, id string) (*domain.Officer, error) + Create(ctx context.Context, args domain.Position) error + Update(ctx context.Context, args domain.Position) error + Delete(ctx context.Context, args domain.Position) error } -type officerRepository struct { +type positionRepository struct { db *dbmodels.Queries } -func NewOfficerRepository(db *dbmodels.Queries) OfficerRepository { - return &officerRepository{db: db} +func NewPositionRepository(db *dbmodels.Queries) OfficerRepository { + return &positionRepository{db: db} } -func (r *officerRepository) GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) { - dbOfficers, err := r.db.GetOfficers(ctx) +func (r *positionRepository) GetAllPositions(ctx context.Context) ([]*domain.Position, error) { + dbPositions, err := r.db.GetPositions(ctx) if err != nil { return nil, err } - var officers []*domain.Officer - for _, dbOfficer := range dbOfficers { - officers = append(officers, convertDBOfficerToDomain(&dbOfficer)) + var positions []*domain.Position + for _, dbPosition := range dbPositions { + positions = append(positions, convertDBPositionToDomain(&dbPosition)) } - return officers, nil + return positions, nil } -func (r *officerRepository) GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) { - row, err := r.db.GetOfficer(ctx, id) // Get officers and get officers return completly different things? - +func (r *positionRepository) GetPositionByID(ctx context.Context, id string) (*domain.Position, error) { + dbPosition, err := r.db.GetPosition(ctx, id) if err != nil { return nil, err } - dbOfficer := dbmodels.Officer{ - Uuid: id, - FullName: row.FullName, - Picture: row.Picture, - Github: row.Github, - Discord: row.Discord, - } - - return convertDBOfficerToDomain(&dbOfficer), nil + return convertDBPositionToDomain(&dbPosition), nil } -func (r *officerRepository) Delete(ctx context.Context, id string) error { - err := r.db.DeleteOfficer(ctx, id) +func (r *positionRepository) Delete(ctx context.Context, args domain.Position) error { + err := r.db.DeletePosition(ctx, *convertDomainToDeleteDBPosition(&args)) if err != nil { return err } return nil } -func (r *officerRepository) Create(ctx context.Context, args domain.Officer) error { - _, err := r.db.CreateOfficer(ctx, *convertDomaintoCreateDBOfficer(&args)) +func (r *positionRepository) Create(ctx context.Context, args domain.Position) error { + _, err := r.db.CreatePosition(ctx, *convertDomainToCreateDBPosition(&args)) if err != nil { return err } return nil } -func (r *officerRepository) Update(ctx context.Context, args domain.Officer) error { - err := r.db.UpdateOfficer(ctx, *convertDomaintoUpdateDBOfficer(&args)) +func (r *positionRepository) Update(ctx context.Context, args domain.Position) error { + err := r.db.UpdatePosition(ctx, *convertDomainToUpdateDBPosition(&args)) if err != nil { return err } return nil } -*/ \ No newline at end of file From e5468cf0f11b4a37272a149f7fdb64cb331569dd Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 7 Feb 2026 12:58:53 -0800 Subject: [PATCH 06/56] quick fix in positions repository --- internal/repository/position.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/repository/position.go b/internal/repository/position.go index 4b78358..727c26b 100644 --- a/internal/repository/position.go +++ b/internal/repository/position.go @@ -8,8 +8,8 @@ import ( ) type PositionRepository interface { - GetAllpositions(ctx context.Context) ([]*domain.Officer, error) - GetpositionByID(ctx context.Context, id string) (*domain.Officer, error) + GetAllPositions(ctx context.Context) ([]*domain.Position, error) + GetPositionByID(ctx context.Context, id string) (*domain.Position, error) Create(ctx context.Context, args domain.Position) error Update(ctx context.Context, args domain.Position) error Delete(ctx context.Context, args domain.Position) error @@ -19,7 +19,7 @@ type positionRepository struct { db *dbmodels.Queries } -func NewPositionRepository(db *dbmodels.Queries) OfficerRepository { +func NewPositionRepository(db *dbmodels.Queries) PositionRepository { return &positionRepository{db: db} } From ed7770541216cac2503d4907bf2ee3c3fd68bec1 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 7 Feb 2026 01:30:52 -0800 Subject: [PATCH 07/56] event repository --- internal/domain/announcements.go | 11 ++++ internal/domain/event.go | 12 ++++ internal/domain/officer.go | 9 +++ internal/repository/event.go | 108 +++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+) create mode 100644 internal/domain/announcements.go create mode 100644 internal/domain/event.go create mode 100644 internal/domain/officer.go create mode 100644 internal/repository/event.go diff --git a/internal/domain/announcements.go b/internal/domain/announcements.go new file mode 100644 index 0000000..0c9b499 --- /dev/null +++ b/internal/domain/announcements.go @@ -0,0 +1,11 @@ +package domain + +import "time" + +type Announcements struct { + Uuid string + Visibility string + AnnounceAt time.Time + DiscordChannelID string + DiscordMessageID string +} diff --git a/internal/domain/event.go b/internal/domain/event.go new file mode 100644 index 0000000..3e56484 --- /dev/null +++ b/internal/domain/event.go @@ -0,0 +1,12 @@ +package domain + +import "time" + +type Event struct { + Uuid string + Location string + StartAt time.Time + EndAt time.Time + IsAllDay bool + Host string +} diff --git a/internal/domain/officer.go b/internal/domain/officer.go new file mode 100644 index 0000000..23c47ca --- /dev/null +++ b/internal/domain/officer.go @@ -0,0 +1,9 @@ +package domain + +type Officer struct { + Uuid string + FullName string + Picture string + Github string + Discord string +} diff --git a/internal/repository/event.go b/internal/repository/event.go new file mode 100644 index 0000000..6d995a3 --- /dev/null +++ b/internal/repository/event.go @@ -0,0 +1,108 @@ +package repository + +import ( + "context" + "database/sql" + "time" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + +type EventRepository interface { + GetAllEvents(ctx context.Context) ([]*domain.Event, error) + + GetEventByID(ctx context.Context, id string) (*domain.Event, error) + Delete(ctx context.Context, id string) error + + Create(ctx context.Context, args domain.Event) error + Update(ctx context.Context, args domain.Event) error +} + +type eventRepository struct { + db *dbmodels.Queries +} + +func NewEventRepository(db *dbmodels.Queries) EventRepository { + return &eventRepository{db: db} +} + +func (r *eventRepository) GetEventByID(ctx context.Context, id string) (*domain.Event, error) { + dbEvent, err := r.db.GetEvent(ctx, id) + if err != nil { + return nil, err + } + + return convertDBEventToDomain(&dbEvent), nil +} + +func (r *eventRepository) GetAllEvents(ctx context.Context) ([]*domain.Event, error) { + dbEvent, err := r.db.GetEvents(ctx) + if err != nil { + return nil, err + } + + var eventSlice []*domain.Event + for _, elm := range dbEvent { + eventSlice = append(eventSlice, convertDBEventToDomain(&elm)) + } + return eventSlice, nil +} + +func (r *eventRepository) Delete(ctx context.Context, id string) error { + err := r.db.DeleteEvent(ctx, id) + if err != nil { + return err + } + return nil +} + +func (r *eventRepository) Create(ctx context.Context, args domain.Event) error { + err := r.db.CreateEvent(ctx, *convertDomaintoCreateDBEvent(&args)) + if err != nil { + return err + } + return nil +} + +func (r *eventRepository) Update(ctx context.Context, args domain.Event) error { + err := r.db.UpdateEvent(ctx, *convertDomaintoUpdateDBEvent(&args)) + if err != nil { + return err + } + return nil +} + +// ---- Helper func ---- +func convertDBEventToDomain(dbEvent *dbmodels.Event) *domain.Event { + return &domain.Event{ + Uuid: dbEvent.Uuid, + Location: dbEvent.Location, + StartAt: time.Unix(dbEvent.StartAt, 0), + EndAt: time.Unix(dbEvent.EndAt, 0), + IsAllDay: dbEvent.IsAllDay, + Host: dbEvent.Host, + } +} + +func convertDomaintoCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventParams { + return &dbmodels.CreateEventParams{ + Uuid: dEvent.Uuid, + Location: dEvent.Location, + StartAt: dEvent.StartAt.Unix(), + EndAt: dEvent.EndAt.Unix(), + IsAllDay: dEvent.IsAllDay, + Host: dEvent.Host, + } +} + +func convertDomaintoUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventParams { + return &dbmodels.UpdateEventParams{ + Uuid: dEvent.Uuid, + Location: sql.NullString{String: dEvent.Location, Valid: true}, + StartAt: sql.NullInt64{Int64: dEvent.StartAt.Unix(), Valid: true}, + EndAt: sql.NullInt64{Int64: dEvent.EndAt.Unix(), Valid: true}, + IsAllDay: sql.NullBool{Bool: dEvent.IsAllDay, Valid: true}, + Host: sql.NullString{String: dEvent.Host, Valid: true}, + } +} From 9b64cca48ef3d61910b717babe7fec67e1a36be9 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 7 Feb 2026 02:00:16 -0800 Subject: [PATCH 08/56] officer repository --- internal/repository/announcements.go | 0 internal/repository/helpers.go | 74 ++++++++++++++++++++++++++ internal/repository/officer.go | 79 ++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 internal/repository/announcements.go create mode 100644 internal/repository/helpers.go create mode 100644 internal/repository/officer.go diff --git a/internal/repository/announcements.go b/internal/repository/announcements.go new file mode 100644 index 0000000..e69de29 diff --git a/internal/repository/helpers.go b/internal/repository/helpers.go new file mode 100644 index 0000000..8d68903 --- /dev/null +++ b/internal/repository/helpers.go @@ -0,0 +1,74 @@ +package repository + +import ( + "database/sql" + "time" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + +// ---- Event Helper ---- +func convertDBEventToDomain(dbEvent *dbmodels.Event) *domain.Event { + return &domain.Event{ + Uuid: dbEvent.Uuid, + Location: dbEvent.Location, + StartAt: time.Unix(dbEvent.StartAt, 0), + EndAt: time.Unix(dbEvent.EndAt, 0), + IsAllDay: dbEvent.IsAllDay, + Host: dbEvent.Host, + } +} + +func convertDomaintoCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventParams { + return &dbmodels.CreateEventParams{ + Uuid: dEvent.Uuid, + Location: dEvent.Location, + StartAt: dEvent.StartAt.Unix(), + EndAt: dEvent.EndAt.Unix(), + IsAllDay: dEvent.IsAllDay, + Host: dEvent.Host, + } +} + +func convertDomaintoUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventParams { + return &dbmodels.UpdateEventParams{ + Uuid: dEvent.Uuid, + Location: sql.NullString{String: dEvent.Location, Valid: true}, + StartAt: sql.NullInt64{Int64: dEvent.StartAt.Unix(), Valid: true}, + EndAt: sql.NullInt64{Int64: dEvent.EndAt.Unix(), Valid: true}, + IsAllDay: sql.NullBool{Bool: dEvent.IsAllDay, Valid: true}, + Host: sql.NullString{String: dEvent.Host, Valid: true}, + } +} + +// ---- Officer Helper ---- +func convertDBOfficerToDomain(dbOfficer *dbmodels.Officer) *domain.Officer { + return &domain.Officer{ + Uuid: dbOfficer.Uuid, + FullName: dbOfficer.FullName, + Picture: dbOfficer.Picture.String, + Github: dbOfficer.Github.String, + Discord: dbOfficer.Discord.String, + } +} + +func convertDomaintoCreateDBOfficer(dOfficer *domain.Officer) *dbmodels.CreateOfficerParams { + return &dbmodels.CreateOfficerParams{ + Uuid: dOfficer.Uuid, + FullName: dOfficer.FullName, + Picture: sql.NullString{String: dOfficer.Picture, Valid: true}, + Github: sql.NullString{String: dOfficer.Github, Valid: true}, + Discord: sql.NullString{String: dOfficer.Discord, Valid: true}, + } +} + +func convertDomaintoUpdateDBOfficer(dOfficer *domain.Officer) *dbmodels.UpdateOfficerParams { + return &dbmodels.UpdateOfficerParams{ + Uuid: dOfficer.Uuid, + FullName: dOfficer.FullName, + Picture: sql.NullString{String: dOfficer.Picture, Valid: true}, + Github: sql.NullString{String: dOfficer.Github, Valid: true}, + Discord: sql.NullString{String: dOfficer.Discord, Valid: true}, + } +} diff --git a/internal/repository/officer.go b/internal/repository/officer.go new file mode 100644 index 0000000..33f55d4 --- /dev/null +++ b/internal/repository/officer.go @@ -0,0 +1,79 @@ +package repository + +import ( + "context" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + +type OfficerRepository interface { + GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) + GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) + Create(ctx context.Context, args domain.Officer) error + Update(ctx context.Context, args domain.Officer) error + Delete(ctx context.Context, id string) error +} + +type officerRepository struct { + db *dbmodels.Queries +} + +func NewOfficerRepository(db *dbmodels.Queries) OfficerRepository { + return &officerRepository{db: db} +} + +func (r *officerRepository) GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) { + dbOfficers, err := r.db.GetOfficers(ctx) + if err != nil { + return nil, err + } + + var officers []*domain.Officer + for _, dbOfficer := range dbOfficers { + officers = append(officers, convertDBOfficerToDomain(&dbOfficer)) + } + return officers, nil +} + +func (r *officerRepository) GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) { + row, err := r.db.GetOfficer(ctx, id) // Get officers and get officers return completly different things? + + if err != nil { + return nil, err + } + + dbOfficer := dbmodels.Officer{ + Uuid: id, + FullName: row.FullName, + Picture: row.Picture, + Github: row.Github, + Discord: row.Discord, + } + + return convertDBOfficerToDomain(&dbOfficer), nil +} + +func (r *officerRepository) Delete(ctx context.Context, id string) error { + err := r.db.DeleteOfficer(ctx, id) + if err != nil { + return err + } + return nil +} + +func (r *officerRepository) Create(ctx context.Context, args domain.Officer) error { + _, err := r.db.CreateOfficer(ctx, *convertDomaintoCreateDBOfficer(&args)) + if err != nil { + return err + } + return nil +} + +func (r *officerRepository) Update(ctx context.Context, args domain.Officer) error { + err := r.db.UpdateOfficer(ctx, *convertDomaintoUpdateDBOfficer(&args)) + if err != nil { + return err + } + return nil +} From 60375dfaf60ba5aefd1fe7e583d3115bd0bda6ad Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 7 Feb 2026 02:17:07 -0800 Subject: [PATCH 09/56] announcement repository --- internal/domain/announcements.go | 2 +- internal/repository/announcements.go | 72 ++++++++++++++++++++++++++++ internal/repository/helpers.go | 31 ++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/internal/domain/announcements.go b/internal/domain/announcements.go index 0c9b499..5019dfb 100644 --- a/internal/domain/announcements.go +++ b/internal/domain/announcements.go @@ -2,7 +2,7 @@ package domain import "time" -type Announcements struct { +type Announcement struct { Uuid string Visibility string AnnounceAt time.Time diff --git a/internal/repository/announcements.go b/internal/repository/announcements.go index e69de29..7ffd248 100644 --- a/internal/repository/announcements.go +++ b/internal/repository/announcements.go @@ -0,0 +1,72 @@ +package repository + +import ( + "context" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + +type AnnouncementRepository interface { + GetAllAnnouncements(ctx context.Context) ([]*domain.Announcement, error) + + GetAnnouncementByID(ctx context.Context, id string) (*domain.Announcement, error) + Delete(ctx context.Context, id string) error + + Create(ctx context.Context, args domain.Announcement) error + Update(ctx context.Context, args domain.Announcement) error +} + +type announcementRepository struct { + db *dbmodels.Queries +} + +func NewAnnouncementRepository(db *dbmodels.Queries) AnnouncementRepository { + return &announcementRepository{db: db} +} + +func (r *announcementRepository) GetAnnouncementByID(ctx context.Context, id string) (*domain.Announcement, error) { + dbAnnouncement, err := r.db.GetAnnouncement(ctx, id) + if err != nil { + return nil, err + } + + return convertDBAnnouncementToDomain(&dbAnnouncement), nil +} + +func (r *announcementRepository) GetAllAnnouncements(ctx context.Context) ([]*domain.Announcement, error) { + dbAnnouncement, err := r.db.GetAnnouncements(ctx) + if err != nil { + return nil, err + } + + var eventSlice []*domain.Announcement + for _, elm := range dbAnnouncement { + eventSlice = append(eventSlice, convertDBAnnouncementToDomain(&elm)) + } + return eventSlice, nil +} + +func (r *announcementRepository) Delete(ctx context.Context, id string) error { + err := r.db.DeleteAnnouncement(ctx, id) + if err != nil { + return err + } + return nil +} + +func (r *announcementRepository) Create(ctx context.Context, args domain.Announcement) error { + err := r.db.CreateAnnouncement(ctx, *convertDomaintoCreateDBAnnouncement(&args)) + if err != nil { + return err + } + return nil +} + +func (r *announcementRepository) Update(ctx context.Context, args domain.Announcement) error { + err := r.db.UpdateAnnouncement(ctx, *convertDomaintoUpdateDBAnnouncement(&args)) + if err != nil { + return err + } + return nil +} diff --git a/internal/repository/helpers.go b/internal/repository/helpers.go index 8d68903..723096b 100644 --- a/internal/repository/helpers.go +++ b/internal/repository/helpers.go @@ -72,3 +72,34 @@ func convertDomaintoUpdateDBOfficer(dOfficer *domain.Officer) *dbmodels.UpdateOf Discord: sql.NullString{String: dOfficer.Discord, Valid: true}, } } + +// ---- Announcement Helper ---- +func convertDBAnnouncementToDomain(dbAnnouncement *dbmodels.Announcement) *domain.Announcement { + return &domain.Announcement{ + Uuid: dbAnnouncement.Uuid, + Visibility: dbAnnouncement.Visibility, + AnnounceAt: time.Unix(dbAnnouncement.AnnounceAt, 0), + DiscordChannelID: dbAnnouncement.DiscordChannelID.String, + DiscordMessageID: dbAnnouncement.DiscordMessageID.String, + } +} + +func convertDomaintoCreateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.CreateAnnouncementParams { + return &dbmodels.CreateAnnouncementParams{ + Uuid: dAnnouncement.Uuid, + Visibility: dAnnouncement.Visibility, + AnnounceAt: dAnnouncement.AnnounceAt.Unix(), + DiscordChannelID: sql.NullString{String: dAnnouncement.DiscordChannelID, Valid: true}, + DiscordMessageID: sql.NullString{String: dAnnouncement.DiscordMessageID, Valid: true}, + } +} + +func convertDomaintoUpdateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.UpdateAnnouncementParams { + return &dbmodels.UpdateAnnouncementParams{ + Uuid: dAnnouncement.Uuid, + Visibility: sql.NullString{String: dAnnouncement.Visibility, Valid: true}, + AnnounceAt: sql.NullInt64{Int64: dAnnouncement.AnnounceAt.Unix(), Valid: true}, + DiscordChannelID: sql.NullString{String: dAnnouncement.DiscordChannelID, Valid: true}, + DiscordMessageID: sql.NullString{String: dAnnouncement.DiscordMessageID, Valid: true}, + } +} From 0c72d90167a7bb8344d131a7a9ba2337b78fa1d0 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 7 Feb 2026 12:44:18 -0800 Subject: [PATCH 10/56] Tiers repository --- internal/domain/tier.go | 8 ++ internal/repository/{helpers.go => conv.go} | 73 ++++++++++++++++--- internal/repository/event.go | 40 +--------- internal/repository/officer.go | 4 +- internal/repository/position.go | 81 +++++++++++++++++++++ internal/repository/tier.go | 71 ++++++++++++++++++ 6 files changed, 228 insertions(+), 49 deletions(-) create mode 100644 internal/domain/tier.go rename internal/repository/{helpers.go => conv.go} (60%) create mode 100644 internal/repository/position.go create mode 100644 internal/repository/tier.go diff --git a/internal/domain/tier.go b/internal/domain/tier.go new file mode 100644 index 0000000..fadefeb --- /dev/null +++ b/internal/domain/tier.go @@ -0,0 +1,8 @@ +package domain + +type Tier struct { + Tier int + Title string + Tindex int + Team string +} diff --git a/internal/repository/helpers.go b/internal/repository/conv.go similarity index 60% rename from internal/repository/helpers.go rename to internal/repository/conv.go index 723096b..f0625a0 100644 --- a/internal/repository/helpers.go +++ b/internal/repository/conv.go @@ -8,7 +8,9 @@ import ( "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" ) -// ---- Event Helper ---- +// File for converting Database models into Doamin models + +// ---- Event Converter ---- func convertDBEventToDomain(dbEvent *dbmodels.Event) *domain.Event { return &domain.Event{ Uuid: dbEvent.Uuid, @@ -20,7 +22,7 @@ func convertDBEventToDomain(dbEvent *dbmodels.Event) *domain.Event { } } -func convertDomaintoCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventParams { +func convertDomainToCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventParams { return &dbmodels.CreateEventParams{ Uuid: dEvent.Uuid, Location: dEvent.Location, @@ -31,7 +33,7 @@ func convertDomaintoCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventPar } } -func convertDomaintoUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventParams { +func convertDomainToUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventParams { return &dbmodels.UpdateEventParams{ Uuid: dEvent.Uuid, Location: sql.NullString{String: dEvent.Location, Valid: true}, @@ -42,7 +44,7 @@ func convertDomaintoUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventPar } } -// ---- Officer Helper ---- +// ---- Officer Converter ---- func convertDBOfficerToDomain(dbOfficer *dbmodels.Officer) *domain.Officer { return &domain.Officer{ Uuid: dbOfficer.Uuid, @@ -53,7 +55,7 @@ func convertDBOfficerToDomain(dbOfficer *dbmodels.Officer) *domain.Officer { } } -func convertDomaintoCreateDBOfficer(dOfficer *domain.Officer) *dbmodels.CreateOfficerParams { +func convertDomainToCreateDBOfficer(dOfficer *domain.Officer) *dbmodels.CreateOfficerParams { return &dbmodels.CreateOfficerParams{ Uuid: dOfficer.Uuid, FullName: dOfficer.FullName, @@ -63,7 +65,7 @@ func convertDomaintoCreateDBOfficer(dOfficer *domain.Officer) *dbmodels.CreateOf } } -func convertDomaintoUpdateDBOfficer(dOfficer *domain.Officer) *dbmodels.UpdateOfficerParams { +func convertDomainToUpdateDBOfficer(dOfficer *domain.Officer) *dbmodels.UpdateOfficerParams { return &dbmodels.UpdateOfficerParams{ Uuid: dOfficer.Uuid, FullName: dOfficer.FullName, @@ -73,7 +75,7 @@ func convertDomaintoUpdateDBOfficer(dOfficer *domain.Officer) *dbmodels.UpdateOf } } -// ---- Announcement Helper ---- +// ---- Announcement Converter ---- func convertDBAnnouncementToDomain(dbAnnouncement *dbmodels.Announcement) *domain.Announcement { return &domain.Announcement{ Uuid: dbAnnouncement.Uuid, @@ -84,7 +86,7 @@ func convertDBAnnouncementToDomain(dbAnnouncement *dbmodels.Announcement) *domai } } -func convertDomaintoCreateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.CreateAnnouncementParams { +func convertDomainToCreateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.CreateAnnouncementParams { return &dbmodels.CreateAnnouncementParams{ Uuid: dAnnouncement.Uuid, Visibility: dAnnouncement.Visibility, @@ -94,7 +96,7 @@ func convertDomaintoCreateDBAnnouncement(dAnnouncement *domain.Announcement) *db } } -func convertDomaintoUpdateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.UpdateAnnouncementParams { +func convertDomainToUpdateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.UpdateAnnouncementParams { return &dbmodels.UpdateAnnouncementParams{ Uuid: dAnnouncement.Uuid, Visibility: sql.NullString{String: dAnnouncement.Visibility, Valid: true}, @@ -103,3 +105,56 @@ func convertDomaintoUpdateDBAnnouncement(dAnnouncement *domain.Announcement) *db DiscordMessageID: sql.NullString{String: dAnnouncement.DiscordMessageID, Valid: true}, } } + +// ---- Tier Converter ---- +func convertDBTierToDomain(dbTier *dbmodels.Tier) *domain.Tier { + return &domain.Tier{ + Tier: int(dbTier.Tier), + Title: dbTier.Title.String, + Tindex: int(dbTier.TIndex.Int64), + Team: dbTier.Team.String, + } +} + +func convertDomainToCreateDBTier(dTier *domain.Tier) *dbmodels.CreateTierParams { + return &dbmodels.CreateTierParams{ + Tier: int64(dTier.Tier), + Title: sql.NullString{String: dTier.Title, Valid: true}, + TIndex: sql.NullInt64{Int64: int64(dTier.Tindex), Valid: true}, + Team: sql.NullString{String: dTier.Team, Valid: true}, + } +} + +func convertDomainToUpdateDBTier(dTier *domain.Tier) *dbmodels.UpdateTierParams { + return &dbmodels.UpdateTierParams{ + Tier: int64(dTier.Tier), + Title: sql.NullString{String: dTier.Title, Valid: true}, + TIndex: sql.NullInt64{Int64: int64(dTier.Tindex), Valid: true}, + Team: sql.NullString{String: dTier.Team, Valid: true}, + } +} + +// ---- Position Converter ---- +func convertDBPositionToDomain(dbPosition *dbmodels.Position) *domain.Position { + return &domain.Position{ + Oid: dbPosition.Oid, + Semester: dbPosition.Semester, + Tier: int(dbPosition.Tier), + } +} + +func convertDomainToCreateDBPosition(dPositon *domain.Position) *dbmodels.CreatePositionParams { + return &dbmodels.CreatePositionParams{ + Oid: dPositon.Oid, + Semester: dPositon.Semester, + Tier: int64(dPositon.Tier), + } +} + +func convertDomainToUpdateDBPosition(dPositon *domain.Position) *dbmodels.UpdatePositionParams { + return &dbmodels.UpdatePositionParams{ + Oid: dPositon.Oid, + Semester: dPositon.Semester, + Tier: int64(dPositon.Tier), + } +} diff --git a/internal/repository/event.go b/internal/repository/event.go index 6d995a3..b435f5f 100644 --- a/internal/repository/event.go +++ b/internal/repository/event.go @@ -2,8 +2,6 @@ package repository import ( "context" - "database/sql" - "time" "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" @@ -58,7 +56,7 @@ func (r *eventRepository) Delete(ctx context.Context, id string) error { } func (r *eventRepository) Create(ctx context.Context, args domain.Event) error { - err := r.db.CreateEvent(ctx, *convertDomaintoCreateDBEvent(&args)) + err := r.db.CreateEvent(ctx, *convertDomainToCreateDBEvent(&args)) if err != nil { return err } @@ -66,43 +64,9 @@ func (r *eventRepository) Create(ctx context.Context, args domain.Event) error { } func (r *eventRepository) Update(ctx context.Context, args domain.Event) error { - err := r.db.UpdateEvent(ctx, *convertDomaintoUpdateDBEvent(&args)) + err := r.db.UpdateEvent(ctx, *convertDomainToUpdateDBEvent(&args)) if err != nil { return err } return nil } - -// ---- Helper func ---- -func convertDBEventToDomain(dbEvent *dbmodels.Event) *domain.Event { - return &domain.Event{ - Uuid: dbEvent.Uuid, - Location: dbEvent.Location, - StartAt: time.Unix(dbEvent.StartAt, 0), - EndAt: time.Unix(dbEvent.EndAt, 0), - IsAllDay: dbEvent.IsAllDay, - Host: dbEvent.Host, - } -} - -func convertDomaintoCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventParams { - return &dbmodels.CreateEventParams{ - Uuid: dEvent.Uuid, - Location: dEvent.Location, - StartAt: dEvent.StartAt.Unix(), - EndAt: dEvent.EndAt.Unix(), - IsAllDay: dEvent.IsAllDay, - Host: dEvent.Host, - } -} - -func convertDomaintoUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventParams { - return &dbmodels.UpdateEventParams{ - Uuid: dEvent.Uuid, - Location: sql.NullString{String: dEvent.Location, Valid: true}, - StartAt: sql.NullInt64{Int64: dEvent.StartAt.Unix(), Valid: true}, - EndAt: sql.NullInt64{Int64: dEvent.EndAt.Unix(), Valid: true}, - IsAllDay: sql.NullBool{Bool: dEvent.IsAllDay, Valid: true}, - Host: sql.NullString{String: dEvent.Host, Valid: true}, - } -} diff --git a/internal/repository/officer.go b/internal/repository/officer.go index 33f55d4..bc8abbb 100644 --- a/internal/repository/officer.go +++ b/internal/repository/officer.go @@ -63,7 +63,7 @@ func (r *officerRepository) Delete(ctx context.Context, id string) error { } func (r *officerRepository) Create(ctx context.Context, args domain.Officer) error { - _, err := r.db.CreateOfficer(ctx, *convertDomaintoCreateDBOfficer(&args)) + _, err := r.db.CreateOfficer(ctx, *convertDomainToCreateDBOfficer(&args)) if err != nil { return err } @@ -71,7 +71,7 @@ func (r *officerRepository) Create(ctx context.Context, args domain.Officer) err } func (r *officerRepository) Update(ctx context.Context, args domain.Officer) error { - err := r.db.UpdateOfficer(ctx, *convertDomaintoUpdateDBOfficer(&args)) + err := r.db.UpdateOfficer(ctx, *convertDomainToUpdateDBOfficer(&args)) if err != nil { return err } diff --git a/internal/repository/position.go b/internal/repository/position.go new file mode 100644 index 0000000..84c1e63 --- /dev/null +++ b/internal/repository/position.go @@ -0,0 +1,81 @@ +/* +package repository + +import ( + "context" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + +type OfficerRepository interface { + GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) + GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) + Create(ctx context.Context, args domain.Officer) error + Update(ctx context.Context, args domain.Officer) error + Delete(ctx context.Context, id string) error +} + +type officerRepository struct { + db *dbmodels.Queries +} + +func NewOfficerRepository(db *dbmodels.Queries) OfficerRepository { + return &officerRepository{db: db} +} + +func (r *officerRepository) GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) { + dbOfficers, err := r.db.GetOfficers(ctx) + if err != nil { + return nil, err + } + + var officers []*domain.Officer + for _, dbOfficer := range dbOfficers { + officers = append(officers, convertDBOfficerToDomain(&dbOfficer)) + } + return officers, nil +} + +func (r *officerRepository) GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) { + row, err := r.db.GetOfficer(ctx, id) // Get officers and get officers return completly different things? + + if err != nil { + return nil, err + } + + dbOfficer := dbmodels.Officer{ + Uuid: id, + FullName: row.FullName, + Picture: row.Picture, + Github: row.Github, + Discord: row.Discord, + } + + return convertDBOfficerToDomain(&dbOfficer), nil +} + +func (r *officerRepository) Delete(ctx context.Context, id string) error { + err := r.db.DeleteOfficer(ctx, id) + if err != nil { + return err + } + return nil +} + +func (r *officerRepository) Create(ctx context.Context, args domain.Officer) error { + _, err := r.db.CreateOfficer(ctx, *convertDomaintoCreateDBOfficer(&args)) + if err != nil { + return err + } + return nil +} + +func (r *officerRepository) Update(ctx context.Context, args domain.Officer) error { + err := r.db.UpdateOfficer(ctx, *convertDomaintoUpdateDBOfficer(&args)) + if err != nil { + return err + } + return nil +} +*/ \ No newline at end of file diff --git a/internal/repository/tier.go b/internal/repository/tier.go new file mode 100644 index 0000000..b1de681 --- /dev/null +++ b/internal/repository/tier.go @@ -0,0 +1,71 @@ +package repository + +import ( + "context" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + +type TierRepository interface { + GetAllTiers(ctx context.Context) ([]*domain.Tier, error) + GetTierByID(ctx context.Context, id int64) (*domain.Tier, error) + Create(ctx context.Context, args domain.Tier) error + Update(ctx context.Context, args domain.Tier) error + Delete(ctx context.Context, id int64) error +} + +type tierRepository struct { + db *dbmodels.Queries +} + +func NewTierRepository(db *dbmodels.Queries) TierRepository { + return &tierRepository{db: db} +} + +func (r *tierRepository) GetAllTiers(ctx context.Context) ([]*domain.Tier, error) { + dbTiers, err := r.db.GetTiers(ctx) + if err != nil { + return nil, err + } + + var Tiers []*domain.Tier + for _, dbTier := range dbTiers { + Tiers = append(Tiers, convertDBTierToDomain(&dbTier)) + } + return Tiers, nil +} + +func (r *tierRepository) GetTierByID(ctx context.Context, id int64) (*domain.Tier, error) { + dbTier, err := r.db.GetTier(ctx, id) + + if err != nil { + return nil, err + } + + return convertDBTierToDomain(&dbTier), nil +} + +func (r *tierRepository) Delete(ctx context.Context, id int64) error { + err := r.db.DeleteTier(ctx, id) + if err != nil { + return err + } + return nil +} + +func (r *tierRepository) Create(ctx context.Context, args domain.Tier) error { + _, err := r.db.CreateTier(ctx, *convertDomainToCreateDBTier(&args)) + if err != nil { + return err + } + return nil +} + +func (r *tierRepository) Update(ctx context.Context, args domain.Tier) error { + err := r.db.UpdateTier(ctx, *convertDomainToUpdateDBTier(&args)) + if err != nil { + return err + } + return nil +} From 88482317637a7779b83277f54cbe06aee54ba4a4 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 7 Feb 2026 12:56:55 -0800 Subject: [PATCH 11/56] Positions repository --- internal/domain/position.go | 7 ++++ internal/repository/conv.go | 8 +++++ internal/repository/position.go | 59 ++++++++++++++------------------- 3 files changed, 39 insertions(+), 35 deletions(-) create mode 100644 internal/domain/position.go diff --git a/internal/domain/position.go b/internal/domain/position.go new file mode 100644 index 0000000..9c0978a --- /dev/null +++ b/internal/domain/position.go @@ -0,0 +1,7 @@ +package domain + +type Position struct { + Oid string + Semester string + Tier int +} diff --git a/internal/repository/conv.go b/internal/repository/conv.go index f0625a0..43e4cba 100644 --- a/internal/repository/conv.go +++ b/internal/repository/conv.go @@ -158,3 +158,11 @@ func convertDomainToUpdateDBPosition(dPositon *domain.Position) *dbmodels.Update Tier: int64(dPositon.Tier), } } + +func convertDomainToDeleteDBPosition(dPositon *domain.Position) *dbmodels.DeletePositionParams { + return &dbmodels.DeletePositionParams{ + Oid: dPositon.Oid, + Semester: dPositon.Semester, + Tier: int64(dPositon.Tier), + } +} diff --git a/internal/repository/position.go b/internal/repository/position.go index 84c1e63..4b78358 100644 --- a/internal/repository/position.go +++ b/internal/repository/position.go @@ -1,4 +1,3 @@ -/* package repository import ( @@ -8,74 +7,64 @@ import ( "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" ) -type OfficerRepository interface { - GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) - GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) - Create(ctx context.Context, args domain.Officer) error - Update(ctx context.Context, args domain.Officer) error - Delete(ctx context.Context, id string) error +type PositionRepository interface { + GetAllpositions(ctx context.Context) ([]*domain.Officer, error) + GetpositionByID(ctx context.Context, id string) (*domain.Officer, error) + Create(ctx context.Context, args domain.Position) error + Update(ctx context.Context, args domain.Position) error + Delete(ctx context.Context, args domain.Position) error } -type officerRepository struct { +type positionRepository struct { db *dbmodels.Queries } -func NewOfficerRepository(db *dbmodels.Queries) OfficerRepository { - return &officerRepository{db: db} +func NewPositionRepository(db *dbmodels.Queries) OfficerRepository { + return &positionRepository{db: db} } -func (r *officerRepository) GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) { - dbOfficers, err := r.db.GetOfficers(ctx) +func (r *positionRepository) GetAllPositions(ctx context.Context) ([]*domain.Position, error) { + dbPositions, err := r.db.GetPositions(ctx) if err != nil { return nil, err } - var officers []*domain.Officer - for _, dbOfficer := range dbOfficers { - officers = append(officers, convertDBOfficerToDomain(&dbOfficer)) + var positions []*domain.Position + for _, dbPosition := range dbPositions { + positions = append(positions, convertDBPositionToDomain(&dbPosition)) } - return officers, nil + return positions, nil } -func (r *officerRepository) GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) { - row, err := r.db.GetOfficer(ctx, id) // Get officers and get officers return completly different things? - +func (r *positionRepository) GetPositionByID(ctx context.Context, id string) (*domain.Position, error) { + dbPosition, err := r.db.GetPosition(ctx, id) if err != nil { return nil, err } - dbOfficer := dbmodels.Officer{ - Uuid: id, - FullName: row.FullName, - Picture: row.Picture, - Github: row.Github, - Discord: row.Discord, - } - - return convertDBOfficerToDomain(&dbOfficer), nil + return convertDBPositionToDomain(&dbPosition), nil } -func (r *officerRepository) Delete(ctx context.Context, id string) error { - err := r.db.DeleteOfficer(ctx, id) +func (r *positionRepository) Delete(ctx context.Context, args domain.Position) error { + err := r.db.DeletePosition(ctx, *convertDomainToDeleteDBPosition(&args)) if err != nil { return err } return nil } -func (r *officerRepository) Create(ctx context.Context, args domain.Officer) error { - _, err := r.db.CreateOfficer(ctx, *convertDomaintoCreateDBOfficer(&args)) +func (r *positionRepository) Create(ctx context.Context, args domain.Position) error { + _, err := r.db.CreatePosition(ctx, *convertDomainToCreateDBPosition(&args)) if err != nil { return err } return nil } -func (r *officerRepository) Update(ctx context.Context, args domain.Officer) error { - err := r.db.UpdateOfficer(ctx, *convertDomaintoUpdateDBOfficer(&args)) +func (r *positionRepository) Update(ctx context.Context, args domain.Position) error { + err := r.db.UpdatePosition(ctx, *convertDomainToUpdateDBPosition(&args)) if err != nil { return err } return nil } -*/ \ No newline at end of file From bf5ce169c9e5ad667d6126817feba7e109d32805 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 7 Feb 2026 12:58:53 -0800 Subject: [PATCH 12/56] quick fix in positions repository --- internal/repository/position.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/repository/position.go b/internal/repository/position.go index 4b78358..727c26b 100644 --- a/internal/repository/position.go +++ b/internal/repository/position.go @@ -8,8 +8,8 @@ import ( ) type PositionRepository interface { - GetAllpositions(ctx context.Context) ([]*domain.Officer, error) - GetpositionByID(ctx context.Context, id string) (*domain.Officer, error) + GetAllPositions(ctx context.Context) ([]*domain.Position, error) + GetPositionByID(ctx context.Context, id string) (*domain.Position, error) Create(ctx context.Context, args domain.Position) error Update(ctx context.Context, args domain.Position) error Delete(ctx context.Context, args domain.Position) error @@ -19,7 +19,7 @@ type positionRepository struct { db *dbmodels.Queries } -func NewPositionRepository(db *dbmodels.Queries) OfficerRepository { +func NewPositionRepository(db *dbmodels.Queries) PositionRepository { return &positionRepository{db: db} } From eb651217d4823621990ffe13922d39a5fe082e8f Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sun, 8 Feb 2026 00:46:33 -0800 Subject: [PATCH 13/56] dto --- internal/dto/request/announcements.go | 10 ++++++++++ internal/dto/request/event.go | 12 ++++++++++++ internal/dto/request/officer.go | 9 +++++++++ internal/dto/request/position.go | 7 +++++++ internal/dto/request/tier.go | 8 ++++++++ internal/dto/response/announcements.go | 11 +++++++++++ internal/dto/response/event.go | 11 +++++++++++ internal/dto/response/officer.go | 8 ++++++++ internal/dto/response/position.go | 7 +++++++ internal/dto/response/tier.go | 8 ++++++++ 10 files changed, 91 insertions(+) create mode 100644 internal/dto/request/announcements.go create mode 100644 internal/dto/request/event.go create mode 100644 internal/dto/request/officer.go create mode 100644 internal/dto/request/position.go create mode 100644 internal/dto/request/tier.go create mode 100644 internal/dto/response/announcements.go create mode 100644 internal/dto/response/event.go create mode 100644 internal/dto/response/officer.go create mode 100644 internal/dto/response/position.go create mode 100644 internal/dto/response/tier.go diff --git a/internal/dto/request/announcements.go b/internal/dto/request/announcements.go new file mode 100644 index 0000000..7322322 --- /dev/null +++ b/internal/dto/request/announcements.go @@ -0,0 +1,10 @@ +package domain + +import "time" + +type Announcement struct { + Visibility string `json:"visibility"` + AnnounceAt time.Time `json:"announce_at"` + DiscordChannelID string `json:"discord_channel_id"` + DiscordMessageID string `json:"discord_message_id"` +} diff --git a/internal/dto/request/event.go b/internal/dto/request/event.go new file mode 100644 index 0000000..dc132db --- /dev/null +++ b/internal/dto/request/event.go @@ -0,0 +1,12 @@ +package domain + +import "time" + +type Event struct { + Uuid string `json:"uuid"` + Location string `json:"location"` + StartAt time.Time `json:"start_at"` + EndAt time.Time `json:"end_at"` + IsAllDay bool `json:"is_all_day"` + Host string `json:"host"` +} diff --git a/internal/dto/request/officer.go b/internal/dto/request/officer.go new file mode 100644 index 0000000..9e725b1 --- /dev/null +++ b/internal/dto/request/officer.go @@ -0,0 +1,9 @@ +package domain + +type Officer struct { + Uuid string `json:"uuid"` + FullName string `json:"full_name"` + Picture string `json:"picture"` + Github string `json:"github"` + Discord string `json:"discord"` +} diff --git a/internal/dto/request/position.go b/internal/dto/request/position.go new file mode 100644 index 0000000..c16ce39 --- /dev/null +++ b/internal/dto/request/position.go @@ -0,0 +1,7 @@ +package domain + +type Position struct { + Oid string `json:"oid"` + Semester string `json:"semester"` + Tier int `json:"tier"` +} diff --git a/internal/dto/request/tier.go b/internal/dto/request/tier.go new file mode 100644 index 0000000..9dbac5c --- /dev/null +++ b/internal/dto/request/tier.go @@ -0,0 +1,8 @@ +package domain + +type Tier struct { + Tier int `json:"tier"` + Title string `json:"title"` + Tindex int `json:"t_index"` + Team string `json:"team"` +} diff --git a/internal/dto/response/announcements.go b/internal/dto/response/announcements.go new file mode 100644 index 0000000..15d6476 --- /dev/null +++ b/internal/dto/response/announcements.go @@ -0,0 +1,11 @@ +package domain + +import "time" + +type Announcement struct { + Uuid string `json:"uuid"` + Visibility string `json:"visibility"` + AnnounceAt time.Time `json:"announce_at"` + DiscordChannelID string `json:"discord_channel_id"` + DiscordMessageID string `json:"discord_message_id"` +} diff --git a/internal/dto/response/event.go b/internal/dto/response/event.go new file mode 100644 index 0000000..c7166b1 --- /dev/null +++ b/internal/dto/response/event.go @@ -0,0 +1,11 @@ +package domain + +import "time" + +type Event struct { + Location string `json:"location"` + StartAt time.Time `json:"start_at"` + EndAt time.Time `json:"end_at"` + IsAllDay bool `json:"is_all_day"` + Host string `json:"host"` +} diff --git a/internal/dto/response/officer.go b/internal/dto/response/officer.go new file mode 100644 index 0000000..7ec6bab --- /dev/null +++ b/internal/dto/response/officer.go @@ -0,0 +1,8 @@ +package domain + +type Officer struct { + FullName string `json:"full_name"` + Picture string `json:"picture"` + Github string `json:"github"` + Discord string `json:"discord"` +} diff --git a/internal/dto/response/position.go b/internal/dto/response/position.go new file mode 100644 index 0000000..c16ce39 --- /dev/null +++ b/internal/dto/response/position.go @@ -0,0 +1,7 @@ +package domain + +type Position struct { + Oid string `json:"oid"` + Semester string `json:"semester"` + Tier int `json:"tier"` +} diff --git a/internal/dto/response/tier.go b/internal/dto/response/tier.go new file mode 100644 index 0000000..9dbac5c --- /dev/null +++ b/internal/dto/response/tier.go @@ -0,0 +1,8 @@ +package domain + +type Tier struct { + Tier int `json:"tier"` + Title string `json:"title"` + Tindex int `json:"t_index"` + Team string `json:"team"` +} From c6d3f95332e2f6d4447698a8962c6eb8bc798716 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sun, 8 Feb 2026 18:02:17 -0800 Subject: [PATCH 14/56] DTO time should be unix int --- internal/dto/request/announcements.go | 10 ++++------ internal/dto/request/event.go | 14 ++++++-------- internal/dto/response/announcements.go | 12 +++++------- internal/dto/response/event.go | 12 +++++------- 4 files changed, 20 insertions(+), 28 deletions(-) diff --git a/internal/dto/request/announcements.go b/internal/dto/request/announcements.go index 7322322..4f8be6e 100644 --- a/internal/dto/request/announcements.go +++ b/internal/dto/request/announcements.go @@ -1,10 +1,8 @@ package domain -import "time" - type Announcement struct { - Visibility string `json:"visibility"` - AnnounceAt time.Time `json:"announce_at"` - DiscordChannelID string `json:"discord_channel_id"` - DiscordMessageID string `json:"discord_message_id"` + Visibility string `json:"visibility"` + AnnounceAt int64 `json:"announce_at"` + DiscordChannelID string `json:"discord_channel_id"` + DiscordMessageID string `json:"discord_message_id"` } diff --git a/internal/dto/request/event.go b/internal/dto/request/event.go index dc132db..05e3955 100644 --- a/internal/dto/request/event.go +++ b/internal/dto/request/event.go @@ -1,12 +1,10 @@ package domain -import "time" - type Event struct { - Uuid string `json:"uuid"` - Location string `json:"location"` - StartAt time.Time `json:"start_at"` - EndAt time.Time `json:"end_at"` - IsAllDay bool `json:"is_all_day"` - Host string `json:"host"` + Uuid string `json:"uuid"` + Location string `json:"location"` + StartAt int64 `json:"start_at"` + EndAt int64 `json:"end_at"` + IsAllDay bool `json:"is_all_day"` + Host string `json:"host"` } diff --git a/internal/dto/response/announcements.go b/internal/dto/response/announcements.go index 15d6476..bb1342e 100644 --- a/internal/dto/response/announcements.go +++ b/internal/dto/response/announcements.go @@ -1,11 +1,9 @@ package domain -import "time" - type Announcement struct { - Uuid string `json:"uuid"` - Visibility string `json:"visibility"` - AnnounceAt time.Time `json:"announce_at"` - DiscordChannelID string `json:"discord_channel_id"` - DiscordMessageID string `json:"discord_message_id"` + Uuid string `json:"uuid"` + Visibility string `json:"visibility"` + AnnounceAt int64 `json:"announce_at"` + DiscordChannelID string `json:"discord_channel_id"` + DiscordMessageID string `json:"discord_message_id"` } diff --git a/internal/dto/response/event.go b/internal/dto/response/event.go index c7166b1..3c5ed0a 100644 --- a/internal/dto/response/event.go +++ b/internal/dto/response/event.go @@ -1,11 +1,9 @@ package domain -import "time" - type Event struct { - Location string `json:"location"` - StartAt time.Time `json:"start_at"` - EndAt time.Time `json:"end_at"` - IsAllDay bool `json:"is_all_day"` - Host string `json:"host"` + Location string `json:"location"` + StartAt int64 `json:"start_at"` + EndAt int64 `json:"end_at"` + IsAllDay bool `json:"is_all_day"` + Host string `json:"host"` } From 99fb4433010fd3bddef203e45ad55598390004d8 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sun, 8 Feb 2026 18:04:52 -0800 Subject: [PATCH 15/56] keep uuid for requests (for now) --- internal/dto/request/announcements.go | 1 + internal/dto/request/event.go | 1 - internal/dto/request/officer.go | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/dto/request/announcements.go b/internal/dto/request/announcements.go index 4f8be6e..bb1342e 100644 --- a/internal/dto/request/announcements.go +++ b/internal/dto/request/announcements.go @@ -1,6 +1,7 @@ package domain type Announcement struct { + Uuid string `json:"uuid"` Visibility string `json:"visibility"` AnnounceAt int64 `json:"announce_at"` DiscordChannelID string `json:"discord_channel_id"` diff --git a/internal/dto/request/event.go b/internal/dto/request/event.go index 05e3955..3c5ed0a 100644 --- a/internal/dto/request/event.go +++ b/internal/dto/request/event.go @@ -1,7 +1,6 @@ package domain type Event struct { - Uuid string `json:"uuid"` Location string `json:"location"` StartAt int64 `json:"start_at"` EndAt int64 `json:"end_at"` diff --git a/internal/dto/request/officer.go b/internal/dto/request/officer.go index 9e725b1..7ec6bab 100644 --- a/internal/dto/request/officer.go +++ b/internal/dto/request/officer.go @@ -1,7 +1,6 @@ package domain type Officer struct { - Uuid string `json:"uuid"` FullName string `json:"full_name"` Picture string `json:"picture"` Github string `json:"github"` From d2d595c63980d7be104fbec4b804e3b700f26efa Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sun, 8 Feb 2026 18:17:17 -0800 Subject: [PATCH 16/56] Update func names for comminality --- internal/api/services/announcement.go | 9 ++++++--- internal/repository/announcements.go | 12 ++++++------ internal/repository/event.go | 8 ++++---- internal/repository/officer.go | 8 ++++---- internal/repository/position.go | 8 ++++---- internal/repository/tier.go | 8 ++++---- 6 files changed, 28 insertions(+), 25 deletions(-) diff --git a/internal/api/services/announcement.go b/internal/api/services/announcement.go index 818e06c..af0f222 100644 --- a/internal/api/services/announcement.go +++ b/internal/api/services/announcement.go @@ -3,8 +3,11 @@ package services import ( "context" - "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "log" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" + "github.com/acmcsufoss/api.acmcsuf.com/internal/repository" ) type AnnouncementServicer interface { @@ -19,11 +22,11 @@ type AnnouncementService struct { // compile time check var _ AnnouncementServicer = (*AnnouncementService)(nil) -func NewAnnouncementService(q *dbmodels.Queries) *AnnouncementService { +func NewAnnouncementService(q *dbmodels.Queries) *repository.AnnouncementService { return &AnnouncementService{q: q} } -func (s *AnnouncementService) Get(ctx context.Context, uuid string) (dbmodels.Announcement, error) { +func (s *AnnouncementService) Get(ctx context.Context, uuid string) (domain.Announcement, error) { announcement, err := s.q.GetAnnouncement(ctx, uuid) if err != nil { return dbmodels.Announcement{}, err diff --git a/internal/repository/announcements.go b/internal/repository/announcements.go index 7ffd248..32d8928 100644 --- a/internal/repository/announcements.go +++ b/internal/repository/announcements.go @@ -8,9 +8,9 @@ import ( ) type AnnouncementRepository interface { - GetAllAnnouncements(ctx context.Context) ([]*domain.Announcement, error) + GetAll(ctx context.Context) ([]*domain.Announcement, error) - GetAnnouncementByID(ctx context.Context, id string) (*domain.Announcement, error) + GetByID(ctx context.Context, id string) (*domain.Announcement, error) Delete(ctx context.Context, id string) error Create(ctx context.Context, args domain.Announcement) error @@ -25,7 +25,7 @@ func NewAnnouncementRepository(db *dbmodels.Queries) AnnouncementRepository { return &announcementRepository{db: db} } -func (r *announcementRepository) GetAnnouncementByID(ctx context.Context, id string) (*domain.Announcement, error) { +func (r *announcementRepository) GetByID(ctx context.Context, id string) (*domain.Announcement, error) { dbAnnouncement, err := r.db.GetAnnouncement(ctx, id) if err != nil { return nil, err @@ -34,7 +34,7 @@ func (r *announcementRepository) GetAnnouncementByID(ctx context.Context, id str return convertDBAnnouncementToDomain(&dbAnnouncement), nil } -func (r *announcementRepository) GetAllAnnouncements(ctx context.Context) ([]*domain.Announcement, error) { +func (r *announcementRepository) GetAll(ctx context.Context) ([]*domain.Announcement, error) { dbAnnouncement, err := r.db.GetAnnouncements(ctx) if err != nil { return nil, err @@ -56,7 +56,7 @@ func (r *announcementRepository) Delete(ctx context.Context, id string) error { } func (r *announcementRepository) Create(ctx context.Context, args domain.Announcement) error { - err := r.db.CreateAnnouncement(ctx, *convertDomaintoCreateDBAnnouncement(&args)) + err := r.db.CreateAnnouncement(ctx, *convertDomainToCreateDBAnnouncement(&args)) if err != nil { return err } @@ -64,7 +64,7 @@ func (r *announcementRepository) Create(ctx context.Context, args domain.Announc } func (r *announcementRepository) Update(ctx context.Context, args domain.Announcement) error { - err := r.db.UpdateAnnouncement(ctx, *convertDomaintoUpdateDBAnnouncement(&args)) + err := r.db.UpdateAnnouncement(ctx, *convertDomainToUpdateDBAnnouncement(&args)) if err != nil { return err } diff --git a/internal/repository/event.go b/internal/repository/event.go index b435f5f..69f4b69 100644 --- a/internal/repository/event.go +++ b/internal/repository/event.go @@ -8,9 +8,9 @@ import ( ) type EventRepository interface { - GetAllEvents(ctx context.Context) ([]*domain.Event, error) + GetAll(ctx context.Context) ([]*domain.Event, error) - GetEventByID(ctx context.Context, id string) (*domain.Event, error) + GetByID(ctx context.Context, id string) (*domain.Event, error) Delete(ctx context.Context, id string) error Create(ctx context.Context, args domain.Event) error @@ -25,7 +25,7 @@ func NewEventRepository(db *dbmodels.Queries) EventRepository { return &eventRepository{db: db} } -func (r *eventRepository) GetEventByID(ctx context.Context, id string) (*domain.Event, error) { +func (r *eventRepository) GetByID(ctx context.Context, id string) (*domain.Event, error) { dbEvent, err := r.db.GetEvent(ctx, id) if err != nil { return nil, err @@ -34,7 +34,7 @@ func (r *eventRepository) GetEventByID(ctx context.Context, id string) (*domain. return convertDBEventToDomain(&dbEvent), nil } -func (r *eventRepository) GetAllEvents(ctx context.Context) ([]*domain.Event, error) { +func (r *eventRepository) GetAll(ctx context.Context) ([]*domain.Event, error) { dbEvent, err := r.db.GetEvents(ctx) if err != nil { return nil, err diff --git a/internal/repository/officer.go b/internal/repository/officer.go index bc8abbb..3f04dbf 100644 --- a/internal/repository/officer.go +++ b/internal/repository/officer.go @@ -8,8 +8,8 @@ import ( ) type OfficerRepository interface { - GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) - GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) + GetAll(ctx context.Context) ([]*domain.Officer, error) + GetByID(ctx context.Context, id string) (*domain.Officer, error) Create(ctx context.Context, args domain.Officer) error Update(ctx context.Context, args domain.Officer) error Delete(ctx context.Context, id string) error @@ -23,7 +23,7 @@ func NewOfficerRepository(db *dbmodels.Queries) OfficerRepository { return &officerRepository{db: db} } -func (r *officerRepository) GetAllOfficers(ctx context.Context) ([]*domain.Officer, error) { +func (r *officerRepository) GetAll(ctx context.Context) ([]*domain.Officer, error) { dbOfficers, err := r.db.GetOfficers(ctx) if err != nil { return nil, err @@ -36,7 +36,7 @@ func (r *officerRepository) GetAllOfficers(ctx context.Context) ([]*domain.Offic return officers, nil } -func (r *officerRepository) GetOfficerByID(ctx context.Context, id string) (*domain.Officer, error) { +func (r *officerRepository) GetByID(ctx context.Context, id string) (*domain.Officer, error) { row, err := r.db.GetOfficer(ctx, id) // Get officers and get officers return completly different things? if err != nil { diff --git a/internal/repository/position.go b/internal/repository/position.go index 727c26b..9483d04 100644 --- a/internal/repository/position.go +++ b/internal/repository/position.go @@ -8,8 +8,8 @@ import ( ) type PositionRepository interface { - GetAllPositions(ctx context.Context) ([]*domain.Position, error) - GetPositionByID(ctx context.Context, id string) (*domain.Position, error) + GetAll(ctx context.Context) ([]*domain.Position, error) + GetByID(ctx context.Context, id string) (*domain.Position, error) Create(ctx context.Context, args domain.Position) error Update(ctx context.Context, args domain.Position) error Delete(ctx context.Context, args domain.Position) error @@ -23,7 +23,7 @@ func NewPositionRepository(db *dbmodels.Queries) PositionRepository { return &positionRepository{db: db} } -func (r *positionRepository) GetAllPositions(ctx context.Context) ([]*domain.Position, error) { +func (r *positionRepository) GetAll(ctx context.Context) ([]*domain.Position, error) { dbPositions, err := r.db.GetPositions(ctx) if err != nil { return nil, err @@ -36,7 +36,7 @@ func (r *positionRepository) GetAllPositions(ctx context.Context) ([]*domain.Pos return positions, nil } -func (r *positionRepository) GetPositionByID(ctx context.Context, id string) (*domain.Position, error) { +func (r *positionRepository) GetByID(ctx context.Context, id string) (*domain.Position, error) { dbPosition, err := r.db.GetPosition(ctx, id) if err != nil { return nil, err diff --git a/internal/repository/tier.go b/internal/repository/tier.go index b1de681..7600f3b 100644 --- a/internal/repository/tier.go +++ b/internal/repository/tier.go @@ -8,8 +8,8 @@ import ( ) type TierRepository interface { - GetAllTiers(ctx context.Context) ([]*domain.Tier, error) - GetTierByID(ctx context.Context, id int64) (*domain.Tier, error) + GetAll(ctx context.Context) ([]*domain.Tier, error) + GetByID(ctx context.Context, id int64) (*domain.Tier, error) Create(ctx context.Context, args domain.Tier) error Update(ctx context.Context, args domain.Tier) error Delete(ctx context.Context, id int64) error @@ -23,7 +23,7 @@ func NewTierRepository(db *dbmodels.Queries) TierRepository { return &tierRepository{db: db} } -func (r *tierRepository) GetAllTiers(ctx context.Context) ([]*domain.Tier, error) { +func (r *tierRepository) GetAll(ctx context.Context) ([]*domain.Tier, error) { dbTiers, err := r.db.GetTiers(ctx) if err != nil { return nil, err @@ -36,7 +36,7 @@ func (r *tierRepository) GetAllTiers(ctx context.Context) ([]*domain.Tier, error return Tiers, nil } -func (r *tierRepository) GetTierByID(ctx context.Context, id int64) (*domain.Tier, error) { +func (r *tierRepository) GetByID(ctx context.Context, id int64) (*domain.Tier, error) { dbTier, err := r.db.GetTier(ctx, id) if err != nil { From b455c195ade119ecc245306785d7643a875c9951 Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Mon, 9 Feb 2026 10:59:04 -0800 Subject: [PATCH 17/56] why tf was I using pointers --- internal/repository/announcements.go | 20 ++++----- internal/repository/conv.go | 64 ++++++++++++++-------------- internal/repository/event.go | 20 ++++----- internal/repository/officer.go | 21 +++++---- internal/repository/position.go | 22 +++++----- internal/repository/tier.go | 21 +++++---- 6 files changed, 83 insertions(+), 85 deletions(-) diff --git a/internal/repository/announcements.go b/internal/repository/announcements.go index 32d8928..78a6dee 100644 --- a/internal/repository/announcements.go +++ b/internal/repository/announcements.go @@ -8,9 +8,9 @@ import ( ) type AnnouncementRepository interface { - GetAll(ctx context.Context) ([]*domain.Announcement, error) + GetAll(ctx context.Context) ([]domain.Announcement, error) - GetByID(ctx context.Context, id string) (*domain.Announcement, error) + GetByID(ctx context.Context, id string) (domain.Announcement, error) Delete(ctx context.Context, id string) error Create(ctx context.Context, args domain.Announcement) error @@ -25,24 +25,24 @@ func NewAnnouncementRepository(db *dbmodels.Queries) AnnouncementRepository { return &announcementRepository{db: db} } -func (r *announcementRepository) GetByID(ctx context.Context, id string) (*domain.Announcement, error) { +func (r *announcementRepository) GetByID(ctx context.Context, id string) (domain.Announcement, error) { dbAnnouncement, err := r.db.GetAnnouncement(ctx, id) if err != nil { - return nil, err + return domain.Announcement{}, err } - return convertDBAnnouncementToDomain(&dbAnnouncement), nil + return convertDBAnnouncementToDomain(dbAnnouncement), nil } -func (r *announcementRepository) GetAll(ctx context.Context) ([]*domain.Announcement, error) { +func (r *announcementRepository) GetAll(ctx context.Context) ([]domain.Announcement, error) { dbAnnouncement, err := r.db.GetAnnouncements(ctx) if err != nil { return nil, err } - var eventSlice []*domain.Announcement + var eventSlice []domain.Announcement for _, elm := range dbAnnouncement { - eventSlice = append(eventSlice, convertDBAnnouncementToDomain(&elm)) + eventSlice = append(eventSlice, convertDBAnnouncementToDomain(elm)) } return eventSlice, nil } @@ -56,7 +56,7 @@ func (r *announcementRepository) Delete(ctx context.Context, id string) error { } func (r *announcementRepository) Create(ctx context.Context, args domain.Announcement) error { - err := r.db.CreateAnnouncement(ctx, *convertDomainToCreateDBAnnouncement(&args)) + err := r.db.CreateAnnouncement(ctx, convertDomainToCreateDBAnnouncement(args)) if err != nil { return err } @@ -64,7 +64,7 @@ func (r *announcementRepository) Create(ctx context.Context, args domain.Announc } func (r *announcementRepository) Update(ctx context.Context, args domain.Announcement) error { - err := r.db.UpdateAnnouncement(ctx, *convertDomainToUpdateDBAnnouncement(&args)) + err := r.db.UpdateAnnouncement(ctx, convertDomainToUpdateDBAnnouncement(args)) if err != nil { return err } diff --git a/internal/repository/conv.go b/internal/repository/conv.go index 43e4cba..b0f694e 100644 --- a/internal/repository/conv.go +++ b/internal/repository/conv.go @@ -11,8 +11,8 @@ import ( // File for converting Database models into Doamin models // ---- Event Converter ---- -func convertDBEventToDomain(dbEvent *dbmodels.Event) *domain.Event { - return &domain.Event{ +func convertDBEventToDomain(dbEvent dbmodels.Event) domain.Event { + return domain.Event{ Uuid: dbEvent.Uuid, Location: dbEvent.Location, StartAt: time.Unix(dbEvent.StartAt, 0), @@ -22,8 +22,8 @@ func convertDBEventToDomain(dbEvent *dbmodels.Event) *domain.Event { } } -func convertDomainToCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventParams { - return &dbmodels.CreateEventParams{ +func convertDomainToCreateDBEvent(dEvent domain.Event) dbmodels.CreateEventParams { + return dbmodels.CreateEventParams{ Uuid: dEvent.Uuid, Location: dEvent.Location, StartAt: dEvent.StartAt.Unix(), @@ -33,8 +33,8 @@ func convertDomainToCreateDBEvent(dEvent *domain.Event) *dbmodels.CreateEventPar } } -func convertDomainToUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventParams { - return &dbmodels.UpdateEventParams{ +func convertDomainToUpdateDBEvent(dEvent domain.Event) dbmodels.UpdateEventParams { + return dbmodels.UpdateEventParams{ Uuid: dEvent.Uuid, Location: sql.NullString{String: dEvent.Location, Valid: true}, StartAt: sql.NullInt64{Int64: dEvent.StartAt.Unix(), Valid: true}, @@ -45,8 +45,8 @@ func convertDomainToUpdateDBEvent(dEvent *domain.Event) *dbmodels.UpdateEventPar } // ---- Officer Converter ---- -func convertDBOfficerToDomain(dbOfficer *dbmodels.Officer) *domain.Officer { - return &domain.Officer{ +func convertDBOfficerToDomain(dbOfficer dbmodels.Officer) domain.Officer { + return domain.Officer{ Uuid: dbOfficer.Uuid, FullName: dbOfficer.FullName, Picture: dbOfficer.Picture.String, @@ -55,8 +55,8 @@ func convertDBOfficerToDomain(dbOfficer *dbmodels.Officer) *domain.Officer { } } -func convertDomainToCreateDBOfficer(dOfficer *domain.Officer) *dbmodels.CreateOfficerParams { - return &dbmodels.CreateOfficerParams{ +func convertDomainToCreateDBOfficer(dOfficer domain.Officer) dbmodels.CreateOfficerParams { + return dbmodels.CreateOfficerParams{ Uuid: dOfficer.Uuid, FullName: dOfficer.FullName, Picture: sql.NullString{String: dOfficer.Picture, Valid: true}, @@ -65,8 +65,8 @@ func convertDomainToCreateDBOfficer(dOfficer *domain.Officer) *dbmodels.CreateOf } } -func convertDomainToUpdateDBOfficer(dOfficer *domain.Officer) *dbmodels.UpdateOfficerParams { - return &dbmodels.UpdateOfficerParams{ +func convertDomainToUpdateDBOfficer(dOfficer domain.Officer) dbmodels.UpdateOfficerParams { + return dbmodels.UpdateOfficerParams{ Uuid: dOfficer.Uuid, FullName: dOfficer.FullName, Picture: sql.NullString{String: dOfficer.Picture, Valid: true}, @@ -76,8 +76,8 @@ func convertDomainToUpdateDBOfficer(dOfficer *domain.Officer) *dbmodels.UpdateOf } // ---- Announcement Converter ---- -func convertDBAnnouncementToDomain(dbAnnouncement *dbmodels.Announcement) *domain.Announcement { - return &domain.Announcement{ +func convertDBAnnouncementToDomain(dbAnnouncement dbmodels.Announcement) domain.Announcement { + return domain.Announcement{ Uuid: dbAnnouncement.Uuid, Visibility: dbAnnouncement.Visibility, AnnounceAt: time.Unix(dbAnnouncement.AnnounceAt, 0), @@ -86,8 +86,8 @@ func convertDBAnnouncementToDomain(dbAnnouncement *dbmodels.Announcement) *domai } } -func convertDomainToCreateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.CreateAnnouncementParams { - return &dbmodels.CreateAnnouncementParams{ +func convertDomainToCreateDBAnnouncement(dAnnouncement domain.Announcement) dbmodels.CreateAnnouncementParams { + return dbmodels.CreateAnnouncementParams{ Uuid: dAnnouncement.Uuid, Visibility: dAnnouncement.Visibility, AnnounceAt: dAnnouncement.AnnounceAt.Unix(), @@ -96,8 +96,8 @@ func convertDomainToCreateDBAnnouncement(dAnnouncement *domain.Announcement) *db } } -func convertDomainToUpdateDBAnnouncement(dAnnouncement *domain.Announcement) *dbmodels.UpdateAnnouncementParams { - return &dbmodels.UpdateAnnouncementParams{ +func convertDomainToUpdateDBAnnouncement(dAnnouncement domain.Announcement) dbmodels.UpdateAnnouncementParams { + return dbmodels.UpdateAnnouncementParams{ Uuid: dAnnouncement.Uuid, Visibility: sql.NullString{String: dAnnouncement.Visibility, Valid: true}, AnnounceAt: sql.NullInt64{Int64: dAnnouncement.AnnounceAt.Unix(), Valid: true}, @@ -107,8 +107,8 @@ func convertDomainToUpdateDBAnnouncement(dAnnouncement *domain.Announcement) *db } // ---- Tier Converter ---- -func convertDBTierToDomain(dbTier *dbmodels.Tier) *domain.Tier { - return &domain.Tier{ +func convertDBTierToDomain(dbTier dbmodels.Tier) domain.Tier { + return domain.Tier{ Tier: int(dbTier.Tier), Title: dbTier.Title.String, Tindex: int(dbTier.TIndex.Int64), @@ -116,8 +116,8 @@ func convertDBTierToDomain(dbTier *dbmodels.Tier) *domain.Tier { } } -func convertDomainToCreateDBTier(dTier *domain.Tier) *dbmodels.CreateTierParams { - return &dbmodels.CreateTierParams{ +func convertDomainToCreateDBTier(dTier domain.Tier) dbmodels.CreateTierParams { + return dbmodels.CreateTierParams{ Tier: int64(dTier.Tier), Title: sql.NullString{String: dTier.Title, Valid: true}, TIndex: sql.NullInt64{Int64: int64(dTier.Tindex), Valid: true}, @@ -125,8 +125,8 @@ func convertDomainToCreateDBTier(dTier *domain.Tier) *dbmodels.CreateTierParams } } -func convertDomainToUpdateDBTier(dTier *domain.Tier) *dbmodels.UpdateTierParams { - return &dbmodels.UpdateTierParams{ +func convertDomainToUpdateDBTier(dTier domain.Tier) dbmodels.UpdateTierParams { + return dbmodels.UpdateTierParams{ Tier: int64(dTier.Tier), Title: sql.NullString{String: dTier.Title, Valid: true}, TIndex: sql.NullInt64{Int64: int64(dTier.Tindex), Valid: true}, @@ -135,32 +135,32 @@ func convertDomainToUpdateDBTier(dTier *domain.Tier) *dbmodels.UpdateTierParams } // ---- Position Converter ---- -func convertDBPositionToDomain(dbPosition *dbmodels.Position) *domain.Position { - return &domain.Position{ +func convertDBPositionToDomain(dbPosition dbmodels.Position) domain.Position { + return domain.Position{ Oid: dbPosition.Oid, Semester: dbPosition.Semester, Tier: int(dbPosition.Tier), } } -func convertDomainToCreateDBPosition(dPositon *domain.Position) *dbmodels.CreatePositionParams { - return &dbmodels.CreatePositionParams{ +func convertDomainToCreateDBPosition(dPositon domain.Position) dbmodels.CreatePositionParams { + return dbmodels.CreatePositionParams{ Oid: dPositon.Oid, Semester: dPositon.Semester, Tier: int64(dPositon.Tier), } } -func convertDomainToUpdateDBPosition(dPositon *domain.Position) *dbmodels.UpdatePositionParams { - return &dbmodels.UpdatePositionParams{ +func convertDomainToUpdateDBPosition(dPositon domain.Position) dbmodels.UpdatePositionParams { + return dbmodels.UpdatePositionParams{ Oid: dPositon.Oid, Semester: dPositon.Semester, Tier: int64(dPositon.Tier), } } -func convertDomainToDeleteDBPosition(dPositon *domain.Position) *dbmodels.DeletePositionParams { - return &dbmodels.DeletePositionParams{ +func convertDomainToDeleteDBPosition(dPositon domain.Position) dbmodels.DeletePositionParams { + return dbmodels.DeletePositionParams{ Oid: dPositon.Oid, Semester: dPositon.Semester, Tier: int64(dPositon.Tier), diff --git a/internal/repository/event.go b/internal/repository/event.go index 69f4b69..6cb6707 100644 --- a/internal/repository/event.go +++ b/internal/repository/event.go @@ -8,9 +8,9 @@ import ( ) type EventRepository interface { - GetAll(ctx context.Context) ([]*domain.Event, error) + GetAll(ctx context.Context) ([]domain.Event, error) - GetByID(ctx context.Context, id string) (*domain.Event, error) + GetByID(ctx context.Context, id string) (domain.Event, error) Delete(ctx context.Context, id string) error Create(ctx context.Context, args domain.Event) error @@ -25,24 +25,24 @@ func NewEventRepository(db *dbmodels.Queries) EventRepository { return &eventRepository{db: db} } -func (r *eventRepository) GetByID(ctx context.Context, id string) (*domain.Event, error) { +func (r *eventRepository) GetByID(ctx context.Context, id string) (domain.Event, error) { dbEvent, err := r.db.GetEvent(ctx, id) if err != nil { - return nil, err + return domain.Event{}, err } - return convertDBEventToDomain(&dbEvent), nil + return convertDBEventToDomain(dbEvent), nil } -func (r *eventRepository) GetAll(ctx context.Context) ([]*domain.Event, error) { +func (r *eventRepository) GetAll(ctx context.Context) ([]domain.Event, error) { dbEvent, err := r.db.GetEvents(ctx) if err != nil { return nil, err } - var eventSlice []*domain.Event + var eventSlice []domain.Event for _, elm := range dbEvent { - eventSlice = append(eventSlice, convertDBEventToDomain(&elm)) + eventSlice = append(eventSlice, convertDBEventToDomain(elm)) } return eventSlice, nil } @@ -56,7 +56,7 @@ func (r *eventRepository) Delete(ctx context.Context, id string) error { } func (r *eventRepository) Create(ctx context.Context, args domain.Event) error { - err := r.db.CreateEvent(ctx, *convertDomainToCreateDBEvent(&args)) + err := r.db.CreateEvent(ctx, convertDomainToCreateDBEvent(args)) if err != nil { return err } @@ -64,7 +64,7 @@ func (r *eventRepository) Create(ctx context.Context, args domain.Event) error { } func (r *eventRepository) Update(ctx context.Context, args domain.Event) error { - err := r.db.UpdateEvent(ctx, *convertDomainToUpdateDBEvent(&args)) + err := r.db.UpdateEvent(ctx, convertDomainToUpdateDBEvent(args)) if err != nil { return err } diff --git a/internal/repository/officer.go b/internal/repository/officer.go index 3f04dbf..c45831e 100644 --- a/internal/repository/officer.go +++ b/internal/repository/officer.go @@ -8,8 +8,8 @@ import ( ) type OfficerRepository interface { - GetAll(ctx context.Context) ([]*domain.Officer, error) - GetByID(ctx context.Context, id string) (*domain.Officer, error) + GetAll(ctx context.Context) ([]domain.Officer, error) + GetByID(ctx context.Context, id string) (domain.Officer, error) Create(ctx context.Context, args domain.Officer) error Update(ctx context.Context, args domain.Officer) error Delete(ctx context.Context, id string) error @@ -23,24 +23,23 @@ func NewOfficerRepository(db *dbmodels.Queries) OfficerRepository { return &officerRepository{db: db} } -func (r *officerRepository) GetAll(ctx context.Context) ([]*domain.Officer, error) { +func (r *officerRepository) GetAll(ctx context.Context) ([]domain.Officer, error) { dbOfficers, err := r.db.GetOfficers(ctx) if err != nil { return nil, err } - var officers []*domain.Officer + var officers []domain.Officer for _, dbOfficer := range dbOfficers { - officers = append(officers, convertDBOfficerToDomain(&dbOfficer)) + officers = append(officers, convertDBOfficerToDomain(dbOfficer)) } return officers, nil } -func (r *officerRepository) GetByID(ctx context.Context, id string) (*domain.Officer, error) { +func (r *officerRepository) GetByID(ctx context.Context, id string) (domain.Officer, error) { row, err := r.db.GetOfficer(ctx, id) // Get officers and get officers return completly different things? - if err != nil { - return nil, err + return domain.Officer{}, err } dbOfficer := dbmodels.Officer{ @@ -51,7 +50,7 @@ func (r *officerRepository) GetByID(ctx context.Context, id string) (*domain.Off Discord: row.Discord, } - return convertDBOfficerToDomain(&dbOfficer), nil + return convertDBOfficerToDomain(dbOfficer), nil } func (r *officerRepository) Delete(ctx context.Context, id string) error { @@ -63,7 +62,7 @@ func (r *officerRepository) Delete(ctx context.Context, id string) error { } func (r *officerRepository) Create(ctx context.Context, args domain.Officer) error { - _, err := r.db.CreateOfficer(ctx, *convertDomainToCreateDBOfficer(&args)) + _, err := r.db.CreateOfficer(ctx, convertDomainToCreateDBOfficer(args)) if err != nil { return err } @@ -71,7 +70,7 @@ func (r *officerRepository) Create(ctx context.Context, args domain.Officer) err } func (r *officerRepository) Update(ctx context.Context, args domain.Officer) error { - err := r.db.UpdateOfficer(ctx, *convertDomainToUpdateDBOfficer(&args)) + err := r.db.UpdateOfficer(ctx, convertDomainToUpdateDBOfficer(args)) if err != nil { return err } diff --git a/internal/repository/position.go b/internal/repository/position.go index 9483d04..369f4e8 100644 --- a/internal/repository/position.go +++ b/internal/repository/position.go @@ -8,8 +8,8 @@ import ( ) type PositionRepository interface { - GetAll(ctx context.Context) ([]*domain.Position, error) - GetByID(ctx context.Context, id string) (*domain.Position, error) + GetAll(ctx context.Context) ([]domain.Position, error) + GetByID(ctx context.Context, id string) (domain.Position, error) Create(ctx context.Context, args domain.Position) error Update(ctx context.Context, args domain.Position) error Delete(ctx context.Context, args domain.Position) error @@ -23,30 +23,30 @@ func NewPositionRepository(db *dbmodels.Queries) PositionRepository { return &positionRepository{db: db} } -func (r *positionRepository) GetAll(ctx context.Context) ([]*domain.Position, error) { +func (r *positionRepository) GetAll(ctx context.Context) ([]domain.Position, error) { dbPositions, err := r.db.GetPositions(ctx) if err != nil { return nil, err } - var positions []*domain.Position + var positions []domain.Position for _, dbPosition := range dbPositions { - positions = append(positions, convertDBPositionToDomain(&dbPosition)) + positions = append(positions, convertDBPositionToDomain(dbPosition)) } return positions, nil } -func (r *positionRepository) GetByID(ctx context.Context, id string) (*domain.Position, error) { +func (r *positionRepository) GetByID(ctx context.Context, id string) (domain.Position, error) { dbPosition, err := r.db.GetPosition(ctx, id) if err != nil { - return nil, err + return domain.Position{}, err } - return convertDBPositionToDomain(&dbPosition), nil + return convertDBPositionToDomain(dbPosition), nil } func (r *positionRepository) Delete(ctx context.Context, args domain.Position) error { - err := r.db.DeletePosition(ctx, *convertDomainToDeleteDBPosition(&args)) + err := r.db.DeletePosition(ctx, convertDomainToDeleteDBPosition(args)) if err != nil { return err } @@ -54,7 +54,7 @@ func (r *positionRepository) Delete(ctx context.Context, args domain.Position) e } func (r *positionRepository) Create(ctx context.Context, args domain.Position) error { - _, err := r.db.CreatePosition(ctx, *convertDomainToCreateDBPosition(&args)) + _, err := r.db.CreatePosition(ctx, convertDomainToCreateDBPosition(args)) if err != nil { return err } @@ -62,7 +62,7 @@ func (r *positionRepository) Create(ctx context.Context, args domain.Position) e } func (r *positionRepository) Update(ctx context.Context, args domain.Position) error { - err := r.db.UpdatePosition(ctx, *convertDomainToUpdateDBPosition(&args)) + err := r.db.UpdatePosition(ctx, convertDomainToUpdateDBPosition(args)) if err != nil { return err } diff --git a/internal/repository/tier.go b/internal/repository/tier.go index 7600f3b..80a4e21 100644 --- a/internal/repository/tier.go +++ b/internal/repository/tier.go @@ -8,8 +8,8 @@ import ( ) type TierRepository interface { - GetAll(ctx context.Context) ([]*domain.Tier, error) - GetByID(ctx context.Context, id int64) (*domain.Tier, error) + GetAll(ctx context.Context) ([]domain.Tier, error) + GetByID(ctx context.Context, id int64) (domain.Tier, error) Create(ctx context.Context, args domain.Tier) error Update(ctx context.Context, args domain.Tier) error Delete(ctx context.Context, id int64) error @@ -23,27 +23,26 @@ func NewTierRepository(db *dbmodels.Queries) TierRepository { return &tierRepository{db: db} } -func (r *tierRepository) GetAll(ctx context.Context) ([]*domain.Tier, error) { +func (r *tierRepository) GetAll(ctx context.Context) ([]domain.Tier, error) { dbTiers, err := r.db.GetTiers(ctx) if err != nil { return nil, err } - var Tiers []*domain.Tier + var Tiers []domain.Tier for _, dbTier := range dbTiers { - Tiers = append(Tiers, convertDBTierToDomain(&dbTier)) + Tiers = append(Tiers, convertDBTierToDomain(dbTier)) } return Tiers, nil } -func (r *tierRepository) GetByID(ctx context.Context, id int64) (*domain.Tier, error) { +func (r *tierRepository) GetByID(ctx context.Context, id int64) (domain.Tier, error) { dbTier, err := r.db.GetTier(ctx, id) - if err != nil { - return nil, err + return domain.Tier{}, err } - return convertDBTierToDomain(&dbTier), nil + return convertDBTierToDomain(dbTier), nil } func (r *tierRepository) Delete(ctx context.Context, id int64) error { @@ -55,7 +54,7 @@ func (r *tierRepository) Delete(ctx context.Context, id int64) error { } func (r *tierRepository) Create(ctx context.Context, args domain.Tier) error { - _, err := r.db.CreateTier(ctx, *convertDomainToCreateDBTier(&args)) + _, err := r.db.CreateTier(ctx, convertDomainToCreateDBTier(args)) if err != nil { return err } @@ -63,7 +62,7 @@ func (r *tierRepository) Create(ctx context.Context, args domain.Tier) error { } func (r *tierRepository) Update(ctx context.Context, args domain.Tier) error { - err := r.db.UpdateTier(ctx, *convertDomainToUpdateDBTier(&args)) + err := r.db.UpdateTier(ctx, convertDomainToUpdateDBTier(args)) if err != nil { return err } From d0ef1739e350a1900072180386f7b492291626a5 Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Mon, 9 Feb 2026 11:20:22 -0800 Subject: [PATCH 18/56] announcements services --- internal/api/handlers/announcement.go | 4 +-- internal/api/services/announcement.go | 37 +++++++++++++-------------- internal/dto/request/announcements.go | 2 +- internal/dto/request/event.go | 2 +- internal/dto/request/officer.go | 2 +- internal/dto/request/position.go | 2 +- internal/dto/request/tier.go | 2 +- 7 files changed, 25 insertions(+), 26 deletions(-) diff --git a/internal/api/handlers/announcement.go b/internal/api/handlers/announcement.go index 2fc804e..9151078 100644 --- a/internal/api/handlers/announcement.go +++ b/internal/api/handlers/announcement.go @@ -7,6 +7,7 @@ import ( "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" + "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" "github.com/gin-gonic/gin" ) @@ -35,7 +36,6 @@ func (h *AnnouncementHandler) GetAnnouncement(c *gin.Context) { id := c.Param("id") announcement, err := h.announcementService.Get(ctx, id) - if err != nil { if err.Error() == "sql: no rows in result set" { c.JSON(http.StatusNotFound, gin.H{ @@ -80,7 +80,7 @@ func (h *AnnouncementHandler) GetAnnouncements(c *gin.Context) { // @Router /v1/announcements [post] func (h *AnnouncementHandler) CreateAnnouncement(c *gin.Context) { ctx := c.Request.Context() - var params dbmodels.CreateAnnouncementParams + var params dto_request.Announcement if err := c.ShouldBindJSON(¶ms); err != nil { c.JSON(http.StatusBadRequest, gin.H{ diff --git a/internal/api/services/announcement.go b/internal/api/services/announcement.go index af0f222..cbe7f07 100644 --- a/internal/api/services/announcement.go +++ b/internal/api/services/announcement.go @@ -2,7 +2,6 @@ package services import ( "context" - "log" "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" @@ -11,46 +10,46 @@ import ( ) type AnnouncementServicer interface { - Service[dbmodels.Announcement, string, dbmodels.CreateAnnouncementParams, - dbmodels.UpdateAnnouncementParams] + Service[domain.Announcement, string, domain.Announcement, + domain.Announcement] } type AnnouncementService struct { - q *dbmodels.Queries + announcementRepository repository.AnnouncementRepository } // compile time check var _ AnnouncementServicer = (*AnnouncementService)(nil) -func NewAnnouncementService(q *dbmodels.Queries) *repository.AnnouncementService { - return &AnnouncementService{q: q} +func NewAnnouncementService(announcementRepository repository.AnnouncementRepository) *AnnouncementService { + return &AnnouncementService{announcementRepository: announcementRepository} } func (s *AnnouncementService) Get(ctx context.Context, uuid string) (domain.Announcement, error) { - announcement, err := s.q.GetAnnouncement(ctx, uuid) + announcement, err := s.announcementRepository.GetByID(ctx, uuid) if err != nil { - return dbmodels.Announcement{}, err + return domain.Announcement{}, err } return announcement, nil } func (s *AnnouncementService) Create(ctx context.Context, - params dbmodels.CreateAnnouncementParams) error { - - if err := s.q.CreateAnnouncement(ctx, params); err != nil { + params domain.Announcement, +) error { + if err := s.announcementRepository.Create(ctx, params); err != nil { return err } return nil } type AnnouncementFilter interface { - Apply(events []dbmodels.Announcement) []dbmodels.Announcement + Apply(events []domain.Announcement) []domain.Announcement } func (s *AnnouncementService) List(ctx context.Context, - filters ...any) ([]dbmodels.Announcement, error) { - - announcements, err := s.q.GetAnnouncements(ctx) + filters ...any, +) ([]domain.Announcement, error) { + announcements, err := s.announcementRepository.GetAll(ctx) if err != nil { return nil, err } @@ -65,9 +64,9 @@ func (s *AnnouncementService) List(ctx context.Context, } func (s *AnnouncementService) Update(ctx context.Context, uuid string, - params dbmodels.UpdateAnnouncementParams) error { - - err := s.q.UpdateAnnouncement(ctx, params) + params domain.Announcement, +) error { + err := s.announcementRepository.Update(ctx, params) if err != nil { log.Printf("Error updating announcement with UUID %s: %v", uuid, err) return err @@ -76,7 +75,7 @@ func (s *AnnouncementService) Update(ctx context.Context, uuid string, } func (s *AnnouncementService) Delete(ctx context.Context, uuid string) error { - err := s.q.DeleteAnnouncement(ctx, uuid) + err := s.announcementRepository.Delete(ctx, uuid) if err != nil { log.Printf("Error deleting announcement with UUID %s: %v", uuid, err) return err diff --git a/internal/dto/request/announcements.go b/internal/dto/request/announcements.go index bb1342e..b6197d9 100644 --- a/internal/dto/request/announcements.go +++ b/internal/dto/request/announcements.go @@ -1,4 +1,4 @@ -package domain +package dto_request type Announcement struct { Uuid string `json:"uuid"` diff --git a/internal/dto/request/event.go b/internal/dto/request/event.go index 3c5ed0a..50db61e 100644 --- a/internal/dto/request/event.go +++ b/internal/dto/request/event.go @@ -1,4 +1,4 @@ -package domain +package dto_request type Event struct { Location string `json:"location"` diff --git a/internal/dto/request/officer.go b/internal/dto/request/officer.go index 7ec6bab..f65b385 100644 --- a/internal/dto/request/officer.go +++ b/internal/dto/request/officer.go @@ -1,4 +1,4 @@ -package domain +package dto_request type Officer struct { FullName string `json:"full_name"` diff --git a/internal/dto/request/position.go b/internal/dto/request/position.go index c16ce39..b390cd0 100644 --- a/internal/dto/request/position.go +++ b/internal/dto/request/position.go @@ -1,4 +1,4 @@ -package domain +package dto_request type Position struct { Oid string `json:"oid"` diff --git a/internal/dto/request/tier.go b/internal/dto/request/tier.go index 9dbac5c..07815db 100644 --- a/internal/dto/request/tier.go +++ b/internal/dto/request/tier.go @@ -1,4 +1,4 @@ -package domain +package dto_request type Tier struct { Tier int `json:"tier"` From 2cba17755992bb5e8ff9d590476b909699659ef8 Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Mon, 9 Feb 2026 11:33:53 -0800 Subject: [PATCH 19/56] Add To domain in dto requests --- internal/dto/request/announcements.go | 16 ++++++++++++++++ internal/dto/request/event.go | 16 ++++++++++++++++ internal/dto/request/officer.go | 11 +++++++++++ internal/dto/request/position.go | 10 ++++++++++ internal/dto/request/tier.go | 11 +++++++++++ 5 files changed, 64 insertions(+) diff --git a/internal/dto/request/announcements.go b/internal/dto/request/announcements.go index b6197d9..b6a1be5 100644 --- a/internal/dto/request/announcements.go +++ b/internal/dto/request/announcements.go @@ -1,5 +1,11 @@ package dto_request +import ( + "time" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + type Announcement struct { Uuid string `json:"uuid"` Visibility string `json:"visibility"` @@ -7,3 +13,13 @@ type Announcement struct { DiscordChannelID string `json:"discord_channel_id"` DiscordMessageID string `json:"discord_message_id"` } + +func (a *Announcement) ToDomain() domain.Announcement { + return domain.Announcement{ + Uuid: a.Uuid, + Visibility: a.Visibility, + AnnounceAt: time.Unix(a.AnnounceAt, 0), + DiscordChannelID: a.DiscordChannelID, + DiscordMessageID: a.DiscordMessageID, + } +} diff --git a/internal/dto/request/event.go b/internal/dto/request/event.go index 50db61e..2831b99 100644 --- a/internal/dto/request/event.go +++ b/internal/dto/request/event.go @@ -1,5 +1,11 @@ package dto_request +import ( + "time" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" +) + type Event struct { Location string `json:"location"` StartAt int64 `json:"start_at"` @@ -7,3 +13,13 @@ type Event struct { IsAllDay bool `json:"is_all_day"` Host string `json:"host"` } + +func (e *Event) ToDomain() domain.Event { + return domain.Event{ + Location: e.Location, + StartAt: time.Unix(e.StartAt, 0), + EndAt: time.Unix(e.EndAt, 0), + IsAllDay: e.IsAllDay, + Host: e.Host, + } +} diff --git a/internal/dto/request/officer.go b/internal/dto/request/officer.go index f65b385..46bac65 100644 --- a/internal/dto/request/officer.go +++ b/internal/dto/request/officer.go @@ -1,8 +1,19 @@ package dto_request +import "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" + type Officer struct { FullName string `json:"full_name"` Picture string `json:"picture"` Github string `json:"github"` Discord string `json:"discord"` } + +func (o *Officer) ToDomain() domain.Officer { + return domain.Officer{ + FullName: o.FullName, + Picture: o.Picture, + Github: o.Github, + Discord: o.Discord, + } +} diff --git a/internal/dto/request/position.go b/internal/dto/request/position.go index b390cd0..415ff56 100644 --- a/internal/dto/request/position.go +++ b/internal/dto/request/position.go @@ -1,7 +1,17 @@ package dto_request +import "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" + type Position struct { Oid string `json:"oid"` Semester string `json:"semester"` Tier int `json:"tier"` } + +func (p *Position) ToDomain() domain.Position { + return domain.Position{ + Oid: p.Oid, + Semester: p.Semester, + Tier: p.Tier, + } +} diff --git a/internal/dto/request/tier.go b/internal/dto/request/tier.go index 07815db..ea3edbf 100644 --- a/internal/dto/request/tier.go +++ b/internal/dto/request/tier.go @@ -1,8 +1,19 @@ package dto_request +import "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" + type Tier struct { Tier int `json:"tier"` Title string `json:"title"` Tindex int `json:"t_index"` Team string `json:"team"` } + +func (t *Tier) ToDomain() domain.Tier { + return domain.Tier{ + Tier: t.Tier, + Title: t.Title, + Tindex: t.Tindex, + Team: t.Team, + } +} From e83dd69202ff681e5e02a18457003af624c1e447 Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Mon, 9 Feb 2026 11:41:48 -0800 Subject: [PATCH 20/56] module name update for dto response --- internal/dto/response/announcements.go | 2 +- internal/dto/response/event.go | 2 +- internal/dto/response/officer.go | 2 +- internal/dto/response/position.go | 2 +- internal/dto/response/tier.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/dto/response/announcements.go b/internal/dto/response/announcements.go index bb1342e..af348a6 100644 --- a/internal/dto/response/announcements.go +++ b/internal/dto/response/announcements.go @@ -1,4 +1,4 @@ -package domain +package dto_response type Announcement struct { Uuid string `json:"uuid"` diff --git a/internal/dto/response/event.go b/internal/dto/response/event.go index 3c5ed0a..cafeee8 100644 --- a/internal/dto/response/event.go +++ b/internal/dto/response/event.go @@ -1,4 +1,4 @@ -package domain +package dto_response type Event struct { Location string `json:"location"` diff --git a/internal/dto/response/officer.go b/internal/dto/response/officer.go index 7ec6bab..1f619e1 100644 --- a/internal/dto/response/officer.go +++ b/internal/dto/response/officer.go @@ -1,4 +1,4 @@ -package domain +package dto_response type Officer struct { FullName string `json:"full_name"` diff --git a/internal/dto/response/position.go b/internal/dto/response/position.go index c16ce39..8667fdd 100644 --- a/internal/dto/response/position.go +++ b/internal/dto/response/position.go @@ -1,4 +1,4 @@ -package domain +package dto_response type Position struct { Oid string `json:"oid"` diff --git a/internal/dto/response/tier.go b/internal/dto/response/tier.go index 9dbac5c..db90182 100644 --- a/internal/dto/response/tier.go +++ b/internal/dto/response/tier.go @@ -1,4 +1,4 @@ -package domain +package dto_response type Tier struct { Tier int `json:"tier"` From 9a50b7c36e2b85fe4726cd67039e7522c562a260 Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Mon, 9 Feb 2026 11:53:46 -0800 Subject: [PATCH 21/56] Domain to DTO Changed so response dto comes with uuid --- internal/domain/announcements.go | 16 +++++++++++++++- internal/domain/event.go | 17 ++++++++++++++++- internal/domain/officer.go | 12 ++++++++++++ internal/domain/position.go | 10 ++++++++++ internal/domain/tier.go | 11 +++++++++++ internal/dto/response/event.go | 1 + internal/dto/response/officer.go | 1 + 7 files changed, 66 insertions(+), 2 deletions(-) diff --git a/internal/domain/announcements.go b/internal/domain/announcements.go index 5019dfb..769b7ae 100644 --- a/internal/domain/announcements.go +++ b/internal/domain/announcements.go @@ -1,6 +1,10 @@ package domain -import "time" +import ( + "time" + + dto_response "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/response" +) type Announcement struct { Uuid string @@ -9,3 +13,13 @@ type Announcement struct { DiscordChannelID string DiscordMessageID string } + +func (a *Announcement) ToDTO() dto_response.Announcement { + return dto_response.Announcement{ + Uuid: a.Uuid, + Visibility: a.Visibility, + AnnounceAt: a.AnnounceAt.Unix(), + DiscordChannelID: a.DiscordChannelID, + DiscordMessageID: a.DiscordMessageID, + } +} diff --git a/internal/domain/event.go b/internal/domain/event.go index 3e56484..65e0fc6 100644 --- a/internal/domain/event.go +++ b/internal/domain/event.go @@ -1,6 +1,10 @@ package domain -import "time" +import ( + "time" + + dto_response "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/response" +) type Event struct { Uuid string @@ -10,3 +14,14 @@ type Event struct { IsAllDay bool Host string } + +func (e *Event) ToDTO() dto_response.Event { + return dto_response.Event{ + Uuid: e.Uuid, + Location: e.Location, + StartAt: e.StartAt.Unix(), + EndAt: e.EndAt.Unix(), + IsAllDay: e.IsAllDay, + Host: e.Host, + } +} diff --git a/internal/domain/officer.go b/internal/domain/officer.go index 23c47ca..c02ed66 100644 --- a/internal/domain/officer.go +++ b/internal/domain/officer.go @@ -1,5 +1,7 @@ package domain +import dto_response "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/response" + type Officer struct { Uuid string FullName string @@ -7,3 +9,13 @@ type Officer struct { Github string Discord string } + +func (o *Officer) ToDTO() dto_response.Officer { + return dto_response.Officer{ + Uuid: o.Uuid, + FullName: o.FullName, + Picture: o.Picture, + Github: o.Github, + Discord: o.Discord, + } +} diff --git a/internal/domain/position.go b/internal/domain/position.go index 9c0978a..35d7012 100644 --- a/internal/domain/position.go +++ b/internal/domain/position.go @@ -1,7 +1,17 @@ package domain +import dto_response "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/response" + type Position struct { Oid string Semester string Tier int } + +func (p *Position) ToDTO() dto_response.Position { + return dto_response.Position{ + Oid: p.Oid, + Semester: p.Semester, + Tier: p.Tier, + } +} diff --git a/internal/domain/tier.go b/internal/domain/tier.go index fadefeb..5f2304f 100644 --- a/internal/domain/tier.go +++ b/internal/domain/tier.go @@ -1,8 +1,19 @@ package domain +import dto_response "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/response" + type Tier struct { Tier int Title string Tindex int Team string } + +func (t *Tier) ToDTO() dto_response.Tier { + return dto_response.Tier{ + Tier: t.Tier, + Title: t.Title, + Tindex: t.Tindex, + Team: t.Team, + } +} diff --git a/internal/dto/response/event.go b/internal/dto/response/event.go index cafeee8..adbef01 100644 --- a/internal/dto/response/event.go +++ b/internal/dto/response/event.go @@ -1,6 +1,7 @@ package dto_response type Event struct { + Uuid string `json:"uuid"` Location string `json:"location"` StartAt int64 `json:"start_at"` EndAt int64 `json:"end_at"` diff --git a/internal/dto/response/officer.go b/internal/dto/response/officer.go index 1f619e1..f0fbd76 100644 --- a/internal/dto/response/officer.go +++ b/internal/dto/response/officer.go @@ -1,6 +1,7 @@ package dto_response type Officer struct { + Uuid string `json:"uuid"` FullName string `json:"full_name"` Picture string `json:"picture"` Github string `json:"github"` From 19d4f33d093a8c28a1e0d33680bba09c72caa417 Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Mon, 9 Feb 2026 21:32:50 -0800 Subject: [PATCH 22/56] omitempty on identifiers --- internal/api/handlers/announcement.go | 9 +++---- internal/api/handlers/event.go | 16 +++++------ internal/api/server.go | 8 +++--- internal/api/services/announcement.go | 4 ++- internal/api/services/event.go | 37 +++++++++++++------------- internal/cli/announcements/post.go | 24 ++++++++++------- internal/cli/events/post.go | 20 +++++++------- internal/dto/request/announcements.go | 2 +- internal/dto/request/event.go | 2 +- internal/dto/request/officer.go | 2 +- internal/dto/request/position.go | 2 +- internal/dto/response/announcements.go | 2 +- internal/dto/response/event.go | 2 +- internal/dto/response/officer.go | 2 +- internal/dto/response/position.go | 2 +- 15 files changed, 72 insertions(+), 62 deletions(-) diff --git a/internal/api/handlers/announcement.go b/internal/api/handlers/announcement.go index 9151078..e5b7afc 100644 --- a/internal/api/handlers/announcement.go +++ b/internal/api/handlers/announcement.go @@ -5,7 +5,6 @@ package handlers import ( "net/http" - "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" "github.com/gin-gonic/gin" @@ -48,7 +47,7 @@ func (h *AnnouncementHandler) GetAnnouncement(c *gin.Context) { }) } - c.JSON(http.StatusOK, announcement) + c.JSON(http.StatusOK, announcement.ToDTO()) } func (h *AnnouncementHandler) GetAnnouncements(c *gin.Context) { @@ -90,7 +89,7 @@ func (h *AnnouncementHandler) CreateAnnouncement(c *gin.Context) { } // TODO: error out if required fields aren't provided - if err := h.announcementService.Create(ctx, params); err != nil { + if err := h.announcementService.Create(ctx, params.ToDomain()); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to create announcement", }) @@ -119,7 +118,7 @@ func (h *AnnouncementHandler) CreateAnnouncement(c *gin.Context) { // @Router /v1/announcements/{id} [put] func (h *AnnouncementHandler) UpdateAnnouncement(c *gin.Context) { ctx := c.Request.Context() - var params dbmodels.UpdateAnnouncementParams + var params dto_request.Announcement id := c.Param("id") if err := c.ShouldBindJSON(¶ms); err != nil { @@ -128,7 +127,7 @@ func (h *AnnouncementHandler) UpdateAnnouncement(c *gin.Context) { }) } - if err := h.announcementService.Update(ctx, id, params); err != nil { + if err := h.announcementService.Update(ctx, id, params.ToDomain()); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to update announcement", }) diff --git a/internal/api/handlers/event.go b/internal/api/handlers/event.go index e3ad379..360dde1 100644 --- a/internal/api/handlers/event.go +++ b/internal/api/handlers/event.go @@ -6,8 +6,8 @@ import ( "fmt" "net/http" - "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" + dto_request "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" "github.com/gin-gonic/gin" ) @@ -38,7 +38,6 @@ func (h *EventsHandler) GetEvent(c *gin.Context) { id := c.Param("id") event, err := h.eventsService.Get(ctx, id) - if err != nil { if err.Error() == "sql: no rows in result set" { c.JSON(http.StatusNotFound, gin.H{ @@ -70,7 +69,7 @@ func (h *EventsHandler) GetEvent(c *gin.Context) { // @Router /v1/events [post] func (h *EventsHandler) CreateEvent(c *gin.Context) { ctx := c.Request.Context() - var params dbmodels.CreateEventParams + var params dto_request.Event if err := c.ShouldBindJSON(¶ms); err != nil { c.JSON(http.StatusBadRequest, gin.H{ @@ -86,7 +85,7 @@ func (h *EventsHandler) CreateEvent(c *gin.Context) { return } - err := h.eventsService.Create(ctx, params) + err := h.eventsService.Create(ctx, params.ToDomain()) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to create event. " + err.Error(), @@ -95,7 +94,7 @@ func (h *EventsHandler) CreateEvent(c *gin.Context) { } c.JSON(http.StatusOK, gin.H{ "message": "Event created successfully", - "uuid": params.Uuid, + "uuid": params.ToDomain().Uuid, }) } @@ -145,7 +144,7 @@ func (h *EventsHandler) GetEvents(c *gin.Context) { // @Router /v1/events/{id} [put] func (h *EventsHandler) UpdateEvent(c *gin.Context) { ctx := c.Request.Context() - var params dbmodels.UpdateEventParams + var params dto_request.Event id := c.Param("id") fmt.Println("UPDATE:", id) @@ -156,16 +155,17 @@ func (h *EventsHandler) UpdateEvent(c *gin.Context) { return } - if err := h.eventsService.Update(ctx, id, params); err != nil { + if err := h.eventsService.Update(ctx, id, params.ToDomain()); err != nil { error := fmt.Sprint("Failed to update event: ", err, " | ", ctx, " | ", id, " | ", params) c.JSON(http.StatusInternalServerError, gin.H{ "error": error, }) return } + c.JSON(http.StatusOK, gin.H{ "message": "Event updated successfully", - "uuid": params.Uuid, + "uuid": params.ToDomain().Uuid, }) } diff --git a/internal/api/server.go b/internal/api/server.go index 91f8ccf..f69239b 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -16,6 +16,7 @@ import ( mw "github.com/acmcsufoss/api.acmcsuf.com/internal/api/middleware" "github.com/acmcsufoss/api.acmcsuf.com/internal/api/routes" "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" + "github.com/acmcsufoss/api.acmcsuf.com/internal/repository" ) // Run initializes the database, services, and router, then starts the server. @@ -31,8 +32,10 @@ func Run(ctx context.Context) { // Now we init services & gin router, and then start the server queries := dbmodels.New(db) - eventsService := services.NewEventsService(queries) - announcementService := services.NewAnnouncementService(queries) + announcementsRepo := repository.NewAnnouncementRepository(queries) + eventsRepo := repository.NewEventRepository(queries) + announcementService := services.NewAnnouncementService(announcementsRepo) + eventsService := services.NewEventsService(eventsRepo) boardService := services.NewBoardService(queries, db) router := gin.Default() router.Use(mw.Cors(), mw.Ratelimiter()) @@ -79,5 +82,4 @@ func NewDB(ctx context.Context, url string) (*sql.DB, func(), error) { return db, func() { db.Close() }, nil - } diff --git a/internal/api/services/announcement.go b/internal/api/services/announcement.go index cbe7f07..5ab1d20 100644 --- a/internal/api/services/announcement.go +++ b/internal/api/services/announcement.go @@ -2,9 +2,9 @@ package services import ( "context" + "fmt" "log" - "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" "github.com/acmcsufoss/api.acmcsuf.com/internal/repository" ) @@ -36,6 +36,7 @@ func (s *AnnouncementService) Get(ctx context.Context, uuid string) (domain.Anno func (s *AnnouncementService) Create(ctx context.Context, params domain.Announcement, ) error { + fmt.Println("SERVICE PARAM:", params) if err := s.announcementRepository.Create(ctx, params); err != nil { return err } @@ -51,6 +52,7 @@ func (s *AnnouncementService) List(ctx context.Context, ) ([]domain.Announcement, error) { announcements, err := s.announcementRepository.GetAll(ctx) if err != nil { + fmt.Println(err) return nil, err } diff --git a/internal/api/services/event.go b/internal/api/services/event.go index bd76bf6..686a6e6 100644 --- a/internal/api/services/event.go +++ b/internal/api/services/event.go @@ -4,34 +4,35 @@ package services import ( "context" - "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" + "github.com/acmcsufoss/api.acmcsuf.com/internal/repository" ) type EventsServicer interface { - Service[dbmodels.Event, string, dbmodels.CreateEventParams, dbmodels.UpdateEventParams] + Service[domain.Event, string, domain.Event, domain.Event] } type EventsService struct { - q *dbmodels.Queries + eventRepo repository.EventRepository } // this checks that EventsService implements EventsServicers at compile time var _ EventsServicer = (*EventsService)(nil) -func NewEventsService(q *dbmodels.Queries) *EventsService { - return &EventsService{q: q} +func NewEventsService(eventRepo repository.EventRepository) *EventsService { + return &EventsService{eventRepo: eventRepo} } -func (s *EventsService) Get(ctx context.Context, uuid string) (dbmodels.Event, error) { - event, err := s.q.GetEvent(ctx, uuid) +func (s *EventsService) Get(ctx context.Context, uuid string) (domain.Event, error) { + event, err := s.eventRepo.GetByID(ctx, uuid) if err != nil { - return dbmodels.Event{}, err + return domain.Event{}, err } return event, nil } -func (s *EventsService) Create(ctx context.Context, params dbmodels.CreateEventParams) error { - if err := s.q.CreateEvent(ctx, params); err != nil { +func (s *EventsService) Create(ctx context.Context, params domain.Event) error { + if err := s.eventRepo.Create(ctx, params); err != nil { return err } return nil @@ -39,7 +40,7 @@ func (s *EventsService) Create(ctx context.Context, params dbmodels.CreateEventP // TODO: Move filters to their own file or module or something type EventFilter interface { - Apply(events []dbmodels.Event) []dbmodels.Event + Apply(events []domain.Event) []domain.Event } type HostFilter struct { @@ -49,12 +50,12 @@ type HostFilter struct { // Ensure HostFilter implements EventFilter var _ EventFilter = (*HostFilter)(nil) -func (f *HostFilter) Apply(events []dbmodels.Event) []dbmodels.Event { +func (f *HostFilter) Apply(events []domain.Event) []domain.Event { if f.Host == "" { return events } - filtered := make([]dbmodels.Event, 0) + filtered := make([]domain.Event, 0) for _, event := range events { if event.Host == f.Host { filtered = append(filtered, event) @@ -63,8 +64,8 @@ func (f *HostFilter) Apply(events []dbmodels.Event) []dbmodels.Event { return filtered } -func (s *EventsService) List(ctx context.Context, filters ...any) ([]dbmodels.Event, error) { - events, err := s.q.GetEvents(ctx) +func (s *EventsService) List(ctx context.Context, filters ...any) ([]domain.Event, error) { + events, err := s.eventRepo.GetAll(ctx) if err != nil { return nil, err } @@ -79,16 +80,16 @@ func (s *EventsService) List(ctx context.Context, filters ...any) ([]dbmodels.Ev return result, nil } -func (s *EventsService) Update(ctx context.Context, uuid string, params dbmodels.UpdateEventParams) error { +func (s *EventsService) Update(ctx context.Context, uuid string, params domain.Event) error { params.Uuid = uuid - if err := s.q.UpdateEvent(ctx, params); err != nil { + if err := s.eventRepo.Update(ctx, params); err != nil { return err } return nil } func (s *EventsService) Delete(ctx context.Context, uuid string) error { - if err := s.q.DeleteEvent(ctx, uuid); err != nil { + if err := s.eventRepo.Delete(ctx, uuid); err != nil { return err } return nil diff --git a/internal/cli/announcements/post.go b/internal/cli/announcements/post.go index 7d8998d..20688d7 100644 --- a/internal/cli/announcements/post.go +++ b/internal/cli/announcements/post.go @@ -9,13 +9,14 @@ import ( "net/url" "os" "strings" + "time" "github.com/charmbracelet/huh" "github.com/spf13/cobra" - "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/oauth" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" "github.com/acmcsufoss/api.acmcsuf.com/utils" ) @@ -24,7 +25,7 @@ var PostAnnouncement = &cobra.Command{ Short: "post a new announcement", Run: func(cmd *cobra.Command, args []string) { - payload := dbmodels.CreateAnnouncementParams{} + payload := domain.Announcement{} err := huh.NewForm().Run() if err != nil { if err == huh.ErrUserAborted { @@ -40,12 +41,12 @@ var PostAnnouncement = &cobra.Command{ channelIdString, _ := cmd.Flags().GetString("channelid") messageIdString, _ := cmd.Flags().GetString("messageid") - payload.DiscordChannelID = utils.StringtoNullString(channelIdString) - payload.DiscordMessageID = utils.StringtoNullString(messageIdString) + payload.DiscordChannelID = channelIdString + payload.DiscordMessageID = messageIdString if announceString != "" { - var err error - payload.AnnounceAt, err = utils.ByteSlicetoUnix([]byte(announceString)) + announceAtUnix, err := utils.ByteSlicetoUnix([]byte(announceString)) + payload.AnnounceAt = time.Unix(announceAtUnix, 0) if err != nil { fmt.Println(err) return @@ -74,7 +75,7 @@ func init() { PostAnnouncement.Flags().StringP("messageid", "m", "", "Set this announcement's message id") } -func postAnnouncement(payload *dbmodels.CreateAnnouncementParams, changedFlags announcementFlags, cfg *config.Config) { +func postAnnouncement(payload *domain.Announcement, changedFlags announcementFlags, cfg *config.Config) { baseURL := &url.URL{ Scheme: "http", Host: fmt.Sprintf("%s:%s", cfg.Host, cfg.Port), @@ -176,7 +177,8 @@ func postAnnouncement(payload *dbmodels.CreateAnnouncementParams, changedFlags a announceatBuffer := scanner.Bytes() - payload.AnnounceAt, err = utils.ByteSlicetoUnix(announceatBuffer) + announceAtUnix, err := utils.ByteSlicetoUnix(announceatBuffer) + payload.AnnounceAt = time.Unix(announceAtUnix, 0) if err != nil { fmt.Println("error converting byte slice to unix time (of type int64):", err) continue @@ -212,7 +214,7 @@ func postAnnouncement(payload *dbmodels.CreateAnnouncementParams, changedFlags a } channelIdBuffer := scanner.Bytes() - payload.DiscordChannelID = utils.StringtoNullString(string(channelIdBuffer)) + payload.DiscordChannelID = string(channelIdBuffer) break } @@ -243,7 +245,7 @@ func postAnnouncement(payload *dbmodels.CreateAnnouncementParams, changedFlags a continue } messageIdBuffer := scanner.Bytes() - payload.DiscordMessageID = utils.StringtoNullString(string(messageIdBuffer)) + payload.DiscordMessageID = string(messageIdBuffer) break } @@ -290,6 +292,7 @@ func postAnnouncement(payload *dbmodels.CreateAnnouncementParams, changedFlags a // ----- Marshalling to Json ----- jsonPayload, err := json.Marshal(*payload) + fmt.Println("JSON MARSHALLED:", payload) if err != nil { fmt.Println("error formating payload to json:", err) return @@ -307,6 +310,7 @@ func postAnnouncement(payload *dbmodels.CreateAnnouncementParams, changedFlags a return } + fmt.Println("HELLO?") res, err := client.Do(req) if err != nil { fmt.Println("error with requesting post", err) diff --git a/internal/cli/events/post.go b/internal/cli/events/post.go index 31fd6d5..7ebabdc 100644 --- a/internal/cli/events/post.go +++ b/internal/cli/events/post.go @@ -9,14 +9,14 @@ import ( "net/url" "os" "strings" + "time" "github.com/charmbracelet/huh" "github.com/spf13/cobra" - // TODO: db params shouldn't be exposed here - "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/oauth" + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" "github.com/acmcsufoss/api.acmcsuf.com/utils" ) @@ -25,7 +25,7 @@ var PostEvent = &cobra.Command{ Short: "Post a new event.", Run: func(cmd *cobra.Command, args []string) { - payload := dbmodels.CreateEventParams{} + payload := domain.Event{} err := huh.NewForm().Run() if err != nil { if err == huh.ErrUserAborted { @@ -44,18 +44,20 @@ var PostEvent = &cobra.Command{ if startAtString != "" { var err error - payload.StartAt, err = utils.ByteSlicetoUnix([]byte(startAtString)) + startAtUnix, err := utils.ByteSlicetoUnix([]byte(startAtString)) if err != nil { fmt.Println(err) return } + payload.StartAt = time.Unix(startAtUnix, 0) if duration != "" { var err error - payload.EndAt, err = utils.TimeAfterDuration(payload.StartAt, duration) + endAtUnix, err := utils.TimeAfterDuration(payload.StartAt.Unix(), duration) if err != nil { fmt.Println(err) return } + payload.EndAt = time.Unix(endAtUnix, 0) } } @@ -85,7 +87,7 @@ func init() { PostEvent.Flags().BoolP("isallday", "a", false, "Set if new event is all day") } -func postEvent(payload *dbmodels.CreateEventParams, changedFlag eventFlags, cfg *config.Config) { +func postEvent(payload *domain.Event, changedFlag eventFlags, cfg *config.Config) { baseURL := &url.URL{ Scheme: "http", Host: fmt.Sprintf("%s:%s", cfg.Host, cfg.Port), @@ -193,7 +195,7 @@ func postEvent(payload *dbmodels.CreateEventParams, changedFlag eventFlags, cfg continue } - payload.StartAt = startTime + payload.StartAt = time.Unix(startTime, 0) break } @@ -226,13 +228,13 @@ func postEvent(payload *dbmodels.CreateEventParams, changedFlag eventFlags, cfg } endTimeBuffer := scanner.Bytes() - endTime, err := utils.TimeAfterDuration(payload.StartAt, string(endTimeBuffer)) + endTime, err := utils.TimeAfterDuration(payload.StartAt.Unix(), string(endTimeBuffer)) if err != nil { fmt.Println(err) continue } - payload.EndAt = endTime + payload.EndAt = time.Unix(endTime, 0) break } diff --git a/internal/dto/request/announcements.go b/internal/dto/request/announcements.go index b6a1be5..7e7ff05 100644 --- a/internal/dto/request/announcements.go +++ b/internal/dto/request/announcements.go @@ -7,7 +7,7 @@ import ( ) type Announcement struct { - Uuid string `json:"uuid"` + Uuid string `json:"uuid,omitempty"` Visibility string `json:"visibility"` AnnounceAt int64 `json:"announce_at"` DiscordChannelID string `json:"discord_channel_id"` diff --git a/internal/dto/request/event.go b/internal/dto/request/event.go index 2831b99..43053f2 100644 --- a/internal/dto/request/event.go +++ b/internal/dto/request/event.go @@ -7,7 +7,7 @@ import ( ) type Event struct { - Location string `json:"location"` + Location string `json:"location,omitempty"` StartAt int64 `json:"start_at"` EndAt int64 `json:"end_at"` IsAllDay bool `json:"is_all_day"` diff --git a/internal/dto/request/officer.go b/internal/dto/request/officer.go index 46bac65..a8d3b6e 100644 --- a/internal/dto/request/officer.go +++ b/internal/dto/request/officer.go @@ -3,7 +3,7 @@ package dto_request import "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" type Officer struct { - FullName string `json:"full_name"` + FullName string `json:"full_name,omitempty"` Picture string `json:"picture"` Github string `json:"github"` Discord string `json:"discord"` diff --git a/internal/dto/request/position.go b/internal/dto/request/position.go index 415ff56..082e9ef 100644 --- a/internal/dto/request/position.go +++ b/internal/dto/request/position.go @@ -3,7 +3,7 @@ package dto_request import "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" type Position struct { - Oid string `json:"oid"` + Oid string `json:"oid,omitempty"` Semester string `json:"semester"` Tier int `json:"tier"` } diff --git a/internal/dto/response/announcements.go b/internal/dto/response/announcements.go index af348a6..ee1babe 100644 --- a/internal/dto/response/announcements.go +++ b/internal/dto/response/announcements.go @@ -1,7 +1,7 @@ package dto_response type Announcement struct { - Uuid string `json:"uuid"` + Uuid string `json:"uuid,omitempty"` Visibility string `json:"visibility"` AnnounceAt int64 `json:"announce_at"` DiscordChannelID string `json:"discord_channel_id"` diff --git a/internal/dto/response/event.go b/internal/dto/response/event.go index adbef01..33d53ca 100644 --- a/internal/dto/response/event.go +++ b/internal/dto/response/event.go @@ -1,7 +1,7 @@ package dto_response type Event struct { - Uuid string `json:"uuid"` + Uuid string `json:"uuid,omitempty"` Location string `json:"location"` StartAt int64 `json:"start_at"` EndAt int64 `json:"end_at"` diff --git a/internal/dto/response/officer.go b/internal/dto/response/officer.go index f0fbd76..f1864da 100644 --- a/internal/dto/response/officer.go +++ b/internal/dto/response/officer.go @@ -1,7 +1,7 @@ package dto_response type Officer struct { - Uuid string `json:"uuid"` + Uuid string `json:"uuid,omitempty"` FullName string `json:"full_name"` Picture string `json:"picture"` Github string `json:"github"` diff --git a/internal/dto/response/position.go b/internal/dto/response/position.go index 8667fdd..b69725c 100644 --- a/internal/dto/response/position.go +++ b/internal/dto/response/position.go @@ -1,7 +1,7 @@ package dto_response type Position struct { - Oid string `json:"oid"` + Oid string `json:"oid,omitempty"` Semester string `json:"semester"` Tier int `json:"tier"` } From 1fb8cdf53bd902aa1a116df5fa33b05bfa583e5a Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Mon, 9 Feb 2026 22:07:33 -0800 Subject: [PATCH 23/56] revert omitempty --- internal/dto/request/announcements.go | 2 +- internal/dto/request/event.go | 2 +- internal/dto/request/officer.go | 2 +- internal/dto/request/position.go | 2 +- internal/dto/response/announcements.go | 2 +- internal/dto/response/event.go | 2 +- internal/dto/response/officer.go | 2 +- internal/dto/response/position.go | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/internal/dto/request/announcements.go b/internal/dto/request/announcements.go index 7e7ff05..b6a1be5 100644 --- a/internal/dto/request/announcements.go +++ b/internal/dto/request/announcements.go @@ -7,7 +7,7 @@ import ( ) type Announcement struct { - Uuid string `json:"uuid,omitempty"` + Uuid string `json:"uuid"` Visibility string `json:"visibility"` AnnounceAt int64 `json:"announce_at"` DiscordChannelID string `json:"discord_channel_id"` diff --git a/internal/dto/request/event.go b/internal/dto/request/event.go index 43053f2..2831b99 100644 --- a/internal/dto/request/event.go +++ b/internal/dto/request/event.go @@ -7,7 +7,7 @@ import ( ) type Event struct { - Location string `json:"location,omitempty"` + Location string `json:"location"` StartAt int64 `json:"start_at"` EndAt int64 `json:"end_at"` IsAllDay bool `json:"is_all_day"` diff --git a/internal/dto/request/officer.go b/internal/dto/request/officer.go index a8d3b6e..46bac65 100644 --- a/internal/dto/request/officer.go +++ b/internal/dto/request/officer.go @@ -3,7 +3,7 @@ package dto_request import "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" type Officer struct { - FullName string `json:"full_name,omitempty"` + FullName string `json:"full_name"` Picture string `json:"picture"` Github string `json:"github"` Discord string `json:"discord"` diff --git a/internal/dto/request/position.go b/internal/dto/request/position.go index 082e9ef..415ff56 100644 --- a/internal/dto/request/position.go +++ b/internal/dto/request/position.go @@ -3,7 +3,7 @@ package dto_request import "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" type Position struct { - Oid string `json:"oid,omitempty"` + Oid string `json:"oid"` Semester string `json:"semester"` Tier int `json:"tier"` } diff --git a/internal/dto/response/announcements.go b/internal/dto/response/announcements.go index ee1babe..af348a6 100644 --- a/internal/dto/response/announcements.go +++ b/internal/dto/response/announcements.go @@ -1,7 +1,7 @@ package dto_response type Announcement struct { - Uuid string `json:"uuid,omitempty"` + Uuid string `json:"uuid"` Visibility string `json:"visibility"` AnnounceAt int64 `json:"announce_at"` DiscordChannelID string `json:"discord_channel_id"` diff --git a/internal/dto/response/event.go b/internal/dto/response/event.go index 33d53ca..adbef01 100644 --- a/internal/dto/response/event.go +++ b/internal/dto/response/event.go @@ -1,7 +1,7 @@ package dto_response type Event struct { - Uuid string `json:"uuid,omitempty"` + Uuid string `json:"uuid"` Location string `json:"location"` StartAt int64 `json:"start_at"` EndAt int64 `json:"end_at"` diff --git a/internal/dto/response/officer.go b/internal/dto/response/officer.go index f1864da..f0fbd76 100644 --- a/internal/dto/response/officer.go +++ b/internal/dto/response/officer.go @@ -1,7 +1,7 @@ package dto_response type Officer struct { - Uuid string `json:"uuid,omitempty"` + Uuid string `json:"uuid"` FullName string `json:"full_name"` Picture string `json:"picture"` Github string `json:"github"` diff --git a/internal/dto/response/position.go b/internal/dto/response/position.go index b69725c..8667fdd 100644 --- a/internal/dto/response/position.go +++ b/internal/dto/response/position.go @@ -1,7 +1,7 @@ package dto_response type Position struct { - Oid string `json:"oid,omitempty"` + Oid string `json:"oid"` Semester string `json:"semester"` Tier int `json:"tier"` } From 313ef5c6cffd7e7b7698eabc3baac4c2df8da24b Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Mon, 9 Feb 2026 22:25:34 -0800 Subject: [PATCH 24/56] uuid check in services for announcements and events --- internal/api/handlers/event.go | 4 ++-- internal/api/services/announcement.go | 4 +++- internal/api/services/event.go | 4 ++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/internal/api/handlers/event.go b/internal/api/handlers/event.go index 360dde1..745455c 100644 --- a/internal/api/handlers/event.go +++ b/internal/api/handlers/event.go @@ -47,7 +47,7 @@ func (h *EventsHandler) GetEvent(c *gin.Context) { } c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to retrieve event", + "error": fmt.Sprintln("Failed to retrieve event:" + err.Error()), }) return } @@ -121,7 +121,7 @@ func (h *EventsHandler) GetEvents(c *gin.Context) { events, err := h.eventsService.List(ctx, filters...) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to retrieve events", + "error": "Failed to retrieve events:" + err.Error(), }) return } diff --git a/internal/api/services/announcement.go b/internal/api/services/announcement.go index 5ab1d20..8c67e55 100644 --- a/internal/api/services/announcement.go +++ b/internal/api/services/announcement.go @@ -36,7 +36,9 @@ func (s *AnnouncementService) Get(ctx context.Context, uuid string) (domain.Anno func (s *AnnouncementService) Create(ctx context.Context, params domain.Announcement, ) error { - fmt.Println("SERVICE PARAM:", params) + if params.Uuid == "" { + return fmt.Errorf("no unique identifier for announcement") + } if err := s.announcementRepository.Create(ctx, params); err != nil { return err } diff --git a/internal/api/services/event.go b/internal/api/services/event.go index 686a6e6..55ee1d2 100644 --- a/internal/api/services/event.go +++ b/internal/api/services/event.go @@ -3,6 +3,7 @@ package services import ( "context" + "fmt" "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" "github.com/acmcsufoss/api.acmcsuf.com/internal/repository" @@ -32,6 +33,9 @@ func (s *EventsService) Get(ctx context.Context, uuid string) (domain.Event, err } func (s *EventsService) Create(ctx context.Context, params domain.Event) error { + if params.Uuid == "" { + return fmt.Errorf("no unique identifier for event") + } if err := s.eventRepo.Create(ctx, params); err != nil { return err } From 867a9caa584713dc401b4f592c95d79eafa4148f Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Tue, 10 Feb 2026 13:23:06 -0800 Subject: [PATCH 25/56] Services for Officers, Positions, and Tiers --- internal/api/routes/v1.go | 6 +- internal/api/server.go | 20 ++- internal/api/services/announcement.go | 3 +- internal/api/services/board.go | 170 -------------------------- internal/api/services/event.go | 2 +- internal/api/services/interfaces.go | 6 +- internal/api/services/officer.go | 84 +++++++++++++ internal/api/services/position.go | 85 +++++++++++++ internal/api/services/tier.go | 72 +++++++++++ 9 files changed, 267 insertions(+), 181 deletions(-) delete mode 100644 internal/api/services/board.go create mode 100644 internal/api/services/officer.go create mode 100644 internal/api/services/position.go create mode 100644 internal/api/services/tier.go diff --git a/internal/api/routes/v1.go b/internal/api/routes/v1.go index 48f13c6..aaa0456 100644 --- a/internal/api/routes/v1.go +++ b/internal/api/routes/v1.go @@ -15,8 +15,8 @@ import ( ) func SetupV1(router *gin.Engine, eventService services.EventsServicer, - announcementService services.AnnouncementServicer, boardService services.BoardServicer) { - + announcementService services.AnnouncementServicer, officerService services.OfficerServicer, positionService services.PositionServicer, tierService services.TierServicer, +) { cfg := config.Load() if cfg.DiscordBotToken == "" && cfg.Env != "development" { log.Fatal("Error: DISCORD_BOT_TOKEN is not set") @@ -38,7 +38,7 @@ func SetupV1(router *gin.Engine, eventService services.EventsServicer, eh := handlers.NewEventHandler(eventService) ah := handlers.NewAnnouncementHandler(announcementService) - bh := handlers.NewBoardHandler(boardService) + oh := handlers.NewBoardHandler(boardService) v1 := router.Group("/v1") // Public (read-only) routes diff --git a/internal/api/server.go b/internal/api/server.go index f69239b..2b51785 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -32,17 +32,33 @@ func Run(ctx context.Context) { // Now we init services & gin router, and then start the server queries := dbmodels.New(db) + // ---- Repositories ---- announcementsRepo := repository.NewAnnouncementRepository(queries) eventsRepo := repository.NewEventRepository(queries) + officerRepo := repository.NewOfficerRepository(queries) + positionRepo := repository.NewPositionRepository(queries) + tierRepo := repository.NewTierRepository(queries) + + // ---- Services ---- announcementService := services.NewAnnouncementService(announcementsRepo) eventsService := services.NewEventsService(eventsRepo) - boardService := services.NewBoardService(queries, db) + officerService := services.NewOfficerService(officerRepo) + positionService := services.NewPositionService(positionRepo) + tierService := services.NewTierService(tierRepo) + router := gin.Default() router.Use(mw.Cors(), mw.Ratelimiter()) router.SetTrustedProxies(cfg.TrustedProxies) routes.SetupRoot(router) - routes.SetupV1(router, eventsService, announcementService, boardService) + routes.SetupV1( + router, + eventsService, + announcementService, + officerService, + positionService, + tierService, + ) go func() { serverAddr := fmt.Sprintf("localhost:%s", cfg.Port) diff --git a/internal/api/services/announcement.go b/internal/api/services/announcement.go index 8c67e55..f070f15 100644 --- a/internal/api/services/announcement.go +++ b/internal/api/services/announcement.go @@ -10,8 +10,7 @@ import ( ) type AnnouncementServicer interface { - Service[domain.Announcement, string, domain.Announcement, - domain.Announcement] + Service[domain.Announcement, string] } type AnnouncementService struct { diff --git a/internal/api/services/board.go b/internal/api/services/board.go deleted file mode 100644 index 955379d..0000000 --- a/internal/api/services/board.go +++ /dev/null @@ -1,170 +0,0 @@ -package services - -import ( - "context" - - "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" -) - -type BoardServicer interface { - // Officer methods - GetOfficer(ctx context.Context, id string) (dbmodels.Officer, error) - ListOfficers(ctx context.Context, filters ...any) ([]dbmodels.Officer, error) - CreateOfficer(ctx context.Context, params dbmodels.CreateOfficerParams) error - UpdateOfficer(ctx context.Context, id string, params dbmodels.UpdateOfficerParams) error - DeleteOfficer(ctx context.Context, id string) error - - // Tier methods - GetTier(ctx context.Context, tierName int64) (dbmodels.Tier, error) - ListTiers(ctx context.Context, filters ...any) ([]dbmodels.Tier, error) - CreateTier(ctx context.Context, params dbmodels.CreateTierParams) error - UpdateTier(ctx context.Context, params dbmodels.UpdateTierParams) error - DeleteTier(ctx context.Context, tierName int64) error - - // Position methods - GetPosition(ctx context.Context, oid string) (dbmodels.Position, error) - ListPositions(ctx context.Context, filters ...any) ([]dbmodels.Position, error) - CreatePosition(ctx context.Context, params dbmodels.CreatePositionParams) error - UpdatePosition(ctx context.Context, params dbmodels.UpdatePositionParams) error - DeletePosition(ctx context.Context, arg dbmodels.DeletePositionParams) error -} - -type BoardService struct { - q *dbmodels.Queries - db dbmodels.DBTX -} - -var _ BoardServicer = (*BoardService)(nil) - -func NewBoardService(q *dbmodels.Queries, db dbmodels.DBTX) *BoardService { - return &BoardService{ - q: q, - db: db, - } -} - -type OfficerFilter interface { - Apply(officers []dbmodels.Officer) []dbmodels.Officer -} - -type TierFilter interface { - Apply(tiers []dbmodels.Tier) []dbmodels.Tier -} - -type PositionFilter interface { - Apply(positions []dbmodels.Position) []dbmodels.Position -} - -// Officer Methods -func (s *BoardService) GetOfficer(ctx context.Context, uuid string) (dbmodels.Officer, error) { - row, err := s.q.GetOfficer(ctx, uuid) - if err != nil { - return dbmodels.Officer{}, err - } - - return dbmodels.Officer{ - Uuid: uuid, - FullName: row.FullName, - Picture: row.Picture, - Github: row.Github, - Discord: row.Discord, - }, nil -} - -func (s *BoardService) ListOfficers(ctx context.Context, filters ...any) ([]dbmodels.Officer, error) { - officers, err := s.q.GetOfficers(ctx) - if err != nil { - return nil, err - } - - result := officers - for _, filter := range filters { - if officerFilter, ok := filter.(OfficerFilter); ok { - result = officerFilter.Apply(result) - } - } - - return result, nil -} - -func (s *BoardService) CreateOfficer(ctx context.Context, params dbmodels.CreateOfficerParams) error { - _, err := s.q.CreateOfficer(ctx, params) - return err -} - -func (s *BoardService) UpdateOfficer(ctx context.Context, uuid string, params dbmodels.UpdateOfficerParams) error { - params.Uuid = uuid - return s.q.UpdateOfficer(ctx, params) -} - -func (s *BoardService) DeleteOfficer(ctx context.Context, uuid string) error { - return s.q.DeleteOfficer(ctx, uuid) -} - -// Tier Methods -func (s *BoardService) GetTier(ctx context.Context, tierName int64) (dbmodels.Tier, error) { - return s.q.GetTier(ctx, tierName) -} - -func (s *BoardService) ListTiers(ctx context.Context, filters ...any) ([]dbmodels.Tier, error) { - tiers, err := s.q.GetTiers(ctx) - if err != nil { - return nil, err - } - - result := tiers - for _, filter := range filters { - if tierFilter, ok := filter.(TierFilter); ok { - result = tierFilter.Apply(result) - } - } - - return result, nil -} - -func (s *BoardService) CreateTier(ctx context.Context, params dbmodels.CreateTierParams) error { - _, err := s.q.CreateTier(ctx, params) - return err -} - -func (s *BoardService) UpdateTier(ctx context.Context, params dbmodels.UpdateTierParams) error { - return s.q.UpdateTier(ctx, params) -} - -func (s *BoardService) DeleteTier(ctx context.Context, tierName int64) error { - return s.q.DeleteTier(ctx, tierName) -} - -// Position Methods -func (s *BoardService) GetPosition(ctx context.Context, oid string) (dbmodels.Position, error) { - return s.q.GetPosition(ctx, oid) -} - -func (s *BoardService) ListPositions(ctx context.Context, filters ...any) ([]dbmodels.Position, error) { - positions, err := s.q.GetPositions(ctx) - if err != nil { - return nil, err - } - - result := positions - for _, filter := range filters { - if positionFilter, ok := filter.(PositionFilter); ok { - result = positionFilter.Apply(result) - } - } - - return result, nil -} - -func (s *BoardService) CreatePosition(ctx context.Context, params dbmodels.CreatePositionParams) error { - _, err := s.q.CreatePosition(ctx, params) - return err -} - -func (s *BoardService) UpdatePosition(ctx context.Context, params dbmodels.UpdatePositionParams) error { - return s.q.UpdatePosition(ctx, params) -} - -func (s *BoardService) DeletePosition(ctx context.Context, arg dbmodels.DeletePositionParams) error { - return s.q.DeletePosition(ctx, arg) -} diff --git a/internal/api/services/event.go b/internal/api/services/event.go index 55ee1d2..a2ec260 100644 --- a/internal/api/services/event.go +++ b/internal/api/services/event.go @@ -10,7 +10,7 @@ import ( ) type EventsServicer interface { - Service[domain.Event, string, domain.Event, domain.Event] + Service[domain.Event, string] } type EventsService struct { diff --git a/internal/api/services/interfaces.go b/internal/api/services/interfaces.go index 10db3d9..e72ed53 100644 --- a/internal/api/services/interfaces.go +++ b/internal/api/services/interfaces.go @@ -4,10 +4,10 @@ import ( "context" ) -type Service[T any, ID any, CreateParams any, UpdateParams any] interface { +type Service[T any, ID any] interface { Get(ctx context.Context, id ID) (T, error) List(ctx context.Context, filters ...any) ([]T, error) - Create(ctx context.Context, params CreateParams) error - Update(ctx context.Context, id ID, params UpdateParams) error + Create(ctx context.Context, params T) error + Update(ctx context.Context, id ID, params T) error Delete(ctx context.Context, id ID) error } diff --git a/internal/api/services/officer.go b/internal/api/services/officer.go new file mode 100644 index 0000000..242fd01 --- /dev/null +++ b/internal/api/services/officer.go @@ -0,0 +1,84 @@ +package services + +import ( + "context" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" + "github.com/acmcsufoss/api.acmcsuf.com/internal/repository" +) + +type OfficerServicer interface { + Service[domain.Officer, string] +} + +type OfficerService struct { + officerRepo repository.OfficerRepository +} + +var _ OfficerServicer = (*OfficerService)(nil) + +// There used to be a dbmodels.DBTX var here but I don't think it was used? +func NewOfficerService(officerRepo repository.OfficerRepository) *OfficerService { + return &OfficerService{officerRepo: officerRepo} +} + +type OfficerFilter interface { + Apply(officers []domain.Officer) []domain.Officer +} + +// Officer Methods +func (s *OfficerService) Get(ctx context.Context, uuid string) (domain.Officer, error) { + row, err := s.officerRepo.GetByID(ctx, uuid) + if err != nil { + return domain.Officer{}, err + } + + return domain.Officer{ + Uuid: uuid, + FullName: row.FullName, + Picture: row.Picture, + Github: row.Github, + Discord: row.Discord, + }, nil +} + +func (s *OfficerService) List(ctx context.Context, filters ...any) ([]domain.Officer, error) { + officers, err := s.officerRepo.GetAll(ctx) + if err != nil { + return nil, err + } + + result := officers + for _, filter := range filters { + if officerFilter, ok := filter.(OfficerFilter); ok { + result = officerFilter.Apply(result) + } + } + + return result, nil +} + +func (s *OfficerService) Create(ctx context.Context, params domain.Officer) error { + err := s.officerRepo.Create(ctx, params) + if err != nil { + return err + } + return nil +} + +func (s *OfficerService) Update(ctx context.Context, uuid string, params domain.Officer) error { + params.Uuid = uuid + err := s.officerRepo.Update(ctx, params) + if err != nil { + return err + } + return nil +} + +func (s *OfficerService) Delete(ctx context.Context, uuid string) error { + err := s.officerRepo.Delete(ctx, uuid) + if err != nil { + return err + } + return nil +} diff --git a/internal/api/services/position.go b/internal/api/services/position.go new file mode 100644 index 0000000..1f8258b --- /dev/null +++ b/internal/api/services/position.go @@ -0,0 +1,85 @@ +package services + +import ( + "context" + "fmt" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" + "github.com/acmcsufoss/api.acmcsuf.com/internal/repository" +) + +type PositionServicer interface { + Service[domain.Position, string] + + DeletePosition(ctx context.Context, arg domain.Position) error +} + +type PositionService struct { + positionRepo repository.PositionRepository +} + +var _ PositionServicer = (*PositionService)(nil) + +// There used to be a dbmodels.DBTX var here but I don't think it was used? +func NewPositionService(positionRepo repository.PositionRepository) *PositionService { + return &PositionService{positionRepo: positionRepo} +} + +type PositionFilter interface { + Apply(positions []domain.Position) []domain.Position +} + +// Position Methods +func (s *PositionService) Get(ctx context.Context, oid string) (domain.Position, error) { + position, err := s.positionRepo.GetByID(ctx, oid) + if err != nil { + return domain.Position{}, err + } + return position, nil +} + +func (s *PositionService) List(ctx context.Context, filters ...any) ([]domain.Position, error) { + positions, err := s.positionRepo.GetAll(ctx) + if err != nil { + return nil, err + } + + result := positions + for _, filter := range filters { + if positionFilter, ok := filter.(PositionFilter); ok { + result = positionFilter.Apply(result) + } + } + + return result, nil +} + +func (s *PositionService) Create(ctx context.Context, params domain.Position) error { + err := s.positionRepo.Create(ctx, params) + if err != nil { + return err + } + return nil +} + +func (s *PositionService) Update(ctx context.Context, uuid string, params domain.Position) error { + err := s.positionRepo.Update(ctx, params) + if err != nil { + return err + } + + return nil +} + +func (s *PositionService) DeletePosition(ctx context.Context, arg domain.Position) error { + err := s.positionRepo.Delete(ctx, arg) + if err != nil { + return err + } + return nil +} + +func (s *PositionService) Delete(ctx context.Context, arg string) error { + // This function is here only to satisfy Service interface, use DeletePosition to delete a position + return fmt.Errorf("error: the developer is using the wrong delete function") +} diff --git a/internal/api/services/tier.go b/internal/api/services/tier.go new file mode 100644 index 0000000..387ff8d --- /dev/null +++ b/internal/api/services/tier.go @@ -0,0 +1,72 @@ +package services + +import ( + "context" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" + "github.com/acmcsufoss/api.acmcsuf.com/internal/repository" +) + +type TierServicer interface { + Service[domain.Tier, int64] +} + +type TierService struct { + tierRepo repository.TierRepository +} + +var _ TierServicer = (*TierService)(nil) + +// There used to be a dbmodels.DBTX var here but I don't think it was used? +func NewTierService(tierRepo repository.TierRepository) *TierService { + return &TierService{tierRepo: tierRepo} +} + +type TierFilter interface { + Apply(tiers []domain.Tier) []domain.Tier +} + +// Tier Methods +func (s *TierService) Get(ctx context.Context, tierName int64) (domain.Tier, error) { + return s.tierRepo.GetByID(ctx, tierName) +} + +func (s *TierService) List(ctx context.Context, filters ...any) ([]domain.Tier, error) { + tiers, err := s.tierRepo.GetAll(ctx) + if err != nil { + return nil, err + } + + result := tiers + for _, filter := range filters { + if tierFilter, ok := filter.(TierFilter); ok { + result = tierFilter.Apply(result) + } + } + + return result, nil +} + +func (s *TierService) Create(ctx context.Context, params domain.Tier) error { + err := s.tierRepo.Create(ctx, params) + if err != nil { + return err + } + return nil +} + +func (s *TierService) Update(ctx context.Context, uuid int64, params domain.Tier) error { + err := s.tierRepo.Update(ctx, params) + if err != nil { + return err + } + return nil +} + +func (s *TierService) Delete(ctx context.Context, tierName int64) error { + err := s.tierRepo.Delete(ctx, tierName) + if err != nil { + return err + } + return nil +} From ee380d69c7f41c6eb3da2153d550ea612398410c Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Tue, 10 Feb 2026 13:51:06 -0800 Subject: [PATCH 26/56] Officer, Position, and Tier handlers --- internal/api/handlers/board.go | 541 ------------------------------ internal/api/handlers/officer.go | 186 ++++++++++ internal/api/handlers/position.go | 190 +++++++++++ internal/api/handlers/tier.go | 202 +++++++++++ 4 files changed, 578 insertions(+), 541 deletions(-) delete mode 100644 internal/api/handlers/board.go create mode 100644 internal/api/handlers/officer.go create mode 100644 internal/api/handlers/position.go create mode 100644 internal/api/handlers/tier.go diff --git a/internal/api/handlers/board.go b/internal/api/handlers/board.go deleted file mode 100644 index 59287de..0000000 --- a/internal/api/handlers/board.go +++ /dev/null @@ -1,541 +0,0 @@ -// Package handlers handles http requests and responses -// Business logic belongs in services, not here -package handlers - -import ( - "net/http" - "strconv" - - "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" - "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" - "github.com/gin-gonic/gin" -) - -type BoardHandler struct { - boardService services.BoardServicer -} - -func NewBoardHandler(boardService services.BoardServicer) *BoardHandler { - return &BoardHandler{boardService: boardService} -} - -// GetOfficer godoc -// -// @Summary Get an Officer by UUID -// @Description Retrieves a single officer from the database. -// @Tags Board -// @Accept json -// @Produce json -// @Param id path string true "Officer UUID" -// @Success 200 {object} dbmodels.Officer "Officer details" -// @Failure 404 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /v1/board/officers/{id} [get] -func (h *BoardHandler) GetOfficer(c *gin.Context) { - ctx := c.Request.Context() - id := c.Param("id") - - officer, err := h.boardService.GetOfficer(ctx, id) - - if err != nil { - if err.Error() == "sql: no rows in result set" { - c.JSON(http.StatusNotFound, gin.H{ - "error": "Officer not found", - }) - return - } - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to retrieve officer", - }) - return - } - - c.JSON(http.StatusOK, officer) -} - -// GetOfficers godoc -// -// @Summary Get all officers -// @Description Get all officers from the database -// @Tags Board -// @Accept json -// @Produce json -// @Success 200 {array} dbmodels.Officer "List of officers" -// @Failure 500 {object} map[string]string -// @Router /v1/board/officers [get] -func (h *BoardHandler) GetOfficers(c *gin.Context) { - ctx := c.Request.Context() - - officers, err := h.boardService.ListOfficers(ctx) - if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to retrieve officers", - }) - return - } - - c.JSON(http.StatusOK, officers) -} - -// CreateOfficer godoc -// -// @Summary Creates a new officer -// @Description Creates a new officer in the database. -// @Tags Board -// @Accept json -// @Produce json -// @Param body body dbmodels.CreateOfficerParams true "Officer data" -// @Success 200 {object} map[string]interface{} "Success message with UUID" -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /v1/board/officers [post] -func (h *BoardHandler) CreateOfficer(c *gin.Context) { - ctx := c.Request.Context() - var params dbmodels.CreateOfficerParams - - if err := c.ShouldBindJSON(¶ms); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": "Invalid request body. " + err.Error(), - }) - return - } - - if params.FullName == "" { - c.JSON(http.StatusBadRequest, gin.H{ - "error": "FullName is a required field", - }) - return - } - - if err := h.boardService.CreateOfficer(ctx, params); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to create officer. " + err.Error(), - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "Officer created successfully", - "uuid": params.Uuid, - }) -} - -// UpdateOfficer godoc -// -// @Summary Updates an officer -// @Description Updates an officer in the database -// @Tags Board -// @Accept json -// @Produce json -// @Param id path string true "Officer UUID" -// @Param body body dbmodels.UpdateOfficerParams true "Updated officer data" -// @Success 200 {object} map[string]string "Success message" -// @Failure 400 {object} map[string]string -// @Failure 404 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /v1/board/officers/{id} [put] -func (h *BoardHandler) UpdateOfficer(c *gin.Context) { - ctx := c.Request.Context() - var params dbmodels.UpdateOfficerParams - id := c.Param("id") - - if err := c.ShouldBindJSON(¶ms); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": "Invalid request body. " + err.Error(), - }) - return - } - - if err := h.boardService.UpdateOfficer(ctx, id, params); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to update officer. " + err.Error(), - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "Officer updated successfully", - "uuid": id, - }) -} - -// DeleteOfficer godoc -// -// @Summary Deletes an officer -// @Description Delete an officer from the database -// @Tags Board -// @Accept json -// @Produce json -// @Param id path string true "Officer UUID" -// @Success 200 {object} map[string]string "Success message" -// @Failure 404 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /v1/board/officers/{id} [delete] -func (h *BoardHandler) DeleteOfficer(c *gin.Context) { - ctx := c.Request.Context() - id := c.Param("id") - - if err := h.boardService.DeleteOfficer(ctx, id); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to delete officer", - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "Officer deleted successfully", - }) -} - -// GetTiers godoc -// -// @Summary Get all tiers -// @Description Get all tiers from the database -// @Tags Board -// @Accept json -// @Produce json -// @Success 200 {array} dbmodels.Tier "List of tiers" -// @Failure 500 {object} map[string]string -// @Router /v1/board/tiers [get] -func (h *BoardHandler) GetTiers(c *gin.Context) { - ctx := c.Request.Context() - - tiers, err := h.boardService.ListTiers(ctx) - if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to retrieve tiers", - }) - return - } - - c.JSON(http.StatusOK, tiers) -} - -// GetTier godoc -// -// @Summary Get a Tier by tier number -// @Description Retrieves a single tier from the database. -// @Tags Board -// @Accept json -// @Produce json -// @Param id path int true "Tier number" -// @Success 200 {object} dbmodels.Tier "Tier details" -// @Failure 400 {object} map[string]string -// @Failure 404 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /v1/board/tiers/{id} [get] -func (h *BoardHandler) GetTier(c *gin.Context) { - ctx := c.Request.Context() - id, err := strconv.Atoi(c.Param("id")) - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": "Invalid tier number", - }) - return - } - - tier, err := h.boardService.GetTier(ctx, int64(id)) - if err != nil { - if err.Error() == "sql: no rows in result set" { - c.JSON(http.StatusNotFound, gin.H{ - "error": "Tier not found", - }) - return - } - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to retrieve tier", - }) - return - } - - c.JSON(http.StatusOK, tier) -} - -// CreateTier godoc -// -// @Summary Creates a new tier -// @Description Creates a new tier in the database. -// @Tags Board -// @Accept json -// @Produce json -// @Param body body dbmodels.CreateTierParams true "Tier data" -// @Success 200 {object} map[string]interface{} "Success message with tier number" -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /v1/board/tiers [post] -func (h *BoardHandler) CreateTier(c *gin.Context) { - ctx := c.Request.Context() - var params dbmodels.CreateTierParams - - if err := c.ShouldBindJSON(¶ms); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": "Invalid request body. " + err.Error(), - }) - return - } - - if err := h.boardService.CreateTier(ctx, params); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to create tier. " + err.Error(), - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "Tier created successfully", - "tier": params.Tier, - }) -} - -// UpdateTier godoc -// -// @Summary Updates a tier -// @Description Updates a tier in the database -// @Tags Board -// @Accept json -// @Produce json -// @Param id path int true "Tier number" -// @Param body body dbmodels.UpdateTierParams true "Updated tier data" -// @Success 200 {object} map[string]string "Success message" -// @Failure 400 {object} map[string]string -// @Failure 404 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /v1/board/tiers/{id} [put] -func (h *BoardHandler) UpdateTier(c *gin.Context) { - ctx := c.Request.Context() - var params dbmodels.UpdateTierParams - id, err := strconv.Atoi(c.Param("id")) - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": "Invalid tier number", - }) - return - } - - if err := c.ShouldBindJSON(¶ms); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": "Invalid request body. " + err.Error(), - }) - return - } - - params.Tier = int64(id) - - if err := h.boardService.UpdateTier(ctx, params); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to update tier. " + err.Error(), - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "Tier updated successfully", - "tier": params.Tier, - }) -} - -// DeleteTier godoc -// -// @Summary Deletes a tier -// @Description Delete a tier from the database -// @Tags Board -// @Accept json -// @Produce json -// @Param id path int true "Tier number" -// @Success 200 {object} map[string]string "Success message" -// @Failure 400 {object} map[string]string -// @Failure 404 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /v1/board/tiers/{id} [delete] -func (h *BoardHandler) DeleteTier(c *gin.Context) { - ctx := c.Request.Context() - id, err := strconv.Atoi(c.Param("id")) - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": "Invalid tier number", - }) - return - } - - if err := h.boardService.DeleteTier(ctx, int64(id)); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to delete tier", - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "Tier deleted successfully", - }) -} - -// GetPositions godoc -// -// @Summary Get all positions -// @Description Get all positions from the database -// @Tags Board -// @Accept json -// @Produce json -// @Success 200 {array} dbmodels.Position "List of positions" -// @Failure 500 {object} map[string]string -// @Router /v1/board/positions [get] -func (h *BoardHandler) GetPositions(c *gin.Context) { - ctx := c.Request.Context() - - positions, err := h.boardService.ListPositions(ctx) - if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to retrieve positions", - }) - return - } - - c.JSON(http.StatusOK, positions) -} - -// GetPosition godoc -// -// @Summary Get a Position by UUID -// @Description Retrieves a single position from the database by officer UUID. -// @Tags Board -// @Accept json -// @Produce json -// @Param id path string true "Officer full name" -// @Success 200 {object} dbmodels.Position "Position details" -// @Failure 404 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /v1/board/positions/{id} [get] -func (h *BoardHandler) GetPosition(c *gin.Context) { - ctx := c.Request.Context() - id := c.Param("id") - - position, err := h.boardService.GetPosition(ctx, id) - - if err != nil { - if err.Error() == "sql: no rows in result set" { - c.JSON(http.StatusNotFound, gin.H{ - "error": "Position not found", - }) - return - } - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to retrieve position", - }) - return - } - - c.JSON(http.StatusOK, position) -} - -// CreatePosition godoc -// -// @Summary Creates a new position -// @Description Creates a new position in the database. -// @Tags Board -// @Accept json -// @Produce json -// @Param body body dbmodels.CreatePositionParams true "Position data" -// @Success 200 {object} map[string]interface{} "Success message" -// @Failure 400 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /v1/board/positions [post] -func (h *BoardHandler) CreatePosition(c *gin.Context) { - ctx := c.Request.Context() - var params dbmodels.CreatePositionParams - - if err := c.ShouldBindJSON(¶ms); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": "Invalid request body. " + err.Error(), - }) - return - } - - if err := h.boardService.CreatePosition(ctx, params); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to create position. " + err.Error(), - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "Position created successfully", - "oid": params.Oid, - "semester": params.Semester, - "tier": params.Tier, - }) -} - -// UpdatePosition godoc -// -// @Summary Updates a position -// @Description Updates a position in the database -// @Tags Board -// @Accept json -// @Produce json -// @Param body body dbmodels.UpdatePositionParams true "Updated position data (must include oid, semester, tier)" -// @Success 200 {object} map[string]string "Success message" -// @Failure 400 {object} map[string]string -// @Failure 404 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /v1/board/positions [put] -func (h *BoardHandler) UpdatePosition(c *gin.Context) { - ctx := c.Request.Context() - var params dbmodels.UpdatePositionParams - - if err := c.ShouldBindJSON(¶ms); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": "Invalid request body. " + err.Error(), - }) - return - } - - if err := h.boardService.UpdatePosition(ctx, params); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to update position. " + err.Error(), - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "Position updated successfully", - "oid": params.Oid, - "semester": params.Semester, - "tier": params.Tier, - }) -} - -// DeletePosition godoc -// -// @Summary Deletes a position -// @Description Delete a position from the database (requires oid, semester, and tier) -// @Tags Board -// @Accept json -// @Produce json -// @Param body body dbmodels.DeletePositionParams true "Position identifier" -// @Success 200 {object} map[string]string "Success message" -// @Failure 400 {object} map[string]string -// @Failure 404 {object} map[string]string -// @Failure 500 {object} map[string]string -// @Router /v1/board/positions [delete] -func (h *BoardHandler) DeletePosition(c *gin.Context) { - ctx := c.Request.Context() - var params dbmodels.DeletePositionParams - - if err := c.ShouldBindJSON(¶ms); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": "Invalid request body. " + err.Error(), - }) - return - } - - if err := h.boardService.DeletePosition(ctx, params); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{ - "error": "Failed to delete position", - }) - return - } - - c.JSON(http.StatusOK, gin.H{ - "message": "Position deleted successfully", - }) -} diff --git a/internal/api/handlers/officer.go b/internal/api/handlers/officer.go new file mode 100644 index 0000000..9006927 --- /dev/null +++ b/internal/api/handlers/officer.go @@ -0,0 +1,186 @@ +// Package handlers handles http requests and responses +// Business logic belongs in services, not here +package handlers + +import ( + "net/http" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" + dto_request "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" + "github.com/gin-gonic/gin" +) + +type OfficerHandler struct { + officerService services.OfficerServicer +} + +func NewOfficerHandler(officerService services.OfficerServicer) *OfficerHandler { + return &OfficerHandler{officerService: officerService} +} + +// GetOfficer godoc +// +// @Summary Get an Officer by UUID +// @Description Retrieves a single officer from the database. +// @Tags Board +// @Accept json +// @Produce json +// @Param id path string true "Officer UUID" +// @Success 200 {object} dbmodels.Officer "Officer details" +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /v1/board/officers/{id} [get] +func (h *OfficerHandler) GetOfficer(c *gin.Context) { + ctx := c.Request.Context() + id := c.Param("id") + + officer, err := h.officerService.Get(ctx, id) + if err != nil { + if err.Error() == "sql: no rows in result set" { + c.JSON(http.StatusNotFound, gin.H{ + "error": "Officer not found", + }) + return + } + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to retrieve officer", + }) + return + } + + c.JSON(http.StatusOK, officer) +} + +// GetOfficers godoc +// +// @Summary Get all officers +// @Description Get all officers from the database +// @Tags Board +// @Accept json +// @Produce json +// @Success 200 {array} dbmodels.Officer "List of officers" +// @Failure 500 {object} map[string]string +// @Router /v1/board/officers [get] +func (h *OfficerHandler) GetOfficers(c *gin.Context) { + ctx := c.Request.Context() + + officers, err := h.officerService.List(ctx) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to retrieve officers", + }) + return + } + + c.JSON(http.StatusOK, officers) +} + +// CreateOfficer godoc +// +// @Summary Creates a new officer +// @Description Creates a new officer in the database. +// @Tags Board +// @Accept json +// @Produce json +// @Param body body dbmodels.CreateOfficerParams true "Officer data" +// @Success 200 {object} map[string]interface{} "Success message with UUID" +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /v1/board/officers [post] +func (h *OfficerHandler) CreateOfficer(c *gin.Context) { + ctx := c.Request.Context() + var params dto_request.Officer + + if err := c.ShouldBindJSON(¶ms); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "Invalid request body. " + err.Error(), + }) + return + } + + if params.FullName == "" { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "FullName is a required field", + }) + return + } + + if err := h.officerService.Create(ctx, params.ToDomain()); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to create officer. " + err.Error(), + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "Officer created successfully", + "uuid": params.ToDomain().Uuid, + }) +} + +// UpdateOfficer godoc +// +// @Summary Updates an officer +// @Description Updates an officer in the database +// @Tags Board +// @Accept json +// @Produce json +// @Param id path string true "Officer UUID" +// @Param body body dbmodels.UpdateOfficerParams true "Updated officer data" +// @Success 200 {object} map[string]string "Success message" +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /v1/board/officers/{id} [put] +func (h *OfficerHandler) UpdateOfficer(c *gin.Context) { + ctx := c.Request.Context() + var params dto_request.Officer + id := c.Param("id") + + if err := c.ShouldBindJSON(¶ms); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "Invalid request body. " + err.Error(), + }) + return + } + + if err := h.officerService.Update(ctx, id, params.ToDomain()); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to update officer. " + err.Error(), + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "Officer updated successfully", + "uuid": id, + }) +} + +// DeleteOfficer godoc +// +// @Summary Deletes an officer +// @Description Delete an officer from the database +// @Tags Board +// @Accept json +// @Produce json +// @Param id path string true "Officer UUID" +// @Success 200 {object} map[string]string "Success message" +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /v1/board/officers/{id} [delete] +func (h *OfficerHandler) DeleteOfficer(c *gin.Context) { + ctx := c.Request.Context() + id := c.Param("id") + + if err := h.officerService.Delete(ctx, id); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to delete officer", + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "Officer deleted successfully", + }) +} diff --git a/internal/api/handlers/position.go b/internal/api/handlers/position.go new file mode 100644 index 0000000..4f4120f --- /dev/null +++ b/internal/api/handlers/position.go @@ -0,0 +1,190 @@ +// Package handlers handles http requests and responses +// Business logic belongs in services, not here +package handlers + +import ( + "net/http" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" + dto_request "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" + "github.com/gin-gonic/gin" +) + +type PositionHandler struct { + positionService services.PositionServicer +} + +func NewPositionHandler(positionService services.PositionServicer) *PositionHandler { + return &PositionHandler{positionService: positionService} +} + +// GetPositions godoc +// +// @Summary Get all positions +// @Description Get all positions from the database +// @Tags Board +// @Accept json +// @Produce json +// @Success 200 {array} dbmodels.Position "List of positions" +// @Failure 500 {object} map[string]string +// @Router /v1/board/positions [get] +func (h *PositionHandler) GetPositions(c *gin.Context) { + ctx := c.Request.Context() + + positions, err := h.positionService.List(ctx) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to retrieve positions", + }) + return + } + + c.JSON(http.StatusOK, positions) +} + +// GetPosition godoc +// +// @Summary Get a Position by UUID +// @Description Retrieves a single position from the database by officer UUID. +// @Tags Board +// @Accept json +// @Produce json +// @Param id path string true "Officer full name" +// @Success 200 {object} dbmodels.Position "Position details" +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /v1/board/positions/{id} [get] +func (h *PositionHandler) GetPosition(c *gin.Context) { + ctx := c.Request.Context() + id := c.Param("id") + + position, err := h.positionService.Get(ctx, id) + if err != nil { + if err.Error() == "sql: no rows in result set" { + c.JSON(http.StatusNotFound, gin.H{ + "error": "Position not found", + }) + return + } + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to retrieve position", + }) + return + } + + c.JSON(http.StatusOK, position) +} + +// CreatePosition godoc +// +// @Summary Creates a new position +// @Description Creates a new position in the database. +// @Tags Board +// @Accept json +// @Produce json +// @Param body body dbmodels.CreatePositionParams true "Position data" +// @Success 200 {object} map[string]interface{} "Success message" +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /v1/board/positions [post] +func (h *PositionHandler) CreatePosition(c *gin.Context) { + ctx := c.Request.Context() + var params dto_request.Position + + if err := c.ShouldBindJSON(¶ms); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "Invalid request body. " + err.Error(), + }) + return + } + + if err := h.positionService.Create(ctx, params.ToDomain()); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to create position. " + err.Error(), + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "Position created successfully", + "oid": params.Oid, + "semester": params.Semester, + "tier": params.Tier, + }) +} + +// UpdatePosition godoc +// +// @Summary Updates a position +// @Description Updates a position in the database +// @Tags Board +// @Accept json +// @Produce json +// @Param body body dbmodels.UpdatePositionParams true "Updated position data (must include oid, semester, tier)" +// @Success 200 {object} map[string]string "Success message" +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /v1/board/positions [put] +func (h *PositionHandler) UpdatePosition(c *gin.Context) { + ctx := c.Request.Context() + var params dto_request.Position + id := c.Param("id") + + if err := c.ShouldBindJSON(¶ms); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "Invalid request body. " + err.Error(), + }) + return + } + + if err := h.positionService.Update(ctx, id, params.ToDomain()); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to update position. " + err.Error(), + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "Position updated successfully", + "oid": params.Oid, + "semester": params.Semester, + "tier": params.Tier, + }) +} + +// DeletePosition godoc +// +// @Summary Deletes a position +// @Description Delete a position from the database (requires oid, semester, and tier) +// @Tags Board +// @Accept json +// @Produce json +// @Param body body dbmodels.DeletePositionParams true "Position identifier" +// @Success 200 {object} map[string]string "Success message" +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /v1/board/positions [delete] +func (h *PositionHandler) Delete(c *gin.Context) { + ctx := c.Request.Context() + var params dto_request.Position + + if err := c.ShouldBindJSON(¶ms); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "Invalid request body. " + err.Error(), + }) + return + } + + if err := h.positionService.DeletePosition(ctx, params.ToDomain()); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to delete position", + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "Position deleted successfully", + }) +} diff --git a/internal/api/handlers/tier.go b/internal/api/handlers/tier.go new file mode 100644 index 0000000..26a6190 --- /dev/null +++ b/internal/api/handlers/tier.go @@ -0,0 +1,202 @@ +// Package handlers handles http requests and responses +// Business logic belongs in services, not here +package handlers + +import ( + "net/http" + "strconv" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" + dto_request "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" + "github.com/gin-gonic/gin" +) + +type TierHandler struct { + tierService services.TierServicer +} + +func NewTierHandler(tierService services.TierServicer) *TierHandler { + return &TierHandler{tierService: tierService} +} + +// GetTiers godoc +// +// @Summary Get all tiers +// @Description Get all tiers from the database +// @Tags Board +// @Accept json +// @Produce json +// @Success 200 {array} dbmodels.Tier "List of tiers" +// @Failure 500 {object} map[string]string +// @Router /v1/board/tiers [get] +func (h *TierHandler) GetTiers(c *gin.Context) { + ctx := c.Request.Context() + + tiers, err := h.tierService.List(ctx) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to retrieve tiers", + }) + return + } + + c.JSON(http.StatusOK, tiers) +} + +// GetTier godoc +// +// @Summary Get a Tier by tier number +// @Description Retrieves a single tier from the database. +// @Tags Board +// @Accept json +// @Produce json +// @Param id path int true "Tier number" +// @Success 200 {object} dbmodels.Tier "Tier details" +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /v1/board/tiers/{id} [get] +func (h *TierHandler) GetTier(c *gin.Context) { + ctx := c.Request.Context() + id, err := strconv.Atoi(c.Param("id")) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "Invalid tier number", + }) + return + } + + tier, err := h.tierService.Get(ctx, int64(id)) + if err != nil { + if err.Error() == "sql: no rows in result set" { + c.JSON(http.StatusNotFound, gin.H{ + "error": "Tier not found", + }) + return + } + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to retrieve tier", + }) + return + } + + c.JSON(http.StatusOK, tier) +} + +// CreateTier godoc +// +// @Summary Creates a new tier +// @Description Creates a new tier in the database. +// @Tags Board +// @Accept json +// @Produce json +// @Param body body dbmodels.CreateTierParams true "Tier data" +// @Success 200 {object} map[string]interface{} "Success message with tier number" +// @Failure 400 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /v1/board/tiers [post] +func (h *TierHandler) CreateTier(c *gin.Context) { + ctx := c.Request.Context() + var params dto_request.Tier + + if err := c.ShouldBindJSON(¶ms); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "Invalid request body. " + err.Error(), + }) + return + } + + if err := h.tierService.Create(ctx, params.ToDomain()); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to create tier. " + err.Error(), + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "Tier created successfully", + "tier": params.Tier, + }) +} + +// UpdateTier godoc +// +// @Summary Updates a tier +// @Description Updates a tier in the database +// @Tags Board +// @Accept json +// @Produce json +// @Param id path int true "Tier number" +// @Param body body dbmodels.UpdateTierParams true "Updated tier data" +// @Success 200 {object} map[string]string "Success message" +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /v1/board/tiers/{id} [put] +func (h *TierHandler) UpdateTier(c *gin.Context) { + ctx := c.Request.Context() + var params dto_request.Tier + id, err := strconv.Atoi(c.Param("id")) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "Invalid tier number", + }) + return + } + + if err := c.ShouldBindJSON(¶ms); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "Invalid request body. " + err.Error(), + }) + return + } + + params.Tier = id + + if err := h.tierService.Update(ctx, int64(id), params.ToDomain()); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to update tier. " + err.Error(), + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "Tier updated successfully", + "tier": params.Tier, + }) +} + +// DeleteTier godoc +// +// @Summary Deletes a tier +// @Description Delete a tier from the database +// @Tags Board +// @Accept json +// @Produce json +// @Param id path int true "Tier number" +// @Success 200 {object} map[string]string "Success message" +// @Failure 400 {object} map[string]string +// @Failure 404 {object} map[string]string +// @Failure 500 {object} map[string]string +// @Router /v1/board/tiers/{id} [delete] +func (h *TierHandler) DeleteTier(c *gin.Context) { + ctx := c.Request.Context() + id, err := strconv.Atoi(c.Param("id")) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": "Invalid tier number", + }) + return + } + + if err := h.tierService.Delete(ctx, int64(id)); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "Failed to delete tier", + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "Tier deleted successfully", + }) +} From 5df60a77c565226516fcb2d1d2802c943537c0f1 Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Tue, 10 Feb 2026 13:55:25 -0800 Subject: [PATCH 27/56] Hook server and routes togther --- internal/api/handlers/position.go | 2 +- internal/api/routes/v1.go | 34 ++++++++++++++++--------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/internal/api/handlers/position.go b/internal/api/handlers/position.go index 4f4120f..80d65b9 100644 --- a/internal/api/handlers/position.go +++ b/internal/api/handlers/position.go @@ -166,7 +166,7 @@ func (h *PositionHandler) UpdatePosition(c *gin.Context) { // @Failure 404 {object} map[string]string // @Failure 500 {object} map[string]string // @Router /v1/board/positions [delete] -func (h *PositionHandler) Delete(c *gin.Context) { +func (h *PositionHandler) DeletePosition(c *gin.Context) { ctx := c.Request.Context() var params dto_request.Position diff --git a/internal/api/routes/v1.go b/internal/api/routes/v1.go index aaa0456..8b32c97 100644 --- a/internal/api/routes/v1.go +++ b/internal/api/routes/v1.go @@ -38,7 +38,9 @@ func SetupV1(router *gin.Engine, eventService services.EventsServicer, eh := handlers.NewEventHandler(eventService) ah := handlers.NewAnnouncementHandler(announcementService) - oh := handlers.NewBoardHandler(boardService) + oh := handlers.NewOfficerHandler(officerService) + ph := handlers.NewPositionHandler(positionService) + th := handlers.NewTierHandler(tierService) v1 := router.Group("/v1") // Public (read-only) routes @@ -51,14 +53,14 @@ func SetupV1(router *gin.Engine, eventService services.EventsServicer, board := v1.Group("/board") { - board.GET("/officers", bh.GetOfficers) - board.GET("/officers/:id", bh.GetOfficer) + board.GET("/officers", oh.GetOfficers) + board.GET("/officers/:id", oh.GetOfficer) - board.GET("/tiers", bh.GetTiers) - board.GET("/tiers/:id", bh.GetTier) + board.GET("/tiers", th.GetTiers) + board.GET("/tiers/:id", th.GetTier) - board.GET("/positions", bh.GetPositions) - board.GET("/positions/:id", bh.GetPosition) + board.GET("/positions", ph.GetPositions) + board.GET("/positions/:id", ph.GetPosition) } } @@ -77,19 +79,19 @@ func SetupV1(router *gin.Engine, eventService services.EventsServicer, board := protected.Group("/board") { // Officers - board.POST("/officers", bh.CreateOfficer) - board.PUT("/officers/:id", bh.UpdateOfficer) - board.DELETE("/officers/:id", bh.DeleteOfficer) + board.POST("/officers", oh.CreateOfficer) + board.PUT("/officers/:id", oh.UpdateOfficer) + board.DELETE("/officers/:id", oh.DeleteOfficer) // Tiers - board.POST("/tiers", bh.CreateTier) - board.PUT("/tiers/:id", bh.UpdateTier) - board.DELETE("/tiers/:id", bh.DeleteTier) + board.POST("/tiers", th.CreateTier) + board.PUT("/tiers/:id", th.UpdateTier) + board.DELETE("/tiers/:id", th.DeleteTier) // Positions - board.POST("/positions", bh.CreatePosition) - board.PUT("/positions", bh.UpdatePosition) - board.DELETE("/positions", bh.DeletePosition) + board.POST("/positions", ph.CreatePosition) + board.PUT("/positions", ph.UpdatePosition) + board.DELETE("/positions", ph.DeletePosition) } } } From 4b538a50ef64697b898bf6e40dcd9134cc64c92a Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Tue, 10 Feb 2026 14:04:24 -0800 Subject: [PATCH 28/56] Use Repo Interface --- internal/api/services/position.go | 2 +- internal/repository/announcements.go | 8 +------- internal/repository/event.go | 8 +------- internal/repository/interfaces.go | 15 +++++++++++++++ internal/repository/officer.go | 6 +----- internal/repository/position.go | 25 ++++++++++++++----------- internal/repository/tier.go | 6 +----- 7 files changed, 34 insertions(+), 36 deletions(-) create mode 100644 internal/repository/interfaces.go diff --git a/internal/api/services/position.go b/internal/api/services/position.go index 1f8258b..9dd6f3a 100644 --- a/internal/api/services/position.go +++ b/internal/api/services/position.go @@ -72,7 +72,7 @@ func (s *PositionService) Update(ctx context.Context, uuid string, params domain } func (s *PositionService) DeletePosition(ctx context.Context, arg domain.Position) error { - err := s.positionRepo.Delete(ctx, arg) + err := s.positionRepo.DeletePosition(ctx, arg) if err != nil { return err } diff --git a/internal/repository/announcements.go b/internal/repository/announcements.go index 78a6dee..61e17e8 100644 --- a/internal/repository/announcements.go +++ b/internal/repository/announcements.go @@ -8,13 +8,7 @@ import ( ) type AnnouncementRepository interface { - GetAll(ctx context.Context) ([]domain.Announcement, error) - - GetByID(ctx context.Context, id string) (domain.Announcement, error) - Delete(ctx context.Context, id string) error - - Create(ctx context.Context, args domain.Announcement) error - Update(ctx context.Context, args domain.Announcement) error + Repository[domain.Announcement, string] } type announcementRepository struct { diff --git a/internal/repository/event.go b/internal/repository/event.go index 6cb6707..bfc2ae7 100644 --- a/internal/repository/event.go +++ b/internal/repository/event.go @@ -8,13 +8,7 @@ import ( ) type EventRepository interface { - GetAll(ctx context.Context) ([]domain.Event, error) - - GetByID(ctx context.Context, id string) (domain.Event, error) - Delete(ctx context.Context, id string) error - - Create(ctx context.Context, args domain.Event) error - Update(ctx context.Context, args domain.Event) error + Repository[domain.Event, string] } type eventRepository struct { diff --git a/internal/repository/interfaces.go b/internal/repository/interfaces.go new file mode 100644 index 0000000..34a1bbb --- /dev/null +++ b/internal/repository/interfaces.go @@ -0,0 +1,15 @@ +package repository + +import ( + "context" +) + +type Repository[T any, ID any] interface { + GetAll(ctx context.Context) ([]T, error) + + GetByID(ctx context.Context, id ID) (T, error) + Delete(ctx context.Context, id ID) error + + Create(ctx context.Context, args T) error + Update(ctx context.Context, args T) error +} diff --git a/internal/repository/officer.go b/internal/repository/officer.go index c45831e..3173619 100644 --- a/internal/repository/officer.go +++ b/internal/repository/officer.go @@ -8,11 +8,7 @@ import ( ) type OfficerRepository interface { - GetAll(ctx context.Context) ([]domain.Officer, error) - GetByID(ctx context.Context, id string) (domain.Officer, error) - Create(ctx context.Context, args domain.Officer) error - Update(ctx context.Context, args domain.Officer) error - Delete(ctx context.Context, id string) error + Repository[domain.Officer, string] } type officerRepository struct { diff --git a/internal/repository/position.go b/internal/repository/position.go index 369f4e8..23cb04e 100644 --- a/internal/repository/position.go +++ b/internal/repository/position.go @@ -2,17 +2,15 @@ package repository import ( "context" + "fmt" "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" ) type PositionRepository interface { - GetAll(ctx context.Context) ([]domain.Position, error) - GetByID(ctx context.Context, id string) (domain.Position, error) - Create(ctx context.Context, args domain.Position) error - Update(ctx context.Context, args domain.Position) error - Delete(ctx context.Context, args domain.Position) error + Repository[domain.Position, string] + DeletePosition(ctx context.Context, args domain.Position) error } type positionRepository struct { @@ -45,24 +43,29 @@ func (r *positionRepository) GetByID(ctx context.Context, id string) (domain.Pos return convertDBPositionToDomain(dbPosition), nil } -func (r *positionRepository) Delete(ctx context.Context, args domain.Position) error { - err := r.db.DeletePosition(ctx, convertDomainToDeleteDBPosition(args)) +func (r *positionRepository) Create(ctx context.Context, args domain.Position) error { + _, err := r.db.CreatePosition(ctx, convertDomainToCreateDBPosition(args)) if err != nil { return err } return nil } -func (r *positionRepository) Create(ctx context.Context, args domain.Position) error { - _, err := r.db.CreatePosition(ctx, convertDomainToCreateDBPosition(args)) +func (r *positionRepository) Update(ctx context.Context, args domain.Position) error { + err := r.db.UpdatePosition(ctx, convertDomainToUpdateDBPosition(args)) if err != nil { return err } return nil } -func (r *positionRepository) Update(ctx context.Context, args domain.Position) error { - err := r.db.UpdatePosition(ctx, convertDomainToUpdateDBPosition(args)) +func (r *positionRepository) Delete(ctx context.Context, args string) error { + // Here to satisfy the Repository interface only, use DeletePosition + return fmt.Errorf("error: developer is using the wrong delete function") +} + +func (r *positionRepository) DeletePosition(ctx context.Context, args domain.Position) error { + err := r.db.DeletePosition(ctx, convertDomainToDeleteDBPosition(args)) if err != nil { return err } diff --git a/internal/repository/tier.go b/internal/repository/tier.go index 80a4e21..e473acb 100644 --- a/internal/repository/tier.go +++ b/internal/repository/tier.go @@ -8,11 +8,7 @@ import ( ) type TierRepository interface { - GetAll(ctx context.Context) ([]domain.Tier, error) - GetByID(ctx context.Context, id int64) (domain.Tier, error) - Create(ctx context.Context, args domain.Tier) error - Update(ctx context.Context, args domain.Tier) error - Delete(ctx context.Context, id int64) error + Repository[domain.Tier, int64] } type tierRepository struct { From b7609f2752ff5c7a39af79d641f6ed5c22de9de3 Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Tue, 10 Feb 2026 14:10:58 -0800 Subject: [PATCH 29/56] revert announcement put cli to use dbmodels --- internal/cli/announcements/post.go | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/internal/cli/announcements/post.go b/internal/cli/announcements/post.go index 20688d7..2ec3e2e 100644 --- a/internal/cli/announcements/post.go +++ b/internal/cli/announcements/post.go @@ -9,14 +9,13 @@ import ( "net/url" "os" "strings" - "time" "github.com/charmbracelet/huh" "github.com/spf13/cobra" + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/oauth" - "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" "github.com/acmcsufoss/api.acmcsuf.com/utils" ) @@ -25,7 +24,7 @@ var PostAnnouncement = &cobra.Command{ Short: "post a new announcement", Run: func(cmd *cobra.Command, args []string) { - payload := domain.Announcement{} + payload := dbmodels.CreateAnnouncementParams{} err := huh.NewForm().Run() if err != nil { if err == huh.ErrUserAborted { @@ -41,12 +40,11 @@ var PostAnnouncement = &cobra.Command{ channelIdString, _ := cmd.Flags().GetString("channelid") messageIdString, _ := cmd.Flags().GetString("messageid") - payload.DiscordChannelID = channelIdString - payload.DiscordMessageID = messageIdString + payload.DiscordChannelID = utils.StringtoNullString(channelIdString) + payload.DiscordMessageID = utils.StringtoNullString(messageIdString) if announceString != "" { - announceAtUnix, err := utils.ByteSlicetoUnix([]byte(announceString)) - payload.AnnounceAt = time.Unix(announceAtUnix, 0) + payload.AnnounceAt, err = utils.ByteSlicetoUnix([]byte(announceString)) if err != nil { fmt.Println(err) return @@ -75,7 +73,7 @@ func init() { PostAnnouncement.Flags().StringP("messageid", "m", "", "Set this announcement's message id") } -func postAnnouncement(payload *domain.Announcement, changedFlags announcementFlags, cfg *config.Config) { +func postAnnouncement(payload *dbmodels.CreateAnnouncementParams, changedFlags announcementFlags, cfg *config.Config) { baseURL := &url.URL{ Scheme: "http", Host: fmt.Sprintf("%s:%s", cfg.Host, cfg.Port), @@ -177,8 +175,7 @@ func postAnnouncement(payload *domain.Announcement, changedFlags announcementFla announceatBuffer := scanner.Bytes() - announceAtUnix, err := utils.ByteSlicetoUnix(announceatBuffer) - payload.AnnounceAt = time.Unix(announceAtUnix, 0) + payload.AnnounceAt, err = utils.ByteSlicetoUnix(announceatBuffer) if err != nil { fmt.Println("error converting byte slice to unix time (of type int64):", err) continue @@ -214,7 +211,7 @@ func postAnnouncement(payload *domain.Announcement, changedFlags announcementFla } channelIdBuffer := scanner.Bytes() - payload.DiscordChannelID = string(channelIdBuffer) + payload.DiscordChannelID = utils.StringtoNullString(string(channelIdBuffer)) break } @@ -245,7 +242,7 @@ func postAnnouncement(payload *domain.Announcement, changedFlags announcementFla continue } messageIdBuffer := scanner.Bytes() - payload.DiscordMessageID = string(messageIdBuffer) + payload.DiscordMessageID = utils.StringtoNullString(string(messageIdBuffer)) break } From d154d496afa042e9db5852bf8fcec82534c0dfdb Mon Sep 17 00:00:00 2001 From: Josh Holman Date: Wed, 11 Feb 2026 08:58:09 -0800 Subject: [PATCH 30/56] Update error formatting internal/api/handlers/event.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- internal/api/handlers/event.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/api/handlers/event.go b/internal/api/handlers/event.go index 745455c..4d1f591 100644 --- a/internal/api/handlers/event.go +++ b/internal/api/handlers/event.go @@ -47,7 +47,7 @@ func (h *EventsHandler) GetEvent(c *gin.Context) { } c.JSON(http.StatusInternalServerError, gin.H{ - "error": fmt.Sprintln("Failed to retrieve event:" + err.Error()), + "error": "Failed to retrieve event: " + err.Error(), }) return } From 8eea6af8b02471325b9d1b96c2aade3736aaa567 Mon Sep 17 00:00:00 2001 From: Josh Holman Date: Wed, 11 Feb 2026 09:01:21 -0800 Subject: [PATCH 31/56] add missing return in announcement handler Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- internal/api/handlers/announcement.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/api/handlers/announcement.go b/internal/api/handlers/announcement.go index e5b7afc..30447ba 100644 --- a/internal/api/handlers/announcement.go +++ b/internal/api/handlers/announcement.go @@ -45,6 +45,7 @@ func (h *AnnouncementHandler) GetAnnouncement(c *gin.Context) { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to retrieve announcement", }) + return } c.JSON(http.StatusOK, announcement.ToDTO()) From f38254341239a6d388dc600b8dd9e62555a8a463 Mon Sep 17 00:00:00 2001 From: Josh Holman Date: Wed, 11 Feb 2026 09:02:31 -0800 Subject: [PATCH 32/56] add missing return in error handler Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- internal/api/handlers/announcement.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/api/handlers/announcement.go b/internal/api/handlers/announcement.go index 30447ba..52b4768 100644 --- a/internal/api/handlers/announcement.go +++ b/internal/api/handlers/announcement.go @@ -126,6 +126,7 @@ func (h *AnnouncementHandler) UpdateAnnouncement(c *gin.Context) { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid request body. " + err.Error(), }) + return } if err := h.announcementService.Update(ctx, id, params.ToDomain()); err != nil { From 613fbbd4a609ed53c991296f7d457aeee16513a3 Mon Sep 17 00:00:00 2001 From: Josh Holman Date: Wed, 11 Feb 2026 09:04:27 -0800 Subject: [PATCH 33/56] fix swagger annotation Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- internal/api/handlers/tier.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/api/handlers/tier.go b/internal/api/handlers/tier.go index 26a6190..101b95d 100644 --- a/internal/api/handlers/tier.go +++ b/internal/api/handlers/tier.go @@ -26,7 +26,7 @@ func NewTierHandler(tierService services.TierServicer) *TierHandler { // @Tags Board // @Accept json // @Produce json -// @Success 200 {array} dbmodels.Tier "List of tiers" +// @Success 200 {array} dto_request.Tier "List of tiers" // @Failure 500 {object} map[string]string // @Router /v1/board/tiers [get] func (h *TierHandler) GetTiers(c *gin.Context) { From bba971298041f748f812cb6357706fce9735340e Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Wed, 11 Feb 2026 09:31:04 -0800 Subject: [PATCH 34/56] revert event post cli --- internal/cli/events/post.go | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/internal/cli/events/post.go b/internal/cli/events/post.go index 7ebabdc..fe7cadb 100644 --- a/internal/cli/events/post.go +++ b/internal/cli/events/post.go @@ -9,14 +9,13 @@ import ( "net/url" "os" "strings" - "time" "github.com/charmbracelet/huh" "github.com/spf13/cobra" + "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/oauth" - "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" "github.com/acmcsufoss/api.acmcsuf.com/utils" ) @@ -25,7 +24,7 @@ var PostEvent = &cobra.Command{ Short: "Post a new event.", Run: func(cmd *cobra.Command, args []string) { - payload := domain.Event{} + payload := dbmodels.CreateEventParams{} err := huh.NewForm().Run() if err != nil { if err == huh.ErrUserAborted { @@ -49,15 +48,15 @@ var PostEvent = &cobra.Command{ fmt.Println(err) return } - payload.StartAt = time.Unix(startAtUnix, 0) + payload.StartAt = startAtUnix if duration != "" { var err error - endAtUnix, err := utils.TimeAfterDuration(payload.StartAt.Unix(), duration) + endAtUnix, err := utils.TimeAfterDuration(payload.StartAt, duration) if err != nil { fmt.Println(err) return } - payload.EndAt = time.Unix(endAtUnix, 0) + payload.EndAt = endAtUnix } } @@ -87,7 +86,7 @@ func init() { PostEvent.Flags().BoolP("isallday", "a", false, "Set if new event is all day") } -func postEvent(payload *domain.Event, changedFlag eventFlags, cfg *config.Config) { +func postEvent(payload *dbmodels.CreateEventParams, changedFlag eventFlags, cfg *config.Config) { baseURL := &url.URL{ Scheme: "http", Host: fmt.Sprintf("%s:%s", cfg.Host, cfg.Port), @@ -195,7 +194,7 @@ func postEvent(payload *domain.Event, changedFlag eventFlags, cfg *config.Config continue } - payload.StartAt = time.Unix(startTime, 0) + payload.StartAt = startTime break } @@ -228,13 +227,13 @@ func postEvent(payload *domain.Event, changedFlag eventFlags, cfg *config.Config } endTimeBuffer := scanner.Bytes() - endTime, err := utils.TimeAfterDuration(payload.StartAt.Unix(), string(endTimeBuffer)) + endTime, err := utils.TimeAfterDuration(payload.StartAt, string(endTimeBuffer)) if err != nil { fmt.Println(err) continue } - payload.EndAt = time.Unix(endTime, 0) + payload.EndAt = endTime break } From 9c25d64663a01e56daf5e632655287e9cbe0d92e Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Thu, 12 Feb 2026 21:19:59 -0800 Subject: [PATCH 35/56] clean leftover debug in announcements cli --- internal/cli/announcements/post.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/cli/announcements/post.go b/internal/cli/announcements/post.go index 2ec3e2e..42d2892 100644 --- a/internal/cli/announcements/post.go +++ b/internal/cli/announcements/post.go @@ -289,7 +289,6 @@ func postAnnouncement(payload *dbmodels.CreateAnnouncementParams, changedFlags a // ----- Marshalling to Json ----- jsonPayload, err := json.Marshal(*payload) - fmt.Println("JSON MARSHALLED:", payload) if err != nil { fmt.Println("error formating payload to json:", err) return From 2813d2bd8e75e6c611f11266f0bf0ff958359d4d Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Thu, 12 Feb 2026 21:22:34 -0800 Subject: [PATCH 36/56] Add uuid to event and announcements --- internal/dto/request/event.go | 1 + internal/dto/request/officer.go | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/dto/request/event.go b/internal/dto/request/event.go index 2831b99..6d7698f 100644 --- a/internal/dto/request/event.go +++ b/internal/dto/request/event.go @@ -7,6 +7,7 @@ import ( ) type Event struct { + Uuid string `json:"uuid"` Location string `json:"location"` StartAt int64 `json:"start_at"` EndAt int64 `json:"end_at"` diff --git a/internal/dto/request/officer.go b/internal/dto/request/officer.go index 46bac65..ff57755 100644 --- a/internal/dto/request/officer.go +++ b/internal/dto/request/officer.go @@ -3,6 +3,7 @@ package dto_request import "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" type Officer struct { + Uuid string `json:"uuid"` FullName string `json:"full_name"` Picture string `json:"picture"` Github string `json:"github"` From 7382dc86509fc8afac1912117081ee10fd1489bd Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Thu, 12 Feb 2026 21:47:34 -0800 Subject: [PATCH 37/56] fix swagger godoc annotations --- internal/api/handlers/announcement.go | 6 +++--- internal/api/handlers/event.go | 8 ++++---- internal/api/handlers/officer.go | 8 ++++---- internal/api/handlers/position.go | 10 +++++----- internal/api/handlers/tier.go | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/internal/api/handlers/announcement.go b/internal/api/handlers/announcement.go index 52b4768..38bd578 100644 --- a/internal/api/handlers/announcement.go +++ b/internal/api/handlers/announcement.go @@ -26,7 +26,7 @@ func NewAnnouncementHandler(announcementService services.AnnouncementServicer) * // @Accept json // @Produce json // @Param id path string true "Announcement ID" -// @Success 200 {object} dbmodels.Announcement "Announcement details" +// @Success 200 {object} dto_request.Announcement "Announcement details" // @Failure 404 {object} map[string]string // @Failure 500 {object} map[string]string // @Router /v1/announcements/{id} [get] @@ -73,7 +73,7 @@ func (h *AnnouncementHandler) GetAnnouncements(c *gin.Context) { // @Tags Announcements // @Accept json // @Produce json -// @Param body body dbmodels.CreateAnnouncementParams true "Announcement data" +// @Param body body domain.CreateAnnouncementParams true "Announcement data" // @Success 200 {object} map[string]interface{} "Success message with UUID" // @Failure 400 {object} map[string]string // @Failure 500 {object} map[string]string @@ -111,7 +111,7 @@ func (h *AnnouncementHandler) CreateAnnouncement(c *gin.Context) { // @Accept json // @Produce json // @Param id path string true "Announcement ID" -// @Param body body dbmodels.UpdateAnnouncementParams true "Updated announcement data" +// @Param body body domain.Announcement true "Updated announcement data" // @Success 200 {object} map[string]string "Success message" // @Failure 400 {object} map[string]string // @Failure 404 {object} map[string]string diff --git a/internal/api/handlers/event.go b/internal/api/handlers/event.go index 4d1f591..410b75d 100644 --- a/internal/api/handlers/event.go +++ b/internal/api/handlers/event.go @@ -29,7 +29,7 @@ func NewEventHandler(eventService services.EventsServicer) *EventsHandler { // @Accept json // @Produce json // @Param id path string true "Event ID" -// @Success 200 {object} dbmodels.Event "Event details" +// @Success 200 {object} dto_request.Event "Event details" // @Failure 404 {object} map[string]string // @Failure 500 {object} map[string]string // @Router /v1/events/{id} [get] @@ -62,7 +62,7 @@ func (h *EventsHandler) GetEvent(c *gin.Context) { // @Tags Events // @Accept json // @Produce json -// @Param body body dbmodels.CreateEventParams true "Event data" +// @Param body body domain.CreateEventParams true "Event data" // @Success 200 {object} map[string]interface{} "Success message with UUID" // @Failure 400 {object} map[string]string // @Failure 500 {object} map[string]string @@ -106,7 +106,7 @@ func (h *EventsHandler) CreateEvent(c *gin.Context) { // @Accept json // @Produce json // @Param host query string false "Filter by host" -// @Success 200 {array} dbmodels.Event "List of events" +// @Success 200 {array} domain.Event "List of events" // @Failure 500 {object} map[string]string // @Router /v1/events [get] func (h *EventsHandler) GetEvents(c *gin.Context) { @@ -136,7 +136,7 @@ func (h *EventsHandler) GetEvents(c *gin.Context) { // @Accept json // @Produce json // @Param id path string true "Event ID" -// @Param body body dbmodels.UpdateEventParams true "Updated event data" +// @Param body body domain.Event true "Updated event data" // @Success 200 {object} map[string]string "Success message" // @Failure 400 {object} map[string]string // @Failure 404 {object} map[string]string diff --git a/internal/api/handlers/officer.go b/internal/api/handlers/officer.go index 9006927..1253247 100644 --- a/internal/api/handlers/officer.go +++ b/internal/api/handlers/officer.go @@ -26,7 +26,7 @@ func NewOfficerHandler(officerService services.OfficerServicer) *OfficerHandler // @Accept json // @Produce json // @Param id path string true "Officer UUID" -// @Success 200 {object} dbmodels.Officer "Officer details" +// @Success 200 {object} dto_request.Officer "Officer details" // @Failure 404 {object} map[string]string // @Failure 500 {object} map[string]string // @Router /v1/board/officers/{id} [get] @@ -58,7 +58,7 @@ func (h *OfficerHandler) GetOfficer(c *gin.Context) { // @Tags Board // @Accept json // @Produce json -// @Success 200 {array} dbmodels.Officer "List of officers" +// @Success 200 {array} domain.Officer "List of officers" // @Failure 500 {object} map[string]string // @Router /v1/board/officers [get] func (h *OfficerHandler) GetOfficers(c *gin.Context) { @@ -82,7 +82,7 @@ func (h *OfficerHandler) GetOfficers(c *gin.Context) { // @Tags Board // @Accept json // @Produce json -// @Param body body dbmodels.CreateOfficerParams true "Officer data" +// @Param body body domain.CreateOfficerParams true "Officer data" // @Success 200 {object} map[string]interface{} "Success message with UUID" // @Failure 400 {object} map[string]string // @Failure 500 {object} map[string]string @@ -126,7 +126,7 @@ func (h *OfficerHandler) CreateOfficer(c *gin.Context) { // @Accept json // @Produce json // @Param id path string true "Officer UUID" -// @Param body body dbmodels.UpdateOfficerParams true "Updated officer data" +// @Param body body domain.Officer true "Updated officer data" // @Success 200 {object} map[string]string "Success message" // @Failure 400 {object} map[string]string // @Failure 404 {object} map[string]string diff --git a/internal/api/handlers/position.go b/internal/api/handlers/position.go index 80d65b9..6bdfd1c 100644 --- a/internal/api/handlers/position.go +++ b/internal/api/handlers/position.go @@ -25,7 +25,7 @@ func NewPositionHandler(positionService services.PositionServicer) *PositionHand // @Tags Board // @Accept json // @Produce json -// @Success 200 {array} dbmodels.Position "List of positions" +// @Success 200 {array} dto_request.Position "List of positions" // @Failure 500 {object} map[string]string // @Router /v1/board/positions [get] func (h *PositionHandler) GetPositions(c *gin.Context) { @@ -50,7 +50,7 @@ func (h *PositionHandler) GetPositions(c *gin.Context) { // @Accept json // @Produce json // @Param id path string true "Officer full name" -// @Success 200 {object} dbmodels.Position "Position details" +// @Success 200 {object} domain.Position "Position details" // @Failure 404 {object} map[string]string // @Failure 500 {object} map[string]string // @Router /v1/board/positions/{id} [get] @@ -82,7 +82,7 @@ func (h *PositionHandler) GetPosition(c *gin.Context) { // @Tags Board // @Accept json // @Produce json -// @Param body body dbmodels.CreatePositionParams true "Position data" +// @Param body body domain.CreatePositionParams true "Position data" // @Success 200 {object} map[string]interface{} "Success message" // @Failure 400 {object} map[string]string // @Failure 500 {object} map[string]string @@ -120,7 +120,7 @@ func (h *PositionHandler) CreatePosition(c *gin.Context) { // @Tags Board // @Accept json // @Produce json -// @Param body body dbmodels.UpdatePositionParams true "Updated position data (must include oid, semester, tier)" +// @Param body body domain.UpdatePositionParams true "Updated position data (must include oid, semester, tier)" // @Success 200 {object} map[string]string "Success message" // @Failure 400 {object} map[string]string // @Failure 404 {object} map[string]string @@ -160,7 +160,7 @@ func (h *PositionHandler) UpdatePosition(c *gin.Context) { // @Tags Board // @Accept json // @Produce json -// @Param body body dbmodels.DeletePositionParams true "Position identifier" +// @Param body body domain.Position true "Position identifier" // @Success 200 {object} map[string]string "Success message" // @Failure 400 {object} map[string]string // @Failure 404 {object} map[string]string diff --git a/internal/api/handlers/tier.go b/internal/api/handlers/tier.go index 101b95d..5fb9f91 100644 --- a/internal/api/handlers/tier.go +++ b/internal/api/handlers/tier.go @@ -90,7 +90,7 @@ func (h *TierHandler) GetTier(c *gin.Context) { // @Tags Board // @Accept json // @Produce json -// @Param body body dbmodels.CreateTierParams true "Tier data" +// @Param body body domain.Tier true "Tier data" // @Success 200 {object} map[string]interface{} "Success message with tier number" // @Failure 400 {object} map[string]string // @Failure 500 {object} map[string]string @@ -127,7 +127,7 @@ func (h *TierHandler) CreateTier(c *gin.Context) { // @Accept json // @Produce json // @Param id path int true "Tier number" -// @Param body body dbmodels.UpdateTierParams true "Updated tier data" +// @Param body body domain.UpdateTierParams true "Updated tier data" // @Success 200 {object} map[string]string "Success message" // @Failure 400 {object} map[string]string // @Failure 404 {object} map[string]string From dd46f1a901705342645fb65f903dcb58bd58a0ff Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Thu, 12 Feb 2026 21:49:25 -0800 Subject: [PATCH 38/56] fix tiers being an export variable --- internal/repository/tier.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/repository/tier.go b/internal/repository/tier.go index e473acb..7cbe801 100644 --- a/internal/repository/tier.go +++ b/internal/repository/tier.go @@ -25,11 +25,11 @@ func (r *tierRepository) GetAll(ctx context.Context) ([]domain.Tier, error) { return nil, err } - var Tiers []domain.Tier + var tiers []domain.Tier for _, dbTier := range dbTiers { - Tiers = append(Tiers, convertDBTierToDomain(dbTier)) + tiers = append(tiers, convertDBTierToDomain(dbTier)) } - return Tiers, nil + return tiers, nil } func (r *tierRepository) GetByID(ctx context.Context, id int64) (domain.Tier, error) { From 709852be748788c0d6f413696a085f689273c2c4 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Thu, 12 Feb 2026 21:52:48 -0800 Subject: [PATCH 39/56] use uuid param in tier update service --- internal/api/services/tier.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/api/services/tier.go b/internal/api/services/tier.go index 387ff8d..1cb98ac 100644 --- a/internal/api/services/tier.go +++ b/internal/api/services/tier.go @@ -56,6 +56,7 @@ func (s *TierService) Create(ctx context.Context, params domain.Tier) error { } func (s *TierService) Update(ctx context.Context, uuid int64, params domain.Tier) error { + params.Tier = int(uuid) err := s.tierRepo.Update(ctx, params) if err != nil { return err From 00348ae60f5f9dfba050b168219b1431a2381c75 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Thu, 12 Feb 2026 21:54:02 -0800 Subject: [PATCH 40/56] update tier update param var name --- internal/api/services/tier.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/api/services/tier.go b/internal/api/services/tier.go index 1cb98ac..904b3bb 100644 --- a/internal/api/services/tier.go +++ b/internal/api/services/tier.go @@ -55,8 +55,8 @@ func (s *TierService) Create(ctx context.Context, params domain.Tier) error { return nil } -func (s *TierService) Update(ctx context.Context, uuid int64, params domain.Tier) error { - params.Tier = int(uuid) +func (s *TierService) Update(ctx context.Context, tierName int64, params domain.Tier) error { + params.Tier = int(tierName) err := s.tierRepo.Update(ctx, params) if err != nil { return err From ed89113ef4bf2abd60bec4b556ca2b92b63a06b1 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Thu, 12 Feb 2026 22:43:34 -0800 Subject: [PATCH 41/56] create mappers directory To avoid domain and dto models having to import each other --- internal/api/handlers/announcement.go | 9 +++-- internal/api/handlers/event.go | 9 +++-- internal/api/handlers/officer.go | 7 ++-- internal/api/handlers/position.go | 7 ++-- internal/api/handlers/tier.go | 5 ++- internal/domain/announcements.go | 12 ------ internal/domain/event.go | 13 ------ internal/domain/officer.go | 12 ------ internal/domain/position.go | 10 ----- internal/domain/tier.go | 11 ------ internal/dto/request/announcements.go | 16 -------- internal/dto/request/event.go | 16 -------- internal/dto/request/officer.go | 11 ------ internal/dto/request/position.go | 10 ----- internal/dto/request/tier.go | 11 ------ internal/mapper/domain_to_dto.go | 57 +++++++++++++++++++++++++++ internal/mapper/dto_to_domain.go | 54 +++++++++++++++++++++++++ 17 files changed, 132 insertions(+), 138 deletions(-) create mode 100644 internal/mapper/domain_to_dto.go create mode 100644 internal/mapper/dto_to_domain.go diff --git a/internal/api/handlers/announcement.go b/internal/api/handlers/announcement.go index 38bd578..416c6f2 100644 --- a/internal/api/handlers/announcement.go +++ b/internal/api/handlers/announcement.go @@ -7,6 +7,7 @@ import ( "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" + "github.com/acmcsufoss/api.acmcsuf.com/internal/mapper" "github.com/gin-gonic/gin" ) @@ -48,7 +49,7 @@ func (h *AnnouncementHandler) GetAnnouncement(c *gin.Context) { return } - c.JSON(http.StatusOK, announcement.ToDTO()) + c.JSON(http.StatusOK, mapper.ToAnnouncementDTO(&announcement)) } func (h *AnnouncementHandler) GetAnnouncements(c *gin.Context) { @@ -73,7 +74,7 @@ func (h *AnnouncementHandler) GetAnnouncements(c *gin.Context) { // @Tags Announcements // @Accept json // @Produce json -// @Param body body domain.CreateAnnouncementParams true "Announcement data" +// @Param body body domain.Announcement true "Announcement data" // @Success 200 {object} map[string]interface{} "Success message with UUID" // @Failure 400 {object} map[string]string // @Failure 500 {object} map[string]string @@ -90,7 +91,7 @@ func (h *AnnouncementHandler) CreateAnnouncement(c *gin.Context) { } // TODO: error out if required fields aren't provided - if err := h.announcementService.Create(ctx, params.ToDomain()); err != nil { + if err := h.announcementService.Create(ctx, mapper.ToAnnouncementDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to create announcement", }) @@ -129,7 +130,7 @@ func (h *AnnouncementHandler) UpdateAnnouncement(c *gin.Context) { return } - if err := h.announcementService.Update(ctx, id, params.ToDomain()); err != nil { + if err := h.announcementService.Update(ctx, id, mapper.ToAnnouncementDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to update announcement", }) diff --git a/internal/api/handlers/event.go b/internal/api/handlers/event.go index 410b75d..9b6ee4c 100644 --- a/internal/api/handlers/event.go +++ b/internal/api/handlers/event.go @@ -8,6 +8,7 @@ import ( "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" dto_request "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" + "github.com/acmcsufoss/api.acmcsuf.com/internal/mapper" "github.com/gin-gonic/gin" ) @@ -85,7 +86,7 @@ func (h *EventsHandler) CreateEvent(c *gin.Context) { return } - err := h.eventsService.Create(ctx, params.ToDomain()) + err := h.eventsService.Create(ctx, mapper.ToEventDomain(¶ms)) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to create event. " + err.Error(), @@ -94,7 +95,7 @@ func (h *EventsHandler) CreateEvent(c *gin.Context) { } c.JSON(http.StatusOK, gin.H{ "message": "Event created successfully", - "uuid": params.ToDomain().Uuid, + "uuid": mapper.ToEventDomain(¶ms).Uuid, }) } @@ -155,7 +156,7 @@ func (h *EventsHandler) UpdateEvent(c *gin.Context) { return } - if err := h.eventsService.Update(ctx, id, params.ToDomain()); err != nil { + if err := h.eventsService.Update(ctx, id, mapper.ToEventDomain(¶ms)); err != nil { error := fmt.Sprint("Failed to update event: ", err, " | ", ctx, " | ", id, " | ", params) c.JSON(http.StatusInternalServerError, gin.H{ "error": error, @@ -165,7 +166,7 @@ func (h *EventsHandler) UpdateEvent(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "Event updated successfully", - "uuid": params.ToDomain().Uuid, + "uuid": mapper.ToEventDomain(¶ms).Uuid, }) } diff --git a/internal/api/handlers/officer.go b/internal/api/handlers/officer.go index 1253247..86649d7 100644 --- a/internal/api/handlers/officer.go +++ b/internal/api/handlers/officer.go @@ -7,6 +7,7 @@ import ( "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" dto_request "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" + "github.com/acmcsufoss/api.acmcsuf.com/internal/mapper" "github.com/gin-gonic/gin" ) @@ -105,7 +106,7 @@ func (h *OfficerHandler) CreateOfficer(c *gin.Context) { return } - if err := h.officerService.Create(ctx, params.ToDomain()); err != nil { + if err := h.officerService.Create(ctx, mapper.ToOfficerDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to create officer. " + err.Error(), }) @@ -114,7 +115,7 @@ func (h *OfficerHandler) CreateOfficer(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "Officer created successfully", - "uuid": params.ToDomain().Uuid, + "uuid": mapper.ToOfficerDomain(¶ms).Uuid, }) } @@ -144,7 +145,7 @@ func (h *OfficerHandler) UpdateOfficer(c *gin.Context) { return } - if err := h.officerService.Update(ctx, id, params.ToDomain()); err != nil { + if err := h.officerService.Update(ctx, id, mapper.ToOfficerDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to update officer. " + err.Error(), }) diff --git a/internal/api/handlers/position.go b/internal/api/handlers/position.go index 6bdfd1c..34f0228 100644 --- a/internal/api/handlers/position.go +++ b/internal/api/handlers/position.go @@ -7,6 +7,7 @@ import ( "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" dto_request "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" + "github.com/acmcsufoss/api.acmcsuf.com/internal/mapper" "github.com/gin-gonic/gin" ) @@ -98,7 +99,7 @@ func (h *PositionHandler) CreatePosition(c *gin.Context) { return } - if err := h.positionService.Create(ctx, params.ToDomain()); err != nil { + if err := h.positionService.Create(ctx, mapper.ToPositionDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to create position. " + err.Error(), }) @@ -138,7 +139,7 @@ func (h *PositionHandler) UpdatePosition(c *gin.Context) { return } - if err := h.positionService.Update(ctx, id, params.ToDomain()); err != nil { + if err := h.positionService.Update(ctx, id, mapper.ToPositionDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to update position. " + err.Error(), }) @@ -177,7 +178,7 @@ func (h *PositionHandler) DeletePosition(c *gin.Context) { return } - if err := h.positionService.DeletePosition(ctx, params.ToDomain()); err != nil { + if err := h.positionService.DeletePosition(ctx, mapper.ToPositionDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to delete position", }) diff --git a/internal/api/handlers/tier.go b/internal/api/handlers/tier.go index 5fb9f91..6e469bb 100644 --- a/internal/api/handlers/tier.go +++ b/internal/api/handlers/tier.go @@ -8,6 +8,7 @@ import ( "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" dto_request "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" + "github.com/acmcsufoss/api.acmcsuf.com/internal/mapper" "github.com/gin-gonic/gin" ) @@ -106,7 +107,7 @@ func (h *TierHandler) CreateTier(c *gin.Context) { return } - if err := h.tierService.Create(ctx, params.ToDomain()); err != nil { + if err := h.tierService.Create(ctx, mapper.ToTierDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to create tier. " + err.Error(), }) @@ -153,7 +154,7 @@ func (h *TierHandler) UpdateTier(c *gin.Context) { params.Tier = id - if err := h.tierService.Update(ctx, int64(id), params.ToDomain()); err != nil { + if err := h.tierService.Update(ctx, int64(id), mapper.ToTierDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to update tier. " + err.Error(), }) diff --git a/internal/domain/announcements.go b/internal/domain/announcements.go index 769b7ae..76661a5 100644 --- a/internal/domain/announcements.go +++ b/internal/domain/announcements.go @@ -2,8 +2,6 @@ package domain import ( "time" - - dto_response "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/response" ) type Announcement struct { @@ -13,13 +11,3 @@ type Announcement struct { DiscordChannelID string DiscordMessageID string } - -func (a *Announcement) ToDTO() dto_response.Announcement { - return dto_response.Announcement{ - Uuid: a.Uuid, - Visibility: a.Visibility, - AnnounceAt: a.AnnounceAt.Unix(), - DiscordChannelID: a.DiscordChannelID, - DiscordMessageID: a.DiscordMessageID, - } -} diff --git a/internal/domain/event.go b/internal/domain/event.go index 65e0fc6..8946cc0 100644 --- a/internal/domain/event.go +++ b/internal/domain/event.go @@ -2,8 +2,6 @@ package domain import ( "time" - - dto_response "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/response" ) type Event struct { @@ -14,14 +12,3 @@ type Event struct { IsAllDay bool Host string } - -func (e *Event) ToDTO() dto_response.Event { - return dto_response.Event{ - Uuid: e.Uuid, - Location: e.Location, - StartAt: e.StartAt.Unix(), - EndAt: e.EndAt.Unix(), - IsAllDay: e.IsAllDay, - Host: e.Host, - } -} diff --git a/internal/domain/officer.go b/internal/domain/officer.go index c02ed66..23c47ca 100644 --- a/internal/domain/officer.go +++ b/internal/domain/officer.go @@ -1,7 +1,5 @@ package domain -import dto_response "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/response" - type Officer struct { Uuid string FullName string @@ -9,13 +7,3 @@ type Officer struct { Github string Discord string } - -func (o *Officer) ToDTO() dto_response.Officer { - return dto_response.Officer{ - Uuid: o.Uuid, - FullName: o.FullName, - Picture: o.Picture, - Github: o.Github, - Discord: o.Discord, - } -} diff --git a/internal/domain/position.go b/internal/domain/position.go index 35d7012..9c0978a 100644 --- a/internal/domain/position.go +++ b/internal/domain/position.go @@ -1,17 +1,7 @@ package domain -import dto_response "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/response" - type Position struct { Oid string Semester string Tier int } - -func (p *Position) ToDTO() dto_response.Position { - return dto_response.Position{ - Oid: p.Oid, - Semester: p.Semester, - Tier: p.Tier, - } -} diff --git a/internal/domain/tier.go b/internal/domain/tier.go index 5f2304f..fadefeb 100644 --- a/internal/domain/tier.go +++ b/internal/domain/tier.go @@ -1,19 +1,8 @@ package domain -import dto_response "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/response" - type Tier struct { Tier int Title string Tindex int Team string } - -func (t *Tier) ToDTO() dto_response.Tier { - return dto_response.Tier{ - Tier: t.Tier, - Title: t.Title, - Tindex: t.Tindex, - Team: t.Team, - } -} diff --git a/internal/dto/request/announcements.go b/internal/dto/request/announcements.go index b6a1be5..b6197d9 100644 --- a/internal/dto/request/announcements.go +++ b/internal/dto/request/announcements.go @@ -1,11 +1,5 @@ package dto_request -import ( - "time" - - "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" -) - type Announcement struct { Uuid string `json:"uuid"` Visibility string `json:"visibility"` @@ -13,13 +7,3 @@ type Announcement struct { DiscordChannelID string `json:"discord_channel_id"` DiscordMessageID string `json:"discord_message_id"` } - -func (a *Announcement) ToDomain() domain.Announcement { - return domain.Announcement{ - Uuid: a.Uuid, - Visibility: a.Visibility, - AnnounceAt: time.Unix(a.AnnounceAt, 0), - DiscordChannelID: a.DiscordChannelID, - DiscordMessageID: a.DiscordMessageID, - } -} diff --git a/internal/dto/request/event.go b/internal/dto/request/event.go index 6d7698f..3497e19 100644 --- a/internal/dto/request/event.go +++ b/internal/dto/request/event.go @@ -1,11 +1,5 @@ package dto_request -import ( - "time" - - "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" -) - type Event struct { Uuid string `json:"uuid"` Location string `json:"location"` @@ -14,13 +8,3 @@ type Event struct { IsAllDay bool `json:"is_all_day"` Host string `json:"host"` } - -func (e *Event) ToDomain() domain.Event { - return domain.Event{ - Location: e.Location, - StartAt: time.Unix(e.StartAt, 0), - EndAt: time.Unix(e.EndAt, 0), - IsAllDay: e.IsAllDay, - Host: e.Host, - } -} diff --git a/internal/dto/request/officer.go b/internal/dto/request/officer.go index ff57755..b820cdf 100644 --- a/internal/dto/request/officer.go +++ b/internal/dto/request/officer.go @@ -1,7 +1,5 @@ package dto_request -import "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" - type Officer struct { Uuid string `json:"uuid"` FullName string `json:"full_name"` @@ -9,12 +7,3 @@ type Officer struct { Github string `json:"github"` Discord string `json:"discord"` } - -func (o *Officer) ToDomain() domain.Officer { - return domain.Officer{ - FullName: o.FullName, - Picture: o.Picture, - Github: o.Github, - Discord: o.Discord, - } -} diff --git a/internal/dto/request/position.go b/internal/dto/request/position.go index 415ff56..b390cd0 100644 --- a/internal/dto/request/position.go +++ b/internal/dto/request/position.go @@ -1,17 +1,7 @@ package dto_request -import "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" - type Position struct { Oid string `json:"oid"` Semester string `json:"semester"` Tier int `json:"tier"` } - -func (p *Position) ToDomain() domain.Position { - return domain.Position{ - Oid: p.Oid, - Semester: p.Semester, - Tier: p.Tier, - } -} diff --git a/internal/dto/request/tier.go b/internal/dto/request/tier.go index ea3edbf..07815db 100644 --- a/internal/dto/request/tier.go +++ b/internal/dto/request/tier.go @@ -1,19 +1,8 @@ package dto_request -import "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" - type Tier struct { Tier int `json:"tier"` Title string `json:"title"` Tindex int `json:"t_index"` Team string `json:"team"` } - -func (t *Tier) ToDomain() domain.Tier { - return domain.Tier{ - Tier: t.Tier, - Title: t.Title, - Tindex: t.Tindex, - Team: t.Team, - } -} diff --git a/internal/mapper/domain_to_dto.go b/internal/mapper/domain_to_dto.go new file mode 100644 index 0000000..ca73175 --- /dev/null +++ b/internal/mapper/domain_to_dto.go @@ -0,0 +1,57 @@ +package mapper + +import ( + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" + + dto_response "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/response" +) + +// File deticated to mapping domain models to dto response models + +func ToAnnouncementDTO(a *domain.Announcement) dto_response.Announcement { + return dto_response.Announcement{ + Uuid: a.Uuid, + Visibility: a.Visibility, + AnnounceAt: a.AnnounceAt.Unix(), + DiscordChannelID: a.DiscordChannelID, + DiscordMessageID: a.DiscordMessageID, + } +} + +func ToEventEventDTO(e *domain.Event) dto_response.Event { + return dto_response.Event{ + Uuid: e.Uuid, + Location: e.Location, + StartAt: e.StartAt.Unix(), + EndAt: e.EndAt.Unix(), + IsAllDay: e.IsAllDay, + Host: e.Host, + } +} + +func ToOfficerDTO(o domain.Officer) dto_response.Officer { + return dto_response.Officer{ + Uuid: o.Uuid, + FullName: o.FullName, + Picture: o.Picture, + Github: o.Github, + Discord: o.Discord, + } +} + +func ToPositionDTO(p *domain.Position) dto_response.Position { + return dto_response.Position{ + Oid: p.Oid, + Semester: p.Semester, + Tier: p.Tier, + } +} + +func ToTierDTO(t *domain.Tier) dto_response.Tier { + return dto_response.Tier{ + Tier: t.Tier, + Title: t.Title, + Tindex: t.Tindex, + Team: t.Team, + } +} diff --git a/internal/mapper/dto_to_domain.go b/internal/mapper/dto_to_domain.go new file mode 100644 index 0000000..35ed1de --- /dev/null +++ b/internal/mapper/dto_to_domain.go @@ -0,0 +1,54 @@ +package mapper + +import ( + "time" + + "github.com/acmcsufoss/api.acmcsuf.com/internal/domain" + dto_request "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" +) + +func ToAnnouncementDomain(a *dto_request.Announcement) domain.Announcement { + return domain.Announcement{ + Uuid: a.Uuid, + Visibility: a.Visibility, + AnnounceAt: time.Unix(a.AnnounceAt, 0), + DiscordChannelID: a.DiscordChannelID, + DiscordMessageID: a.DiscordMessageID, + } +} + +func ToEventDomain(e *dto_request.Event) domain.Event { + return domain.Event{ + Location: e.Location, + StartAt: time.Unix(e.StartAt, 0), + EndAt: time.Unix(e.EndAt, 0), + IsAllDay: e.IsAllDay, + Host: e.Host, + } +} + +func ToOfficerDomain(o *dto_request.Officer) domain.Officer { + return domain.Officer{ + FullName: o.FullName, + Picture: o.Picture, + Github: o.Github, + Discord: o.Discord, + } +} + +func ToPositionDomain(p *dto_request.Position) domain.Position { + return domain.Position{ + Oid: p.Oid, + Semester: p.Semester, + Tier: p.Tier, + } +} + +func ToTierDomain(t *dto_request.Tier) domain.Tier { + return domain.Tier{ + Tier: t.Tier, + Title: t.Title, + Tindex: t.Tindex, + Team: t.Team, + } +} From 8e8604391e43588dd0ed2429a6da2787da95c4f3 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 14 Feb 2026 20:03:06 -0800 Subject: [PATCH 42/56] Fix godoc --- internal/api/handlers/event.go | 2 +- internal/api/handlers/officer.go | 2 +- internal/api/handlers/position.go | 4 ++-- internal/api/handlers/tier.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/api/handlers/event.go b/internal/api/handlers/event.go index 9b6ee4c..dc0bf07 100644 --- a/internal/api/handlers/event.go +++ b/internal/api/handlers/event.go @@ -63,7 +63,7 @@ func (h *EventsHandler) GetEvent(c *gin.Context) { // @Tags Events // @Accept json // @Produce json -// @Param body body domain.CreateEventParams true "Event data" +// @Param body body domain.Event true "Event data" // @Success 200 {object} map[string]interface{} "Success message with UUID" // @Failure 400 {object} map[string]string // @Failure 500 {object} map[string]string diff --git a/internal/api/handlers/officer.go b/internal/api/handlers/officer.go index 86649d7..0899644 100644 --- a/internal/api/handlers/officer.go +++ b/internal/api/handlers/officer.go @@ -83,7 +83,7 @@ func (h *OfficerHandler) GetOfficers(c *gin.Context) { // @Tags Board // @Accept json // @Produce json -// @Param body body domain.CreateOfficerParams true "Officer data" +// @Param body body domain.Officer true "Officer data" // @Success 200 {object} map[string]interface{} "Success message with UUID" // @Failure 400 {object} map[string]string // @Failure 500 {object} map[string]string diff --git a/internal/api/handlers/position.go b/internal/api/handlers/position.go index 34f0228..c11736b 100644 --- a/internal/api/handlers/position.go +++ b/internal/api/handlers/position.go @@ -83,7 +83,7 @@ func (h *PositionHandler) GetPosition(c *gin.Context) { // @Tags Board // @Accept json // @Produce json -// @Param body body domain.CreatePositionParams true "Position data" +// @Param body body domain.Postion true "Position data" // @Success 200 {object} map[string]interface{} "Success message" // @Failure 400 {object} map[string]string // @Failure 500 {object} map[string]string @@ -121,7 +121,7 @@ func (h *PositionHandler) CreatePosition(c *gin.Context) { // @Tags Board // @Accept json // @Produce json -// @Param body body domain.UpdatePositionParams true "Updated position data (must include oid, semester, tier)" +// @Param body body domain.Position true "Updated position data (must include oid, semester, tier)" // @Success 200 {object} map[string]string "Success message" // @Failure 400 {object} map[string]string // @Failure 404 {object} map[string]string diff --git a/internal/api/handlers/tier.go b/internal/api/handlers/tier.go index 6e469bb..85da24f 100644 --- a/internal/api/handlers/tier.go +++ b/internal/api/handlers/tier.go @@ -128,7 +128,7 @@ func (h *TierHandler) CreateTier(c *gin.Context) { // @Accept json // @Produce json // @Param id path int true "Tier number" -// @Param body body domain.UpdateTierParams true "Updated tier data" +// @Param body body domain.Tier true "Updated tier data" // @Success 200 {object} map[string]string "Success message" // @Failure 400 {object} map[string]string // @Failure 404 {object} map[string]string From 153c9bbf50d19acd172c888f5e27b4d6b3f9b6aa Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 14 Feb 2026 20:08:39 -0800 Subject: [PATCH 43/56] Fix typo in repository model conv --- internal/repository/conv.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/internal/repository/conv.go b/internal/repository/conv.go index b0f694e..c594ffc 100644 --- a/internal/repository/conv.go +++ b/internal/repository/conv.go @@ -143,26 +143,26 @@ func convertDBPositionToDomain(dbPosition dbmodels.Position) domain.Position { } } -func convertDomainToCreateDBPosition(dPositon domain.Position) dbmodels.CreatePositionParams { +func convertDomainToCreateDBPosition(dPosition domain.Position) dbmodels.CreatePositionParams { return dbmodels.CreatePositionParams{ - Oid: dPositon.Oid, - Semester: dPositon.Semester, - Tier: int64(dPositon.Tier), + Oid: dPosition.Oid, + Semester: dPosition.Semester, + Tier: int64(dPosition.Tier), } } -func convertDomainToUpdateDBPosition(dPositon domain.Position) dbmodels.UpdatePositionParams { +func convertDomainToUpdateDBPosition(dPosition domain.Position) dbmodels.UpdatePositionParams { return dbmodels.UpdatePositionParams{ - Oid: dPositon.Oid, - Semester: dPositon.Semester, - Tier: int64(dPositon.Tier), + Oid: dPosition.Oid, + Semester: dPosition.Semester, + Tier: int64(dPosition.Tier), } } -func convertDomainToDeleteDBPosition(dPositon domain.Position) dbmodels.DeletePositionParams { +func convertDomainToDeleteDBPosition(dPosition domain.Position) dbmodels.DeletePositionParams { return dbmodels.DeletePositionParams{ - Oid: dPositon.Oid, - Semester: dPositon.Semester, - Tier: int64(dPositon.Tier), + Oid: dPosition.Oid, + Semester: dPosition.Semester, + Tier: int64(dPosition.Tier), } } From 3a71aac51c1f08e1e8024af3255ed0ccadbf0b1a Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 14 Feb 2026 20:29:35 -0800 Subject: [PATCH 44/56] fix godoc typo in positions --- internal/api/handlers/position.go | 2 +- internal/domain/announcements.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/api/handlers/position.go b/internal/api/handlers/position.go index c11736b..35bb134 100644 --- a/internal/api/handlers/position.go +++ b/internal/api/handlers/position.go @@ -83,7 +83,7 @@ func (h *PositionHandler) GetPosition(c *gin.Context) { // @Tags Board // @Accept json // @Produce json -// @Param body body domain.Postion true "Position data" +// @Param body body domain.Position true "Position data" // @Success 200 {object} map[string]interface{} "Success message" // @Failure 400 {object} map[string]string // @Failure 500 {object} map[string]string diff --git a/internal/domain/announcements.go b/internal/domain/announcements.go index 76661a5..8ba3a81 100644 --- a/internal/domain/announcements.go +++ b/internal/domain/announcements.go @@ -8,6 +8,6 @@ type Announcement struct { Uuid string Visibility string AnnounceAt time.Time - DiscordChannelID string - DiscordMessageID string + DiscordChannelID *string + DiscordMessageID *string } From 22ce0d18ac241a4c948a3a3adf58def9327d2985 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 14 Feb 2026 20:46:59 -0800 Subject: [PATCH 45/56] add update domain model With the exception of position, will implement poisition after studying it more --- internal/domain/announcements.go | 8 ++++++++ internal/domain/event.go | 9 +++++++++ internal/domain/officer.go | 14 +++++++++++--- internal/domain/tier.go | 13 ++++++++++--- 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/internal/domain/announcements.go b/internal/domain/announcements.go index 8ba3a81..25328c8 100644 --- a/internal/domain/announcements.go +++ b/internal/domain/announcements.go @@ -11,3 +11,11 @@ type Announcement struct { DiscordChannelID *string DiscordMessageID *string } + +type UpdateAnnouncement struct { + Uuid string + Visibility *string + AnnounceAt *time.Time + DiscordChannelID *string + DiscordMessageID *string +} diff --git a/internal/domain/event.go b/internal/domain/event.go index 8946cc0..d859137 100644 --- a/internal/domain/event.go +++ b/internal/domain/event.go @@ -12,3 +12,12 @@ type Event struct { IsAllDay bool Host string } + +type UpdateEvent struct { + Uuid string + Location *string + StartAt *time.Time + EndAt *time.Time + IsAllDay *bool + Host *string +} diff --git a/internal/domain/officer.go b/internal/domain/officer.go index 23c47ca..6c8e7c8 100644 --- a/internal/domain/officer.go +++ b/internal/domain/officer.go @@ -3,7 +3,15 @@ package domain type Officer struct { Uuid string FullName string - Picture string - Github string - Discord string + Picture *string + Github *string + Discord *string +} + +type UpdateOfficer struct { + Uuid string + FullName *string + Picture *string + Github *string + Discord *string } diff --git a/internal/domain/tier.go b/internal/domain/tier.go index fadefeb..104053a 100644 --- a/internal/domain/tier.go +++ b/internal/domain/tier.go @@ -2,7 +2,14 @@ package domain type Tier struct { Tier int - Title string - Tindex int - Team string + Title *string + Tindex *int + Team *string +} + +type UpdateTier struct { + Tier int + Title *string + Tindex *int + Team *string } From 99ad120cbc20c9c579c5913cb8c75672db90a976 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sat, 14 Feb 2026 21:03:18 -0800 Subject: [PATCH 46/56] Fix casting issues in mapper and repository --- internal/mapper/domain_to_dto.go | 16 +++++----- internal/mapper/dto_to_domain.go | 16 +++++----- internal/repository/conv.go | 50 +++++++++++++++++--------------- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/internal/mapper/domain_to_dto.go b/internal/mapper/domain_to_dto.go index ca73175..97e8c46 100644 --- a/internal/mapper/domain_to_dto.go +++ b/internal/mapper/domain_to_dto.go @@ -13,8 +13,8 @@ func ToAnnouncementDTO(a *domain.Announcement) dto_response.Announcement { Uuid: a.Uuid, Visibility: a.Visibility, AnnounceAt: a.AnnounceAt.Unix(), - DiscordChannelID: a.DiscordChannelID, - DiscordMessageID: a.DiscordMessageID, + DiscordChannelID: *a.DiscordChannelID, + DiscordMessageID: *a.DiscordMessageID, } } @@ -33,9 +33,9 @@ func ToOfficerDTO(o domain.Officer) dto_response.Officer { return dto_response.Officer{ Uuid: o.Uuid, FullName: o.FullName, - Picture: o.Picture, - Github: o.Github, - Discord: o.Discord, + Picture: *o.Picture, + Github: *o.Github, + Discord: *o.Discord, } } @@ -50,8 +50,8 @@ func ToPositionDTO(p *domain.Position) dto_response.Position { func ToTierDTO(t *domain.Tier) dto_response.Tier { return dto_response.Tier{ Tier: t.Tier, - Title: t.Title, - Tindex: t.Tindex, - Team: t.Team, + Title: *t.Title, + Tindex: *t.Tindex, + Team: *t.Team, } } diff --git a/internal/mapper/dto_to_domain.go b/internal/mapper/dto_to_domain.go index 35ed1de..bd749e2 100644 --- a/internal/mapper/dto_to_domain.go +++ b/internal/mapper/dto_to_domain.go @@ -12,8 +12,8 @@ func ToAnnouncementDomain(a *dto_request.Announcement) domain.Announcement { Uuid: a.Uuid, Visibility: a.Visibility, AnnounceAt: time.Unix(a.AnnounceAt, 0), - DiscordChannelID: a.DiscordChannelID, - DiscordMessageID: a.DiscordMessageID, + DiscordChannelID: &a.DiscordChannelID, + DiscordMessageID: &a.DiscordMessageID, } } @@ -30,9 +30,9 @@ func ToEventDomain(e *dto_request.Event) domain.Event { func ToOfficerDomain(o *dto_request.Officer) domain.Officer { return domain.Officer{ FullName: o.FullName, - Picture: o.Picture, - Github: o.Github, - Discord: o.Discord, + Picture: &o.Picture, + Github: &o.Github, + Discord: &o.Discord, } } @@ -47,8 +47,8 @@ func ToPositionDomain(p *dto_request.Position) domain.Position { func ToTierDomain(t *dto_request.Tier) domain.Tier { return domain.Tier{ Tier: t.Tier, - Title: t.Title, - Tindex: t.Tindex, - Team: t.Team, + Title: &t.Title, + Tindex: &t.Tindex, + Team: &t.Team, } } diff --git a/internal/repository/conv.go b/internal/repository/conv.go index c594ffc..fad1eb6 100644 --- a/internal/repository/conv.go +++ b/internal/repository/conv.go @@ -49,9 +49,9 @@ func convertDBOfficerToDomain(dbOfficer dbmodels.Officer) domain.Officer { return domain.Officer{ Uuid: dbOfficer.Uuid, FullName: dbOfficer.FullName, - Picture: dbOfficer.Picture.String, - Github: dbOfficer.Github.String, - Discord: dbOfficer.Discord.String, + Picture: &dbOfficer.Picture.String, + Github: &dbOfficer.Github.String, + Discord: &dbOfficer.Discord.String, } } @@ -59,9 +59,9 @@ func convertDomainToCreateDBOfficer(dOfficer domain.Officer) dbmodels.CreateOffi return dbmodels.CreateOfficerParams{ Uuid: dOfficer.Uuid, FullName: dOfficer.FullName, - Picture: sql.NullString{String: dOfficer.Picture, Valid: true}, - Github: sql.NullString{String: dOfficer.Github, Valid: true}, - Discord: sql.NullString{String: dOfficer.Discord, Valid: true}, + Picture: sql.NullString{String: *dOfficer.Picture, Valid: true}, + Github: sql.NullString{String: *dOfficer.Github, Valid: true}, + Discord: sql.NullString{String: *dOfficer.Discord, Valid: true}, } } @@ -69,9 +69,9 @@ func convertDomainToUpdateDBOfficer(dOfficer domain.Officer) dbmodels.UpdateOffi return dbmodels.UpdateOfficerParams{ Uuid: dOfficer.Uuid, FullName: dOfficer.FullName, - Picture: sql.NullString{String: dOfficer.Picture, Valid: true}, - Github: sql.NullString{String: dOfficer.Github, Valid: true}, - Discord: sql.NullString{String: dOfficer.Discord, Valid: true}, + Picture: sql.NullString{String: *dOfficer.Picture, Valid: true}, + Github: sql.NullString{String: *dOfficer.Github, Valid: true}, + Discord: sql.NullString{String: *dOfficer.Discord, Valid: true}, } } @@ -81,8 +81,8 @@ func convertDBAnnouncementToDomain(dbAnnouncement dbmodels.Announcement) domain. Uuid: dbAnnouncement.Uuid, Visibility: dbAnnouncement.Visibility, AnnounceAt: time.Unix(dbAnnouncement.AnnounceAt, 0), - DiscordChannelID: dbAnnouncement.DiscordChannelID.String, - DiscordMessageID: dbAnnouncement.DiscordMessageID.String, + DiscordChannelID: &dbAnnouncement.DiscordChannelID.String, + DiscordMessageID: &dbAnnouncement.DiscordMessageID.String, } } @@ -91,8 +91,8 @@ func convertDomainToCreateDBAnnouncement(dAnnouncement domain.Announcement) dbmo Uuid: dAnnouncement.Uuid, Visibility: dAnnouncement.Visibility, AnnounceAt: dAnnouncement.AnnounceAt.Unix(), - DiscordChannelID: sql.NullString{String: dAnnouncement.DiscordChannelID, Valid: true}, - DiscordMessageID: sql.NullString{String: dAnnouncement.DiscordMessageID, Valid: true}, + DiscordChannelID: sql.NullString{String: *dAnnouncement.DiscordChannelID, Valid: true}, + DiscordMessageID: sql.NullString{String: *dAnnouncement.DiscordMessageID, Valid: true}, } } @@ -101,36 +101,38 @@ func convertDomainToUpdateDBAnnouncement(dAnnouncement domain.Announcement) dbmo Uuid: dAnnouncement.Uuid, Visibility: sql.NullString{String: dAnnouncement.Visibility, Valid: true}, AnnounceAt: sql.NullInt64{Int64: dAnnouncement.AnnounceAt.Unix(), Valid: true}, - DiscordChannelID: sql.NullString{String: dAnnouncement.DiscordChannelID, Valid: true}, - DiscordMessageID: sql.NullString{String: dAnnouncement.DiscordMessageID, Valid: true}, + DiscordChannelID: sql.NullString{String: *dAnnouncement.DiscordChannelID, Valid: true}, + DiscordMessageID: sql.NullString{String: *dAnnouncement.DiscordMessageID, Valid: true}, } } // ---- Tier Converter ---- func convertDBTierToDomain(dbTier dbmodels.Tier) domain.Tier { + // note: &int(exp) / &(int)(exp) is illegal, so it is split into v and then &v + v := int(dbTier.TIndex.Int64) return domain.Tier{ Tier: int(dbTier.Tier), - Title: dbTier.Title.String, - Tindex: int(dbTier.TIndex.Int64), - Team: dbTier.Team.String, + Title: &dbTier.Title.String, + Tindex: &v, + Team: &dbTier.Team.String, } } func convertDomainToCreateDBTier(dTier domain.Tier) dbmodels.CreateTierParams { return dbmodels.CreateTierParams{ Tier: int64(dTier.Tier), - Title: sql.NullString{String: dTier.Title, Valid: true}, - TIndex: sql.NullInt64{Int64: int64(dTier.Tindex), Valid: true}, - Team: sql.NullString{String: dTier.Team, Valid: true}, + Title: sql.NullString{String: *dTier.Title, Valid: true}, + TIndex: sql.NullInt64{Int64: int64(*dTier.Tindex), Valid: true}, + Team: sql.NullString{String: *dTier.Team, Valid: true}, } } func convertDomainToUpdateDBTier(dTier domain.Tier) dbmodels.UpdateTierParams { return dbmodels.UpdateTierParams{ Tier: int64(dTier.Tier), - Title: sql.NullString{String: dTier.Title, Valid: true}, - TIndex: sql.NullInt64{Int64: int64(dTier.Tindex), Valid: true}, - Team: sql.NullString{String: dTier.Team, Valid: true}, + Title: sql.NullString{String: *dTier.Title, Valid: true}, + TIndex: sql.NullInt64{Int64: int64(*dTier.Tindex), Valid: true}, + Team: sql.NullString{String: *dTier.Team, Valid: true}, } } From 19897519aee2752e9a2df5a10e56964f72384df2 Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sun, 15 Feb 2026 01:23:56 -0800 Subject: [PATCH 47/56] fix position models --- internal/api/dbmodels/board.sql.go | 25 ++- internal/api/docs/docs.go | 255 ++++++++--------------------- internal/api/docs/swagger.json | 255 ++++++++--------------------- internal/api/docs/swagger.yaml | 211 ++++++++---------------- internal/domain/position.go | 12 ++ internal/dto/request/position.go | 9 +- internal/dto/response/position.go | 9 +- internal/mapper/domain_to_dto.go | 3 + internal/mapper/dto_to_domain.go | 3 + 9 files changed, 249 insertions(+), 533 deletions(-) diff --git a/internal/api/dbmodels/board.sql.go b/internal/api/dbmodels/board.sql.go index 1ce78a0..217ce3d 100644 --- a/internal/api/dbmodels/board.sql.go +++ b/internal/api/dbmodels/board.sql.go @@ -56,21 +56,34 @@ INSERT INTO position ( oid, semester, - tier + tier, + full_name, + title, + team ) VALUES -(?, ?, ?) +(?, ?, ?, ?, ?, ?) RETURNING oid, semester, tier, full_name, title, team ` type CreatePositionParams struct { - Oid string `json:"oid"` - Semester string `json:"semester"` - Tier int64 `json:"tier"` + Oid string `json:"oid"` + Semester string `json:"semester"` + Tier int64 `json:"tier"` + FullName string `json:"full_name"` + Title sql.NullString `json:"title"` + Team sql.NullString `json:"team"` } func (q *Queries) CreatePosition(ctx context.Context, arg CreatePositionParams) (Position, error) { - row := q.db.QueryRowContext(ctx, createPosition, arg.Oid, arg.Semester, arg.Tier) + row := q.db.QueryRowContext(ctx, createPosition, + arg.Oid, + arg.Semester, + arg.Tier, + arg.FullName, + arg.Title, + arg.Team, + ) var i Position err := row.Scan( &i.Oid, diff --git a/internal/api/docs/docs.go b/internal/api/docs/docs.go index 808210d..5779bea 100644 --- a/internal/api/docs/docs.go +++ b/internal/api/docs/docs.go @@ -35,7 +35,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.CreateAnnouncementParams" + "$ref": "#/definitions/domain.Announcement" } } ], @@ -94,7 +94,7 @@ const docTemplate = `{ "200": { "description": "Announcement details", "schema": { - "$ref": "#/definitions/dbmodels.Announcement" + "$ref": "#/definitions/dto_request.Announcement" } }, "404": { @@ -143,7 +143,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.UpdateAnnouncementParams" + "$ref": "#/definitions/domain.Announcement" } } ], @@ -257,7 +257,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/dbmodels.Officer" + "$ref": "#/definitions/domain.Officer" } } }, @@ -291,7 +291,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.CreateOfficerParams" + "$ref": "#/definitions/domain.Officer" } } ], @@ -350,7 +350,7 @@ const docTemplate = `{ "200": { "description": "Officer details", "schema": { - "$ref": "#/definitions/dbmodels.Officer" + "$ref": "#/definitions/dto_request.Officer" } }, "404": { @@ -399,7 +399,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.UpdateOfficerParams" + "$ref": "#/definitions/domain.Officer" } } ], @@ -513,7 +513,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/dbmodels.Position" + "$ref": "#/definitions/dto_request.Position" } } }, @@ -547,7 +547,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.UpdatePositionParams" + "$ref": "#/definitions/domain.Position" } } ], @@ -609,7 +609,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.CreatePositionParams" + "$ref": "#/definitions/domain.Position" } } ], @@ -660,7 +660,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.DeletePositionParams" + "$ref": "#/definitions/domain.Position" } } ], @@ -730,7 +730,7 @@ const docTemplate = `{ "200": { "description": "Position details", "schema": { - "$ref": "#/definitions/dbmodels.Position" + "$ref": "#/definitions/domain.Position" } }, "404": { @@ -773,7 +773,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/dbmodels.Tier" + "$ref": "#/definitions/dto_request.Tier" } } }, @@ -807,7 +807,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.CreateTierParams" + "$ref": "#/definitions/domain.Tier" } } ], @@ -924,7 +924,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.UpdateTierParams" + "$ref": "#/definitions/domain.Tier" } } ], @@ -1055,7 +1055,7 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/dbmodels.Event" + "$ref": "#/definitions/domain.Event" } } }, @@ -1089,7 +1089,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.CreateEventParams" + "$ref": "#/definitions/domain.Event" } } ], @@ -1148,7 +1148,7 @@ const docTemplate = `{ "200": { "description": "Event details", "schema": { - "$ref": "#/definitions/dbmodels.Event" + "$ref": "#/definitions/dto_request.Event" } }, "404": { @@ -1197,7 +1197,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.UpdateEventParams" + "$ref": "#/definitions/domain.Event" } } ], @@ -1294,329 +1294,208 @@ const docTemplate = `{ } }, "definitions": { - "dbmodels.Announcement": { + "dbmodels.Tier": { "type": "object", "properties": { - "announce_at": { - "type": "integer" - }, - "discord_channel_id": { - "$ref": "#/definitions/sql.NullString" + "t_index": { + "$ref": "#/definitions/sql.NullInt64" }, - "discord_message_id": { + "team": { "$ref": "#/definitions/sql.NullString" }, - "uuid": { - "type": "string" - }, - "visibility": { - "type": "string" - } - } - }, - "dbmodels.CreateAnnouncementParams": { - "type": "object", - "properties": { - "announce_at": { + "tier": { "type": "integer" }, - "discord_channel_id": { - "$ref": "#/definitions/sql.NullString" - }, - "discord_message_id": { + "title": { "$ref": "#/definitions/sql.NullString" - }, - "uuid": { - "type": "string" - }, - "visibility": { - "type": "string" } } }, - "dbmodels.CreateEventParams": { + "domain.Announcement": { "type": "object", "properties": { - "end_at": { - "type": "integer" - }, - "host": { + "announceAt": { "type": "string" }, - "is_all_day": { - "type": "boolean" - }, - "location": { - "type": "string" - }, - "start_at": { - "type": "integer" - }, - "uuid": { + "discordChannelID": { "type": "string" - } - } - }, - "dbmodels.CreateOfficerParams": { - "type": "object", - "properties": { - "discord": { - "$ref": "#/definitions/sql.NullString" }, - "full_name": { + "discordMessageID": { "type": "string" }, - "github": { - "$ref": "#/definitions/sql.NullString" - }, - "picture": { - "$ref": "#/definitions/sql.NullString" - }, "uuid": { "type": "string" - } - } - }, - "dbmodels.CreatePositionParams": { - "type": "object", - "properties": { - "oid": { - "type": "string" }, - "semester": { + "visibility": { "type": "string" - }, - "tier": { - "type": "integer" - } - } - }, - "dbmodels.CreateTierParams": { - "type": "object", - "properties": { - "t_index": { - "$ref": "#/definitions/sql.NullInt64" - }, - "team": { - "$ref": "#/definitions/sql.NullString" - }, - "tier": { - "type": "integer" - }, - "title": { - "$ref": "#/definitions/sql.NullString" } } }, - "dbmodels.DeletePositionParams": { + "domain.Event": { "type": "object", "properties": { - "oid": { + "endAt": { "type": "string" }, - "semester": { - "type": "string" - }, - "tier": { - "type": "integer" - } - } - }, - "dbmodels.Event": { - "type": "object", - "properties": { - "end_at": { - "type": "integer" - }, "host": { "type": "string" }, - "is_all_day": { + "isAllDay": { "type": "boolean" }, "location": { "type": "string" }, - "start_at": { - "type": "integer" + "startAt": { + "type": "string" }, "uuid": { "type": "string" } } }, - "dbmodels.Officer": { + "domain.Officer": { "type": "object", "properties": { "discord": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, - "full_name": { + "fullName": { "type": "string" }, "github": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "picture": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "uuid": { "type": "string" } } }, - "dbmodels.Position": { + "domain.Position": { "type": "object", "properties": { - "full_name": { - "type": "string" - }, "oid": { "type": "string" }, "semester": { "type": "string" }, - "team": { - "$ref": "#/definitions/sql.NullString" - }, "tier": { "type": "integer" - }, - "title": { - "$ref": "#/definitions/sql.NullString" } } }, - "dbmodels.Tier": { + "domain.Tier": { "type": "object", "properties": { - "t_index": { - "$ref": "#/definitions/sql.NullInt64" - }, "team": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "tier": { "type": "integer" }, + "tindex": { + "type": "integer" + }, "title": { - "$ref": "#/definitions/sql.NullString" + "type": "string" } } }, - "dbmodels.UpdateAnnouncementParams": { + "dto_request.Announcement": { "type": "object", "properties": { "announce_at": { - "$ref": "#/definitions/sql.NullInt64" + "type": "integer" }, "discord_channel_id": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "discord_message_id": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "uuid": { "type": "string" }, "visibility": { - "$ref": "#/definitions/sql.NullString" + "type": "string" } } }, - "dbmodels.UpdateEventParams": { + "dto_request.Event": { "type": "object", "properties": { "end_at": { - "$ref": "#/definitions/sql.NullInt64" + "type": "integer" }, "host": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "is_all_day": { - "$ref": "#/definitions/sql.NullBool" + "type": "boolean" }, "location": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "start_at": { - "$ref": "#/definitions/sql.NullInt64" + "type": "integer" }, "uuid": { "type": "string" } } }, - "dbmodels.UpdateOfficerParams": { + "dto_request.Officer": { "type": "object", "properties": { "discord": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "full_name": { "type": "string" }, "github": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "picture": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "uuid": { "type": "string" } } }, - "dbmodels.UpdatePositionParams": { + "dto_request.Position": { "type": "object", "properties": { - "full_name": { - "type": "string" - }, "oid": { "type": "string" }, "semester": { "type": "string" }, - "team": { - "$ref": "#/definitions/sql.NullString" - }, "tier": { "type": "integer" - }, - "title": { - "$ref": "#/definitions/sql.NullString" } } }, - "dbmodels.UpdateTierParams": { + "dto_request.Tier": { "type": "object", "properties": { "t_index": { - "$ref": "#/definitions/sql.NullInt64" + "type": "integer" }, "team": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "tier": { "type": "integer" }, "title": { - "$ref": "#/definitions/sql.NullString" - } - } - }, - "sql.NullBool": { - "type": "object", - "properties": { - "bool": { - "type": "boolean" - }, - "valid": { - "description": "Valid is true if Bool is not NULL", - "type": "boolean" + "type": "string" } } }, diff --git a/internal/api/docs/swagger.json b/internal/api/docs/swagger.json index 08f8668..6647931 100644 --- a/internal/api/docs/swagger.json +++ b/internal/api/docs/swagger.json @@ -24,7 +24,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.CreateAnnouncementParams" + "$ref": "#/definitions/domain.Announcement" } } ], @@ -83,7 +83,7 @@ "200": { "description": "Announcement details", "schema": { - "$ref": "#/definitions/dbmodels.Announcement" + "$ref": "#/definitions/dto_request.Announcement" } }, "404": { @@ -132,7 +132,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.UpdateAnnouncementParams" + "$ref": "#/definitions/domain.Announcement" } } ], @@ -246,7 +246,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/dbmodels.Officer" + "$ref": "#/definitions/domain.Officer" } } }, @@ -280,7 +280,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.CreateOfficerParams" + "$ref": "#/definitions/domain.Officer" } } ], @@ -339,7 +339,7 @@ "200": { "description": "Officer details", "schema": { - "$ref": "#/definitions/dbmodels.Officer" + "$ref": "#/definitions/dto_request.Officer" } }, "404": { @@ -388,7 +388,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.UpdateOfficerParams" + "$ref": "#/definitions/domain.Officer" } } ], @@ -502,7 +502,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/dbmodels.Position" + "$ref": "#/definitions/dto_request.Position" } } }, @@ -536,7 +536,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.UpdatePositionParams" + "$ref": "#/definitions/domain.Position" } } ], @@ -598,7 +598,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.CreatePositionParams" + "$ref": "#/definitions/domain.Position" } } ], @@ -649,7 +649,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.DeletePositionParams" + "$ref": "#/definitions/domain.Position" } } ], @@ -719,7 +719,7 @@ "200": { "description": "Position details", "schema": { - "$ref": "#/definitions/dbmodels.Position" + "$ref": "#/definitions/domain.Position" } }, "404": { @@ -762,7 +762,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/dbmodels.Tier" + "$ref": "#/definitions/dto_request.Tier" } } }, @@ -796,7 +796,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.CreateTierParams" + "$ref": "#/definitions/domain.Tier" } } ], @@ -913,7 +913,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.UpdateTierParams" + "$ref": "#/definitions/domain.Tier" } } ], @@ -1044,7 +1044,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/dbmodels.Event" + "$ref": "#/definitions/domain.Event" } } }, @@ -1078,7 +1078,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.CreateEventParams" + "$ref": "#/definitions/domain.Event" } } ], @@ -1137,7 +1137,7 @@ "200": { "description": "Event details", "schema": { - "$ref": "#/definitions/dbmodels.Event" + "$ref": "#/definitions/dto_request.Event" } }, "404": { @@ -1186,7 +1186,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dbmodels.UpdateEventParams" + "$ref": "#/definitions/domain.Event" } } ], @@ -1283,329 +1283,208 @@ } }, "definitions": { - "dbmodels.Announcement": { + "dbmodels.Tier": { "type": "object", "properties": { - "announce_at": { - "type": "integer" - }, - "discord_channel_id": { - "$ref": "#/definitions/sql.NullString" + "t_index": { + "$ref": "#/definitions/sql.NullInt64" }, - "discord_message_id": { + "team": { "$ref": "#/definitions/sql.NullString" }, - "uuid": { - "type": "string" - }, - "visibility": { - "type": "string" - } - } - }, - "dbmodels.CreateAnnouncementParams": { - "type": "object", - "properties": { - "announce_at": { + "tier": { "type": "integer" }, - "discord_channel_id": { - "$ref": "#/definitions/sql.NullString" - }, - "discord_message_id": { + "title": { "$ref": "#/definitions/sql.NullString" - }, - "uuid": { - "type": "string" - }, - "visibility": { - "type": "string" } } }, - "dbmodels.CreateEventParams": { + "domain.Announcement": { "type": "object", "properties": { - "end_at": { - "type": "integer" - }, - "host": { + "announceAt": { "type": "string" }, - "is_all_day": { - "type": "boolean" - }, - "location": { - "type": "string" - }, - "start_at": { - "type": "integer" - }, - "uuid": { + "discordChannelID": { "type": "string" - } - } - }, - "dbmodels.CreateOfficerParams": { - "type": "object", - "properties": { - "discord": { - "$ref": "#/definitions/sql.NullString" }, - "full_name": { + "discordMessageID": { "type": "string" }, - "github": { - "$ref": "#/definitions/sql.NullString" - }, - "picture": { - "$ref": "#/definitions/sql.NullString" - }, "uuid": { "type": "string" - } - } - }, - "dbmodels.CreatePositionParams": { - "type": "object", - "properties": { - "oid": { - "type": "string" }, - "semester": { + "visibility": { "type": "string" - }, - "tier": { - "type": "integer" - } - } - }, - "dbmodels.CreateTierParams": { - "type": "object", - "properties": { - "t_index": { - "$ref": "#/definitions/sql.NullInt64" - }, - "team": { - "$ref": "#/definitions/sql.NullString" - }, - "tier": { - "type": "integer" - }, - "title": { - "$ref": "#/definitions/sql.NullString" } } }, - "dbmodels.DeletePositionParams": { + "domain.Event": { "type": "object", "properties": { - "oid": { + "endAt": { "type": "string" }, - "semester": { - "type": "string" - }, - "tier": { - "type": "integer" - } - } - }, - "dbmodels.Event": { - "type": "object", - "properties": { - "end_at": { - "type": "integer" - }, "host": { "type": "string" }, - "is_all_day": { + "isAllDay": { "type": "boolean" }, "location": { "type": "string" }, - "start_at": { - "type": "integer" + "startAt": { + "type": "string" }, "uuid": { "type": "string" } } }, - "dbmodels.Officer": { + "domain.Officer": { "type": "object", "properties": { "discord": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, - "full_name": { + "fullName": { "type": "string" }, "github": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "picture": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "uuid": { "type": "string" } } }, - "dbmodels.Position": { + "domain.Position": { "type": "object", "properties": { - "full_name": { - "type": "string" - }, "oid": { "type": "string" }, "semester": { "type": "string" }, - "team": { - "$ref": "#/definitions/sql.NullString" - }, "tier": { "type": "integer" - }, - "title": { - "$ref": "#/definitions/sql.NullString" } } }, - "dbmodels.Tier": { + "domain.Tier": { "type": "object", "properties": { - "t_index": { - "$ref": "#/definitions/sql.NullInt64" - }, "team": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "tier": { "type": "integer" }, + "tindex": { + "type": "integer" + }, "title": { - "$ref": "#/definitions/sql.NullString" + "type": "string" } } }, - "dbmodels.UpdateAnnouncementParams": { + "dto_request.Announcement": { "type": "object", "properties": { "announce_at": { - "$ref": "#/definitions/sql.NullInt64" + "type": "integer" }, "discord_channel_id": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "discord_message_id": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "uuid": { "type": "string" }, "visibility": { - "$ref": "#/definitions/sql.NullString" + "type": "string" } } }, - "dbmodels.UpdateEventParams": { + "dto_request.Event": { "type": "object", "properties": { "end_at": { - "$ref": "#/definitions/sql.NullInt64" + "type": "integer" }, "host": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "is_all_day": { - "$ref": "#/definitions/sql.NullBool" + "type": "boolean" }, "location": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "start_at": { - "$ref": "#/definitions/sql.NullInt64" + "type": "integer" }, "uuid": { "type": "string" } } }, - "dbmodels.UpdateOfficerParams": { + "dto_request.Officer": { "type": "object", "properties": { "discord": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "full_name": { "type": "string" }, "github": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "picture": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "uuid": { "type": "string" } } }, - "dbmodels.UpdatePositionParams": { + "dto_request.Position": { "type": "object", "properties": { - "full_name": { - "type": "string" - }, "oid": { "type": "string" }, "semester": { "type": "string" }, - "team": { - "$ref": "#/definitions/sql.NullString" - }, "tier": { "type": "integer" - }, - "title": { - "$ref": "#/definitions/sql.NullString" } } }, - "dbmodels.UpdateTierParams": { + "dto_request.Tier": { "type": "object", "properties": { "t_index": { - "$ref": "#/definitions/sql.NullInt64" + "type": "integer" }, "team": { - "$ref": "#/definitions/sql.NullString" + "type": "string" }, "tier": { "type": "integer" }, "title": { - "$ref": "#/definitions/sql.NullString" - } - } - }, - "sql.NullBool": { - "type": "object", - "properties": { - "bool": { - "type": "boolean" - }, - "valid": { - "description": "Valid is true if Bool is not NULL", - "type": "boolean" + "type": "string" } } }, diff --git a/internal/api/docs/swagger.yaml b/internal/api/docs/swagger.yaml index c767958..7d788c0 100644 --- a/internal/api/docs/swagger.yaml +++ b/internal/api/docs/swagger.yaml @@ -1,68 +1,5 @@ definitions: - dbmodels.Announcement: - properties: - announce_at: - type: integer - discord_channel_id: - $ref: '#/definitions/sql.NullString' - discord_message_id: - $ref: '#/definitions/sql.NullString' - uuid: - type: string - visibility: - type: string - type: object - dbmodels.CreateAnnouncementParams: - properties: - announce_at: - type: integer - discord_channel_id: - $ref: '#/definitions/sql.NullString' - discord_message_id: - $ref: '#/definitions/sql.NullString' - uuid: - type: string - visibility: - type: string - type: object - dbmodels.CreateEventParams: - properties: - end_at: - type: integer - host: - type: string - is_all_day: - type: boolean - location: - type: string - start_at: - type: integer - uuid: - type: string - type: object - dbmodels.CreateOfficerParams: - properties: - discord: - $ref: '#/definitions/sql.NullString' - full_name: - type: string - github: - $ref: '#/definitions/sql.NullString' - picture: - $ref: '#/definitions/sql.NullString' - uuid: - type: string - type: object - dbmodels.CreatePositionParams: - properties: - oid: - type: string - semester: - type: string - tier: - type: integer - type: object - dbmodels.CreateTierParams: + dbmodels.Tier: properties: t_index: $ref: '#/definitions/sql.NullInt64' @@ -73,143 +10,127 @@ definitions: title: $ref: '#/definitions/sql.NullString' type: object - dbmodels.DeletePositionParams: + domain.Announcement: properties: - oid: + announceAt: type: string - semester: + discordChannelID: + type: string + discordMessageID: + type: string + uuid: + type: string + visibility: type: string - tier: - type: integer type: object - dbmodels.Event: + domain.Event: properties: - end_at: - type: integer + endAt: + type: string host: type: string - is_all_day: + isAllDay: type: boolean location: type: string - start_at: - type: integer + startAt: + type: string uuid: type: string type: object - dbmodels.Officer: + domain.Officer: properties: discord: - $ref: '#/definitions/sql.NullString' - full_name: + type: string + fullName: type: string github: - $ref: '#/definitions/sql.NullString' + type: string picture: - $ref: '#/definitions/sql.NullString' + type: string uuid: type: string type: object - dbmodels.Position: + domain.Position: properties: - full_name: - type: string oid: type: string semester: type: string - team: - $ref: '#/definitions/sql.NullString' tier: type: integer - title: - $ref: '#/definitions/sql.NullString' type: object - dbmodels.Tier: + domain.Tier: properties: - t_index: - $ref: '#/definitions/sql.NullInt64' team: - $ref: '#/definitions/sql.NullString' + type: string tier: type: integer + tindex: + type: integer title: - $ref: '#/definitions/sql.NullString' + type: string type: object - dbmodels.UpdateAnnouncementParams: + dto_request.Announcement: properties: announce_at: - $ref: '#/definitions/sql.NullInt64' + type: integer discord_channel_id: - $ref: '#/definitions/sql.NullString' + type: string discord_message_id: - $ref: '#/definitions/sql.NullString' + type: string uuid: type: string visibility: - $ref: '#/definitions/sql.NullString' + type: string type: object - dbmodels.UpdateEventParams: + dto_request.Event: properties: end_at: - $ref: '#/definitions/sql.NullInt64' + type: integer host: - $ref: '#/definitions/sql.NullString' + type: string is_all_day: - $ref: '#/definitions/sql.NullBool' + type: boolean location: - $ref: '#/definitions/sql.NullString' + type: string start_at: - $ref: '#/definitions/sql.NullInt64' + type: integer uuid: type: string type: object - dbmodels.UpdateOfficerParams: + dto_request.Officer: properties: discord: - $ref: '#/definitions/sql.NullString' + type: string full_name: type: string github: - $ref: '#/definitions/sql.NullString' + type: string picture: - $ref: '#/definitions/sql.NullString' + type: string uuid: type: string type: object - dbmodels.UpdatePositionParams: + dto_request.Position: properties: - full_name: - type: string oid: type: string semester: type: string - team: - $ref: '#/definitions/sql.NullString' tier: type: integer - title: - $ref: '#/definitions/sql.NullString' type: object - dbmodels.UpdateTierParams: + dto_request.Tier: properties: t_index: - $ref: '#/definitions/sql.NullInt64' + type: integer team: - $ref: '#/definitions/sql.NullString' + type: string tier: type: integer title: - $ref: '#/definitions/sql.NullString' - type: object - sql.NullBool: - properties: - bool: - type: boolean - valid: - description: Valid is true if Bool is not NULL - type: boolean + type: string type: object sql.NullInt64: properties: @@ -242,7 +163,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/dbmodels.CreateAnnouncementParams' + $ref: '#/definitions/domain.Announcement' produces: - application/json responses: @@ -317,7 +238,7 @@ paths: "200": description: Announcement details schema: - $ref: '#/definitions/dbmodels.Announcement' + $ref: '#/definitions/dto_request.Announcement' "404": description: Not Found schema: @@ -348,7 +269,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/dbmodels.UpdateAnnouncementParams' + $ref: '#/definitions/domain.Announcement' produces: - application/json responses: @@ -391,7 +312,7 @@ paths: description: List of officers schema: items: - $ref: '#/definitions/dbmodels.Officer' + $ref: '#/definitions/domain.Officer' type: array "500": description: Internal Server Error @@ -412,7 +333,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/dbmodels.CreateOfficerParams' + $ref: '#/definitions/domain.Officer' produces: - application/json responses: @@ -487,7 +408,7 @@ paths: "200": description: Officer details schema: - $ref: '#/definitions/dbmodels.Officer' + $ref: '#/definitions/dto_request.Officer' "404": description: Not Found schema: @@ -518,7 +439,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/dbmodels.UpdateOfficerParams' + $ref: '#/definitions/domain.Officer' produces: - application/json responses: @@ -561,7 +482,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/dbmodels.DeletePositionParams' + $ref: '#/definitions/domain.Position' produces: - application/json responses: @@ -603,7 +524,7 @@ paths: description: List of positions schema: items: - $ref: '#/definitions/dbmodels.Position' + $ref: '#/definitions/dto_request.Position' type: array "500": description: Internal Server Error @@ -624,7 +545,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/dbmodels.CreatePositionParams' + $ref: '#/definitions/domain.Position' produces: - application/json responses: @@ -658,7 +579,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/dbmodels.UpdatePositionParams' + $ref: '#/definitions/domain.Position' produces: - application/json responses: @@ -706,7 +627,7 @@ paths: "200": description: Position details schema: - $ref: '#/definitions/dbmodels.Position' + $ref: '#/definitions/domain.Position' "404": description: Not Found schema: @@ -734,7 +655,7 @@ paths: description: List of tiers schema: items: - $ref: '#/definitions/dbmodels.Tier' + $ref: '#/definitions/dto_request.Tier' type: array "500": description: Internal Server Error @@ -755,7 +676,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/dbmodels.CreateTierParams' + $ref: '#/definitions/domain.Tier' produces: - application/json responses: @@ -873,7 +794,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/dbmodels.UpdateTierParams' + $ref: '#/definitions/domain.Tier' produces: - application/json responses: @@ -921,7 +842,7 @@ paths: description: List of events schema: items: - $ref: '#/definitions/dbmodels.Event' + $ref: '#/definitions/domain.Event' type: array "500": description: Internal Server Error @@ -942,7 +863,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/dbmodels.CreateEventParams' + $ref: '#/definitions/domain.Event' produces: - application/json responses: @@ -1017,7 +938,7 @@ paths: "200": description: Event details schema: - $ref: '#/definitions/dbmodels.Event' + $ref: '#/definitions/dto_request.Event' "404": description: Not Found schema: @@ -1048,7 +969,7 @@ paths: name: body required: true schema: - $ref: '#/definitions/dbmodels.UpdateEventParams' + $ref: '#/definitions/domain.Event' produces: - application/json responses: diff --git a/internal/domain/position.go b/internal/domain/position.go index 9c0978a..6b07cb3 100644 --- a/internal/domain/position.go +++ b/internal/domain/position.go @@ -4,4 +4,16 @@ type Position struct { Oid string Semester string Tier int + FullName string + Title *string + Team *string +} + +type UpdatePosition struct { + Oid string + Semester string + Tier int + FullName string + Title *string + Team *string } diff --git a/internal/dto/request/position.go b/internal/dto/request/position.go index b390cd0..f5c5f81 100644 --- a/internal/dto/request/position.go +++ b/internal/dto/request/position.go @@ -1,7 +1,10 @@ package dto_request type Position struct { - Oid string `json:"oid"` - Semester string `json:"semester"` - Tier int `json:"tier"` + Oid string `json:"oid"` + Semester string `json:"semester"` + Tier int `json:"tier"` + FullName string `json:"tier"` + Title *string `json:"title"` + Team *string `json:"team"` } diff --git a/internal/dto/response/position.go b/internal/dto/response/position.go index 8667fdd..5d061ff 100644 --- a/internal/dto/response/position.go +++ b/internal/dto/response/position.go @@ -1,7 +1,10 @@ package dto_response type Position struct { - Oid string `json:"oid"` - Semester string `json:"semester"` - Tier int `json:"tier"` + Oid string `json:"oid"` + Semester string `json:"semester"` + Tier int `json:"tier"` + FullName string `json:"tier"` + Title *string `json:"title"` + Team *string `json:"team"` } diff --git a/internal/mapper/domain_to_dto.go b/internal/mapper/domain_to_dto.go index 97e8c46..87ed2ee 100644 --- a/internal/mapper/domain_to_dto.go +++ b/internal/mapper/domain_to_dto.go @@ -44,6 +44,9 @@ func ToPositionDTO(p *domain.Position) dto_response.Position { Oid: p.Oid, Semester: p.Semester, Tier: p.Tier, + FullName: p.FullName, + Title: p.Title, + Team: p.Team, } } diff --git a/internal/mapper/dto_to_domain.go b/internal/mapper/dto_to_domain.go index bd749e2..ed15446 100644 --- a/internal/mapper/dto_to_domain.go +++ b/internal/mapper/dto_to_domain.go @@ -41,6 +41,9 @@ func ToPositionDomain(p *dto_request.Position) domain.Position { Oid: p.Oid, Semester: p.Semester, Tier: p.Tier, + FullName: p.FullName, + Title: p.Title, + Team: p.Team, } } From 8972cbc225fadfe8f93c556ad33700a3bb3acffa Mon Sep 17 00:00:00 2001 From: GabllaGit Date: Sun, 15 Feb 2026 02:11:23 -0800 Subject: [PATCH 48/56] attempt at conditional sql value validity --- internal/api/services/announcement.go | 4 +- internal/api/services/event.go | 4 +- internal/api/services/interfaces.go | 4 +- internal/api/services/officer.go | 4 +- internal/api/services/position.go | 4 +- internal/api/services/tier.go | 4 +- internal/repository/announcements.go | 4 +- internal/repository/conv.go | 140 ++++++++++++++++++++------ internal/repository/event.go | 4 +- internal/repository/interfaces.go | 4 +- internal/repository/officer.go | 4 +- internal/repository/position.go | 4 +- internal/repository/tier.go | 4 +- 13 files changed, 135 insertions(+), 53 deletions(-) diff --git a/internal/api/services/announcement.go b/internal/api/services/announcement.go index f070f15..65c4f25 100644 --- a/internal/api/services/announcement.go +++ b/internal/api/services/announcement.go @@ -10,7 +10,7 @@ import ( ) type AnnouncementServicer interface { - Service[domain.Announcement, string] + Service[domain.Announcement, string, domain.UpdateAnnouncement] } type AnnouncementService struct { @@ -67,7 +67,7 @@ func (s *AnnouncementService) List(ctx context.Context, } func (s *AnnouncementService) Update(ctx context.Context, uuid string, - params domain.Announcement, + params domain.UpdateAnnouncement, ) error { err := s.announcementRepository.Update(ctx, params) if err != nil { diff --git a/internal/api/services/event.go b/internal/api/services/event.go index a2ec260..689a9df 100644 --- a/internal/api/services/event.go +++ b/internal/api/services/event.go @@ -10,7 +10,7 @@ import ( ) type EventsServicer interface { - Service[domain.Event, string] + Service[domain.Event, string, domain.UpdateEvent] } type EventsService struct { @@ -84,7 +84,7 @@ func (s *EventsService) List(ctx context.Context, filters ...any) ([]domain.Even return result, nil } -func (s *EventsService) Update(ctx context.Context, uuid string, params domain.Event) error { +func (s *EventsService) Update(ctx context.Context, uuid string, params domain.UpdateEvent) error { params.Uuid = uuid if err := s.eventRepo.Update(ctx, params); err != nil { return err diff --git a/internal/api/services/interfaces.go b/internal/api/services/interfaces.go index e72ed53..c3eb1d3 100644 --- a/internal/api/services/interfaces.go +++ b/internal/api/services/interfaces.go @@ -4,10 +4,10 @@ import ( "context" ) -type Service[T any, ID any] interface { +type Service[T any, ID any, Update any] interface { Get(ctx context.Context, id ID) (T, error) List(ctx context.Context, filters ...any) ([]T, error) Create(ctx context.Context, params T) error - Update(ctx context.Context, id ID, params T) error + Update(ctx context.Context, id ID, params Update) error Delete(ctx context.Context, id ID) error } diff --git a/internal/api/services/officer.go b/internal/api/services/officer.go index 242fd01..3d01098 100644 --- a/internal/api/services/officer.go +++ b/internal/api/services/officer.go @@ -8,7 +8,7 @@ import ( ) type OfficerServicer interface { - Service[domain.Officer, string] + Service[domain.Officer, string, domain.UpdateOfficer] } type OfficerService struct { @@ -66,7 +66,7 @@ func (s *OfficerService) Create(ctx context.Context, params domain.Officer) erro return nil } -func (s *OfficerService) Update(ctx context.Context, uuid string, params domain.Officer) error { +func (s *OfficerService) Update(ctx context.Context, uuid string, params domain.UpdateOfficer) error { params.Uuid = uuid err := s.officerRepo.Update(ctx, params) if err != nil { diff --git a/internal/api/services/position.go b/internal/api/services/position.go index 9dd6f3a..c82fba9 100644 --- a/internal/api/services/position.go +++ b/internal/api/services/position.go @@ -9,7 +9,7 @@ import ( ) type PositionServicer interface { - Service[domain.Position, string] + Service[domain.Position, string, domain.UpdatePosition] DeletePosition(ctx context.Context, arg domain.Position) error } @@ -62,7 +62,7 @@ func (s *PositionService) Create(ctx context.Context, params domain.Position) er return nil } -func (s *PositionService) Update(ctx context.Context, uuid string, params domain.Position) error { +func (s *PositionService) Update(ctx context.Context, uuid string, params domain.UpdatePosition) error { err := s.positionRepo.Update(ctx, params) if err != nil { return err diff --git a/internal/api/services/tier.go b/internal/api/services/tier.go index 904b3bb..192848a 100644 --- a/internal/api/services/tier.go +++ b/internal/api/services/tier.go @@ -8,7 +8,7 @@ import ( ) type TierServicer interface { - Service[domain.Tier, int64] + Service[domain.Tier, int64, domain.UpdateTier] } type TierService struct { @@ -55,7 +55,7 @@ func (s *TierService) Create(ctx context.Context, params domain.Tier) error { return nil } -func (s *TierService) Update(ctx context.Context, tierName int64, params domain.Tier) error { +func (s *TierService) Update(ctx context.Context, tierName int64, params domain.UpdateTier) error { params.Tier = int(tierName) err := s.tierRepo.Update(ctx, params) if err != nil { diff --git a/internal/repository/announcements.go b/internal/repository/announcements.go index 61e17e8..4ba4d51 100644 --- a/internal/repository/announcements.go +++ b/internal/repository/announcements.go @@ -8,7 +8,7 @@ import ( ) type AnnouncementRepository interface { - Repository[domain.Announcement, string] + Repository[domain.Announcement, string, domain.UpdateAnnouncement] } type announcementRepository struct { @@ -57,7 +57,7 @@ func (r *announcementRepository) Create(ctx context.Context, args domain.Announc return nil } -func (r *announcementRepository) Update(ctx context.Context, args domain.Announcement) error { +func (r *announcementRepository) Update(ctx context.Context, args domain.UpdateAnnouncement) error { err := r.db.UpdateAnnouncement(ctx, convertDomainToUpdateDBAnnouncement(args)) if err != nil { return err diff --git a/internal/repository/conv.go b/internal/repository/conv.go index fad1eb6..a616dd3 100644 --- a/internal/repository/conv.go +++ b/internal/repository/conv.go @@ -33,14 +33,20 @@ func convertDomainToCreateDBEvent(dEvent domain.Event) dbmodels.CreateEventParam } } -func convertDomainToUpdateDBEvent(dEvent domain.Event) dbmodels.UpdateEventParams { +func convertDomainToUpdateDBEvent(dEvent domain.UpdateEvent) dbmodels.UpdateEventParams { + // -- sql null values -- + start := dEvent.StartAt.Unix() + end := dEvent.EndAt.Unix() + allday := dEvent.IsAllDay + host := dEvent.Host + return dbmodels.UpdateEventParams{ Uuid: dEvent.Uuid, - Location: sql.NullString{String: dEvent.Location, Valid: true}, - StartAt: sql.NullInt64{Int64: dEvent.StartAt.Unix(), Valid: true}, - EndAt: sql.NullInt64{Int64: dEvent.EndAt.Unix(), Valid: true}, - IsAllDay: sql.NullBool{Bool: dEvent.IsAllDay, Valid: true}, - Host: sql.NullString{String: dEvent.Host, Valid: true}, + Location: sql.NullString{String: *dEvent.Location, Valid: validString(*&dEvent.Location)}, + StartAt: sql.NullInt64{Int64: start, Valid: validInt64(&start)}, + EndAt: sql.NullInt64{Int64: end, Valid: validInt64(&end)}, + IsAllDay: sql.NullBool{Bool: *allday, Valid: validBool(allday)}, + Host: sql.NullString{String: *host, Valid: validString(host)}, } } @@ -56,22 +62,32 @@ func convertDBOfficerToDomain(dbOfficer dbmodels.Officer) domain.Officer { } func convertDomainToCreateDBOfficer(dOfficer domain.Officer) dbmodels.CreateOfficerParams { + // -- sql null values -- + pic := dOfficer.Picture + github := dOfficer.Github + discord := dOfficer.Discord + return dbmodels.CreateOfficerParams{ Uuid: dOfficer.Uuid, FullName: dOfficer.FullName, - Picture: sql.NullString{String: *dOfficer.Picture, Valid: true}, - Github: sql.NullString{String: *dOfficer.Github, Valid: true}, - Discord: sql.NullString{String: *dOfficer.Discord, Valid: true}, + Picture: sql.NullString{String: *pic, Valid: validString(pic)}, + Github: sql.NullString{String: *github, Valid: validString(pic)}, + Discord: sql.NullString{String: *discord, Valid: validString(pic)}, } } -func convertDomainToUpdateDBOfficer(dOfficer domain.Officer) dbmodels.UpdateOfficerParams { +func convertDomainToUpdateDBOfficer(dOfficer domain.UpdateOfficer) dbmodels.UpdateOfficerParams { + // -- sql null values -- + pic := dOfficer.Picture + github := dOfficer.Github + discord := dOfficer.Discord + return dbmodels.UpdateOfficerParams{ Uuid: dOfficer.Uuid, - FullName: dOfficer.FullName, - Picture: sql.NullString{String: *dOfficer.Picture, Valid: true}, - Github: sql.NullString{String: *dOfficer.Github, Valid: true}, - Discord: sql.NullString{String: *dOfficer.Discord, Valid: true}, + FullName: *dOfficer.FullName, + Picture: sql.NullString{String: *pic, Valid: validString(pic)}, + Github: sql.NullString{String: *github, Valid: validString(github)}, + Discord: sql.NullString{String: *discord, Valid: validString(discord)}, } } @@ -87,22 +103,32 @@ func convertDBAnnouncementToDomain(dbAnnouncement dbmodels.Announcement) domain. } func convertDomainToCreateDBAnnouncement(dAnnouncement domain.Announcement) dbmodels.CreateAnnouncementParams { + // -- sql null values -- + chanID := dAnnouncement.DiscordChannelID + msgID := dAnnouncement.DiscordMessageID + return dbmodels.CreateAnnouncementParams{ Uuid: dAnnouncement.Uuid, Visibility: dAnnouncement.Visibility, AnnounceAt: dAnnouncement.AnnounceAt.Unix(), - DiscordChannelID: sql.NullString{String: *dAnnouncement.DiscordChannelID, Valid: true}, - DiscordMessageID: sql.NullString{String: *dAnnouncement.DiscordMessageID, Valid: true}, + DiscordChannelID: sql.NullString{String: *chanID, Valid: validString(chanID)}, + DiscordMessageID: sql.NullString{String: *msgID, Valid: validString(msgID)}, } } -func convertDomainToUpdateDBAnnouncement(dAnnouncement domain.Announcement) dbmodels.UpdateAnnouncementParams { +func convertDomainToUpdateDBAnnouncement(dAnnouncement domain.UpdateAnnouncement) dbmodels.UpdateAnnouncementParams { + // -- sql null values -- + vis := dAnnouncement.Visibility + announceAt := dAnnouncement.AnnounceAt.Unix() + chanID := dAnnouncement.DiscordChannelID + msgID := dAnnouncement.DiscordMessageID + return dbmodels.UpdateAnnouncementParams{ Uuid: dAnnouncement.Uuid, - Visibility: sql.NullString{String: dAnnouncement.Visibility, Valid: true}, - AnnounceAt: sql.NullInt64{Int64: dAnnouncement.AnnounceAt.Unix(), Valid: true}, - DiscordChannelID: sql.NullString{String: *dAnnouncement.DiscordChannelID, Valid: true}, - DiscordMessageID: sql.NullString{String: *dAnnouncement.DiscordMessageID, Valid: true}, + Visibility: sql.NullString{String: *vis, Valid: validString(vis)}, + AnnounceAt: sql.NullInt64{Int64: announceAt, Valid: validInt64(&announceAt)}, + DiscordChannelID: sql.NullString{String: *chanID, Valid: validString(chanID)}, + DiscordMessageID: sql.NullString{String: *msgID, Valid: validString(msgID)}, } } @@ -119,20 +145,30 @@ func convertDBTierToDomain(dbTier dbmodels.Tier) domain.Tier { } func convertDomainToCreateDBTier(dTier domain.Tier) dbmodels.CreateTierParams { + // -- sql null values -- + title := dTier.Title + tIdx := int64(*dTier.Tindex) + team := dTier.Team + return dbmodels.CreateTierParams{ Tier: int64(dTier.Tier), - Title: sql.NullString{String: *dTier.Title, Valid: true}, - TIndex: sql.NullInt64{Int64: int64(*dTier.Tindex), Valid: true}, - Team: sql.NullString{String: *dTier.Team, Valid: true}, + Title: sql.NullString{String: *title, Valid: validString(title)}, + TIndex: sql.NullInt64{Int64: tIdx, Valid: validInt64(&tIdx)}, + Team: sql.NullString{String: *team, Valid: validString(team)}, } } -func convertDomainToUpdateDBTier(dTier domain.Tier) dbmodels.UpdateTierParams { +func convertDomainToUpdateDBTier(dTier domain.UpdateTier) dbmodels.UpdateTierParams { + // -- sql null values -- + title := dTier.Title + tIdx := int64(*dTier.Tindex) + team := dTier.Team + return dbmodels.UpdateTierParams{ Tier: int64(dTier.Tier), - Title: sql.NullString{String: *dTier.Title, Valid: true}, - TIndex: sql.NullInt64{Int64: int64(*dTier.Tindex), Valid: true}, - Team: sql.NullString{String: *dTier.Team, Valid: true}, + Title: sql.NullString{String: *title, Valid: validString(title)}, + TIndex: sql.NullInt64{Int64: tIdx, Valid: validInt64(&tIdx)}, + Team: sql.NullString{String: *team, Valid: validString(team)}, } } @@ -142,22 +178,39 @@ func convertDBPositionToDomain(dbPosition dbmodels.Position) domain.Position { Oid: dbPosition.Oid, Semester: dbPosition.Semester, Tier: int(dbPosition.Tier), + FullName: dbPosition.FullName, + Title: &dbPosition.Team.String, + Team: &dbPosition.Team.String, } } func convertDomainToCreateDBPosition(dPosition domain.Position) dbmodels.CreatePositionParams { + // -- sql null types -- + title := dPosition.Title + team := dPosition.Team + return dbmodels.CreatePositionParams{ Oid: dPosition.Oid, Semester: dPosition.Semester, Tier: int64(dPosition.Tier), + FullName: dPosition.FullName, + Title: sql.NullString{String: *title, Valid: validString(title)}, + Team: sql.NullString{String: *team, Valid: validString(team)}, } } -func convertDomainToUpdateDBPosition(dPosition domain.Position) dbmodels.UpdatePositionParams { +func convertDomainToUpdateDBPosition(dPosition domain.UpdatePosition) dbmodels.UpdatePositionParams { + // -- sql null types -- + title := dPosition.Title + team := dPosition.Team + return dbmodels.UpdatePositionParams{ Oid: dPosition.Oid, Semester: dPosition.Semester, Tier: int64(dPosition.Tier), + FullName: dPosition.FullName, + Title: sql.NullString{String: *title, Valid: validString(title)}, + Team: sql.NullString{String: *team, Valid: validString(team)}, } } @@ -168,3 +221,32 @@ func convertDomainToDeleteDBPosition(dPosition domain.Position) dbmodels.DeleteP Tier: int64(dPosition.Tier), } } + +// ---- Functions to check validity ---- +func validInt64(i *int64) bool { + if i == nil { + return false + } + return true +} + +func validString(s *string) bool { + if s == nil { + return false + } + return true +} + +func validBool(b *bool) bool { + if b == nil { + return false + } + return true +} + +func validTime(t *time.Time) bool { + if t == nil { + return false + } + return true +} diff --git a/internal/repository/event.go b/internal/repository/event.go index bfc2ae7..1204d34 100644 --- a/internal/repository/event.go +++ b/internal/repository/event.go @@ -8,7 +8,7 @@ import ( ) type EventRepository interface { - Repository[domain.Event, string] + Repository[domain.Event, string, domain.UpdateEvent] } type eventRepository struct { @@ -57,7 +57,7 @@ func (r *eventRepository) Create(ctx context.Context, args domain.Event) error { return nil } -func (r *eventRepository) Update(ctx context.Context, args domain.Event) error { +func (r *eventRepository) Update(ctx context.Context, args domain.UpdateEvent) error { err := r.db.UpdateEvent(ctx, convertDomainToUpdateDBEvent(args)) if err != nil { return err diff --git a/internal/repository/interfaces.go b/internal/repository/interfaces.go index 34a1bbb..5b3367e 100644 --- a/internal/repository/interfaces.go +++ b/internal/repository/interfaces.go @@ -4,12 +4,12 @@ import ( "context" ) -type Repository[T any, ID any] interface { +type Repository[T any, ID any, Update any] interface { GetAll(ctx context.Context) ([]T, error) GetByID(ctx context.Context, id ID) (T, error) Delete(ctx context.Context, id ID) error Create(ctx context.Context, args T) error - Update(ctx context.Context, args T) error + Update(ctx context.Context, args Update) error } diff --git a/internal/repository/officer.go b/internal/repository/officer.go index 3173619..728f239 100644 --- a/internal/repository/officer.go +++ b/internal/repository/officer.go @@ -8,7 +8,7 @@ import ( ) type OfficerRepository interface { - Repository[domain.Officer, string] + Repository[domain.Officer, string, domain.UpdateOfficer] } type officerRepository struct { @@ -65,7 +65,7 @@ func (r *officerRepository) Create(ctx context.Context, args domain.Officer) err return nil } -func (r *officerRepository) Update(ctx context.Context, args domain.Officer) error { +func (r *officerRepository) Update(ctx context.Context, args domain.UpdateOfficer) error { err := r.db.UpdateOfficer(ctx, convertDomainToUpdateDBOfficer(args)) if err != nil { return err diff --git a/internal/repository/position.go b/internal/repository/position.go index 23cb04e..7a0a6ce 100644 --- a/internal/repository/position.go +++ b/internal/repository/position.go @@ -9,7 +9,7 @@ import ( ) type PositionRepository interface { - Repository[domain.Position, string] + Repository[domain.Position, string, domain.UpdatePosition] DeletePosition(ctx context.Context, args domain.Position) error } @@ -51,7 +51,7 @@ func (r *positionRepository) Create(ctx context.Context, args domain.Position) e return nil } -func (r *positionRepository) Update(ctx context.Context, args domain.Position) error { +func (r *positionRepository) Update(ctx context.Context, args domain.UpdatePosition) error { err := r.db.UpdatePosition(ctx, convertDomainToUpdateDBPosition(args)) if err != nil { return err diff --git a/internal/repository/tier.go b/internal/repository/tier.go index 7cbe801..b0988d9 100644 --- a/internal/repository/tier.go +++ b/internal/repository/tier.go @@ -8,7 +8,7 @@ import ( ) type TierRepository interface { - Repository[domain.Tier, int64] + Repository[domain.Tier, int64, domain.UpdateTier] } type tierRepository struct { @@ -57,7 +57,7 @@ func (r *tierRepository) Create(ctx context.Context, args domain.Tier) error { return nil } -func (r *tierRepository) Update(ctx context.Context, args domain.Tier) error { +func (r *tierRepository) Update(ctx context.Context, args domain.UpdateTier) error { err := r.db.UpdateTier(ctx, convertDomainToUpdateDBTier(args)) if err != nil { return err From 18895b1e042707d4998b8fc8b473e9519cd7c4be Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Wed, 18 Feb 2026 15:26:06 -0800 Subject: [PATCH 49/56] Prettier test --- Building | 0 Makefile | 5 ++++- internal/api/docs/docs.go | 17 ++++++++++++++++- internal/api/docs/swagger.json | 17 ++++++++++++++++- internal/api/docs/swagger.yaml | 12 +++++++++++- 5 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 Building diff --git a/Building b/Building new file mode 100644 index 0000000..e69de29 diff --git a/Makefile b/Makefile index 28b2eab..5d38b09 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,10 @@ fmt: ## Format all go files @go fmt ./... check: ## Run static analysis on all go files - staticcheck ./... + @printf "\033[1;34m==> Building project... \033[0m\n" + @go build ./... 2>&1 || (printf "\033[1;31;1mError building: \033[0m: "; exit 1) + @printf "\033[1;34m==> Running staticcheck... \033[0m\n" + staticcheck -f stylish ./... test: check ## Run all tests go test ./... diff --git a/internal/api/docs/docs.go b/internal/api/docs/docs.go index 5779bea..f545ffa 100644 --- a/internal/api/docs/docs.go +++ b/internal/api/docs/docs.go @@ -1377,14 +1377,23 @@ const docTemplate = `{ "domain.Position": { "type": "object", "properties": { + "fullName": { + "type": "string" + }, "oid": { "type": "string" }, "semester": { "type": "string" }, + "team": { + "type": "string" + }, "tier": { "type": "integer" + }, + "title": { + "type": "string" } } }, @@ -1477,8 +1486,14 @@ const docTemplate = `{ "semester": { "type": "string" }, + "team": { + "type": "string" + }, "tier": { - "type": "integer" + "type": "string" + }, + "title": { + "type": "string" } } }, diff --git a/internal/api/docs/swagger.json b/internal/api/docs/swagger.json index 6647931..6f97316 100644 --- a/internal/api/docs/swagger.json +++ b/internal/api/docs/swagger.json @@ -1366,14 +1366,23 @@ "domain.Position": { "type": "object", "properties": { + "fullName": { + "type": "string" + }, "oid": { "type": "string" }, "semester": { "type": "string" }, + "team": { + "type": "string" + }, "tier": { "type": "integer" + }, + "title": { + "type": "string" } } }, @@ -1466,8 +1475,14 @@ "semester": { "type": "string" }, + "team": { + "type": "string" + }, "tier": { - "type": "integer" + "type": "string" + }, + "title": { + "type": "string" } } }, diff --git a/internal/api/docs/swagger.yaml b/internal/api/docs/swagger.yaml index 7d788c0..d12ef40 100644 --- a/internal/api/docs/swagger.yaml +++ b/internal/api/docs/swagger.yaml @@ -53,12 +53,18 @@ definitions: type: object domain.Position: properties: + fullName: + type: string oid: type: string semester: type: string + team: + type: string tier: type: integer + title: + type: string type: object domain.Tier: properties: @@ -118,8 +124,12 @@ definitions: type: string semester: type: string + team: + type: string tier: - type: integer + type: string + title: + type: string type: object dto_request.Tier: properties: From e129e2db6f62230119b9b836eff0770c47eba57f Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Wed, 18 Feb 2026 15:53:36 -0800 Subject: [PATCH 50/56] add update models for DTO --- internal/dto/request/announcements.go | 18 +++++++++++++----- internal/dto/request/event.go | 21 +++++++++++++++------ internal/dto/request/officer.go | 18 +++++++++++++----- internal/dto/request/position.go | 9 +++++++++ internal/dto/request/tier.go | 15 +++++++++++---- 5 files changed, 61 insertions(+), 20 deletions(-) diff --git a/internal/dto/request/announcements.go b/internal/dto/request/announcements.go index b6197d9..c6e30af 100644 --- a/internal/dto/request/announcements.go +++ b/internal/dto/request/announcements.go @@ -1,9 +1,17 @@ package dto_request type Announcement struct { - Uuid string `json:"uuid"` - Visibility string `json:"visibility"` - AnnounceAt int64 `json:"announce_at"` - DiscordChannelID string `json:"discord_channel_id"` - DiscordMessageID string `json:"discord_message_id"` + Uuid string `json:"uuid"` + Visibility string `json:"visibility"` + AnnounceAt int64 `json:"announce_at"` + DiscordChannelID *string `json:"discord_channel_id"` + DiscordMessageID *string `json:"discord_message_id"` +} + +type UpdateAnnouncement struct { + Uuid string `json:"uuid"` + Visibility *string `json:"visibility"` + AnnounceAt *int64 `json:"announce_at"` + DiscordChannelID *string `json:"discord_channel_id"` + DiscordMessageID *string `json:"discord_message_id"` } diff --git a/internal/dto/request/event.go b/internal/dto/request/event.go index 3497e19..9bf6018 100644 --- a/internal/dto/request/event.go +++ b/internal/dto/request/event.go @@ -1,10 +1,19 @@ package dto_request type Event struct { - Uuid string `json:"uuid"` - Location string `json:"location"` - StartAt int64 `json:"start_at"` - EndAt int64 `json:"end_at"` - IsAllDay bool `json:"is_all_day"` - Host string `json:"host"` + Uuid string `json: "uuid"` + Location string `json: "location"` + StartAt int64 `json: "start_at"` + EndAt int64 `json: "end_at"` + IsAllDay bool `json: "is_all_day"` + Host string `json: "host"` +} + +type UpdateEvent struct { + Uuid string `json: "uuid"` + Location *string `json: "location"` + StartAt *int64 `json: "start_at"` + EndAt *int64 `json: "end_at"` + IsAllDay *bool `json: "is_all_day"` + Host *string `json: :"host"` } diff --git a/internal/dto/request/officer.go b/internal/dto/request/officer.go index b820cdf..be1ca31 100644 --- a/internal/dto/request/officer.go +++ b/internal/dto/request/officer.go @@ -1,9 +1,17 @@ package dto_request type Officer struct { - Uuid string `json:"uuid"` - FullName string `json:"full_name"` - Picture string `json:"picture"` - Github string `json:"github"` - Discord string `json:"discord"` + Uuid string `json:"uuid"` + FullName string `json:"full_name"` + Picture *string `json:"picture"` + Github *string `json:"github"` + Discord *string `json:"discord"` +} + +type UpdateOfficer struct { + Uuid string `json:"uuid"` + FullName *string `json:"full_name"` + Picture *string `json:"picture"` + Github *string `json:"github"` + Discord *string `json:"discord"` } diff --git a/internal/dto/request/position.go b/internal/dto/request/position.go index f5c5f81..cf9015b 100644 --- a/internal/dto/request/position.go +++ b/internal/dto/request/position.go @@ -8,3 +8,12 @@ type Position struct { Title *string `json:"title"` Team *string `json:"team"` } + +type UpdatePosition struct { + Oid string `json:"oid"` + Semester string `json:"semester"` + Tier int `json:"tier"` + FullName string `json:"full_name"` + Title *string `json:"title"` + Team *string `json:"team"` +} diff --git a/internal/dto/request/tier.go b/internal/dto/request/tier.go index 07815db..1f6c62a 100644 --- a/internal/dto/request/tier.go +++ b/internal/dto/request/tier.go @@ -1,8 +1,15 @@ package dto_request type Tier struct { - Tier int `json:"tier"` - Title string `json:"title"` - Tindex int `json:"t_index"` - Team string `json:"team"` + Tier int `json:"tier"` + Title *string `json:"title"` + Tindex *int `json:"t_index"` + Team *string `json:"team"` +} + +type UpdateTier struct { + Tier int `json:"tier"` + Title *string `json:"title"` + Tindex *int `json:"t_index"` + Team *string `json:"team"` } From 11d11519b7731a894dafbce909af25b628a03a4a Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Wed, 18 Feb 2026 23:48:25 -0800 Subject: [PATCH 51/56] Add Update models to Domain and DTO layer --- Makefile | 2 +- internal/api/docs/docs.go | 6 +-- internal/api/docs/swagger.json | 6 +-- internal/api/docs/swagger.yaml | 6 +-- internal/api/handlers/announcement.go | 4 +- internal/api/handlers/event.go | 6 +-- internal/api/handlers/officer.go | 4 +- internal/api/handlers/position.go | 4 +- internal/api/handlers/tier.go | 4 +- internal/mapper/dto_to_domain.go | 68 +++++++++++++++++++++++---- 10 files changed, 81 insertions(+), 29 deletions(-) diff --git a/Makefile b/Makefile index 5d38b09..caeff29 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ fmt: ## Format all go files check: ## Run static analysis on all go files @printf "\033[1;34m==> Building project... \033[0m\n" - @go build ./... 2>&1 || (printf "\033[1;31;1mError building: \033[0m: "; exit 1) + @go build ./... 2>&1 || (printf "\033[1;31;1mError building\033[0m: "; exit 1) @printf "\033[1;34m==> Running staticcheck... \033[0m\n" staticcheck -f stylish ./... diff --git a/internal/api/docs/docs.go b/internal/api/docs/docs.go index f545ffa..936cd4b 100644 --- a/internal/api/docs/docs.go +++ b/internal/api/docs/docs.go @@ -1437,19 +1437,19 @@ const docTemplate = `{ "dto_request.Event": { "type": "object", "properties": { - "end_at": { + "endAt": { "type": "integer" }, "host": { "type": "string" }, - "is_all_day": { + "isAllDay": { "type": "boolean" }, "location": { "type": "string" }, - "start_at": { + "startAt": { "type": "integer" }, "uuid": { diff --git a/internal/api/docs/swagger.json b/internal/api/docs/swagger.json index 6f97316..2f2dff6 100644 --- a/internal/api/docs/swagger.json +++ b/internal/api/docs/swagger.json @@ -1426,19 +1426,19 @@ "dto_request.Event": { "type": "object", "properties": { - "end_at": { + "endAt": { "type": "integer" }, "host": { "type": "string" }, - "is_all_day": { + "isAllDay": { "type": "boolean" }, "location": { "type": "string" }, - "start_at": { + "startAt": { "type": "integer" }, "uuid": { diff --git a/internal/api/docs/swagger.yaml b/internal/api/docs/swagger.yaml index d12ef40..53f6a3e 100644 --- a/internal/api/docs/swagger.yaml +++ b/internal/api/docs/swagger.yaml @@ -92,15 +92,15 @@ definitions: type: object dto_request.Event: properties: - end_at: + endAt: type: integer host: type: string - is_all_day: + isAllDay: type: boolean location: type: string - start_at: + startAt: type: integer uuid: type: string diff --git a/internal/api/handlers/announcement.go b/internal/api/handlers/announcement.go index 416c6f2..d31b2fa 100644 --- a/internal/api/handlers/announcement.go +++ b/internal/api/handlers/announcement.go @@ -120,7 +120,7 @@ func (h *AnnouncementHandler) CreateAnnouncement(c *gin.Context) { // @Router /v1/announcements/{id} [put] func (h *AnnouncementHandler) UpdateAnnouncement(c *gin.Context) { ctx := c.Request.Context() - var params dto_request.Announcement + var params dto_request.UpdateAnnouncement id := c.Param("id") if err := c.ShouldBindJSON(¶ms); err != nil { @@ -130,7 +130,7 @@ func (h *AnnouncementHandler) UpdateAnnouncement(c *gin.Context) { return } - if err := h.announcementService.Update(ctx, id, mapper.ToAnnouncementDomain(¶ms)); err != nil { + if err := h.announcementService.Update(ctx, id, mapper.ToUpdateAnnouncementDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to update announcement", }) diff --git a/internal/api/handlers/event.go b/internal/api/handlers/event.go index dc0bf07..53ecc2c 100644 --- a/internal/api/handlers/event.go +++ b/internal/api/handlers/event.go @@ -145,7 +145,7 @@ func (h *EventsHandler) GetEvents(c *gin.Context) { // @Router /v1/events/{id} [put] func (h *EventsHandler) UpdateEvent(c *gin.Context) { ctx := c.Request.Context() - var params dto_request.Event + var params dto_request.UpdateEvent id := c.Param("id") fmt.Println("UPDATE:", id) @@ -156,7 +156,7 @@ func (h *EventsHandler) UpdateEvent(c *gin.Context) { return } - if err := h.eventsService.Update(ctx, id, mapper.ToEventDomain(¶ms)); err != nil { + if err := h.eventsService.Update(ctx, id, mapper.ToUpdateEventDomain(¶ms)); err != nil { error := fmt.Sprint("Failed to update event: ", err, " | ", ctx, " | ", id, " | ", params) c.JSON(http.StatusInternalServerError, gin.H{ "error": error, @@ -166,7 +166,7 @@ func (h *EventsHandler) UpdateEvent(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "message": "Event updated successfully", - "uuid": mapper.ToEventDomain(¶ms).Uuid, + "uuid": mapper.ToUpdateEventDomain(¶ms).Uuid, }) } diff --git a/internal/api/handlers/officer.go b/internal/api/handlers/officer.go index 0899644..9752426 100644 --- a/internal/api/handlers/officer.go +++ b/internal/api/handlers/officer.go @@ -135,7 +135,7 @@ func (h *OfficerHandler) CreateOfficer(c *gin.Context) { // @Router /v1/board/officers/{id} [put] func (h *OfficerHandler) UpdateOfficer(c *gin.Context) { ctx := c.Request.Context() - var params dto_request.Officer + var params dto_request.UpdateOfficer id := c.Param("id") if err := c.ShouldBindJSON(¶ms); err != nil { @@ -145,7 +145,7 @@ func (h *OfficerHandler) UpdateOfficer(c *gin.Context) { return } - if err := h.officerService.Update(ctx, id, mapper.ToOfficerDomain(¶ms)); err != nil { + if err := h.officerService.Update(ctx, id, mapper.ToUpdateOfficerDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to update officer. " + err.Error(), }) diff --git a/internal/api/handlers/position.go b/internal/api/handlers/position.go index 35bb134..78a3e27 100644 --- a/internal/api/handlers/position.go +++ b/internal/api/handlers/position.go @@ -129,7 +129,7 @@ func (h *PositionHandler) CreatePosition(c *gin.Context) { // @Router /v1/board/positions [put] func (h *PositionHandler) UpdatePosition(c *gin.Context) { ctx := c.Request.Context() - var params dto_request.Position + var params dto_request.UpdatePosition id := c.Param("id") if err := c.ShouldBindJSON(¶ms); err != nil { @@ -139,7 +139,7 @@ func (h *PositionHandler) UpdatePosition(c *gin.Context) { return } - if err := h.positionService.Update(ctx, id, mapper.ToPositionDomain(¶ms)); err != nil { + if err := h.positionService.Update(ctx, id, mapper.ToUpdatePositionDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to update position. " + err.Error(), }) diff --git a/internal/api/handlers/tier.go b/internal/api/handlers/tier.go index 85da24f..b4802b3 100644 --- a/internal/api/handlers/tier.go +++ b/internal/api/handlers/tier.go @@ -136,7 +136,7 @@ func (h *TierHandler) CreateTier(c *gin.Context) { // @Router /v1/board/tiers/{id} [put] func (h *TierHandler) UpdateTier(c *gin.Context) { ctx := c.Request.Context() - var params dto_request.Tier + var params dto_request.UpdateTier id, err := strconv.Atoi(c.Param("id")) if err != nil { c.JSON(http.StatusBadRequest, gin.H{ @@ -154,7 +154,7 @@ func (h *TierHandler) UpdateTier(c *gin.Context) { params.Tier = id - if err := h.tierService.Update(ctx, int64(id), mapper.ToTierDomain(¶ms)); err != nil { + if err := h.tierService.Update(ctx, int64(id), mapper.ToUpdateTierDomain(¶ms)); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "Failed to update tier. " + err.Error(), }) diff --git a/internal/mapper/dto_to_domain.go b/internal/mapper/dto_to_domain.go index ed15446..6d4b081 100644 --- a/internal/mapper/dto_to_domain.go +++ b/internal/mapper/dto_to_domain.go @@ -12,8 +12,19 @@ func ToAnnouncementDomain(a *dto_request.Announcement) domain.Announcement { Uuid: a.Uuid, Visibility: a.Visibility, AnnounceAt: time.Unix(a.AnnounceAt, 0), - DiscordChannelID: &a.DiscordChannelID, - DiscordMessageID: &a.DiscordMessageID, + DiscordChannelID: a.DiscordChannelID, + DiscordMessageID: a.DiscordMessageID, + } +} + +func ToUpdateAnnouncementDomain(a *dto_request.UpdateAnnouncement) domain.UpdateAnnouncement { + announce_at := time.Unix(*a.AnnounceAt, 0) + return domain.UpdateAnnouncement{ + Uuid: a.Uuid, + Visibility: a.Visibility, + AnnounceAt: &announce_at, + DiscordChannelID: a.DiscordChannelID, + DiscordMessageID: a.DiscordMessageID, } } @@ -27,12 +38,33 @@ func ToEventDomain(e *dto_request.Event) domain.Event { } } +func ToUpdateEventDomain(e *dto_request.UpdateEvent) domain.UpdateEvent { + start_at := time.Unix(*e.StartAt, 0) + end_at := time.Unix(*e.EndAt, 0) + return domain.UpdateEvent{ + Location: e.Location, + StartAt: &start_at, + EndAt: &end_at, + IsAllDay: e.IsAllDay, + Host: e.Host, + } +} + func ToOfficerDomain(o *dto_request.Officer) domain.Officer { return domain.Officer{ FullName: o.FullName, - Picture: &o.Picture, - Github: &o.Github, - Discord: &o.Discord, + Picture: o.Picture, + Github: o.Github, + Discord: o.Discord, + } +} + +func ToUpdateOfficerDomain(o *dto_request.UpdateOfficer) domain.UpdateOfficer { + return domain.UpdateOfficer{ + FullName: o.FullName, + Picture: o.Picture, + Github: o.Github, + Discord: o.Discord, } } @@ -47,11 +79,31 @@ func ToPositionDomain(p *dto_request.Position) domain.Position { } } +func ToUpdatePositionDomain(p *dto_request.UpdatePosition) domain.UpdatePosition { + return domain.UpdatePosition{ + Oid: p.Oid, + Semester: p.Semester, + Tier: p.Tier, + FullName: p.FullName, + Title: p.Title, + Team: p.Team, + } +} + func ToTierDomain(t *dto_request.Tier) domain.Tier { return domain.Tier{ Tier: t.Tier, - Title: &t.Title, - Tindex: &t.Tindex, - Team: &t.Team, + Title: t.Title, + Tindex: t.Tindex, + Team: t.Team, + } +} + +func ToUpdateTierDomain(t *dto_request.UpdateTier) domain.UpdateTier { + return domain.UpdateTier{ + Tier: t.Tier, + Title: t.Title, + Tindex: t.Tindex, + Team: t.Team, } } From c8ca007adc0164f7ed22952773e518d5fdbd30cf Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Wed, 18 Feb 2026 23:51:48 -0800 Subject: [PATCH 52/56] fix lint issues --- internal/repository/conv.go | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/internal/repository/conv.go b/internal/repository/conv.go index a616dd3..46b954a 100644 --- a/internal/repository/conv.go +++ b/internal/repository/conv.go @@ -42,7 +42,7 @@ func convertDomainToUpdateDBEvent(dEvent domain.UpdateEvent) dbmodels.UpdateEven return dbmodels.UpdateEventParams{ Uuid: dEvent.Uuid, - Location: sql.NullString{String: *dEvent.Location, Valid: validString(*&dEvent.Location)}, + Location: sql.NullString{String: *dEvent.Location, Valid: validString(dEvent.Location)}, StartAt: sql.NullInt64{Int64: start, Valid: validInt64(&start)}, EndAt: sql.NullInt64{Int64: end, Valid: validInt64(&end)}, IsAllDay: sql.NullBool{Bool: *allday, Valid: validBool(allday)}, @@ -224,29 +224,13 @@ func convertDomainToDeleteDBPosition(dPosition domain.Position) dbmodels.DeleteP // ---- Functions to check validity ---- func validInt64(i *int64) bool { - if i == nil { - return false - } - return true + return i != nil } func validString(s *string) bool { - if s == nil { - return false - } - return true + return s != nil } func validBool(b *bool) bool { - if b == nil { - return false - } - return true -} - -func validTime(t *time.Time) bool { - if t == nil { - return false - } - return true + return b != nil } From 6c97cf4076c9522aff48a4459ba08ac2c7235c8a Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Wed, 18 Feb 2026 23:57:38 -0800 Subject: [PATCH 53/56] make test prettier --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index caeff29..30e9ecc 100644 --- a/Makefile +++ b/Makefile @@ -47,12 +47,13 @@ fmt: ## Format all go files @go fmt ./... check: ## Run static analysis on all go files - @printf "\033[1;34m==> Building project... \033[0m\n" + @printf "[\t\033[1;34mBuilding project\033[0m\t]\n" @go build ./... 2>&1 || (printf "\033[1;31;1mError building\033[0m: "; exit 1) - @printf "\033[1;34m==> Running staticcheck... \033[0m\n" + @printf "[\t\033[1;34mRunning staticcheck\033[0m\t]\n" staticcheck -f stylish ./... test: check ## Run all tests + @printf "[\t\033[1;34mRunning go tests\033[0m\t]\n" go test ./... check-sql: ## Lint all sql files From cd2c4d8b065f770eb9d2c287ff45b69e2aee9486 Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Mon, 23 Feb 2026 18:46:20 -0800 Subject: [PATCH 54/56] change announcements cli to use dto request --- internal/api/docs/docs.go | 11 +++++++---- internal/api/docs/swagger.json | 11 +++++++---- internal/api/docs/swagger.yaml | 10 ++++++---- internal/api/handlers/announcement.go | 3 +++ internal/api/services/announcement.go | 2 ++ internal/cli/announcements/post.go | 12 +++++------- internal/cli/announcements/put.go | 16 ++++++++-------- internal/dto/request/event.go | 24 ++++++++++++------------ internal/dto/request/position.go | 2 +- 9 files changed, 51 insertions(+), 40 deletions(-) diff --git a/internal/api/docs/docs.go b/internal/api/docs/docs.go index 936cd4b..e0d3c64 100644 --- a/internal/api/docs/docs.go +++ b/internal/api/docs/docs.go @@ -1437,19 +1437,19 @@ const docTemplate = `{ "dto_request.Event": { "type": "object", "properties": { - "endAt": { + "end_at": { "type": "integer" }, "host": { "type": "string" }, - "isAllDay": { + "is_all_day": { "type": "boolean" }, "location": { "type": "string" }, - "startAt": { + "start_at": { "type": "integer" }, "uuid": { @@ -1480,6 +1480,9 @@ const docTemplate = `{ "dto_request.Position": { "type": "object", "properties": { + "full_name": { + "type": "string" + }, "oid": { "type": "string" }, @@ -1490,7 +1493,7 @@ const docTemplate = `{ "type": "string" }, "tier": { - "type": "string" + "type": "integer" }, "title": { "type": "string" diff --git a/internal/api/docs/swagger.json b/internal/api/docs/swagger.json index 2f2dff6..049f92e 100644 --- a/internal/api/docs/swagger.json +++ b/internal/api/docs/swagger.json @@ -1426,19 +1426,19 @@ "dto_request.Event": { "type": "object", "properties": { - "endAt": { + "end_at": { "type": "integer" }, "host": { "type": "string" }, - "isAllDay": { + "is_all_day": { "type": "boolean" }, "location": { "type": "string" }, - "startAt": { + "start_at": { "type": "integer" }, "uuid": { @@ -1469,6 +1469,9 @@ "dto_request.Position": { "type": "object", "properties": { + "full_name": { + "type": "string" + }, "oid": { "type": "string" }, @@ -1479,7 +1482,7 @@ "type": "string" }, "tier": { - "type": "string" + "type": "integer" }, "title": { "type": "string" diff --git a/internal/api/docs/swagger.yaml b/internal/api/docs/swagger.yaml index 53f6a3e..a04f579 100644 --- a/internal/api/docs/swagger.yaml +++ b/internal/api/docs/swagger.yaml @@ -92,15 +92,15 @@ definitions: type: object dto_request.Event: properties: - endAt: + end_at: type: integer host: type: string - isAllDay: + is_all_day: type: boolean location: type: string - startAt: + start_at: type: integer uuid: type: string @@ -120,6 +120,8 @@ definitions: type: object dto_request.Position: properties: + full_name: + type: string oid: type: string semester: @@ -127,7 +129,7 @@ definitions: team: type: string tier: - type: string + type: integer title: type: string type: object diff --git a/internal/api/handlers/announcement.go b/internal/api/handlers/announcement.go index d31b2fa..24e0179 100644 --- a/internal/api/handlers/announcement.go +++ b/internal/api/handlers/announcement.go @@ -3,6 +3,7 @@ package handlers import ( + "fmt" "net/http" "github.com/acmcsufoss/api.acmcsuf.com/internal/api/services" @@ -83,6 +84,8 @@ func (h *AnnouncementHandler) CreateAnnouncement(c *gin.Context) { ctx := c.Request.Context() var params dto_request.Announcement + // fmt.Println(params) + fmt.Println(c.Request.Body) if err := c.ShouldBindJSON(¶ms); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "Invalid request body. " + err.Error(), diff --git a/internal/api/services/announcement.go b/internal/api/services/announcement.go index 65c4f25..ac89c12 100644 --- a/internal/api/services/announcement.go +++ b/internal/api/services/announcement.go @@ -36,9 +36,11 @@ func (s *AnnouncementService) Create(ctx context.Context, params domain.Announcement, ) error { if params.Uuid == "" { + fmt.Println("No id") return fmt.Errorf("no unique identifier for announcement") } if err := s.announcementRepository.Create(ctx, params); err != nil { + fmt.Println("Error with creation:", params, ":", err) return err } return nil diff --git a/internal/cli/announcements/post.go b/internal/cli/announcements/post.go index 6586a3a..ef8d64f 100644 --- a/internal/cli/announcements/post.go +++ b/internal/cli/announcements/post.go @@ -10,10 +10,10 @@ import ( "github.com/charmbracelet/huh" "github.com/spf13/cobra" - "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/forms" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/oauth" + dto_request "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" "github.com/acmcsufoss/api.acmcsuf.com/utils" ) @@ -22,7 +22,6 @@ var PostAnnouncement = &cobra.Command{ Short: "post a new announcement", Run: func(cmd *cobra.Command, args []string) { - postAnnouncement(config.Cfg) }, } @@ -48,7 +47,6 @@ func postAnnouncement(cfg *config.Config) { return } - fmt.Println("HELLO?") res, err := client.Do(req) if err != nil { fmt.Println("Error: could not send request:", err) @@ -70,8 +68,8 @@ func postAnnouncement(cfg *config.Config) { } // TODO: Use DTO models instaad of dbmodels -func postForm() (*dbmodels.CreateAnnouncementParams, error) { - var payload dbmodels.CreateAnnouncementParams +func postForm() (*dto_request.Announcement, error) { + var payload dto_request.Announcement var err error var ( announceAtStr string @@ -112,8 +110,8 @@ func postForm() (*dbmodels.CreateAnnouncementParams, error) { if err != nil { return nil, err } - payload.DiscordChannelID = utils.StringtoNullString(channelIDStr) - payload.DiscordMessageID = utils.StringtoNullString(messageIDStr) + payload.DiscordChannelID = &channelIDStr + payload.DiscordMessageID = &messageIDStr return &payload, err } diff --git a/internal/cli/announcements/put.go b/internal/cli/announcements/put.go index e4ab804..036cc08 100644 --- a/internal/cli/announcements/put.go +++ b/internal/cli/announcements/put.go @@ -10,9 +10,9 @@ import ( "github.com/charmbracelet/huh" "github.com/spf13/cobra" - "github.com/acmcsufoss/api.acmcsuf.com/internal/api/dbmodels" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/config" "github.com/acmcsufoss/api.acmcsuf.com/internal/cli/oauth" + dto_request "github.com/acmcsufoss/api.acmcsuf.com/internal/dto/request" "github.com/acmcsufoss/api.acmcsuf.com/utils" ) @@ -58,7 +58,7 @@ func putAnnouncements(id string, cfg *config.Config) { } // ----- Update found announceement ----- - var oldPayload dbmodels.CreateAnnouncementParams + var oldPayload dto_request.UpdateAnnouncement err = json.Unmarshal(body, &oldPayload) if err != nil { fmt.Println("Error: failed to unmarshal response body:", err) @@ -99,8 +99,8 @@ func putAnnouncements(id string, cfg *config.Config) { } // TODO: Use DTO models instaad of dbmodels -func putForm(uuid string) (*dbmodels.UpdateAnnouncementParams, error) { - var payload dbmodels.UpdateAnnouncementParams +func putForm(uuid string) (*dto_request.UpdateAnnouncement, error) { + var payload dto_request.UpdateAnnouncement var err error var ( visibilityStr string @@ -134,20 +134,20 @@ func putForm(uuid string) (*dbmodels.UpdateAnnouncementParams, error) { payload.Uuid = uuid // HACK: These conversions won't be necessary once we start using DTO models here if visibilityStr != "" { - payload.Visibility = utils.StringtoNullString(visibilityStr) + payload.Visibility = &visibilityStr } if announceAtStr != "" { timestamp, err := utils.ByteSlicetoUnix([]byte(announceAtStr)) if err != nil { return nil, err } - payload.AnnounceAt = utils.Int64toNullInt64(timestamp) + payload.AnnounceAt = ×tamp } if channelIDStr != "" { - payload.DiscordChannelID = utils.StringtoNullString(channelIDStr) + payload.DiscordChannelID = &channelIDStr } if messageIDStr != "" { - payload.DiscordMessageID = utils.StringtoNullString(messageIDStr) + payload.DiscordMessageID = &messageIDStr } return &payload, nil } diff --git a/internal/dto/request/event.go b/internal/dto/request/event.go index 9bf6018..102f343 100644 --- a/internal/dto/request/event.go +++ b/internal/dto/request/event.go @@ -1,19 +1,19 @@ package dto_request type Event struct { - Uuid string `json: "uuid"` - Location string `json: "location"` - StartAt int64 `json: "start_at"` - EndAt int64 `json: "end_at"` - IsAllDay bool `json: "is_all_day"` - Host string `json: "host"` + Uuid string `json:"uuid"` + Location string `json:"location"` + StartAt int64 `json:"start_at"` + EndAt int64 `json:"end_at"` + IsAllDay bool `json:"is_all_day"` + Host string `json:"host"` } type UpdateEvent struct { - Uuid string `json: "uuid"` - Location *string `json: "location"` - StartAt *int64 `json: "start_at"` - EndAt *int64 `json: "end_at"` - IsAllDay *bool `json: "is_all_day"` - Host *string `json: :"host"` + Uuid string `json:"uuid"` + Location *string `json:"location"` + StartAt *int64 `json:"start_at"` + EndAt *int64 `json:"end_at"` + IsAllDay *bool `json:"is_all_day"` + Host *string `json:"host"` } diff --git a/internal/dto/request/position.go b/internal/dto/request/position.go index cf9015b..9ab4a4d 100644 --- a/internal/dto/request/position.go +++ b/internal/dto/request/position.go @@ -4,7 +4,7 @@ type Position struct { Oid string `json:"oid"` Semester string `json:"semester"` Tier int `json:"tier"` - FullName string `json:"tier"` + FullName string `json:"full_name"` Title *string `json:"title"` Team *string `json:"team"` } From de3856933f40da9695a8a1a3a88ff9e969dee7dd Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Mon, 23 Feb 2026 19:16:30 -0800 Subject: [PATCH 55/56] check against illegal var reference for announcements --- internal/mapper/dto_to_domain.go | 15 ++++++++------ internal/repository/conv.go | 35 ++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/internal/mapper/dto_to_domain.go b/internal/mapper/dto_to_domain.go index 6d4b081..e14a189 100644 --- a/internal/mapper/dto_to_domain.go +++ b/internal/mapper/dto_to_domain.go @@ -18,11 +18,14 @@ func ToAnnouncementDomain(a *dto_request.Announcement) domain.Announcement { } func ToUpdateAnnouncementDomain(a *dto_request.UpdateAnnouncement) domain.UpdateAnnouncement { - announce_at := time.Unix(*a.AnnounceAt, 0) + var announceAt time.Time + if a.AnnounceAt != nil { + announceAt = time.Unix(*a.AnnounceAt, 0) + } return domain.UpdateAnnouncement{ Uuid: a.Uuid, Visibility: a.Visibility, - AnnounceAt: &announce_at, + AnnounceAt: &announceAt, DiscordChannelID: a.DiscordChannelID, DiscordMessageID: a.DiscordMessageID, } @@ -39,12 +42,12 @@ func ToEventDomain(e *dto_request.Event) domain.Event { } func ToUpdateEventDomain(e *dto_request.UpdateEvent) domain.UpdateEvent { - start_at := time.Unix(*e.StartAt, 0) - end_at := time.Unix(*e.EndAt, 0) + startAt := time.Unix(*e.StartAt, 0) + endAt := time.Unix(*e.EndAt, 0) return domain.UpdateEvent{ Location: e.Location, - StartAt: &start_at, - EndAt: &end_at, + StartAt: &startAt, + EndAt: &endAt, IsAllDay: e.IsAllDay, Host: e.Host, } diff --git a/internal/repository/conv.go b/internal/repository/conv.go index 46b954a..1cad731 100644 --- a/internal/repository/conv.go +++ b/internal/repository/conv.go @@ -118,17 +118,32 @@ func convertDomainToCreateDBAnnouncement(dAnnouncement domain.Announcement) dbmo func convertDomainToUpdateDBAnnouncement(dAnnouncement domain.UpdateAnnouncement) dbmodels.UpdateAnnouncementParams { // -- sql null values -- - vis := dAnnouncement.Visibility - announceAt := dAnnouncement.AnnounceAt.Unix() - chanID := dAnnouncement.DiscordChannelID - msgID := dAnnouncement.DiscordMessageID + + var vis string + if dAnnouncement.Visibility != nil { + vis = *dAnnouncement.Visibility + } + var announceAt int64 + announceAtPtr := dAnnouncement.AnnounceAt + if announceAtPtr != nil { + announceAt = announceAtPtr.Unix() + } + var chanID string + if dAnnouncement.DiscordChannelID != nil { + chanID = *dAnnouncement.DiscordChannelID + } + + var msgID string + if dAnnouncement.DiscordMessageID != nil { + msgID = *dAnnouncement.DiscordMessageID + } return dbmodels.UpdateAnnouncementParams{ Uuid: dAnnouncement.Uuid, - Visibility: sql.NullString{String: *vis, Valid: validString(vis)}, - AnnounceAt: sql.NullInt64{Int64: announceAt, Valid: validInt64(&announceAt)}, - DiscordChannelID: sql.NullString{String: *chanID, Valid: validString(chanID)}, - DiscordMessageID: sql.NullString{String: *msgID, Valid: validString(msgID)}, + Visibility: sql.NullString{String: vis, Valid: validString(dAnnouncement.Visibility)}, + AnnounceAt: sql.NullInt64{Int64: announceAt, Valid: validTime(announceAtPtr)}, + DiscordChannelID: sql.NullString{String: chanID, Valid: validString(dAnnouncement.DiscordChannelID)}, + DiscordMessageID: sql.NullString{String: msgID, Valid: validString(dAnnouncement.DiscordMessageID)}, } } @@ -234,3 +249,7 @@ func validString(s *string) bool { func validBool(b *bool) bool { return b != nil } + +func validTime(t *time.Time) bool { + return t != nil +} From e0b07c3fc9298fe337cb36486b2e8f1800123f6e Mon Sep 17 00:00:00 2001 From: Mark Gaballa Date: Mon, 23 Feb 2026 19:31:33 -0800 Subject: [PATCH 56/56] event nil dereference protection --- internal/repository/conv.go | 38 ++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/internal/repository/conv.go b/internal/repository/conv.go index 1cad731..5c6d40c 100644 --- a/internal/repository/conv.go +++ b/internal/repository/conv.go @@ -35,18 +35,38 @@ func convertDomainToCreateDBEvent(dEvent domain.Event) dbmodels.CreateEventParam func convertDomainToUpdateDBEvent(dEvent domain.UpdateEvent) dbmodels.UpdateEventParams { // -- sql null values -- - start := dEvent.StartAt.Unix() - end := dEvent.EndAt.Unix() - allday := dEvent.IsAllDay - host := dEvent.Host + var loc string + if dEvent.Location != nil { + loc = *dEvent.Location + } + + var start int64 + if dEvent.StartAt != nil { + start = dEvent.StartAt.Unix() + } + + var end int64 + if dEvent.EndAt != nil { + end = dEvent.StartAt.Unix() + } + + var allDay bool + if dEvent.IsAllDay != nil { + allDay = *dEvent.IsAllDay + } + + var host string + if dEvent.Host != nil { + host = *dEvent.Host + } return dbmodels.UpdateEventParams{ Uuid: dEvent.Uuid, - Location: sql.NullString{String: *dEvent.Location, Valid: validString(dEvent.Location)}, - StartAt: sql.NullInt64{Int64: start, Valid: validInt64(&start)}, - EndAt: sql.NullInt64{Int64: end, Valid: validInt64(&end)}, - IsAllDay: sql.NullBool{Bool: *allday, Valid: validBool(allday)}, - Host: sql.NullString{String: *host, Valid: validString(host)}, + Location: sql.NullString{String: loc, Valid: validString(dEvent.Location)}, + StartAt: sql.NullInt64{Int64: start, Valid: validTime(dEvent.StartAt)}, + EndAt: sql.NullInt64{Int64: end, Valid: validTime(dEvent.EndAt)}, + IsAllDay: sql.NullBool{Bool: allDay, Valid: validBool(dEvent.IsAllDay)}, + Host: sql.NullString{String: host, Valid: validString(dEvent.Host)}, } }