homebox/backend/internal/core/services/service_items.go

197 lines
4.1 KiB
Go
Raw Normal View History

2022-09-03 09:17:48 +00:00
package services
import (
"context"
"errors"
2022-09-03 09:17:48 +00:00
"github.com/google/uuid"
"github.com/hay-kot/homebox/backend/internal/data/repo"
2022-09-06 19:15:07 +00:00
"github.com/rs/zerolog/log"
2022-09-03 09:17:48 +00:00
)
var (
ErrNotFound = errors.New("not found")
ErrFileNotFound = errors.New("file not found")
)
2022-09-03 09:17:48 +00:00
type ItemService struct {
repo *repo.AllRepos
filepath string
// at is a map of tokens to attachment IDs. This is used to store the attachment ID
// for issued URLs
at attachmentTokens
2022-09-03 09:17:48 +00:00
}
func (svc *ItemService) CsvImport(ctx context.Context, gid uuid.UUID, data [][]string) (int, error) {
2022-09-06 19:15:07 +00:00
loaded := []csvRow{}
// Skip first row
for _, row := range data[1:] {
// Skip empty rows
if len(row) == 0 {
continue
}
if len(row) != NumOfCols {
return 0, ErrInvalidCsv
2022-09-06 19:15:07 +00:00
}
r := newCsvRow(row)
loaded = append(loaded, r)
}
// validate rows
var errMap = map[int][]error{}
var hasErr bool
for i, r := range loaded {
errs := r.validate()
if len(errs) > 0 {
hasErr = true
lineNum := i + 2
errMap[lineNum] = errs
}
}
if hasErr {
for lineNum, errs := range errMap {
for _, err := range errs {
log.Error().Err(err).Int("line", lineNum).Msg("csv import error")
}
}
}
2022-09-06 19:15:07 +00:00
// Bootstrap the locations and labels so we can reuse the created IDs for the items
locations := map[string]uuid.UUID{}
existingLocation, err := svc.repo.Locations.GetAll(ctx, gid)
if err != nil {
return 0, err
2022-09-06 19:15:07 +00:00
}
for _, loc := range existingLocation {
locations[loc.Name] = loc.ID
}
labels := map[string]uuid.UUID{}
existingLabels, err := svc.repo.Labels.GetAll(ctx, gid)
if err != nil {
return 0, err
2022-09-06 19:15:07 +00:00
}
for _, label := range existingLabels {
labels[label.Name] = label.ID
}
for _, row := range loaded {
// Locations
if _, exists := locations[row.Location]; !exists {
result, err := svc.repo.Locations.Create(ctx, gid, repo.LocationCreate{
Name: row.Location,
Description: "",
})
if err != nil {
return 0, err
}
locations[row.Location] = result.ID
2022-09-06 19:15:07 +00:00
}
// Labels
for _, label := range row.getLabels() {
if _, exists := labels[label]; exists {
2022-09-06 19:15:07 +00:00
continue
}
result, err := svc.repo.Labels.Create(ctx, gid, repo.LabelCreate{
2022-09-06 19:15:07 +00:00
Name: label,
Description: "",
})
if err != nil {
return 0, err
2022-09-06 19:15:07 +00:00
}
labels[label] = result.ID
}
}
// Create the items
var count int
2022-09-06 19:15:07 +00:00
for _, row := range loaded {
// Check Import Ref
if row.Item.ImportRef != "" {
exists, err := svc.repo.Items.CheckRef(ctx, gid, row.Item.ImportRef)
if exists {
continue
}
if err != nil {
log.Err(err).Msg("error checking import ref")
}
}
2022-09-06 19:15:07 +00:00
locationID := locations[row.Location]
labelIDs := []uuid.UUID{}
for _, label := range row.getLabels() {
labelIDs = append(labelIDs, labels[label])
}
log.Info().
Str("name", row.Item.Name).
2022-09-06 19:15:07 +00:00
Str("location", row.Location).
Msgf("Creating Item: %s", row.Item.Name)
2022-09-06 19:15:07 +00:00
result, err := svc.repo.Items.Create(ctx, gid, repo.ItemCreate{
ImportRef: row.Item.ImportRef,
Name: row.Item.Name,
Description: row.Item.Description,
2022-09-06 19:15:07 +00:00
LabelIDs: labelIDs,
LocationID: locationID,
})
if err != nil {
return count, err
2022-09-06 19:15:07 +00:00
}
// Update the item with the rest of the data
_, err = svc.repo.Items.UpdateByGroup(ctx, gid, repo.ItemUpdate{
// Edges
LocationID: locationID,
LabelIDs: labelIDs,
// General Fields
ID: result.ID,
Name: result.Name,
Description: result.Description,
Insured: row.Item.Insured,
Notes: row.Item.Notes,
Quantity: row.Item.Quantity,
// Identifies the item as imported
SerialNumber: row.Item.SerialNumber,
ModelNumber: row.Item.ModelNumber,
Manufacturer: row.Item.Manufacturer,
// Purchase
PurchaseFrom: row.Item.PurchaseFrom,
PurchasePrice: row.Item.PurchasePrice,
PurchaseTime: row.Item.PurchaseTime,
// Warranty
LifetimeWarranty: row.Item.LifetimeWarranty,
WarrantyExpires: row.Item.WarrantyExpires,
WarrantyDetails: row.Item.WarrantyDetails,
SoldTo: row.Item.SoldTo,
SoldPrice: row.Item.SoldPrice,
SoldTime: row.Item.SoldTime,
SoldNotes: row.Item.SoldNotes,
2022-09-06 19:15:07 +00:00
})
if err != nil {
return count, err
2022-09-06 19:15:07 +00:00
}
count++
2022-09-06 19:15:07 +00:00
}
return count, nil
2022-09-06 19:15:07 +00:00
}