diff --git a/backend/ent/client.go b/backend/ent/client.go index 54a0d47..a9a8168 100644 --- a/backend/ent/client.go +++ b/backend/ent/client.go @@ -1043,6 +1043,38 @@ func (c *ItemClient) GetX(ctx context.Context, id uuid.UUID) *Item { return obj } +// QueryParent queries the parent edge of a Item. +func (c *ItemClient) QueryParent(i *Item) *ItemQuery { + query := &ItemQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := i.ID + step := sqlgraph.NewStep( + sqlgraph.From(item.Table, item.FieldID, id), + sqlgraph.To(item.Table, item.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, item.ParentTable, item.ParentColumn), + ) + fromV = sqlgraph.Neighbors(i.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// QueryChildren queries the children edge of a Item. +func (c *ItemClient) QueryChildren(i *Item) *ItemQuery { + query := &ItemQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := i.ID + step := sqlgraph.NewStep( + sqlgraph.From(item.Table, item.FieldID, id), + sqlgraph.To(item.Table, item.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, item.ChildrenTable, item.ChildrenColumn), + ) + fromV = sqlgraph.Neighbors(i.driver.Dialect(), step) + return fromV, nil + } + return query +} + // QueryGroup queries the group edge of a Item. func (c *ItemClient) QueryGroup(i *Item) *GroupQuery { query := &GroupQuery{config: c.config} @@ -1441,6 +1473,38 @@ func (c *LocationClient) GetX(ctx context.Context, id uuid.UUID) *Location { return obj } +// QueryParent queries the parent edge of a Location. +func (c *LocationClient) QueryParent(l *Location) *LocationQuery { + query := &LocationQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := l.ID + step := sqlgraph.NewStep( + sqlgraph.From(location.Table, location.FieldID, id), + sqlgraph.To(location.Table, location.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, location.ParentTable, location.ParentColumn), + ) + fromV = sqlgraph.Neighbors(l.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// QueryChildren queries the children edge of a Location. +func (c *LocationClient) QueryChildren(l *Location) *LocationQuery { + query := &LocationQuery{config: c.config} + query.path = func(ctx context.Context) (fromV *sql.Selector, _ error) { + id := l.ID + step := sqlgraph.NewStep( + sqlgraph.From(location.Table, location.FieldID, id), + sqlgraph.To(location.Table, location.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, location.ChildrenTable, location.ChildrenColumn), + ) + fromV = sqlgraph.Neighbors(l.driver.Dialect(), step) + return fromV, nil + } + return query +} + // QueryGroup queries the group edge of a Location. func (c *LocationClient) QueryGroup(l *Location) *GroupQuery { query := &GroupQuery{config: c.config} diff --git a/backend/ent/item.go b/backend/ent/item.go index 3aad369..c1b1eff 100644 --- a/backend/ent/item.go +++ b/backend/ent/item.go @@ -65,11 +65,16 @@ type Item struct { // The values are being populated by the ItemQuery when eager-loading is set. Edges ItemEdges `json:"edges"` group_items *uuid.UUID + item_children *uuid.UUID location_items *uuid.UUID } // ItemEdges holds the relations/edges for other nodes in the graph. type ItemEdges struct { + // Parent holds the value of the parent edge. + Parent *Item `json:"parent,omitempty"` + // Children holds the value of the children edge. + Children []*Item `json:"children,omitempty"` // Group holds the value of the group edge. Group *Group `json:"group,omitempty"` // Label holds the value of the label edge. @@ -82,13 +87,35 @@ type ItemEdges struct { Attachments []*Attachment `json:"attachments,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [5]bool + loadedTypes [7]bool +} + +// ParentOrErr returns the Parent value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e ItemEdges) ParentOrErr() (*Item, error) { + if e.loadedTypes[0] { + if e.Parent == nil { + // Edge was loaded but was not found. + return nil, &NotFoundError{label: item.Label} + } + return e.Parent, nil + } + return nil, &NotLoadedError{edge: "parent"} +} + +// ChildrenOrErr returns the Children value or an error if the edge +// was not loaded in eager-loading. +func (e ItemEdges) ChildrenOrErr() ([]*Item, error) { + if e.loadedTypes[1] { + return e.Children, nil + } + return nil, &NotLoadedError{edge: "children"} } // GroupOrErr returns the Group value or an error if the edge // was not loaded in eager-loading, or loaded but was not found. func (e ItemEdges) GroupOrErr() (*Group, error) { - if e.loadedTypes[0] { + if e.loadedTypes[2] { if e.Group == nil { // Edge was loaded but was not found. return nil, &NotFoundError{label: group.Label} @@ -101,7 +128,7 @@ func (e ItemEdges) GroupOrErr() (*Group, error) { // LabelOrErr returns the Label value or an error if the edge // was not loaded in eager-loading. func (e ItemEdges) LabelOrErr() ([]*Label, error) { - if e.loadedTypes[1] { + if e.loadedTypes[3] { return e.Label, nil } return nil, &NotLoadedError{edge: "label"} @@ -110,7 +137,7 @@ func (e ItemEdges) LabelOrErr() ([]*Label, error) { // LocationOrErr returns the Location value or an error if the edge // was not loaded in eager-loading, or loaded but was not found. func (e ItemEdges) LocationOrErr() (*Location, error) { - if e.loadedTypes[2] { + if e.loadedTypes[4] { if e.Location == nil { // Edge was loaded but was not found. return nil, &NotFoundError{label: location.Label} @@ -123,7 +150,7 @@ func (e ItemEdges) LocationOrErr() (*Location, error) { // FieldsOrErr returns the Fields value or an error if the edge // was not loaded in eager-loading. func (e ItemEdges) FieldsOrErr() ([]*ItemField, error) { - if e.loadedTypes[3] { + if e.loadedTypes[5] { return e.Fields, nil } return nil, &NotLoadedError{edge: "fields"} @@ -132,7 +159,7 @@ func (e ItemEdges) FieldsOrErr() ([]*ItemField, error) { // AttachmentsOrErr returns the Attachments value or an error if the edge // was not loaded in eager-loading. func (e ItemEdges) AttachmentsOrErr() ([]*Attachment, error) { - if e.loadedTypes[4] { + if e.loadedTypes[6] { return e.Attachments, nil } return nil, &NotLoadedError{edge: "attachments"} @@ -157,7 +184,9 @@ func (*Item) scanValues(columns []string) ([]any, error) { values[i] = new(uuid.UUID) case item.ForeignKeys[0]: // group_items values[i] = &sql.NullScanner{S: new(uuid.UUID)} - case item.ForeignKeys[1]: // location_items + case item.ForeignKeys[1]: // item_children + values[i] = &sql.NullScanner{S: new(uuid.UUID)} + case item.ForeignKeys[2]: // location_items values[i] = &sql.NullScanner{S: new(uuid.UUID)} default: return nil, fmt.Errorf("unexpected column %q for type Item", columns[i]) @@ -314,6 +343,13 @@ func (i *Item) assignValues(columns []string, values []any) error { *i.group_items = *value.S.(*uuid.UUID) } case item.ForeignKeys[1]: + if value, ok := values[j].(*sql.NullScanner); !ok { + return fmt.Errorf("unexpected type %T for field item_children", values[j]) + } else if value.Valid { + i.item_children = new(uuid.UUID) + *i.item_children = *value.S.(*uuid.UUID) + } + case item.ForeignKeys[2]: if value, ok := values[j].(*sql.NullScanner); !ok { return fmt.Errorf("unexpected type %T for field location_items", values[j]) } else if value.Valid { @@ -325,6 +361,16 @@ func (i *Item) assignValues(columns []string, values []any) error { return nil } +// QueryParent queries the "parent" edge of the Item entity. +func (i *Item) QueryParent() *ItemQuery { + return (&ItemClient{config: i.config}).QueryParent(i) +} + +// QueryChildren queries the "children" edge of the Item entity. +func (i *Item) QueryChildren() *ItemQuery { + return (&ItemClient{config: i.config}).QueryChildren(i) +} + // QueryGroup queries the "group" edge of the Item entity. func (i *Item) QueryGroup() *GroupQuery { return (&ItemClient{config: i.config}).QueryGroup(i) diff --git a/backend/ent/item/item.go b/backend/ent/item/item.go index 6b9f38c..7592f5b 100644 --- a/backend/ent/item/item.go +++ b/backend/ent/item/item.go @@ -55,6 +55,10 @@ const ( FieldSoldPrice = "sold_price" // FieldSoldNotes holds the string denoting the sold_notes field in the database. FieldSoldNotes = "sold_notes" + // EdgeParent holds the string denoting the parent edge name in mutations. + EdgeParent = "parent" + // EdgeChildren holds the string denoting the children edge name in mutations. + EdgeChildren = "children" // EdgeGroup holds the string denoting the group edge name in mutations. EdgeGroup = "group" // EdgeLabel holds the string denoting the label edge name in mutations. @@ -67,6 +71,14 @@ const ( EdgeAttachments = "attachments" // Table holds the table name of the item in the database. Table = "items" + // ParentTable is the table that holds the parent relation/edge. + ParentTable = "items" + // ParentColumn is the table column denoting the parent relation/edge. + ParentColumn = "item_children" + // ChildrenTable is the table that holds the children relation/edge. + ChildrenTable = "items" + // ChildrenColumn is the table column denoting the children relation/edge. + ChildrenColumn = "item_children" // GroupTable is the table that holds the group relation/edge. GroupTable = "items" // GroupInverseTable is the table name for the Group entity. @@ -132,6 +144,7 @@ var Columns = []string{ // table and are not defined as standalone fields in the schema. var ForeignKeys = []string{ "group_items", + "item_children", "location_items", } diff --git a/backend/ent/item/where.go b/backend/ent/item/where.go index d0d191e..ec74275 100644 --- a/backend/ent/item/where.go +++ b/backend/ent/item/where.go @@ -2040,6 +2040,62 @@ func SoldNotesContainsFold(v string) predicate.Item { }) } +// HasParent applies the HasEdge predicate on the "parent" edge. +func HasParent() predicate.Item { + return predicate.Item(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ParentTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ParentTable, ParentColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasParentWith applies the HasEdge predicate on the "parent" edge with a given conditions (other predicates). +func HasParentWith(preds ...predicate.Item) predicate.Item { + return predicate.Item(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ParentTable, ParentColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// HasChildren applies the HasEdge predicate on the "children" edge. +func HasChildren() predicate.Item { + return predicate.Item(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ChildrenTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, ChildrenTable, ChildrenColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasChildrenWith applies the HasEdge predicate on the "children" edge with a given conditions (other predicates). +func HasChildrenWith(preds ...predicate.Item) predicate.Item { + return predicate.Item(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, ChildrenTable, ChildrenColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // HasGroup applies the HasEdge predicate on the "group" edge. func HasGroup() predicate.Item { return predicate.Item(func(s *sql.Selector) { diff --git a/backend/ent/item_create.go b/backend/ent/item_create.go index 3aee458..6134705 100644 --- a/backend/ent/item_create.go +++ b/backend/ent/item_create.go @@ -326,6 +326,40 @@ func (ic *ItemCreate) SetNillableID(u *uuid.UUID) *ItemCreate { return ic } +// SetParentID sets the "parent" edge to the Item entity by ID. +func (ic *ItemCreate) SetParentID(id uuid.UUID) *ItemCreate { + ic.mutation.SetParentID(id) + return ic +} + +// SetNillableParentID sets the "parent" edge to the Item entity by ID if the given value is not nil. +func (ic *ItemCreate) SetNillableParentID(id *uuid.UUID) *ItemCreate { + if id != nil { + ic = ic.SetParentID(*id) + } + return ic +} + +// SetParent sets the "parent" edge to the Item entity. +func (ic *ItemCreate) SetParent(i *Item) *ItemCreate { + return ic.SetParentID(i.ID) +} + +// AddChildIDs adds the "children" edge to the Item entity by IDs. +func (ic *ItemCreate) AddChildIDs(ids ...uuid.UUID) *ItemCreate { + ic.mutation.AddChildIDs(ids...) + return ic +} + +// AddChildren adds the "children" edges to the Item entity. +func (ic *ItemCreate) AddChildren(i ...*Item) *ItemCreate { + ids := make([]uuid.UUID, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return ic.AddChildIDs(ids...) +} + // SetGroupID sets the "group" edge to the Group entity by ID. func (ic *ItemCreate) SetGroupID(id uuid.UUID) *ItemCreate { ic.mutation.SetGroupID(id) @@ -790,6 +824,45 @@ func (ic *ItemCreate) createSpec() (*Item, *sqlgraph.CreateSpec) { }) _node.SoldNotes = value } + if nodes := ic.mutation.ParentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: item.ParentTable, + Columns: []string{item.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.item_children = &nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + if nodes := ic.mutation.ChildrenIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.ChildrenTable, + Columns: []string{item.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } if nodes := ic.mutation.GroupIDs(); len(nodes) > 0 { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.M2O, diff --git a/backend/ent/item_query.go b/backend/ent/item_query.go index 3bf5877..e6d1173 100644 --- a/backend/ent/item_query.go +++ b/backend/ent/item_query.go @@ -30,6 +30,8 @@ type ItemQuery struct { order []OrderFunc fields []string predicates []predicate.Item + withParent *ItemQuery + withChildren *ItemQuery withGroup *GroupQuery withLabel *LabelQuery withLocation *LocationQuery @@ -72,6 +74,50 @@ func (iq *ItemQuery) Order(o ...OrderFunc) *ItemQuery { return iq } +// QueryParent chains the current query on the "parent" edge. +func (iq *ItemQuery) QueryParent() *ItemQuery { + query := &ItemQuery{config: iq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := iq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := iq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(item.Table, item.FieldID, selector), + sqlgraph.To(item.Table, item.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, item.ParentTable, item.ParentColumn), + ) + fromU = sqlgraph.SetNeighbors(iq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// QueryChildren chains the current query on the "children" edge. +func (iq *ItemQuery) QueryChildren() *ItemQuery { + query := &ItemQuery{config: iq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := iq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := iq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(item.Table, item.FieldID, selector), + sqlgraph.To(item.Table, item.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, item.ChildrenTable, item.ChildrenColumn), + ) + fromU = sqlgraph.SetNeighbors(iq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // QueryGroup chains the current query on the "group" edge. func (iq *ItemQuery) QueryGroup() *GroupQuery { query := &GroupQuery{config: iq.config} @@ -363,6 +409,8 @@ func (iq *ItemQuery) Clone() *ItemQuery { offset: iq.offset, order: append([]OrderFunc{}, iq.order...), predicates: append([]predicate.Item{}, iq.predicates...), + withParent: iq.withParent.Clone(), + withChildren: iq.withChildren.Clone(), withGroup: iq.withGroup.Clone(), withLabel: iq.withLabel.Clone(), withLocation: iq.withLocation.Clone(), @@ -375,6 +423,28 @@ func (iq *ItemQuery) Clone() *ItemQuery { } } +// WithParent tells the query-builder to eager-load the nodes that are connected to +// the "parent" edge. The optional arguments are used to configure the query builder of the edge. +func (iq *ItemQuery) WithParent(opts ...func(*ItemQuery)) *ItemQuery { + query := &ItemQuery{config: iq.config} + for _, opt := range opts { + opt(query) + } + iq.withParent = query + return iq +} + +// WithChildren tells the query-builder to eager-load the nodes that are connected to +// the "children" edge. The optional arguments are used to configure the query builder of the edge. +func (iq *ItemQuery) WithChildren(opts ...func(*ItemQuery)) *ItemQuery { + query := &ItemQuery{config: iq.config} + for _, opt := range opts { + opt(query) + } + iq.withChildren = query + return iq +} + // WithGroup tells the query-builder to eager-load the nodes that are connected to // the "group" edge. The optional arguments are used to configure the query builder of the edge. func (iq *ItemQuery) WithGroup(opts ...func(*GroupQuery)) *ItemQuery { @@ -499,7 +569,9 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e nodes = []*Item{} withFKs = iq.withFKs _spec = iq.querySpec() - loadedTypes = [5]bool{ + loadedTypes = [7]bool{ + iq.withParent != nil, + iq.withChildren != nil, iq.withGroup != nil, iq.withLabel != nil, iq.withLocation != nil, @@ -507,7 +579,7 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e iq.withAttachments != nil, } ) - if iq.withGroup != nil || iq.withLocation != nil { + if iq.withParent != nil || iq.withGroup != nil || iq.withLocation != nil { withFKs = true } if withFKs { @@ -531,6 +603,19 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e if len(nodes) == 0 { return nodes, nil } + if query := iq.withParent; query != nil { + if err := iq.loadParent(ctx, query, nodes, nil, + func(n *Item, e *Item) { n.Edges.Parent = e }); err != nil { + return nil, err + } + } + if query := iq.withChildren; query != nil { + if err := iq.loadChildren(ctx, query, nodes, + func(n *Item) { n.Edges.Children = []*Item{} }, + func(n *Item, e *Item) { n.Edges.Children = append(n.Edges.Children, e) }); err != nil { + return nil, err + } + } if query := iq.withGroup; query != nil { if err := iq.loadGroup(ctx, query, nodes, nil, func(n *Item, e *Group) { n.Edges.Group = e }); err != nil { @@ -567,6 +652,66 @@ func (iq *ItemQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Item, e return nodes, nil } +func (iq *ItemQuery) loadParent(ctx context.Context, query *ItemQuery, nodes []*Item, init func(*Item), assign func(*Item, *Item)) error { + ids := make([]uuid.UUID, 0, len(nodes)) + nodeids := make(map[uuid.UUID][]*Item) + for i := range nodes { + if nodes[i].item_children == nil { + continue + } + fk := *nodes[i].item_children + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + query.Where(item.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "item_children" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} +func (iq *ItemQuery) loadChildren(ctx context.Context, query *ItemQuery, nodes []*Item, init func(*Item), assign func(*Item, *Item)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[uuid.UUID]*Item) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + if init != nil { + init(nodes[i]) + } + } + query.withFKs = true + query.Where(predicate.Item(func(s *sql.Selector) { + s.Where(sql.InValues(item.ChildrenColumn, fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.item_children + if fk == nil { + return fmt.Errorf(`foreign-key "item_children" is nil for node %v`, n.ID) + } + node, ok := nodeids[*fk] + if !ok { + return fmt.Errorf(`unexpected foreign-key "item_children" returned %v for node %v`, *fk, n.ID) + } + assign(node, n) + } + return nil +} func (iq *ItemQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*Item, init func(*Item), assign func(*Item, *Group)) error { ids := make([]uuid.UUID, 0, len(nodes)) nodeids := make(map[uuid.UUID][]*Item) diff --git a/backend/ent/item_update.go b/backend/ent/item_update.go index a5b880d..5b08da7 100644 --- a/backend/ent/item_update.go +++ b/backend/ent/item_update.go @@ -377,6 +377,40 @@ func (iu *ItemUpdate) ClearSoldNotes() *ItemUpdate { return iu } +// SetParentID sets the "parent" edge to the Item entity by ID. +func (iu *ItemUpdate) SetParentID(id uuid.UUID) *ItemUpdate { + iu.mutation.SetParentID(id) + return iu +} + +// SetNillableParentID sets the "parent" edge to the Item entity by ID if the given value is not nil. +func (iu *ItemUpdate) SetNillableParentID(id *uuid.UUID) *ItemUpdate { + if id != nil { + iu = iu.SetParentID(*id) + } + return iu +} + +// SetParent sets the "parent" edge to the Item entity. +func (iu *ItemUpdate) SetParent(i *Item) *ItemUpdate { + return iu.SetParentID(i.ID) +} + +// AddChildIDs adds the "children" edge to the Item entity by IDs. +func (iu *ItemUpdate) AddChildIDs(ids ...uuid.UUID) *ItemUpdate { + iu.mutation.AddChildIDs(ids...) + return iu +} + +// AddChildren adds the "children" edges to the Item entity. +func (iu *ItemUpdate) AddChildren(i ...*Item) *ItemUpdate { + ids := make([]uuid.UUID, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iu.AddChildIDs(ids...) +} + // SetGroupID sets the "group" edge to the Group entity by ID. func (iu *ItemUpdate) SetGroupID(id uuid.UUID) *ItemUpdate { iu.mutation.SetGroupID(id) @@ -457,6 +491,33 @@ func (iu *ItemUpdate) Mutation() *ItemMutation { return iu.mutation } +// ClearParent clears the "parent" edge to the Item entity. +func (iu *ItemUpdate) ClearParent() *ItemUpdate { + iu.mutation.ClearParent() + return iu +} + +// ClearChildren clears all "children" edges to the Item entity. +func (iu *ItemUpdate) ClearChildren() *ItemUpdate { + iu.mutation.ClearChildren() + return iu +} + +// RemoveChildIDs removes the "children" edge to Item entities by IDs. +func (iu *ItemUpdate) RemoveChildIDs(ids ...uuid.UUID) *ItemUpdate { + iu.mutation.RemoveChildIDs(ids...) + return iu +} + +// RemoveChildren removes "children" edges to Item entities. +func (iu *ItemUpdate) RemoveChildren(i ...*Item) *ItemUpdate { + ids := make([]uuid.UUID, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iu.RemoveChildIDs(ids...) +} + // ClearGroup clears the "group" edge to the Group entity. func (iu *ItemUpdate) ClearGroup() *ItemUpdate { iu.mutation.ClearGroup() @@ -899,6 +960,95 @@ func (iu *ItemUpdate) sqlSave(ctx context.Context) (n int, err error) { Column: item.FieldSoldNotes, }) } + if iu.mutation.ParentCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: item.ParentTable, + Columns: []string{item.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iu.mutation.ParentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: item.ParentTable, + Columns: []string{item.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if iu.mutation.ChildrenCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.ChildrenTable, + Columns: []string{item.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iu.mutation.RemovedChildrenIDs(); len(nodes) > 0 && !iu.mutation.ChildrenCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.ChildrenTable, + Columns: []string{item.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iu.mutation.ChildrenIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.ChildrenTable, + Columns: []string{item.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if iu.mutation.GroupCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.M2O, @@ -1493,6 +1643,40 @@ func (iuo *ItemUpdateOne) ClearSoldNotes() *ItemUpdateOne { return iuo } +// SetParentID sets the "parent" edge to the Item entity by ID. +func (iuo *ItemUpdateOne) SetParentID(id uuid.UUID) *ItemUpdateOne { + iuo.mutation.SetParentID(id) + return iuo +} + +// SetNillableParentID sets the "parent" edge to the Item entity by ID if the given value is not nil. +func (iuo *ItemUpdateOne) SetNillableParentID(id *uuid.UUID) *ItemUpdateOne { + if id != nil { + iuo = iuo.SetParentID(*id) + } + return iuo +} + +// SetParent sets the "parent" edge to the Item entity. +func (iuo *ItemUpdateOne) SetParent(i *Item) *ItemUpdateOne { + return iuo.SetParentID(i.ID) +} + +// AddChildIDs adds the "children" edge to the Item entity by IDs. +func (iuo *ItemUpdateOne) AddChildIDs(ids ...uuid.UUID) *ItemUpdateOne { + iuo.mutation.AddChildIDs(ids...) + return iuo +} + +// AddChildren adds the "children" edges to the Item entity. +func (iuo *ItemUpdateOne) AddChildren(i ...*Item) *ItemUpdateOne { + ids := make([]uuid.UUID, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iuo.AddChildIDs(ids...) +} + // SetGroupID sets the "group" edge to the Group entity by ID. func (iuo *ItemUpdateOne) SetGroupID(id uuid.UUID) *ItemUpdateOne { iuo.mutation.SetGroupID(id) @@ -1573,6 +1757,33 @@ func (iuo *ItemUpdateOne) Mutation() *ItemMutation { return iuo.mutation } +// ClearParent clears the "parent" edge to the Item entity. +func (iuo *ItemUpdateOne) ClearParent() *ItemUpdateOne { + iuo.mutation.ClearParent() + return iuo +} + +// ClearChildren clears all "children" edges to the Item entity. +func (iuo *ItemUpdateOne) ClearChildren() *ItemUpdateOne { + iuo.mutation.ClearChildren() + return iuo +} + +// RemoveChildIDs removes the "children" edge to Item entities by IDs. +func (iuo *ItemUpdateOne) RemoveChildIDs(ids ...uuid.UUID) *ItemUpdateOne { + iuo.mutation.RemoveChildIDs(ids...) + return iuo +} + +// RemoveChildren removes "children" edges to Item entities. +func (iuo *ItemUpdateOne) RemoveChildren(i ...*Item) *ItemUpdateOne { + ids := make([]uuid.UUID, len(i)) + for j := range i { + ids[j] = i[j].ID + } + return iuo.RemoveChildIDs(ids...) +} + // ClearGroup clears the "group" edge to the Group entity. func (iuo *ItemUpdateOne) ClearGroup() *ItemUpdateOne { iuo.mutation.ClearGroup() @@ -2045,6 +2256,95 @@ func (iuo *ItemUpdateOne) sqlSave(ctx context.Context) (_node *Item, err error) Column: item.FieldSoldNotes, }) } + if iuo.mutation.ParentCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: item.ParentTable, + Columns: []string{item.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iuo.mutation.ParentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: item.ParentTable, + Columns: []string{item.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if iuo.mutation.ChildrenCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.ChildrenTable, + Columns: []string{item.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iuo.mutation.RemovedChildrenIDs(); len(nodes) > 0 && !iuo.mutation.ChildrenCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.ChildrenTable, + Columns: []string{item.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := iuo.mutation.ChildrenIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: item.ChildrenTable, + Columns: []string{item.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: item.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if iuo.mutation.GroupCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.M2O, diff --git a/backend/ent/location.go b/backend/ent/location.go index 85b0b16..337126b 100644 --- a/backend/ent/location.go +++ b/backend/ent/location.go @@ -28,25 +28,52 @@ type Location struct { Description string `json:"description,omitempty"` // Edges holds the relations/edges for other nodes in the graph. // The values are being populated by the LocationQuery when eager-loading is set. - Edges LocationEdges `json:"edges"` - group_locations *uuid.UUID + Edges LocationEdges `json:"edges"` + group_locations *uuid.UUID + location_children *uuid.UUID } // LocationEdges holds the relations/edges for other nodes in the graph. type LocationEdges struct { + // Parent holds the value of the parent edge. + Parent *Location `json:"parent,omitempty"` + // Children holds the value of the children edge. + Children []*Location `json:"children,omitempty"` // Group holds the value of the group edge. Group *Group `json:"group,omitempty"` // Items holds the value of the items edge. Items []*Item `json:"items,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [2]bool + loadedTypes [4]bool +} + +// ParentOrErr returns the Parent value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e LocationEdges) ParentOrErr() (*Location, error) { + if e.loadedTypes[0] { + if e.Parent == nil { + // Edge was loaded but was not found. + return nil, &NotFoundError{label: location.Label} + } + return e.Parent, nil + } + return nil, &NotLoadedError{edge: "parent"} +} + +// ChildrenOrErr returns the Children value or an error if the edge +// was not loaded in eager-loading. +func (e LocationEdges) ChildrenOrErr() ([]*Location, error) { + if e.loadedTypes[1] { + return e.Children, nil + } + return nil, &NotLoadedError{edge: "children"} } // GroupOrErr returns the Group value or an error if the edge // was not loaded in eager-loading, or loaded but was not found. func (e LocationEdges) GroupOrErr() (*Group, error) { - if e.loadedTypes[0] { + if e.loadedTypes[2] { if e.Group == nil { // Edge was loaded but was not found. return nil, &NotFoundError{label: group.Label} @@ -59,7 +86,7 @@ func (e LocationEdges) GroupOrErr() (*Group, error) { // ItemsOrErr returns the Items value or an error if the edge // was not loaded in eager-loading. func (e LocationEdges) ItemsOrErr() ([]*Item, error) { - if e.loadedTypes[1] { + if e.loadedTypes[3] { return e.Items, nil } return nil, &NotLoadedError{edge: "items"} @@ -78,6 +105,8 @@ func (*Location) scanValues(columns []string) ([]any, error) { values[i] = new(uuid.UUID) case location.ForeignKeys[0]: // group_locations values[i] = &sql.NullScanner{S: new(uuid.UUID)} + case location.ForeignKeys[1]: // location_children + values[i] = &sql.NullScanner{S: new(uuid.UUID)} default: return nil, fmt.Errorf("unexpected column %q for type Location", columns[i]) } @@ -130,11 +159,28 @@ func (l *Location) assignValues(columns []string, values []any) error { l.group_locations = new(uuid.UUID) *l.group_locations = *value.S.(*uuid.UUID) } + case location.ForeignKeys[1]: + if value, ok := values[i].(*sql.NullScanner); !ok { + return fmt.Errorf("unexpected type %T for field location_children", values[i]) + } else if value.Valid { + l.location_children = new(uuid.UUID) + *l.location_children = *value.S.(*uuid.UUID) + } } } return nil } +// QueryParent queries the "parent" edge of the Location entity. +func (l *Location) QueryParent() *LocationQuery { + return (&LocationClient{config: l.config}).QueryParent(l) +} + +// QueryChildren queries the "children" edge of the Location entity. +func (l *Location) QueryChildren() *LocationQuery { + return (&LocationClient{config: l.config}).QueryChildren(l) +} + // QueryGroup queries the "group" edge of the Location entity. func (l *Location) QueryGroup() *GroupQuery { return (&LocationClient{config: l.config}).QueryGroup(l) diff --git a/backend/ent/location/location.go b/backend/ent/location/location.go index 322658e..96cb75c 100644 --- a/backend/ent/location/location.go +++ b/backend/ent/location/location.go @@ -21,12 +21,24 @@ const ( FieldName = "name" // FieldDescription holds the string denoting the description field in the database. FieldDescription = "description" + // EdgeParent holds the string denoting the parent edge name in mutations. + EdgeParent = "parent" + // EdgeChildren holds the string denoting the children edge name in mutations. + EdgeChildren = "children" // EdgeGroup holds the string denoting the group edge name in mutations. EdgeGroup = "group" // EdgeItems holds the string denoting the items edge name in mutations. EdgeItems = "items" // Table holds the table name of the location in the database. Table = "locations" + // ParentTable is the table that holds the parent relation/edge. + ParentTable = "locations" + // ParentColumn is the table column denoting the parent relation/edge. + ParentColumn = "location_children" + // ChildrenTable is the table that holds the children relation/edge. + ChildrenTable = "locations" + // ChildrenColumn is the table column denoting the children relation/edge. + ChildrenColumn = "location_children" // GroupTable is the table that holds the group relation/edge. GroupTable = "locations" // GroupInverseTable is the table name for the Group entity. @@ -56,6 +68,7 @@ var Columns = []string{ // table and are not defined as standalone fields in the schema. var ForeignKeys = []string{ "group_locations", + "location_children", } // ValidColumn reports if the column name is valid (part of the table columns). diff --git a/backend/ent/location/where.go b/backend/ent/location/where.go index 819c893..20738b7 100644 --- a/backend/ent/location/where.go +++ b/backend/ent/location/where.go @@ -450,6 +450,62 @@ func DescriptionContainsFold(v string) predicate.Location { }) } +// HasParent applies the HasEdge predicate on the "parent" edge. +func HasParent() predicate.Location { + return predicate.Location(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ParentTable, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ParentTable, ParentColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasParentWith applies the HasEdge predicate on the "parent" edge with a given conditions (other predicates). +func HasParentWith(preds ...predicate.Location) predicate.Location { + return predicate.Location(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(Table, FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, ParentTable, ParentColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// HasChildren applies the HasEdge predicate on the "children" edge. +func HasChildren() predicate.Location { + return predicate.Location(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(ChildrenTable, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, ChildrenTable, ChildrenColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasChildrenWith applies the HasEdge predicate on the "children" edge with a given conditions (other predicates). +func HasChildrenWith(preds ...predicate.Location) predicate.Location { + return predicate.Location(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, ChildrenTable, ChildrenColumn), + ) + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // HasGroup applies the HasEdge predicate on the "group" edge. func HasGroup() predicate.Location { return predicate.Location(func(s *sql.Selector) { diff --git a/backend/ent/location_create.go b/backend/ent/location_create.go index df6a88e..ceff804 100644 --- a/backend/ent/location_create.go +++ b/backend/ent/location_create.go @@ -85,6 +85,40 @@ func (lc *LocationCreate) SetNillableID(u *uuid.UUID) *LocationCreate { return lc } +// SetParentID sets the "parent" edge to the Location entity by ID. +func (lc *LocationCreate) SetParentID(id uuid.UUID) *LocationCreate { + lc.mutation.SetParentID(id) + return lc +} + +// SetNillableParentID sets the "parent" edge to the Location entity by ID if the given value is not nil. +func (lc *LocationCreate) SetNillableParentID(id *uuid.UUID) *LocationCreate { + if id != nil { + lc = lc.SetParentID(*id) + } + return lc +} + +// SetParent sets the "parent" edge to the Location entity. +func (lc *LocationCreate) SetParent(l *Location) *LocationCreate { + return lc.SetParentID(l.ID) +} + +// AddChildIDs adds the "children" edge to the Location entity by IDs. +func (lc *LocationCreate) AddChildIDs(ids ...uuid.UUID) *LocationCreate { + lc.mutation.AddChildIDs(ids...) + return lc +} + +// AddChildren adds the "children" edges to the Location entity. +func (lc *LocationCreate) AddChildren(l ...*Location) *LocationCreate { + ids := make([]uuid.UUID, len(l)) + for i := range l { + ids[i] = l[i].ID + } + return lc.AddChildIDs(ids...) +} + // SetGroupID sets the "group" edge to the Group entity by ID. func (lc *LocationCreate) SetGroupID(id uuid.UUID) *LocationCreate { lc.mutation.SetGroupID(id) @@ -294,6 +328,45 @@ func (lc *LocationCreate) createSpec() (*Location, *sqlgraph.CreateSpec) { }) _node.Description = value } + if nodes := lc.mutation.ParentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: location.ParentTable, + Columns: []string{location.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: location.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.location_children = &nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + if nodes := lc.mutation.ChildrenIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: location.ChildrenTable, + Columns: []string{location.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: location.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } if nodes := lc.mutation.GroupIDs(); len(nodes) > 0 { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.M2O, diff --git a/backend/ent/location_query.go b/backend/ent/location_query.go index 0097cb5..9cf0b55 100644 --- a/backend/ent/location_query.go +++ b/backend/ent/location_query.go @@ -21,15 +21,17 @@ import ( // LocationQuery is the builder for querying Location entities. type LocationQuery struct { config - limit *int - offset *int - unique *bool - order []OrderFunc - fields []string - predicates []predicate.Location - withGroup *GroupQuery - withItems *ItemQuery - withFKs bool + limit *int + offset *int + unique *bool + order []OrderFunc + fields []string + predicates []predicate.Location + withParent *LocationQuery + withChildren *LocationQuery + withGroup *GroupQuery + withItems *ItemQuery + withFKs bool // intermediate query (i.e. traversal path). sql *sql.Selector path func(context.Context) (*sql.Selector, error) @@ -66,6 +68,50 @@ func (lq *LocationQuery) Order(o ...OrderFunc) *LocationQuery { return lq } +// QueryParent chains the current query on the "parent" edge. +func (lq *LocationQuery) QueryParent() *LocationQuery { + query := &LocationQuery{config: lq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := lq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := lq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(location.Table, location.FieldID, selector), + sqlgraph.To(location.Table, location.FieldID), + sqlgraph.Edge(sqlgraph.M2O, true, location.ParentTable, location.ParentColumn), + ) + fromU = sqlgraph.SetNeighbors(lq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// QueryChildren chains the current query on the "children" edge. +func (lq *LocationQuery) QueryChildren() *LocationQuery { + query := &LocationQuery{config: lq.config} + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := lq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := lq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(location.Table, location.FieldID, selector), + sqlgraph.To(location.Table, location.FieldID), + sqlgraph.Edge(sqlgraph.O2M, false, location.ChildrenTable, location.ChildrenColumn), + ) + fromU = sqlgraph.SetNeighbors(lq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // QueryGroup chains the current query on the "group" edge. func (lq *LocationQuery) QueryGroup() *GroupQuery { query := &GroupQuery{config: lq.config} @@ -286,13 +332,15 @@ func (lq *LocationQuery) Clone() *LocationQuery { return nil } return &LocationQuery{ - config: lq.config, - limit: lq.limit, - offset: lq.offset, - order: append([]OrderFunc{}, lq.order...), - predicates: append([]predicate.Location{}, lq.predicates...), - withGroup: lq.withGroup.Clone(), - withItems: lq.withItems.Clone(), + config: lq.config, + limit: lq.limit, + offset: lq.offset, + order: append([]OrderFunc{}, lq.order...), + predicates: append([]predicate.Location{}, lq.predicates...), + withParent: lq.withParent.Clone(), + withChildren: lq.withChildren.Clone(), + withGroup: lq.withGroup.Clone(), + withItems: lq.withItems.Clone(), // clone intermediate query. sql: lq.sql.Clone(), path: lq.path, @@ -300,6 +348,28 @@ func (lq *LocationQuery) Clone() *LocationQuery { } } +// WithParent tells the query-builder to eager-load the nodes that are connected to +// the "parent" edge. The optional arguments are used to configure the query builder of the edge. +func (lq *LocationQuery) WithParent(opts ...func(*LocationQuery)) *LocationQuery { + query := &LocationQuery{config: lq.config} + for _, opt := range opts { + opt(query) + } + lq.withParent = query + return lq +} + +// WithChildren tells the query-builder to eager-load the nodes that are connected to +// the "children" edge. The optional arguments are used to configure the query builder of the edge. +func (lq *LocationQuery) WithChildren(opts ...func(*LocationQuery)) *LocationQuery { + query := &LocationQuery{config: lq.config} + for _, opt := range opts { + opt(query) + } + lq.withChildren = query + return lq +} + // WithGroup tells the query-builder to eager-load the nodes that are connected to // the "group" edge. The optional arguments are used to configure the query builder of the edge. func (lq *LocationQuery) WithGroup(opts ...func(*GroupQuery)) *LocationQuery { @@ -391,12 +461,14 @@ func (lq *LocationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Loc nodes = []*Location{} withFKs = lq.withFKs _spec = lq.querySpec() - loadedTypes = [2]bool{ + loadedTypes = [4]bool{ + lq.withParent != nil, + lq.withChildren != nil, lq.withGroup != nil, lq.withItems != nil, } ) - if lq.withGroup != nil { + if lq.withParent != nil || lq.withGroup != nil { withFKs = true } if withFKs { @@ -420,6 +492,19 @@ func (lq *LocationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Loc if len(nodes) == 0 { return nodes, nil } + if query := lq.withParent; query != nil { + if err := lq.loadParent(ctx, query, nodes, nil, + func(n *Location, e *Location) { n.Edges.Parent = e }); err != nil { + return nil, err + } + } + if query := lq.withChildren; query != nil { + if err := lq.loadChildren(ctx, query, nodes, + func(n *Location) { n.Edges.Children = []*Location{} }, + func(n *Location, e *Location) { n.Edges.Children = append(n.Edges.Children, e) }); err != nil { + return nil, err + } + } if query := lq.withGroup; query != nil { if err := lq.loadGroup(ctx, query, nodes, nil, func(n *Location, e *Group) { n.Edges.Group = e }); err != nil { @@ -436,6 +521,66 @@ func (lq *LocationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Loc return nodes, nil } +func (lq *LocationQuery) loadParent(ctx context.Context, query *LocationQuery, nodes []*Location, init func(*Location), assign func(*Location, *Location)) error { + ids := make([]uuid.UUID, 0, len(nodes)) + nodeids := make(map[uuid.UUID][]*Location) + for i := range nodes { + if nodes[i].location_children == nil { + continue + } + fk := *nodes[i].location_children + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + query.Where(location.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "location_children" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} +func (lq *LocationQuery) loadChildren(ctx context.Context, query *LocationQuery, nodes []*Location, init func(*Location), assign func(*Location, *Location)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[uuid.UUID]*Location) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + if init != nil { + init(nodes[i]) + } + } + query.withFKs = true + query.Where(predicate.Location(func(s *sql.Selector) { + s.Where(sql.InValues(location.ChildrenColumn, fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.location_children + if fk == nil { + return fmt.Errorf(`foreign-key "location_children" is nil for node %v`, n.ID) + } + node, ok := nodeids[*fk] + if !ok { + return fmt.Errorf(`unexpected foreign-key "location_children" returned %v for node %v`, *fk, n.ID) + } + assign(node, n) + } + return nil +} func (lq *LocationQuery) loadGroup(ctx context.Context, query *GroupQuery, nodes []*Location, init func(*Location), assign func(*Location, *Group)) error { ids := make([]uuid.UUID, 0, len(nodes)) nodeids := make(map[uuid.UUID][]*Location) diff --git a/backend/ent/location_update.go b/backend/ent/location_update.go index 064634c..785036a 100644 --- a/backend/ent/location_update.go +++ b/backend/ent/location_update.go @@ -63,6 +63,40 @@ func (lu *LocationUpdate) ClearDescription() *LocationUpdate { return lu } +// SetParentID sets the "parent" edge to the Location entity by ID. +func (lu *LocationUpdate) SetParentID(id uuid.UUID) *LocationUpdate { + lu.mutation.SetParentID(id) + return lu +} + +// SetNillableParentID sets the "parent" edge to the Location entity by ID if the given value is not nil. +func (lu *LocationUpdate) SetNillableParentID(id *uuid.UUID) *LocationUpdate { + if id != nil { + lu = lu.SetParentID(*id) + } + return lu +} + +// SetParent sets the "parent" edge to the Location entity. +func (lu *LocationUpdate) SetParent(l *Location) *LocationUpdate { + return lu.SetParentID(l.ID) +} + +// AddChildIDs adds the "children" edge to the Location entity by IDs. +func (lu *LocationUpdate) AddChildIDs(ids ...uuid.UUID) *LocationUpdate { + lu.mutation.AddChildIDs(ids...) + return lu +} + +// AddChildren adds the "children" edges to the Location entity. +func (lu *LocationUpdate) AddChildren(l ...*Location) *LocationUpdate { + ids := make([]uuid.UUID, len(l)) + for i := range l { + ids[i] = l[i].ID + } + return lu.AddChildIDs(ids...) +} + // SetGroupID sets the "group" edge to the Group entity by ID. func (lu *LocationUpdate) SetGroupID(id uuid.UUID) *LocationUpdate { lu.mutation.SetGroupID(id) @@ -94,6 +128,33 @@ func (lu *LocationUpdate) Mutation() *LocationMutation { return lu.mutation } +// ClearParent clears the "parent" edge to the Location entity. +func (lu *LocationUpdate) ClearParent() *LocationUpdate { + lu.mutation.ClearParent() + return lu +} + +// ClearChildren clears all "children" edges to the Location entity. +func (lu *LocationUpdate) ClearChildren() *LocationUpdate { + lu.mutation.ClearChildren() + return lu +} + +// RemoveChildIDs removes the "children" edge to Location entities by IDs. +func (lu *LocationUpdate) RemoveChildIDs(ids ...uuid.UUID) *LocationUpdate { + lu.mutation.RemoveChildIDs(ids...) + return lu +} + +// RemoveChildren removes "children" edges to Location entities. +func (lu *LocationUpdate) RemoveChildren(l ...*Location) *LocationUpdate { + ids := make([]uuid.UUID, len(l)) + for i := range l { + ids[i] = l[i].ID + } + return lu.RemoveChildIDs(ids...) +} + // ClearGroup clears the "group" edge to the Group entity. func (lu *LocationUpdate) ClearGroup() *LocationUpdate { lu.mutation.ClearGroup() @@ -253,6 +314,95 @@ func (lu *LocationUpdate) sqlSave(ctx context.Context) (n int, err error) { Column: location.FieldDescription, }) } + if lu.mutation.ParentCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: location.ParentTable, + Columns: []string{location.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: location.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := lu.mutation.ParentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: location.ParentTable, + Columns: []string{location.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: location.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if lu.mutation.ChildrenCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: location.ChildrenTable, + Columns: []string{location.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: location.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := lu.mutation.RemovedChildrenIDs(); len(nodes) > 0 && !lu.mutation.ChildrenCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: location.ChildrenTable, + Columns: []string{location.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: location.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := lu.mutation.ChildrenIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: location.ChildrenTable, + Columns: []string{location.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: location.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if lu.mutation.GroupCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.M2O, @@ -393,6 +543,40 @@ func (luo *LocationUpdateOne) ClearDescription() *LocationUpdateOne { return luo } +// SetParentID sets the "parent" edge to the Location entity by ID. +func (luo *LocationUpdateOne) SetParentID(id uuid.UUID) *LocationUpdateOne { + luo.mutation.SetParentID(id) + return luo +} + +// SetNillableParentID sets the "parent" edge to the Location entity by ID if the given value is not nil. +func (luo *LocationUpdateOne) SetNillableParentID(id *uuid.UUID) *LocationUpdateOne { + if id != nil { + luo = luo.SetParentID(*id) + } + return luo +} + +// SetParent sets the "parent" edge to the Location entity. +func (luo *LocationUpdateOne) SetParent(l *Location) *LocationUpdateOne { + return luo.SetParentID(l.ID) +} + +// AddChildIDs adds the "children" edge to the Location entity by IDs. +func (luo *LocationUpdateOne) AddChildIDs(ids ...uuid.UUID) *LocationUpdateOne { + luo.mutation.AddChildIDs(ids...) + return luo +} + +// AddChildren adds the "children" edges to the Location entity. +func (luo *LocationUpdateOne) AddChildren(l ...*Location) *LocationUpdateOne { + ids := make([]uuid.UUID, len(l)) + for i := range l { + ids[i] = l[i].ID + } + return luo.AddChildIDs(ids...) +} + // SetGroupID sets the "group" edge to the Group entity by ID. func (luo *LocationUpdateOne) SetGroupID(id uuid.UUID) *LocationUpdateOne { luo.mutation.SetGroupID(id) @@ -424,6 +608,33 @@ func (luo *LocationUpdateOne) Mutation() *LocationMutation { return luo.mutation } +// ClearParent clears the "parent" edge to the Location entity. +func (luo *LocationUpdateOne) ClearParent() *LocationUpdateOne { + luo.mutation.ClearParent() + return luo +} + +// ClearChildren clears all "children" edges to the Location entity. +func (luo *LocationUpdateOne) ClearChildren() *LocationUpdateOne { + luo.mutation.ClearChildren() + return luo +} + +// RemoveChildIDs removes the "children" edge to Location entities by IDs. +func (luo *LocationUpdateOne) RemoveChildIDs(ids ...uuid.UUID) *LocationUpdateOne { + luo.mutation.RemoveChildIDs(ids...) + return luo +} + +// RemoveChildren removes "children" edges to Location entities. +func (luo *LocationUpdateOne) RemoveChildren(l ...*Location) *LocationUpdateOne { + ids := make([]uuid.UUID, len(l)) + for i := range l { + ids[i] = l[i].ID + } + return luo.RemoveChildIDs(ids...) +} + // ClearGroup clears the "group" edge to the Group entity. func (luo *LocationUpdateOne) ClearGroup() *LocationUpdateOne { luo.mutation.ClearGroup() @@ -613,6 +824,95 @@ func (luo *LocationUpdateOne) sqlSave(ctx context.Context) (_node *Location, err Column: location.FieldDescription, }) } + if luo.mutation.ParentCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: location.ParentTable, + Columns: []string{location.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: location.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := luo.mutation.ParentIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.M2O, + Inverse: true, + Table: location.ParentTable, + Columns: []string{location.ParentColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: location.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } + if luo.mutation.ChildrenCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: location.ChildrenTable, + Columns: []string{location.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: location.FieldID, + }, + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := luo.mutation.RemovedChildrenIDs(); len(nodes) > 0 && !luo.mutation.ChildrenCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: location.ChildrenTable, + Columns: []string{location.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: location.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := luo.mutation.ChildrenIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2M, + Inverse: false, + Table: location.ChildrenTable, + Columns: []string{location.ChildrenColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: &sqlgraph.FieldSpec{ + Type: field.TypeUUID, + Column: location.FieldID, + }, + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } if luo.mutation.GroupCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.M2O, diff --git a/backend/ent/migrate/schema.go b/backend/ent/migrate/schema.go index 901b3bd..5aa35b5 100644 --- a/backend/ent/migrate/schema.go +++ b/backend/ent/migrate/schema.go @@ -184,6 +184,7 @@ var ( {Name: "sold_price", Type: field.TypeFloat64, Default: 0}, {Name: "sold_notes", Type: field.TypeString, Nullable: true, Size: 1000}, {Name: "group_items", Type: field.TypeUUID}, + {Name: "item_children", Type: field.TypeUUID, Nullable: true}, {Name: "location_items", Type: field.TypeUUID, Nullable: true}, } // ItemsTable holds the schema information for the "items" table. @@ -199,8 +200,14 @@ var ( OnDelete: schema.Cascade, }, { - Symbol: "items_locations_items", + Symbol: "items_items_children", Columns: []*schema.Column{ItemsColumns[23]}, + RefColumns: []*schema.Column{ItemsColumns[0]}, + OnDelete: schema.SetNull, + }, + { + Symbol: "items_locations_items", + Columns: []*schema.Column{ItemsColumns[24]}, RefColumns: []*schema.Column{LocationsColumns[0]}, OnDelete: schema.Cascade, }, @@ -288,6 +295,7 @@ var ( {Name: "name", Type: field.TypeString, Size: 255}, {Name: "description", Type: field.TypeString, Nullable: true, Size: 1000}, {Name: "group_locations", Type: field.TypeUUID}, + {Name: "location_children", Type: field.TypeUUID, Nullable: true}, } // LocationsTable holds the schema information for the "locations" table. LocationsTable = &schema.Table{ @@ -301,6 +309,12 @@ var ( RefColumns: []*schema.Column{GroupsColumns[0]}, OnDelete: schema.Cascade, }, + { + Symbol: "locations_locations_children", + Columns: []*schema.Column{LocationsColumns[6]}, + RefColumns: []*schema.Column{LocationsColumns[0]}, + OnDelete: schema.SetNull, + }, }, } // UsersColumns holds the columns for the "users" table. @@ -381,10 +395,12 @@ func init() { DocumentTokensTable.ForeignKeys[0].RefTable = DocumentsTable GroupInvitationTokensTable.ForeignKeys[0].RefTable = GroupsTable ItemsTable.ForeignKeys[0].RefTable = GroupsTable - ItemsTable.ForeignKeys[1].RefTable = LocationsTable + ItemsTable.ForeignKeys[1].RefTable = ItemsTable + ItemsTable.ForeignKeys[2].RefTable = LocationsTable ItemFieldsTable.ForeignKeys[0].RefTable = ItemsTable LabelsTable.ForeignKeys[0].RefTable = GroupsTable LocationsTable.ForeignKeys[0].RefTable = GroupsTable + LocationsTable.ForeignKeys[1].RefTable = LocationsTable UsersTable.ForeignKeys[0].RefTable = GroupsTable LabelItemsTable.ForeignKeys[0].RefTable = LabelsTable LabelItemsTable.ForeignKeys[1].RefTable = ItemsTable diff --git a/backend/ent/mutation.go b/backend/ent/mutation.go index 9155ee6..eb2e853 100644 --- a/backend/ent/mutation.go +++ b/backend/ent/mutation.go @@ -4149,6 +4149,11 @@ type ItemMutation struct { addsold_price *float64 sold_notes *string clearedFields map[string]struct{} + parent *uuid.UUID + clearedparent bool + children map[uuid.UUID]struct{} + removedchildren map[uuid.UUID]struct{} + clearedchildren bool group *uuid.UUID clearedgroup bool label map[uuid.UUID]struct{} @@ -5256,6 +5261,99 @@ func (m *ItemMutation) ResetSoldNotes() { delete(m.clearedFields, item.FieldSoldNotes) } +// SetParentID sets the "parent" edge to the Item entity by id. +func (m *ItemMutation) SetParentID(id uuid.UUID) { + m.parent = &id +} + +// ClearParent clears the "parent" edge to the Item entity. +func (m *ItemMutation) ClearParent() { + m.clearedparent = true +} + +// ParentCleared reports if the "parent" edge to the Item entity was cleared. +func (m *ItemMutation) ParentCleared() bool { + return m.clearedparent +} + +// ParentID returns the "parent" edge ID in the mutation. +func (m *ItemMutation) ParentID() (id uuid.UUID, exists bool) { + if m.parent != nil { + return *m.parent, true + } + return +} + +// ParentIDs returns the "parent" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// ParentID instead. It exists only for internal usage by the builders. +func (m *ItemMutation) ParentIDs() (ids []uuid.UUID) { + if id := m.parent; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetParent resets all changes to the "parent" edge. +func (m *ItemMutation) ResetParent() { + m.parent = nil + m.clearedparent = false +} + +// AddChildIDs adds the "children" edge to the Item entity by ids. +func (m *ItemMutation) AddChildIDs(ids ...uuid.UUID) { + if m.children == nil { + m.children = make(map[uuid.UUID]struct{}) + } + for i := range ids { + m.children[ids[i]] = struct{}{} + } +} + +// ClearChildren clears the "children" edge to the Item entity. +func (m *ItemMutation) ClearChildren() { + m.clearedchildren = true +} + +// ChildrenCleared reports if the "children" edge to the Item entity was cleared. +func (m *ItemMutation) ChildrenCleared() bool { + return m.clearedchildren +} + +// RemoveChildIDs removes the "children" edge to the Item entity by IDs. +func (m *ItemMutation) RemoveChildIDs(ids ...uuid.UUID) { + if m.removedchildren == nil { + m.removedchildren = make(map[uuid.UUID]struct{}) + } + for i := range ids { + delete(m.children, ids[i]) + m.removedchildren[ids[i]] = struct{}{} + } +} + +// RemovedChildren returns the removed IDs of the "children" edge to the Item entity. +func (m *ItemMutation) RemovedChildrenIDs() (ids []uuid.UUID) { + for id := range m.removedchildren { + ids = append(ids, id) + } + return +} + +// ChildrenIDs returns the "children" edge IDs in the mutation. +func (m *ItemMutation) ChildrenIDs() (ids []uuid.UUID) { + for id := range m.children { + ids = append(ids, id) + } + return +} + +// ResetChildren resets all changes to the "children" edge. +func (m *ItemMutation) ResetChildren() { + m.children = nil + m.clearedchildren = false + m.removedchildren = nil +} + // SetGroupID sets the "group" edge to the Group entity by id. func (m *ItemMutation) SetGroupID(id uuid.UUID) { m.group = &id @@ -6074,7 +6172,13 @@ func (m *ItemMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *ItemMutation) AddedEdges() []string { - edges := make([]string, 0, 5) + edges := make([]string, 0, 7) + if m.parent != nil { + edges = append(edges, item.EdgeParent) + } + if m.children != nil { + edges = append(edges, item.EdgeChildren) + } if m.group != nil { edges = append(edges, item.EdgeGroup) } @@ -6097,6 +6201,16 @@ func (m *ItemMutation) AddedEdges() []string { // name in this mutation. func (m *ItemMutation) AddedIDs(name string) []ent.Value { switch name { + case item.EdgeParent: + if id := m.parent; id != nil { + return []ent.Value{*id} + } + case item.EdgeChildren: + ids := make([]ent.Value, 0, len(m.children)) + for id := range m.children { + ids = append(ids, id) + } + return ids case item.EdgeGroup: if id := m.group; id != nil { return []ent.Value{*id} @@ -6129,7 +6243,10 @@ func (m *ItemMutation) AddedIDs(name string) []ent.Value { // RemovedEdges returns all edge names that were removed in this mutation. func (m *ItemMutation) RemovedEdges() []string { - edges := make([]string, 0, 5) + edges := make([]string, 0, 7) + if m.removedchildren != nil { + edges = append(edges, item.EdgeChildren) + } if m.removedlabel != nil { edges = append(edges, item.EdgeLabel) } @@ -6146,6 +6263,12 @@ func (m *ItemMutation) RemovedEdges() []string { // the given name in this mutation. func (m *ItemMutation) RemovedIDs(name string) []ent.Value { switch name { + case item.EdgeChildren: + ids := make([]ent.Value, 0, len(m.removedchildren)) + for id := range m.removedchildren { + ids = append(ids, id) + } + return ids case item.EdgeLabel: ids := make([]ent.Value, 0, len(m.removedlabel)) for id := range m.removedlabel { @@ -6170,7 +6293,13 @@ func (m *ItemMutation) RemovedIDs(name string) []ent.Value { // ClearedEdges returns all edge names that were cleared in this mutation. func (m *ItemMutation) ClearedEdges() []string { - edges := make([]string, 0, 5) + edges := make([]string, 0, 7) + if m.clearedparent { + edges = append(edges, item.EdgeParent) + } + if m.clearedchildren { + edges = append(edges, item.EdgeChildren) + } if m.clearedgroup { edges = append(edges, item.EdgeGroup) } @@ -6193,6 +6322,10 @@ func (m *ItemMutation) ClearedEdges() []string { // was cleared in this mutation. func (m *ItemMutation) EdgeCleared(name string) bool { switch name { + case item.EdgeParent: + return m.clearedparent + case item.EdgeChildren: + return m.clearedchildren case item.EdgeGroup: return m.clearedgroup case item.EdgeLabel: @@ -6211,6 +6344,9 @@ func (m *ItemMutation) EdgeCleared(name string) bool { // if that edge is not defined in the schema. func (m *ItemMutation) ClearEdge(name string) error { switch name { + case item.EdgeParent: + m.ClearParent() + return nil case item.EdgeGroup: m.ClearGroup() return nil @@ -6225,6 +6361,12 @@ func (m *ItemMutation) ClearEdge(name string) error { // It returns an error if the edge is not defined in the schema. func (m *ItemMutation) ResetEdge(name string) error { switch name { + case item.EdgeParent: + m.ResetParent() + return nil + case item.EdgeChildren: + m.ResetChildren() + return nil case item.EdgeGroup: m.ResetGroup() return nil @@ -7886,22 +8028,27 @@ func (m *LabelMutation) ResetEdge(name string) error { // LocationMutation represents an operation that mutates the Location nodes in the graph. type LocationMutation struct { config - op Op - typ string - id *uuid.UUID - created_at *time.Time - updated_at *time.Time - name *string - description *string - clearedFields map[string]struct{} - group *uuid.UUID - clearedgroup bool - items map[uuid.UUID]struct{} - removeditems map[uuid.UUID]struct{} - cleareditems bool - done bool - oldValue func(context.Context) (*Location, error) - predicates []predicate.Location + op Op + typ string + id *uuid.UUID + created_at *time.Time + updated_at *time.Time + name *string + description *string + clearedFields map[string]struct{} + parent *uuid.UUID + clearedparent bool + children map[uuid.UUID]struct{} + removedchildren map[uuid.UUID]struct{} + clearedchildren bool + group *uuid.UUID + clearedgroup bool + items map[uuid.UUID]struct{} + removeditems map[uuid.UUID]struct{} + cleareditems bool + done bool + oldValue func(context.Context) (*Location, error) + predicates []predicate.Location } var _ ent.Mutation = (*LocationMutation)(nil) @@ -8165,6 +8312,99 @@ func (m *LocationMutation) ResetDescription() { delete(m.clearedFields, location.FieldDescription) } +// SetParentID sets the "parent" edge to the Location entity by id. +func (m *LocationMutation) SetParentID(id uuid.UUID) { + m.parent = &id +} + +// ClearParent clears the "parent" edge to the Location entity. +func (m *LocationMutation) ClearParent() { + m.clearedparent = true +} + +// ParentCleared reports if the "parent" edge to the Location entity was cleared. +func (m *LocationMutation) ParentCleared() bool { + return m.clearedparent +} + +// ParentID returns the "parent" edge ID in the mutation. +func (m *LocationMutation) ParentID() (id uuid.UUID, exists bool) { + if m.parent != nil { + return *m.parent, true + } + return +} + +// ParentIDs returns the "parent" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// ParentID instead. It exists only for internal usage by the builders. +func (m *LocationMutation) ParentIDs() (ids []uuid.UUID) { + if id := m.parent; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetParent resets all changes to the "parent" edge. +func (m *LocationMutation) ResetParent() { + m.parent = nil + m.clearedparent = false +} + +// AddChildIDs adds the "children" edge to the Location entity by ids. +func (m *LocationMutation) AddChildIDs(ids ...uuid.UUID) { + if m.children == nil { + m.children = make(map[uuid.UUID]struct{}) + } + for i := range ids { + m.children[ids[i]] = struct{}{} + } +} + +// ClearChildren clears the "children" edge to the Location entity. +func (m *LocationMutation) ClearChildren() { + m.clearedchildren = true +} + +// ChildrenCleared reports if the "children" edge to the Location entity was cleared. +func (m *LocationMutation) ChildrenCleared() bool { + return m.clearedchildren +} + +// RemoveChildIDs removes the "children" edge to the Location entity by IDs. +func (m *LocationMutation) RemoveChildIDs(ids ...uuid.UUID) { + if m.removedchildren == nil { + m.removedchildren = make(map[uuid.UUID]struct{}) + } + for i := range ids { + delete(m.children, ids[i]) + m.removedchildren[ids[i]] = struct{}{} + } +} + +// RemovedChildren returns the removed IDs of the "children" edge to the Location entity. +func (m *LocationMutation) RemovedChildrenIDs() (ids []uuid.UUID) { + for id := range m.removedchildren { + ids = append(ids, id) + } + return +} + +// ChildrenIDs returns the "children" edge IDs in the mutation. +func (m *LocationMutation) ChildrenIDs() (ids []uuid.UUID) { + for id := range m.children { + ids = append(ids, id) + } + return +} + +// ResetChildren resets all changes to the "children" edge. +func (m *LocationMutation) ResetChildren() { + m.children = nil + m.clearedchildren = false + m.removedchildren = nil +} + // SetGroupID sets the "group" edge to the Group entity by id. func (m *LocationMutation) SetGroupID(id uuid.UUID) { m.group = &id @@ -8436,7 +8676,13 @@ func (m *LocationMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *LocationMutation) AddedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 4) + if m.parent != nil { + edges = append(edges, location.EdgeParent) + } + if m.children != nil { + edges = append(edges, location.EdgeChildren) + } if m.group != nil { edges = append(edges, location.EdgeGroup) } @@ -8450,6 +8696,16 @@ func (m *LocationMutation) AddedEdges() []string { // name in this mutation. func (m *LocationMutation) AddedIDs(name string) []ent.Value { switch name { + case location.EdgeParent: + if id := m.parent; id != nil { + return []ent.Value{*id} + } + case location.EdgeChildren: + ids := make([]ent.Value, 0, len(m.children)) + for id := range m.children { + ids = append(ids, id) + } + return ids case location.EdgeGroup: if id := m.group; id != nil { return []ent.Value{*id} @@ -8466,7 +8722,10 @@ func (m *LocationMutation) AddedIDs(name string) []ent.Value { // RemovedEdges returns all edge names that were removed in this mutation. func (m *LocationMutation) RemovedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 4) + if m.removedchildren != nil { + edges = append(edges, location.EdgeChildren) + } if m.removeditems != nil { edges = append(edges, location.EdgeItems) } @@ -8477,6 +8736,12 @@ func (m *LocationMutation) RemovedEdges() []string { // the given name in this mutation. func (m *LocationMutation) RemovedIDs(name string) []ent.Value { switch name { + case location.EdgeChildren: + ids := make([]ent.Value, 0, len(m.removedchildren)) + for id := range m.removedchildren { + ids = append(ids, id) + } + return ids case location.EdgeItems: ids := make([]ent.Value, 0, len(m.removeditems)) for id := range m.removeditems { @@ -8489,7 +8754,13 @@ func (m *LocationMutation) RemovedIDs(name string) []ent.Value { // ClearedEdges returns all edge names that were cleared in this mutation. func (m *LocationMutation) ClearedEdges() []string { - edges := make([]string, 0, 2) + edges := make([]string, 0, 4) + if m.clearedparent { + edges = append(edges, location.EdgeParent) + } + if m.clearedchildren { + edges = append(edges, location.EdgeChildren) + } if m.clearedgroup { edges = append(edges, location.EdgeGroup) } @@ -8503,6 +8774,10 @@ func (m *LocationMutation) ClearedEdges() []string { // was cleared in this mutation. func (m *LocationMutation) EdgeCleared(name string) bool { switch name { + case location.EdgeParent: + return m.clearedparent + case location.EdgeChildren: + return m.clearedchildren case location.EdgeGroup: return m.clearedgroup case location.EdgeItems: @@ -8515,6 +8790,9 @@ func (m *LocationMutation) EdgeCleared(name string) bool { // if that edge is not defined in the schema. func (m *LocationMutation) ClearEdge(name string) error { switch name { + case location.EdgeParent: + m.ClearParent() + return nil case location.EdgeGroup: m.ClearGroup() return nil @@ -8526,6 +8804,12 @@ func (m *LocationMutation) ClearEdge(name string) error { // It returns an error if the edge is not defined in the schema. func (m *LocationMutation) ResetEdge(name string) error { switch name { + case location.EdgeParent: + m.ResetParent() + return nil + case location.EdgeChildren: + m.ResetChildren() + return nil case location.EdgeGroup: m.ResetGroup() return nil diff --git a/backend/go.sum b/backend/go.sum index 9dfe70c..7650162 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -61,11 +61,13 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -75,6 +77,8 @@ github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY= github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= +github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/backend/internal/migrations/migrations/20221020043305_allow_nesting_types.sql b/backend/internal/migrations/migrations/20221020043305_allow_nesting_types.sql new file mode 100644 index 0000000..7f24658 --- /dev/null +++ b/backend/internal/migrations/migrations/20221020043305_allow_nesting_types.sql @@ -0,0 +1,28 @@ +-- disable the enforcement of foreign-keys constraints +PRAGMA foreign_keys = off; +-- create "new_items" table +CREATE TABLE `new_items` (`id` uuid NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, `name` text NOT NULL, `description` text NULL, `import_ref` text NULL, `notes` text NULL, `quantity` integer NOT NULL DEFAULT 1, `insured` bool NOT NULL DEFAULT false, `serial_number` text NULL, `model_number` text NULL, `manufacturer` text NULL, `lifetime_warranty` bool NOT NULL DEFAULT false, `warranty_expires` datetime NULL, `warranty_details` text NULL, `purchase_time` datetime NULL, `purchase_from` text NULL, `purchase_price` real NOT NULL DEFAULT 0, `sold_time` datetime NULL, `sold_to` text NULL, `sold_price` real NOT NULL DEFAULT 0, `sold_notes` text NULL, `group_items` uuid NOT NULL, `item_children` uuid NULL, `location_items` uuid NULL, PRIMARY KEY (`id`), CONSTRAINT `items_groups_items` FOREIGN KEY (`group_items`) REFERENCES `groups` (`id`) ON DELETE CASCADE, CONSTRAINT `items_items_children` FOREIGN KEY (`item_children`) REFERENCES `items` (`id`) ON DELETE SET NULL, CONSTRAINT `items_locations_items` FOREIGN KEY (`location_items`) REFERENCES `locations` (`id`) ON DELETE CASCADE); +-- copy rows from old table "items" to new temporary table "new_items" +INSERT INTO `new_items` (`id`, `created_at`, `updated_at`, `name`, `description`, `import_ref`, `notes`, `quantity`, `insured`, `serial_number`, `model_number`, `manufacturer`, `lifetime_warranty`, `warranty_expires`, `warranty_details`, `purchase_time`, `purchase_from`, `purchase_price`, `sold_time`, `sold_to`, `sold_price`, `sold_notes`, `group_items`, `location_items`) SELECT `id`, `created_at`, `updated_at`, `name`, `description`, `import_ref`, `notes`, `quantity`, `insured`, `serial_number`, `model_number`, `manufacturer`, `lifetime_warranty`, `warranty_expires`, `warranty_details`, `purchase_time`, `purchase_from`, `purchase_price`, `sold_time`, `sold_to`, `sold_price`, `sold_notes`, `group_items`, `location_items` FROM `items`; +-- drop "items" table after copying rows +DROP TABLE `items`; +-- rename temporary table "new_items" to "items" +ALTER TABLE `new_items` RENAME TO `items`; +-- create index "item_name" to table: "items" +CREATE INDEX `item_name` ON `items` (`name`); +-- create index "item_manufacturer" to table: "items" +CREATE INDEX `item_manufacturer` ON `items` (`manufacturer`); +-- create index "item_model_number" to table: "items" +CREATE INDEX `item_model_number` ON `items` (`model_number`); +-- create index "item_serial_number" to table: "items" +CREATE INDEX `item_serial_number` ON `items` (`serial_number`); +-- create "new_locations" table +CREATE TABLE `new_locations` (`id` uuid NOT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, `name` text NOT NULL, `description` text NULL, `group_locations` uuid NOT NULL, `location_children` uuid NULL, PRIMARY KEY (`id`), CONSTRAINT `locations_groups_locations` FOREIGN KEY (`group_locations`) REFERENCES `groups` (`id`) ON DELETE CASCADE, CONSTRAINT `locations_locations_children` FOREIGN KEY (`location_children`) REFERENCES `locations` (`id`) ON DELETE SET NULL); +-- copy rows from old table "locations" to new temporary table "new_locations" +INSERT INTO `new_locations` (`id`, `created_at`, `updated_at`, `name`, `description`, `group_locations`) SELECT `id`, `created_at`, `updated_at`, `name`, `description`, `group_locations` FROM `locations`; +-- drop "locations" table after copying rows +DROP TABLE `locations`; +-- rename temporary table "new_locations" to "locations" +ALTER TABLE `new_locations` RENAME TO `locations`; +-- enable back the enforcement of foreign-keys constraints +PRAGMA foreign_keys = on; diff --git a/backend/internal/migrations/migrations/atlas.sum b/backend/internal/migrations/migrations/atlas.sum index 0bc29a5..04a34fb 100644 --- a/backend/internal/migrations/migrations/atlas.sum +++ b/backend/internal/migrations/migrations/atlas.sum @@ -1,4 +1,5 @@ -h1:nN8ZUHScToap+2yJKsb+AnKu8o2DubUoiKc9neQJ93M= +h1:mYTnmyrnBDST/r93NGJM33mIJqhp/U9qR440zI99eqQ= 20220929052825_init.sql h1:ZlCqm1wzjDmofeAcSX3jE4h4VcdTNGpRg2eabztDy9Q= 20221001210956_group_invitations.sql h1:YQKJFtE39wFOcRNbZQ/d+ZlHwrcfcsZlcv/pLEYdpjw= 20221009173029_add_user_roles.sql h1:vWmzAfgEWQeGk0Vn70zfVPCcfEZth3E0JcvyKTjpYyU= +20221020043305_allow_nesting_types.sql h1:4AyJpZ7l7SSJtJAQETYY802FHJ64ufYPJTqvwdiGn3M=