mirror of
https://github.com/hay-kot/homebox.git
synced 2025-08-06 01:20:31 +00:00
implement repository layer
This commit is contained in:
parent
f1082dafed
commit
ba739a02da
4 changed files with 195 additions and 10 deletions
|
@ -16,17 +16,16 @@ func mapTErrFunc[T any, Y any](fn func(T) Y) func(T, error) (Y, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Future Usage
|
func mapTEachFunc[T any, Y any](fn func(T) Y) func([]T) []Y {
|
||||||
// func mapEachFunc[T any, Y any](fn func(T) Y) func([]T) []Y {
|
return func(items []T) []Y {
|
||||||
// return func(items []T) []Y {
|
result := make([]Y, len(items))
|
||||||
// result := make([]Y, len(items))
|
for i, item := range items {
|
||||||
// for i, item := range items {
|
result[i] = fn(item)
|
||||||
// result[i] = fn(item)
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// return result
|
return result
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
func mapTEachErrFunc[T any, Y any](fn func(T) Y) func([]T, error) ([]Y, error) {
|
func mapTEachErrFunc[T any, Y any](fn func(T) Y) func([]T, error) ([]Y, error) {
|
||||||
return func(items []T, err error) ([]Y, error) {
|
return func(items []T, err error) ([]Y, error) {
|
||||||
|
|
118
backend/internal/data/repo/repo_maintenance_entry.go
Normal file
118
backend/internal/data/repo/repo_maintenance_entry.go
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/hay-kot/homebox/backend/internal/data/ent"
|
||||||
|
"github.com/hay-kot/homebox/backend/internal/data/ent/maintenanceentry"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MaintenanceEntryRepository is a repository for maintenance entries that are
|
||||||
|
// associated with an item in the database. An entry represents a maintenance event
|
||||||
|
// that has been performed on an item.
|
||||||
|
type MaintenanceEntryRepository struct {
|
||||||
|
db *ent.Client
|
||||||
|
}
|
||||||
|
type (
|
||||||
|
MaintenanceEntryCreate struct {
|
||||||
|
ItemID uuid.UUID `json:"itemId"`
|
||||||
|
Date time.Time `json:"date"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Cost float64 `json:"cost"`
|
||||||
|
}
|
||||||
|
|
||||||
|
MaintenanceEntry struct {
|
||||||
|
ID uuid.UUID `json:"id"`
|
||||||
|
Date time.Time `json:"date"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Cost float64 `json:"cost"`
|
||||||
|
}
|
||||||
|
|
||||||
|
MaintenanceLog struct {
|
||||||
|
ItemID uuid.UUID `json:"itemId"`
|
||||||
|
CostAverage float64 `json:"costAverage"`
|
||||||
|
CostTotal float64 `json:"costTotal"`
|
||||||
|
Entries []MaintenanceEntry
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
mapMaintenanceEntryErr = mapTErrFunc(mapMaintenanceEntry)
|
||||||
|
mapEachMaintenanceEntry = mapTEachFunc(mapMaintenanceEntry)
|
||||||
|
)
|
||||||
|
|
||||||
|
func mapMaintenanceEntry(entry *ent.MaintenanceEntry) MaintenanceEntry {
|
||||||
|
return MaintenanceEntry{
|
||||||
|
ID: entry.ID,
|
||||||
|
Date: entry.Date,
|
||||||
|
Name: entry.Name,
|
||||||
|
Description: entry.Description,
|
||||||
|
Cost: entry.Cost,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MaintenanceEntryRepository) Create(ctx context.Context, input MaintenanceEntryCreate) (MaintenanceEntry, error) {
|
||||||
|
item, err := r.db.MaintenanceEntry.Create().
|
||||||
|
SetItemID(input.ItemID).
|
||||||
|
SetDate(input.Date).
|
||||||
|
SetName(input.Name).
|
||||||
|
SetDescription(input.Description).
|
||||||
|
SetCost(input.Cost).
|
||||||
|
Save(ctx)
|
||||||
|
|
||||||
|
return mapMaintenanceEntryErr(item, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MaintenanceEntryRepository) GetLog(ctx context.Context, itemID uuid.UUID) (MaintenanceLog, error) {
|
||||||
|
log := MaintenanceLog{
|
||||||
|
ItemID: itemID,
|
||||||
|
}
|
||||||
|
|
||||||
|
entries, err := r.db.MaintenanceEntry.Query().
|
||||||
|
Where(maintenanceentry.ItemID(itemID)).
|
||||||
|
All(ctx)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return MaintenanceLog{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Entries = mapEachMaintenanceEntry(entries)
|
||||||
|
|
||||||
|
var maybeTotal *float64
|
||||||
|
var maybeAverage *float64
|
||||||
|
|
||||||
|
q := `
|
||||||
|
SELECT
|
||||||
|
SUM(cost_total) AS total_of_totals,
|
||||||
|
AVG(cost_total) AS avg_of_averages
|
||||||
|
FROM
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
strftime('%m-%Y', date) AS my,
|
||||||
|
SUM(cost) AS cost_total
|
||||||
|
FROM
|
||||||
|
maintenance_entries
|
||||||
|
WHERE
|
||||||
|
item_id = ?
|
||||||
|
GROUP BY
|
||||||
|
my
|
||||||
|
)`
|
||||||
|
|
||||||
|
row := r.db.Sql().QueryRowContext(ctx, q, itemID)
|
||||||
|
err = row.Scan(&maybeTotal, &maybeAverage)
|
||||||
|
if err != nil {
|
||||||
|
return MaintenanceLog{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.CostAverage = orDefault(maybeAverage, 0)
|
||||||
|
log.CostTotal = orDefault(maybeTotal, 0)
|
||||||
|
return log, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MaintenanceEntryRepository) Delete(ctx context.Context, ID uuid.UUID) error {
|
||||||
|
return r.db.MaintenanceEntry.DeleteOneID(ID).Exec(ctx)
|
||||||
|
}
|
66
backend/internal/data/repo/repo_maintenance_entry_test.go
Normal file
66
backend/internal/data/repo/repo_maintenance_entry_test.go
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
package repo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMaintenanceEntryRepository_GetLog(t *testing.T) {
|
||||||
|
item := useItems(t, 1)[0]
|
||||||
|
|
||||||
|
// Create 10 maintenance entries for the item
|
||||||
|
created := make([]MaintenanceEntryCreate, 10)
|
||||||
|
|
||||||
|
lastMonth := time.Now().AddDate(0, -1, 0)
|
||||||
|
thisMonth := time.Now()
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
dt := lastMonth
|
||||||
|
if i%2 == 0 {
|
||||||
|
dt = thisMonth
|
||||||
|
}
|
||||||
|
|
||||||
|
created[i] = MaintenanceEntryCreate{
|
||||||
|
ItemID: item.ID,
|
||||||
|
Date: dt,
|
||||||
|
Name: "Maintenance",
|
||||||
|
Description: "Maintenance description",
|
||||||
|
Cost: 10,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range created {
|
||||||
|
_, err := tRepos.MaintEntry.Create(context.Background(), entry)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create maintenance entry: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the log for the item
|
||||||
|
log, err := tRepos.MaintEntry.GetLog(context.Background(), item.ID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to get maintenance log: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, item.ID, log.ItemID)
|
||||||
|
assert.Equal(t, 10, len(log.Entries))
|
||||||
|
|
||||||
|
// Calculate the average cost
|
||||||
|
var total float64
|
||||||
|
|
||||||
|
for _, entry := range log.Entries {
|
||||||
|
total += entry.Cost
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, total, log.CostTotal, "total cost should be equal to the sum of all entries")
|
||||||
|
assert.Equal(t, total/2, log.CostAverage, "average cost should be the average of the two months")
|
||||||
|
|
||||||
|
for _, entry := range log.Entries {
|
||||||
|
err := tRepos.MaintEntry.Delete(context.Background(), entry.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ type AllRepos struct {
|
||||||
Items *ItemsRepository
|
Items *ItemsRepository
|
||||||
Docs *DocumentRepository
|
Docs *DocumentRepository
|
||||||
Attachments *AttachmentRepo
|
Attachments *AttachmentRepo
|
||||||
|
MaintEntry *MaintenanceEntryRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(db *ent.Client, root string) *AllRepos {
|
func New(db *ent.Client, root string) *AllRepos {
|
||||||
|
@ -24,5 +25,6 @@ func New(db *ent.Client, root string) *AllRepos {
|
||||||
Items: &ItemsRepository{db},
|
Items: &ItemsRepository{db},
|
||||||
Docs: &DocumentRepository{db, root},
|
Docs: &DocumentRepository{db, root},
|
||||||
Attachments: &AttachmentRepo{db},
|
Attachments: &AttachmentRepo{db},
|
||||||
|
MaintEntry: &MaintenanceEntryRepository{db},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue