ensure export contains locations path

This commit is contained in:
Hayden 2023-04-01 14:49:20 -08:00
parent 30fb679b95
commit e4562cd770
No known key found for this signature in database
GPG key ID: 17CF79474E257545
8 changed files with 108 additions and 25 deletions

View file

@ -1,7 +0,0 @@
Import Ref,Location,Labels,Quantity,Name,Description,Insured,Serial Number,Mode Number,Manufacturer,Notes,Purchase From,Purchased Price,Purchased Time,Lifetime Warranty,Warranty Expires,Warranty Details,Sold To,Sold Price,Sold Time,Sold Notes
A,Garage,IOT;Home Assistant; Z-Wave,1,Zooz Universal Relay ZEN17,Description 1,TRUE,,ZEN17,Zooz,,Amazon,39.95,10/13/2021,,10/13/2021,,,,10/13/2021,
B,Living Room,IOT;Home Assistant; Z-Wave,1,Zooz Motion Sensor,Description 2,FALSE,,ZSE18,Zooz,,Amazon,29.95,10/15/2021,,10/15/2021,,,,10/15/2021,
C,Office,IOT;Home Assistant; Z-Wave,1,Zooz 110v Power Switch,Description 3,TRUE,,ZEN15,Zooz,,Amazon,39.95,10/13/2021,,10/13/2021,,,,10/13/2021,
D,Downstairs,IOT;Home Assistant; Z-Wave,1,Ecolink Z-Wave PIR Motion Sensor,Description 4,FALSE,,PIRZWAVE2.5-ECO,Ecolink,,Amazon,35.58,10/21/2020,,10/21/2020,,,,10/21/2020,
E,Entry,IOT;Home Assistant; Z-Wave,1,Yale Security Touchscreen Deadbolt,Description 5,TRUE,,YRD226ZW2619,Yale,,Amazon,120.39,10/14/2020,,10/14/2020,,,,10/14/2020,
F,Kitchen,IOT;Home Assistant; Z-Wave,1,Smart Rocker Light Dimmer,Description 6,FALSE,,39351,Honeywell,,Amazon,65.98,09/30/2020,,09/30/2020,,,,09/30/2020,
1 Import Ref Location Labels Quantity Name Description Insured Serial Number Mode Number Manufacturer Notes Purchase From Purchased Price Purchased Time Lifetime Warranty Warranty Expires Warranty Details Sold To Sold Price Sold Time Sold Notes
2 A Garage IOT;Home Assistant; Z-Wave 1 Zooz Universal Relay ZEN17 Description 1 TRUE ZEN17 Zooz Amazon 39.95 10/13/2021 10/13/2021 10/13/2021
3 B Living Room IOT;Home Assistant; Z-Wave 1 Zooz Motion Sensor Description 2 FALSE ZSE18 Zooz Amazon 29.95 10/15/2021 10/15/2021 10/15/2021
4 C Office IOT;Home Assistant; Z-Wave 1 Zooz 110v Power Switch Description 3 TRUE ZEN15 Zooz Amazon 39.95 10/13/2021 10/13/2021 10/13/2021
5 D Downstairs IOT;Home Assistant; Z-Wave 1 Ecolink Z-Wave PIR Motion Sensor Description 4 FALSE PIRZWAVE2.5-ECO Ecolink Amazon 35.58 10/21/2020 10/21/2020 10/21/2020
6 E Entry IOT;Home Assistant; Z-Wave 1 Yale Security Touchscreen Deadbolt Description 5 TRUE YRD226ZW2619 Yale Amazon 120.39 10/14/2020 10/14/2020 10/14/2020
7 F Kitchen IOT;Home Assistant; Z-Wave 1 Smart Rocker Light Dimmer Description 6 FALSE 39351 Honeywell Amazon 65.98 09/30/2020 09/30/2020 09/30/2020

View file

