homebox/backend/internal/repo/repo_locations.go
Hayden 343290a55a
refactor: repositories (#28)
* cleanup unnecessary mocks

* refactor document storage location

* remove unused function

* move ownership to document types to repo package

* move types and mappers to repo package

* refactor sets to own package
2022-09-27 15:52:13 -08:00

167 lines
3.8 KiB
Go

package repo
import (
"context"
"time"
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/ent"
"github.com/hay-kot/homebox/backend/ent/group"
"github.com/hay-kot/homebox/backend/ent/location"
"github.com/hay-kot/homebox/backend/ent/predicate"
)
type LocationRepository struct {
db *ent.Client
}
type (
LocationCreate struct {
Name string `json:"name"`
Description string `json:"description"`
}
LocationUpdate struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
}
LocationSummary struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
LocationOutCount struct {
LocationSummary
ItemCount int `json:"itemCount"`
}
LocationOut struct {
LocationSummary
Items []ItemSummary `json:"items"`
}
)
func mapLocationSummary(location *ent.Location) LocationSummary {
return LocationSummary{
ID: location.ID,
Name: location.Name,
Description: location.Description,
CreatedAt: location.CreatedAt,
UpdatedAt: location.UpdatedAt,
}
}
var (
mapLocationOutErr = mapTErrFunc(mapLocationOut)
)
func mapLocationOut(location *ent.Location) LocationOut {
return LocationOut{
LocationSummary: LocationSummary{
ID: location.ID,
Name: location.Name,
Description: location.Description,
CreatedAt: location.CreatedAt,
UpdatedAt: location.UpdatedAt,
},
Items: mapEach(location.Edges.Items, mapItemSummary),
}
}
// GetALlWithCount returns all locations with item count field populated
func (r *LocationRepository) GetAll(ctx context.Context, groupId uuid.UUID) ([]LocationOutCount, error) {
query := `--sql
SELECT
id,
name,
description,
created_at,
updated_at,
(
SELECT
COUNT(*)
FROM
items
WHERE
items.location_items = locations.id
) as item_count
FROM
locations
WHERE
locations.group_locations = ?
`
rows, err := r.db.Sql().QueryContext(ctx, query, groupId)
if err != nil {
return nil, err
}
list := []LocationOutCount{}
for rows.Next() {
var ct LocationOutCount
err := rows.Scan(&ct.ID, &ct.Name, &ct.Description, &ct.CreatedAt, &ct.UpdatedAt, &ct.ItemCount)
if err != nil {
return nil, err
}
list = append(list, ct)
}
return list, err
}
func (r *LocationRepository) getOne(ctx context.Context, where ...predicate.Location) (LocationOut, error) {
return mapLocationOutErr(r.db.Location.Query().
Where(where...).
WithGroup().
WithItems(func(iq *ent.ItemQuery) {
iq.WithLabel()
}).
Only(ctx))
}
func (r *LocationRepository) Get(ctx context.Context, ID uuid.UUID) (LocationOut, error) {
return r.getOne(ctx, location.ID(ID))
}
func (r *LocationRepository) GetOneByGroup(ctx context.Context, GID, ID uuid.UUID) (LocationOut, error) {
return r.getOne(ctx, location.ID(ID), location.HasGroupWith(group.ID(GID)))
}
func (r *LocationRepository) Create(ctx context.Context, gid uuid.UUID, data LocationCreate) (LocationOut, error) {
location, err := r.db.Location.Create().
SetName(data.Name).
SetDescription(data.Description).
SetGroupID(gid).
Save(ctx)
if err != nil {
return LocationOut{}, err
}
location.Edges.Group = &ent.Group{ID: gid} // bootstrap group ID
return mapLocationOut(location), nil
}
func (r *LocationRepository) Update(ctx context.Context, data LocationUpdate) (LocationOut, error) {
_, err := r.db.Location.UpdateOneID(data.ID).
SetName(data.Name).
SetDescription(data.Description).
Save(ctx)
if err != nil {
return LocationOut{}, err
}
return r.Get(ctx, data.ID)
}
func (r *LocationRepository) Delete(ctx context.Context, id uuid.UUID) error {
return r.db.Location.DeleteOneID(id).Exec(ctx)
}