Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions backend/internal/core/services/reporting/io_row.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ type ExportItemFields struct {
}

type ExportCSVRow struct {
ImportRef string `csv:"HB.import_ref"`
Location LocationString `csv:"HB.location"`
TagStr TagString `csv:"HB.tags|HB.labels"`
AssetID repo.AssetID `csv:"HB.asset_id"`
Archived bool `csv:"HB.archived"`
URL string `csv:"HB.url"`
ImportRef string `csv:"HB.import_ref"`
ParentImportRef string `csv:"HB.parent_import_ref"`
Location LocationString `csv:"HB.location"`
TagStr TagString `csv:"HB.tags|HB.labels"`
AssetID repo.AssetID `csv:"HB.asset_id"`
Archived bool `csv:"HB.archived"`
URL string `csv:"HB.url"`

Name string `csv:"HB.name"`
Quantity float64 `csv:"HB.quantity"`
Expand Down
27 changes: 19 additions & 8 deletions backend/internal/core/services/reporting/io_sheet.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,19 +235,30 @@ func (s *IOSheet) ReadItems(ctx context.Context, entities []repo.EntityOut, gid
}
})

// Resolve parent import ref for CSV output
var parentImportRef string
if item.Parent != nil {
// Find the parent entity to get its import_ref
parentEntity, err := repos.Entities.GetByID(ctx, gid, item.Parent.ID)
if err == nil && parentEntity.ImportRef != "" {
parentImportRef = parentEntity.ImportRef
}
}

s.Rows[i] = ExportCSVRow{
// fill struct
Location: locString,
TagStr: tagString,

ImportRef: item.ImportRef,
AssetID: item.AssetID,
Name: item.Name,
Quantity: item.Quantity,
Description: item.Description,
Insured: item.Insured,
Archived: item.Archived,
URL: url,
ImportRef: item.ImportRef,
ParentImportRef: parentImportRef,
AssetID: item.AssetID,
Comment on lines +238 to +255
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don’t swallow parent lookup failures.

A failed GetByID call currently becomes an empty ParentImportRef, which is indistinguishable from “no parent” and can silently drop hierarchy data on re-import. This also adds a per-row repository read; if this stays in the export path, cache parent refs by ID to avoid the N+1 pattern.

🔧 Suggested fix
-		parentEntity, err := repos.Entities.GetByID(ctx, gid, item.Parent.ID)
-		if err == nil && parentEntity.ImportRef != "" {
-			parentImportRef = parentEntity.ImportRef
-		}
+		parentEntity, err := repos.Entities.GetByID(ctx, gid, item.Parent.ID)
+		if err != nil {
+			return err
+		}
+		parentImportRef = parentEntity.ImportRef
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/internal/core/services/reporting/io_sheet.go` around lines 238 - 255,
The code currently swallows errors from repos.Entities.GetByID and does per-row
reads; change the logic in the export loop to (1) stop hiding lookup failures by
returning or logging the error when GetByID returns a non-nil err for a row that
has a Parent (i.e., don't treat errors as "no parent") and (2) eliminate the N+1
reads by adding a local cache map[parentID]string (lookup key item.Parent.ID)
that you consult before calling repos.Entities.GetByID; populate the cache on
first successful read and use cached ImportRef for subsequent rows, and ensure
the ParentImportRef assigned into ExportCSVRow uses the cached value or surfaces
the GetByID error instead of silently leaving it empty.

Name: item.Name,
Quantity: item.Quantity,
Description: item.Description,
Insured: item.Insured,
Archived: item.Archived,
URL: url,

PurchasePrice: item.PurchasePrice,
PurchaseFrom: item.PurchaseFrom,
Expand Down
Loading