diff --git a/pkg/training/error.go b/pkg/training/error.go index 69ca6fe..a9bdc11 100644 --- a/pkg/training/error.go +++ b/pkg/training/error.go @@ -3,5 +3,6 @@ package training import "errors" var ( - ErrTrainingNotFound = errors.New("training not found") + ErrTrainingNotFound = errors.New("training not found") + ErrTrainingDateNotFound = errors.New("training date not found") ) diff --git a/pkg/training/model.go b/pkg/training/model.go index eb3c1b9..e129fb2 100644 --- a/pkg/training/model.go +++ b/pkg/training/model.go @@ -1,6 +1,8 @@ package training import ( + "time" + "github.com/google/uuid" "github.com/shopspring/decimal" "gitlab.mareshq.com/hq/yggdrasil/internal/currency" @@ -32,3 +34,28 @@ const ( OpenTrainingPrice TrainingPriceType = "OPEN" CorporateTrainingPrice TrainingPriceType = "CORPORATE" ) + +type TrainingDateID = uuid.UUID + +func NewTrainingDateID() TrainingDateID { + return uuid.Must(uuid.NewV7()) +} + +type TrainingDate struct { + trainingID TrainingID + + ID TrainingDateID + Date time.Time + StartTime time.Time + Days int8 + IsOnline bool + Location string + Address string + Capacity int8 + Price TrainingDatePrice +} + +type TrainingDatePrice struct { + Amount decimal.Decimal + Currency currency.Currency +} diff --git a/pkg/training/repository.go b/pkg/training/repository.go index 2e4fce0..5fc2313 100644 --- a/pkg/training/repository.go +++ b/pkg/training/repository.go @@ -242,3 +242,104 @@ func (r *InMemoryTrainingRepository) Delete(id TrainingID) error { delete(r.trainings, id) return nil } + +type TrainingDateRepository interface { + Create(trainingID TrainingID, trainingDate *TrainingDate) error + FindByID(id TrainingDateID) (*TrainingDate, error) + FindAll() ([]TrainingDate, error) + FindAllByTrainingID(trainingID TrainingID) ([]TrainingDate, error) + Update(trainingDate *TrainingDate) error + Delete(id TrainingDateID) error +} + +type InMemoryTrainingDateRepository struct { + trainingDates map[TrainingDateID]TrainingDate + trainingToDates map[TrainingID][]TrainingDateID + + lock sync.RWMutex +} + +func NewInMemoryTrainingDateRepository() *InMemoryTrainingDateRepository { + return &InMemoryTrainingDateRepository{ + trainingDates: make(map[TrainingDateID]TrainingDate), + trainingToDates: make(map[TrainingID][]TrainingDateID), + } +} + +func (r *InMemoryTrainingDateRepository) Create(trainingID TrainingID, trainingDate *TrainingDate) error { + r.lock.Lock() + defer r.lock.Unlock() + + trainingDate.ID = NewTrainingDateID() + trainingDate.trainingID = trainingID + + r.trainingDates[trainingDate.ID] = *trainingDate + r.trainingToDates[trainingID] = append(r.trainingToDates[trainingID], trainingDate.ID) + return nil +} + +func (r *InMemoryTrainingDateRepository) FindByID(id TrainingDateID) (*TrainingDate, error) { + r.lock.RLock() + defer r.lock.RUnlock() + + date, ok := r.trainingDates[id] + if !ok { + return nil, ErrTrainingDateNotFound + } + return &date, nil +} + +func (r *InMemoryTrainingDateRepository) FindAll() ([]TrainingDate, error) { + r.lock.RLock() + defer r.lock.RUnlock() + + dates := make([]TrainingDate, len(r.trainingDates)) + for _, date := range r.trainingDates { + dates = append(dates, date) + } + + return dates, nil +} + +func (r *InMemoryTrainingDateRepository) FindAllByTrainingID(trainingID TrainingID) ([]TrainingDate, error) { + r.lock.RLock() + defer r.lock.RUnlock() + + dates := make([]TrainingDate, 0) + for _, id := range r.trainingToDates[trainingID] { + dates = append(dates, r.trainingDates[id]) + } + + return dates, nil +} + +func (r *InMemoryTrainingDateRepository) Update(trainingDate *TrainingDate) error { + r.lock.Lock() + defer r.lock.Unlock() + + oldDate := r.trainingDates[trainingDate.ID] + trainingDate.trainingID = oldDate.trainingID + r.trainingDates[trainingDate.ID] = *trainingDate + return nil +} + +func (r *InMemoryTrainingDateRepository) Delete(id TrainingDateID) error { + r.lock.Lock() + defer r.lock.Unlock() + + date, ok := r.trainingDates[id] + if !ok { + return ErrTrainingDateNotFound + } + + delete(r.trainingDates, id) + dates := r.trainingToDates[date.trainingID] + for idx, d := range dates { + if d == id { + r.trainingToDates[date.trainingID] = append(dates[:idx], dates[idx+1:]...) + break + } + } + + return nil +}