Skip to content

Commit

Permalink
Separate database models from OpenAPI types
Browse files Browse the repository at this point in the history
  • Loading branch information
m110 committed Sep 1, 2020
1 parent 92c3412 commit e48fbc3
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 77 deletions.
26 changes: 19 additions & 7 deletions internal/trainer/firestore.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ import (
"google.golang.org/api/iterator"
)

type DateModel struct {
Date time.Time `firestore:"Date"`
HasFreeHours bool `firestore:"HasFreeHours"`
Hours []HourModel `firestore:"Hours"`
}

type HourModel struct {
Available bool `firestore:"Available"`
HasTrainingScheduled bool `firestore:"HasTrainingScheduled"`
Hour time.Time `firestore:"Hour"`
}

type db struct {
firestoreClient *firestore.Client
}
Expand All @@ -21,7 +33,7 @@ func (d db) DocumentRef(dateTimeToUpdate time.Time) *firestore.DocumentRef {
return d.TrainerHoursCollection().Doc(dateTimeToUpdate.Format("2006-01-02"))
}

func (d db) GetDates(ctx context.Context, params *GetTrainerAvailableHoursParams) ([]Date, error) {
func (d db) GetDates(ctx context.Context, params *GetTrainerAvailableHoursParams) ([]DateModel, error) {
dates, err := d.QueryDates(params, ctx)
if err != nil {
return nil, err
Expand All @@ -31,19 +43,19 @@ func (d db) GetDates(ctx context.Context, params *GetTrainerAvailableHoursParams
for _, date := range dates {
sort.Slice(date.Hours, func(i, j int) bool { return date.Hours[i].Hour.Before(date.Hours[j].Hour) })
}
sort.Slice(dates, func(i, j int) bool { return dates[i].Date.Before(dates[j].Date.Time) })
sort.Slice(dates, func(i, j int) bool { return dates[i].Date.Before(dates[j].Date) })

return dates, nil
}

func (d db) QueryDates(params *GetTrainerAvailableHoursParams, ctx context.Context) ([]Date, error) {
func (d db) QueryDates(params *GetTrainerAvailableHoursParams, ctx context.Context) ([]DateModel, error) {
iter := d.
TrainerHoursCollection().
Where("Date.Time", ">=", params.DateFrom).
Where("Date.Time", "<=", params.DateTo).
Where("Date", ">=", params.DateFrom).
Where("Date", "<=", params.DateTo).
Documents(ctx)

var dates []Date
var dates []DateModel

for {
doc, err := iter.Next()
Expand All @@ -54,7 +66,7 @@ func (d db) QueryDates(params *GetTrainerAvailableHoursParams, ctx context.Conte
return nil, err
}

date := Date{}
date := DateModel{}
if err := doc.DataTo(&date); err != nil {
return nil, err
}
Expand Down
29 changes: 14 additions & 15 deletions internal/trainer/hour_firestore_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"cloud.google.com/go/firestore"
"github.com/ThreeDotsLabs/wild-workouts-go-ddd-example/internal/trainer/domain/hour"
"github.com/deepmap/oapi-codegen/pkg/types"
"github.com/pkg/errors"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
Expand Down Expand Up @@ -97,27 +96,27 @@ func (f FirestoreHourRepository) documentRef(hourTime time.Time) *firestore.Docu
func (f FirestoreHourRepository) getDateDTO(
getDocumentFn func() (doc *firestore.DocumentSnapshot, err error),
dateTime time.Time,
) (Date, error) {
) (DateModel, error) {
doc, err := getDocumentFn()
if status.Code(err) == codes.NotFound {
// in reality this date exists, even if it's not persisted
return NewEmptyDateDTO(dateTime), nil
}
if err != nil {
return Date{}, err
return DateModel{}, err
}

date := Date{}
date := DateModel{}
if err := doc.DataTo(&date); err != nil {
return Date{}, errors.Wrap(err, "unable to unmarshal Date from Firestore")
return DateModel{}, errors.Wrap(err, "unable to unmarshal DateModel from Firestore")
}

return date, nil
}

// for now we are keeping backward comparability, because of that it's a bit messy and overcomplicated
// todo - we will clean it up later with CQRS :-)
func (f FirestoreHourRepository) domainHourFromDateDTO(date Date, hourTime time.Time) (*hour.Hour, error) {
func (f FirestoreHourRepository) domainHourFromDateDTO(date DateModel, hourTime time.Time) (*hour.Hour, error) {
firebaseHour, found := findHourInDateDTO(date, hourTime)
if !found {
// in reality this date exists, even if it's not persisted
Expand All @@ -134,7 +133,7 @@ func (f FirestoreHourRepository) domainHourFromDateDTO(date Date, hourTime time.

// for now we are keeping backward comparability, because of that it's a bit messy and overcomplicated
// todo - we will clean it up later with CQRS :-)
func updateHourInDataDTO(updatedHour *hour.Hour, firebaseDate *Date) {
func updateHourInDataDTO(updatedHour *hour.Hour, firebaseDate *DateModel) {
firebaseHourDTO := domainHourToDTO(updatedHour)

hourFound := false
Expand All @@ -161,7 +160,7 @@ func updateHourInDataDTO(updatedHour *hour.Hour, firebaseDate *Date) {
}
}

func mapAvailabilityFromDTO(firebaseHour Hour) (hour.Availability, error) {
func mapAvailabilityFromDTO(firebaseHour HourModel) (hour.Availability, error) {
if firebaseHour.Available && !firebaseHour.HasTrainingScheduled {
return hour.Available, nil
}
Expand All @@ -179,15 +178,15 @@ func mapAvailabilityFromDTO(firebaseHour Hour) (hour.Availability, error) {
)
}

func domainHourToDTO(updatedHour *hour.Hour) Hour {
return Hour{
func domainHourToDTO(updatedHour *hour.Hour) HourModel {
return HourModel{
Available: updatedHour.IsAvailable(),
HasTrainingScheduled: updatedHour.HasTrainingScheduled(),
Hour: updatedHour.Time(),
}
}

func findHourInDateDTO(firebaseDate Date, time time.Time) (Hour, bool) {
func findHourInDateDTO(firebaseDate DateModel, time time.Time) (HourModel, bool) {
for i := range firebaseDate.Hours {
firebaseHour := firebaseDate.Hours[i]

Expand All @@ -198,11 +197,11 @@ func findHourInDateDTO(firebaseDate Date, time time.Time) (Hour, bool) {
return firebaseHour, true
}

return Hour{}, false
return HourModel{}, false
}

func NewEmptyDateDTO(t time.Time) Date {
return Date{
Date: types.Date{Time: t.UTC().Truncate(time.Hour * 24)},
func NewEmptyDateDTO(t time.Time) DateModel {
return DateModel{
Date: t.UTC().Truncate(time.Hour * 24),
}
}
29 changes: 28 additions & 1 deletion internal/trainer/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package main
import (
"net/http"

openapi_types "github.com/deepmap/oapi-codegen/pkg/types"

"github.com/ThreeDotsLabs/wild-workouts-go-ddd-example/internal/common/auth"
"github.com/ThreeDotsLabs/wild-workouts-go-ddd-example/internal/common/server/httperr"
"github.com/ThreeDotsLabs/wild-workouts-go-ddd-example/internal/trainer/domain/hour"
Expand All @@ -22,15 +24,40 @@ func (h HttpServer) GetTrainerAvailableHours(w http.ResponseWriter, r *http.Requ
return
}

dates, err := h.db.GetDates(r.Context(), queryParams)
dateModels, err := h.db.GetDates(r.Context(), queryParams)
if err != nil {
httperr.InternalError("unable-to-get-dates", err, w, r)
return
}

dates := dateModelsToResponse(dateModels)
render.Respond(w, r, dates)
}

func dateModelsToResponse(models []DateModel) []Date {
var dates []Date
for _, d := range models {
var hours []Hour
for _, h := range d.Hours {
hours = append(hours, Hour{
Available: h.Available,
HasTrainingScheduled: h.HasTrainingScheduled,
Hour: h.Hour,
})
}

dates = append(dates, Date{
Date: openapi_types.Date{
Time: d.Date,
},
HasFreeHours: d.HasFreeHours,
Hours: hours,
})
}

return dates
}

func (h HttpServer) MakeHourAvailable(w http.ResponseWriter, r *http.Request) {
user, err := auth.UserFromCtx(r.Context())
if err != nil {
Expand Down
24 changes: 5 additions & 19 deletions internal/trainer/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package main

import (
"time"

"github.com/deepmap/oapi-codegen/pkg/types"
)

const (
Expand All @@ -12,7 +10,7 @@ const (
)

// setDefaultAvailability adds missing hours to Date model if they were not set
func setDefaultAvailability(date Date) Date {
func setDefaultAvailability(date DateModel) DateModel {

HoursLoop:
for hour := minHour; hour <= maxHour; hour++ {
Expand All @@ -23,7 +21,7 @@ HoursLoop:
continue HoursLoop
}
}
newHour := Hour{
newHour := HourModel{
Available: false,
Hour: hour,
}
Expand All @@ -34,7 +32,7 @@ HoursLoop:
return date
}

func addMissingDates(params *GetTrainerAvailableHoursParams, dates []Date) []Date {
func addMissingDates(params *GetTrainerAvailableHoursParams, dates []DateModel) []DateModel {
for day := params.DateFrom.UTC(); day.Before(params.DateTo) || day.Equal(params.DateTo); day = day.Add(time.Hour * 24) {
found := false
for _, date := range dates {
Expand All @@ -45,10 +43,8 @@ func addMissingDates(params *GetTrainerAvailableHoursParams, dates []Date) []Dat
}

if !found {
date := Date{
Date: types.Date{
Time: day,
},
date := DateModel{
Date: day,
}
date = setDefaultAvailability(date)
dates = append(dates, date)
Expand All @@ -57,13 +53,3 @@ func addMissingDates(params *GetTrainerAvailableHoursParams, dates []Date) []Dat

return dates
}

func (d Date) FindHourInDate(timeToCheck time.Time) (*Hour, bool) {
for i, hour := range d.Hours {
if hour.Hour == timeToCheck {
return &d.Hours[i], true
}
}

return nil, false
}
25 changes: 19 additions & 6 deletions internal/trainings/firestore.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@ import (
"google.golang.org/api/iterator"
)

type TrainingModel struct {
UUID string `firestore:"Uuid"`
UserUUID string `firestore:"UserUuid"`
User string `firestore:"User"`

Time time.Time `firestore:"Time"`
Notes string `firestore:"Notes"`

ProposedTime *time.Time `firestore:"ProposedTime"`
MoveProposedBy *string `firestore:"MoveProposedBy"`
}

func (t TrainingModel) canBeCancelled() bool {
return t.Time.Sub(time.Now()) > time.Hour*24
}

type db struct {
firestoreClient *firestore.Client
}
Expand All @@ -18,7 +34,7 @@ func (d db) TrainingsCollection() *firestore.CollectionRef {
return d.firestoreClient.Collection("trainings")
}

func (d db) GetTrainings(ctx context.Context, user auth.User) ([]Training, error) {
func (d db) GetTrainings(ctx context.Context, user auth.User) ([]TrainingModel, error) {
query := d.TrainingsCollection().Query.Where("Time", ">=", time.Now().Add(-time.Hour*24))

if user.Role != "trainer" {
Expand All @@ -27,7 +43,7 @@ func (d db) GetTrainings(ctx context.Context, user auth.User) ([]Training, error

iter := query.Documents(ctx)

var trainings []Training
var trainings []TrainingModel

for {
doc, err := iter.Next()
Expand All @@ -38,14 +54,11 @@ func (d db) GetTrainings(ctx context.Context, user auth.User) ([]Training, error
return nil, err
}

t := Training{}
t := TrainingModel{}
if err := doc.DataTo(&t); err != nil {
return nil, err
}

t.CanBeCancelled = t.canBeCancelled()
t.MoveRequiresAccept = !t.canBeCancelled()

trainings = append(trainings, t)
}

Expand Down
Loading

0 comments on commit e48fbc3

Please sign in to comment.