@ -1,7 +0,0 @@
Import Ref Location Labels Quantity Name Description Insured Serial Number Mode Number Manufacturer Notes Purchase From Purchased Price Purchased Time Lifetime Warranty Warranty Expires Warranty Details Sold To Sold Price Sold Time Sold Notes
A Garage IOT;Home Assistant; Z-Wave 1 Zooz Universal Relay ZEN17 Description 1 TRUE ZEN17 Zooz Amazon 39.95 10/13/2021 10/13/2021 10/13/2021
B Living Room IOT;Home Assistant; Z-Wave 1 Zooz Motion Sensor Description 2 FALSE ZSE18 Zooz Amazon 29.95 10/15/2021 10/15/2021 10/15/2021
C Office IOT;Home Assistant; Z-Wave 1 Zooz 110v Power Switch Description 3 TRUE ZEN15 Zooz Amazon 39.95 10/13/2021 10/13/2021 10/13/2021
D Downstairs IOT;Home Assistant; Z-Wave 1 Ecolink Z-Wave PIR Motion Sensor Description 4 FALSE PIRZWAVE2.5-ECO Ecolink Amazon 35.58 10/21/2020 10/21/2020 10/21/2020
E Entry IOT;Home Assistant; Z-Wave 1 Yale Security Touchscreen Deadbolt Description 5 TRUE YRD226ZW2619 Yale Amazon 120.39 10/14/2020 10/14/2020 10/14/2020
F Kitchen IOT;Home Assistant; Z-Wave 1 Smart Rocker Light Dimmer Description 6 FALSE 39351 Honeywell Amazon 65.98 09/30/2020 09/30/2020 09/30/2020
1 Import Ref Location Labels Quantity Name Description Insured Serial Number Mode Number Manufacturer Notes Purchase From Purchased Price Purchased Time Lifetime Warranty Warranty Expires Warranty Details Sold To Sold Price Sold Time Sold Notes
2 A Garage IOT;Home Assistant; Z-Wave 1 Zooz Universal Relay ZEN17 Description 1 TRUE ZEN17 Zooz Amazon 39.95 10/13/2021 10/13/2021 10/13/2021
3 B Living Room IOT;Home Assistant; Z-Wave 1 Zooz Motion Sensor Description 2 FALSE ZSE18 Zooz Amazon 29.95 10/15/2021 10/15/2021 10/15/2021
4 C Office IOT;Home Assistant; Z-Wave 1 Zooz 110v Power Switch Description 3 TRUE ZEN15 Zooz Amazon 39.95 10/13/2021 10/13/2021 10/13/2021
5 D Downstairs IOT;Home Assistant; Z-Wave 1 Ecolink Z-Wave PIR Motion Sensor Description 4 FALSE PIRZWAVE2.5-ECO Ecolink Amazon 35.58 10/21/2020 10/21/2020 10/21/2020
6 E Entry IOT;Home Assistant; Z-Wave 1 Yale Security Touchscreen Deadbolt Description 5 TRUE YRD226ZW2619 Yale Amazon 120.39 10/14/2020 10/14/2020 10/14/2020
7 F Kitchen IOT;Home Assistant; Z-Wave 1 Smart Rocker Light Dimmer Description 6 FALSE 39351 Honeywell Amazon 65.98 09/30/2020 09/30/2020 09/30/2020

View file

@ -83,3 +83,13 @@ func parseLocationString(s string) LocationString {
func (csf LocationString) String() string {
return strings.Join(csf, " / ")
}
func fromPathSlice(s []repo.LocationPath) LocationString {
v := make(LocationString, len(s))
for i := range s {
v[i] = s[i].Name
}
return v
}

View file

@ -1,6 +1,7 @@
package reporting
import (
"context"
"fmt"
"io"
"reflect"
@ -8,6 +9,7 @@ import (
"strconv"
"strings"
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/data/repo"
"github.com/hay-kot/homebox/backend/internal/data/types"
"github.com/rs/zerolog/log"
@ -151,7 +153,7 @@ func (s *IOSheet) Read(data io.Reader) error {
}
// Write writes the sheet to a writer.
func (s *IOSheet) ReadItems(items []repo.ItemOut) {
func (s *IOSheet) ReadItems(ctx context.Context, items []repo.ItemOut, GID uuid.UUID, repos *repo.AllRepos) error {
s.Rows = make([]ExportTSVRow, len(items))
extraHeaders := map[string]struct{}{}
@ -160,7 +162,15 @@ func (s *IOSheet) ReadItems(items []repo.ItemOut) {
item := items[i]
// TODO: Support fetching nested locations
locString := LocationString{item.Location.Name}
locId := item.Location.ID
locPaths, err := repos.Locations.PathForLoc(context.Background(), GID, locId)
if err != nil {
log.Error().Err(err).Msg("could not get location path")
return err
}
locString := fromPathSlice(locPaths)
labelString := make([]string, len(item.Labels))
@ -238,6 +248,8 @@ func (s *IOSheet) ReadItems(items []repo.ItemOut) {
for _, h := range customHeaders {
s.headers = append(s.headers, "HB.field."+h)
}
return nil
}
// Writes the current sheet to a writer in TSV format.

View file

@ -20,12 +20,6 @@ var (
//go:embed .testdata/import/types.csv
customTypesImportCSV []byte
//go:embed .testdata/import.csv
CSVData_Comma []byte
//go:embed .testdata/import.tsv
CSVData_Tab []byte
)
func TestSheet_Read(t *testing.T) {
@ -189,7 +183,7 @@ func Test_determineSeparator(t *testing.T) {
{
name: "comma",
args: args{
data: CSVData_Comma,
data: []byte("a,b,c"),
},
want: ',',
wantErr: false,
@ -197,7 +191,7 @@ func Test_determineSeparator(t *testing.T) {
{
name: "tab",
args: args{
data: CSVData_Tab,
data: []byte("a\tb\tc"),
},
want: '\t',
wantErr: false,

View file

@ -337,7 +337,10 @@ func (svc *ItemService) ExportTSV(ctx context.Context, GID uuid.UUID) ([][]strin
sheet := reporting.IOSheet{}
sheet.ReadItems(items)
err = sheet.ReadItems(ctx, items, GID, svc.repo)
if err != nil {
return nil, err
}
return sheet.TSV()
}

View file

@ -249,6 +249,56 @@ type TreeQuery struct {
WithItems bool `json:"withItems" schema:"withItems"`
}
type LocationPath struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
}
func (lr *LocationRepository) PathForLoc(ctx context.Context, GID, locID uuid.UUID) ([]LocationPath, error) {
query := `WITH RECURSIVE location_path AS (
SELECT id, name, location_children
FROM locations
WHERE id = ? -- Replace ? with the ID of the item's location
AND group_locations = ? -- Replace ? with the ID of the group
UNION ALL
SELECT loc.id, loc.name, loc.location_children
FROM locations loc
JOIN location_path lp ON loc.id = lp.location_children
)
SELECT id, name
FROM location_path`
rows, err := lr.db.Sql().QueryContext(ctx, query, locID, GID)
if err != nil {
return nil, err
}
var locations []LocationPath
for rows.Next() {
var location LocationPath
if err := rows.Scan(&location.ID, &location.Name); err != nil {
return nil, err
}
locations = append(locations, location)
}
if err := rows.Err(); err != nil {
return nil, err
}
// Reverse the order of the locations so that the root is last
for i := len(locations)/2 - 1; i >= 0; i-- {
opp := len(locations) - 1 - i
locations[i], locations[opp] = locations[opp], locations[i]
}
return locations, nil
}
func (lr *LocationRepository) Tree(ctx context.Context, GID uuid.UUID, tq TreeQuery) ([]TreeItem, error) {
query := `
WITH recursive location_tree(id, NAME, parent_id, level, node_type) AS

View file

@ -146,6 +146,34 @@ func TestItemRepository_TreeQuery(t *testing.T) {
}
}
func TestLocationRepository_PathForLoc(t *testing.T) {
locs := useLocations(t, 3)
// Set relations 3 -> 2 -> 1
for i := 0; i < 2; i++ {
_, err := tRepos.Locations.UpdateByGroup(context.Background(), tGroup.ID, locs[i].ID, LocationUpdate{
ID: locs[i].ID,
ParentID: locs[i+1].ID,
Name: locs[i].Name,
Description: locs[i].Description,
})
assert.NoError(t, err)
}
last := locs[0]
path, err := tRepos.Locations.PathForLoc(context.Background(), tGroup.ID, last.ID)
assert.NoError(t, err)
assert.Equal(t, 3, len(path))
// Check path and order
for i, loc := range path {
assert.Equal(t, locs[i].ID, loc.ID)
assert.Equal(t, locs[i].Name, loc.Name)
}
}
func TestConvertLocationsToTree(t *testing.T) {
uuid1, uuid2, uuid3, uuid4 := uuid.New(), uuid.New(), uuid.New(), uuid.New()