mirror of
https://github.com/sysadminsmedia/homebox.git
synced 2025-12-28 16:06:37 +01:00
Implement syncing child's locations to that of parent.
This commit is contained in:
committed by
Matt Kilgore
parent
7d462a4dd3
commit
17e7e24070
@@ -2242,6 +2242,9 @@ const docTemplate = `{
|
||||
"soldTo": {
|
||||
"type": "string"
|
||||
},
|
||||
"syncChildItemsLocations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -2440,6 +2443,9 @@ const docTemplate = `{
|
||||
"type": "string",
|
||||
"maxLength": 255
|
||||
},
|
||||
"syncChildItemsLocations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"warrantyDetails": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
@@ -2235,6 +2235,9 @@
|
||||
"soldTo": {
|
||||
"type": "string"
|
||||
},
|
||||
"syncChildItemsLocations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"updatedAt": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -2433,6 +2436,9 @@
|
||||
"type": "string",
|
||||
"maxLength": 255
|
||||
},
|
||||
"syncChildItemsLocations": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"warrantyDetails": {
|
||||
"type": "string"
|
||||
},
|
||||
|
||||
@@ -188,6 +188,8 @@ definitions:
|
||||
type: string
|
||||
soldTo:
|
||||
type: string
|
||||
syncChildItemsLocations:
|
||||
type: boolean
|
||||
updatedAt:
|
||||
type: string
|
||||
warrantyDetails:
|
||||
@@ -323,6 +325,8 @@ definitions:
|
||||
soldTo:
|
||||
maxLength: 255
|
||||
type: string
|
||||
syncChildItemsLocations:
|
||||
type: boolean
|
||||
warrantyDetails:
|
||||
type: string
|
||||
warrantyExpires:
|
||||
|
||||
@@ -40,6 +40,8 @@ type Item struct {
|
||||
Archived bool `json:"archived,omitempty"`
|
||||
// AssetID holds the value of the "asset_id" field.
|
||||
AssetID int `json:"asset_id,omitempty"`
|
||||
// SyncChildItemsLocations holds the value of the "sync_child_items_locations" field.
|
||||
SyncChildItemsLocations bool `json:"sync_child_items_locations,omitempty"`
|
||||
// SerialNumber holds the value of the "serial_number" field.
|
||||
SerialNumber string `json:"serial_number,omitempty"`
|
||||
// ModelNumber holds the value of the "model_number" field.
|
||||
@@ -181,7 +183,7 @@ func (*Item) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case item.FieldInsured, item.FieldArchived, item.FieldLifetimeWarranty:
|
||||
case item.FieldInsured, item.FieldArchived, item.FieldSyncChildItemsLocations, item.FieldLifetimeWarranty:
|
||||
values[i] = new(sql.NullBool)
|
||||
case item.FieldPurchasePrice, item.FieldSoldPrice:
|
||||
values[i] = new(sql.NullFloat64)
|
||||
@@ -280,6 +282,12 @@ func (i *Item) assignValues(columns []string, values []any) error {
|
||||
} else if value.Valid {
|
||||
i.AssetID = int(value.Int64)
|
||||
}
|
||||
case item.FieldSyncChildItemsLocations:
|
||||
if value, ok := values[j].(*sql.NullBool); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field sync_child_items_locations", values[j])
|
||||
} else if value.Valid {
|
||||
i.SyncChildItemsLocations = value.Bool
|
||||
}
|
||||
case item.FieldSerialNumber:
|
||||
if value, ok := values[j].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field serial_number", values[j])
|
||||
@@ -485,6 +493,9 @@ func (i *Item) String() string {
|
||||
builder.WriteString("asset_id=")
|
||||
builder.WriteString(fmt.Sprintf("%v", i.AssetID))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("sync_child_items_locations=")
|
||||
builder.WriteString(fmt.Sprintf("%v", i.SyncChildItemsLocations))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("serial_number=")
|
||||
builder.WriteString(i.SerialNumber)
|
||||
builder.WriteString(", ")
|
||||
|
||||
@@ -35,6 +35,8 @@ const (
|
||||
FieldArchived = "archived"
|
||||
// FieldAssetID holds the string denoting the asset_id field in the database.
|
||||
FieldAssetID = "asset_id"
|
||||
// FieldSyncChildItemsLocations holds the string denoting the sync_child_items_locations field in the database.
|
||||
FieldSyncChildItemsLocations = "sync_child_items_locations"
|
||||
// FieldSerialNumber holds the string denoting the serial_number field in the database.
|
||||
FieldSerialNumber = "serial_number"
|
||||
// FieldModelNumber holds the string denoting the model_number field in the database.
|
||||
@@ -142,6 +144,7 @@ var Columns = []string{
|
||||
FieldInsured,
|
||||
FieldArchived,
|
||||
FieldAssetID,
|
||||
FieldSyncChildItemsLocations,
|
||||
FieldSerialNumber,
|
||||
FieldModelNumber,
|
||||
FieldManufacturer,
|
||||
@@ -209,6 +212,8 @@ var (
|
||||
DefaultArchived bool
|
||||
// DefaultAssetID holds the default value on creation for the "asset_id" field.
|
||||
DefaultAssetID int
|
||||
// DefaultSyncChildItemsLocations holds the default value on creation for the "sync_child_items_locations" field.
|
||||
DefaultSyncChildItemsLocations bool
|
||||
// SerialNumberValidator is a validator for the "serial_number" field. It is called by the builders before save.
|
||||
SerialNumberValidator func(string) error
|
||||
// ModelNumberValidator is a validator for the "model_number" field. It is called by the builders before save.
|
||||
@@ -287,6 +292,11 @@ func ByAssetID(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldAssetID, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// BySyncChildItemsLocations orders the results by the sync_child_items_locations field.
|
||||
func BySyncChildItemsLocations(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldSyncChildItemsLocations, opts...).ToFunc()
|
||||
}
|
||||
|
||||
// BySerialNumber orders the results by the serial_number field.
|
||||
func BySerialNumber(opts ...sql.OrderTermOption) OrderOption {
|
||||
return sql.OrderByField(FieldSerialNumber, opts...).ToFunc()
|
||||
|
||||
@@ -106,6 +106,11 @@ func AssetID(v int) predicate.Item {
|
||||
return predicate.Item(sql.FieldEQ(FieldAssetID, v))
|
||||
}
|
||||
|
||||
// SyncChildItemsLocations applies equality check predicate on the "sync_child_items_locations" field. It's identical to SyncChildItemsLocationsEQ.
|
||||
func SyncChildItemsLocations(v bool) predicate.Item {
|
||||
return predicate.Item(sql.FieldEQ(FieldSyncChildItemsLocations, v))
|
||||
}
|
||||
|
||||
// SerialNumber applies equality check predicate on the "serial_number" field. It's identical to SerialNumberEQ.
|
||||
func SerialNumber(v string) predicate.Item {
|
||||
return predicate.Item(sql.FieldEQ(FieldSerialNumber, v))
|
||||
@@ -641,6 +646,16 @@ func AssetIDLTE(v int) predicate.Item {
|
||||
return predicate.Item(sql.FieldLTE(FieldAssetID, v))
|
||||
}
|
||||
|
||||
// SyncChildItemsLocationsEQ applies the EQ predicate on the "sync_child_items_locations" field.
|
||||
func SyncChildItemsLocationsEQ(v bool) predicate.Item {
|
||||
return predicate.Item(sql.FieldEQ(FieldSyncChildItemsLocations, v))
|
||||
}
|
||||
|
||||
// SyncChildItemsLocationsNEQ applies the NEQ predicate on the "sync_child_items_locations" field.
|
||||
func SyncChildItemsLocationsNEQ(v bool) predicate.Item {
|
||||
return predicate.Item(sql.FieldNEQ(FieldSyncChildItemsLocations, v))
|
||||
}
|
||||
|
||||
// SerialNumberEQ applies the EQ predicate on the "serial_number" field.
|
||||
func SerialNumberEQ(v string) predicate.Item {
|
||||
return predicate.Item(sql.FieldEQ(FieldSerialNumber, v))
|
||||
|
||||
@@ -185,6 +185,20 @@ func (iu *ItemUpdate) AddAssetID(i int) *ItemUpdate {
|
||||
return iu
|
||||
}
|
||||
|
||||
// SetSyncChildItemsLocations sets the "sync_child_items_locations" field.
|
||||
func (iu *ItemUpdate) SetSyncChildItemsLocations(b bool) *ItemUpdate {
|
||||
iu.mutation.SetSyncChildItemsLocations(b)
|
||||
return iu
|
||||
}
|
||||
|
||||
// SetNillableSyncChildItemsLocations sets the "sync_child_items_locations" field if the given value is not nil.
|
||||
func (iu *ItemUpdate) SetNillableSyncChildItemsLocations(b *bool) *ItemUpdate {
|
||||
if b != nil {
|
||||
iu.SetSyncChildItemsLocations(*b)
|
||||
}
|
||||
return iu
|
||||
}
|
||||
|
||||
// SetSerialNumber sets the "serial_number" field.
|
||||
func (iu *ItemUpdate) SetSerialNumber(s string) *ItemUpdate {
|
||||
iu.mutation.SetSerialNumber(s)
|
||||
@@ -836,6 +850,9 @@ func (iu *ItemUpdate) sqlSave(ctx context.Context) (n int, err error) {
|
||||
if value, ok := iu.mutation.AddedAssetID(); ok {
|
||||
_spec.AddField(item.FieldAssetID, field.TypeInt, value)
|
||||
}
|
||||
if value, ok := iu.mutation.SyncChildItemsLocations(); ok {
|
||||
_spec.SetField(item.FieldSyncChildItemsLocations, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := iu.mutation.SerialNumber(); ok {
|
||||
_spec.SetField(item.FieldSerialNumber, field.TypeString, value)
|
||||
}
|
||||
@@ -1393,6 +1410,20 @@ func (iuo *ItemUpdateOne) AddAssetID(i int) *ItemUpdateOne {
|
||||
return iuo
|
||||
}
|
||||
|
||||
// SetSyncChildItemsLocations sets the "sync_child_items_locations" field.
|
||||
func (iuo *ItemUpdateOne) SetSyncChildItemsLocations(b bool) *ItemUpdateOne {
|
||||
iuo.mutation.SetSyncChildItemsLocations(b)
|
||||
return iuo
|
||||
}
|
||||
|
||||
// SetNillableSyncChildItemsLocations sets the "sync_child_items_locations" field if the given value is not nil.
|
||||
func (iuo *ItemUpdateOne) SetNillableSyncChildItemsLocations(b *bool) *ItemUpdateOne {
|
||||
if b != nil {
|
||||
iuo.SetSyncChildItemsLocations(*b)
|
||||
}
|
||||
return iuo
|
||||
}
|
||||
|
||||
// SetSerialNumber sets the "serial_number" field.
|
||||
func (iuo *ItemUpdateOne) SetSerialNumber(s string) *ItemUpdateOne {
|
||||
iuo.mutation.SetSerialNumber(s)
|
||||
@@ -2074,6 +2105,9 @@ func (iuo *ItemUpdateOne) sqlSave(ctx context.Context) (_node *Item, err error)
|
||||
if value, ok := iuo.mutation.AddedAssetID(); ok {
|
||||
_spec.AddField(item.FieldAssetID, field.TypeInt, value)
|
||||
}
|
||||
if value, ok := iuo.mutation.SyncChildItemsLocations(); ok {
|
||||
_spec.SetField(item.FieldSyncChildItemsLocations, field.TypeBool, value)
|
||||
}
|
||||
if value, ok := iuo.mutation.SerialNumber(); ok {
|
||||
_spec.SetField(item.FieldSerialNumber, field.TypeString, value)
|
||||
}
|
||||
|
||||
@@ -162,6 +162,7 @@ var (
|
||||
{Name: "insured", Type: field.TypeBool, Default: false},
|
||||
{Name: "archived", Type: field.TypeBool, Default: false},
|
||||
{Name: "asset_id", Type: field.TypeInt, Default: 0},
|
||||
{Name: "sync_child_items_locations", Type: field.TypeBool, Default: false},
|
||||
{Name: "serial_number", Type: field.TypeString, Nullable: true, Size: 255},
|
||||
{Name: "model_number", Type: field.TypeString, Nullable: true, Size: 255},
|
||||
{Name: "manufacturer", Type: field.TypeString, Nullable: true, Size: 255},
|
||||
@@ -187,19 +188,19 @@ var (
|
||||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "items_groups_items",
|
||||
Columns: []*schema.Column{ItemsColumns[24]},
|
||||
Columns: []*schema.Column{ItemsColumns[25]},
|
||||
RefColumns: []*schema.Column{GroupsColumns[0]},
|
||||
OnDelete: schema.Cascade,
|
||||
},
|
||||
{
|
||||
Symbol: "items_items_children",
|
||||
Columns: []*schema.Column{ItemsColumns[25]},
|
||||
Columns: []*schema.Column{ItemsColumns[26]},
|
||||
RefColumns: []*schema.Column{ItemsColumns[0]},
|
||||
OnDelete: schema.SetNull,
|
||||
},
|
||||
{
|
||||
Symbol: "items_locations_items",
|
||||
Columns: []*schema.Column{ItemsColumns[26]},
|
||||
Columns: []*schema.Column{ItemsColumns[27]},
|
||||
RefColumns: []*schema.Column{LocationsColumns[0]},
|
||||
OnDelete: schema.Cascade,
|
||||
},
|
||||
@@ -213,17 +214,17 @@ var (
|
||||
{
|
||||
Name: "item_manufacturer",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{ItemsColumns[13]},
|
||||
Columns: []*schema.Column{ItemsColumns[14]},
|
||||
},
|
||||
{
|
||||
Name: "item_model_number",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{ItemsColumns[12]},
|
||||
Columns: []*schema.Column{ItemsColumns[13]},
|
||||
},
|
||||
{
|
||||
Name: "item_serial_number",
|
||||
Unique: false,
|
||||
Columns: []*schema.Column{ItemsColumns[11]},
|
||||
Columns: []*schema.Column{ItemsColumns[12]},
|
||||
},
|
||||
{
|
||||
Name: "item_archived",
|
||||
|
||||
@@ -4085,6 +4085,7 @@ type ItemMutation struct {
|
||||
archived *bool
|
||||
asset_id *int
|
||||
addasset_id *int
|
||||
sync_child_items_locations *bool
|
||||
serial_number *string
|
||||
model_number *string
|
||||
manufacturer *string
|
||||
@@ -4670,6 +4671,42 @@ func (m *ItemMutation) ResetAssetID() {
|
||||
m.addasset_id = nil
|
||||
}
|
||||
|
||||
// SetSyncChildItemsLocations sets the "sync_child_items_locations" field.
|
||||
func (m *ItemMutation) SetSyncChildItemsLocations(b bool) {
|
||||
m.sync_child_items_locations = &b
|
||||
}
|
||||
|
||||
// SyncChildItemsLocations returns the value of the "sync_child_items_locations" field in the mutation.
|
||||
func (m *ItemMutation) SyncChildItemsLocations() (r bool, exists bool) {
|
||||
v := m.sync_child_items_locations
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
return *v, true
|
||||
}
|
||||
|
||||
// OldSyncChildItemsLocations returns the old "sync_child_items_locations" field's value of the Item entity.
|
||||
// If the Item object wasn't provided to the builder, the object is fetched from the database.
|
||||
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
|
||||
func (m *ItemMutation) OldSyncChildItemsLocations(ctx context.Context) (v bool, err error) {
|
||||
if !m.op.Is(OpUpdateOne) {
|
||||
return v, errors.New("OldSyncChildItemsLocations is only allowed on UpdateOne operations")
|
||||
}
|
||||
if m.id == nil || m.oldValue == nil {
|
||||
return v, errors.New("OldSyncChildItemsLocations requires an ID field in the mutation")
|
||||
}
|
||||
oldValue, err := m.oldValue(ctx)
|
||||
if err != nil {
|
||||
return v, fmt.Errorf("querying old value for OldSyncChildItemsLocations: %w", err)
|
||||
}
|
||||
return oldValue.SyncChildItemsLocations, nil
|
||||
}
|
||||
|
||||
// ResetSyncChildItemsLocations resets all changes to the "sync_child_items_locations" field.
|
||||
func (m *ItemMutation) ResetSyncChildItemsLocations() {
|
||||
m.sync_child_items_locations = nil
|
||||
}
|
||||
|
||||
// SetSerialNumber sets the "serial_number" field.
|
||||
func (m *ItemMutation) SetSerialNumber(s string) {
|
||||
m.serial_number = &s
|
||||
@@ -5729,7 +5766,7 @@ func (m *ItemMutation) Type() string {
|
||||
// order to get all numeric fields that were incremented/decremented, call
|
||||
// AddedFields().
|
||||
func (m *ItemMutation) Fields() []string {
|
||||
fields := make([]string, 0, 23)
|
||||
fields := make([]string, 0, 24)
|
||||
if m.created_at != nil {
|
||||
fields = append(fields, item.FieldCreatedAt)
|
||||
}
|
||||
@@ -5760,6 +5797,9 @@ func (m *ItemMutation) Fields() []string {
|
||||
if m.asset_id != nil {
|
||||
fields = append(fields, item.FieldAssetID)
|
||||
}
|
||||
if m.sync_child_items_locations != nil {
|
||||
fields = append(fields, item.FieldSyncChildItemsLocations)
|
||||
}
|
||||
if m.serial_number != nil {
|
||||
fields = append(fields, item.FieldSerialNumber)
|
||||
}
|
||||
@@ -5827,6 +5867,8 @@ func (m *ItemMutation) Field(name string) (ent.Value, bool) {
|
||||
return m.Archived()
|
||||
case item.FieldAssetID:
|
||||
return m.AssetID()
|
||||
case item.FieldSyncChildItemsLocations:
|
||||
return m.SyncChildItemsLocations()
|
||||
case item.FieldSerialNumber:
|
||||
return m.SerialNumber()
|
||||
case item.FieldModelNumber:
|
||||
@@ -5882,6 +5924,8 @@ func (m *ItemMutation) OldField(ctx context.Context, name string) (ent.Value, er
|
||||
return m.OldArchived(ctx)
|
||||
case item.FieldAssetID:
|
||||
return m.OldAssetID(ctx)
|
||||
case item.FieldSyncChildItemsLocations:
|
||||
return m.OldSyncChildItemsLocations(ctx)
|
||||
case item.FieldSerialNumber:
|
||||
return m.OldSerialNumber(ctx)
|
||||
case item.FieldModelNumber:
|
||||
@@ -5987,6 +6031,13 @@ func (m *ItemMutation) SetField(name string, value ent.Value) error {
|
||||
}
|
||||
m.SetAssetID(v)
|
||||
return nil
|
||||
case item.FieldSyncChildItemsLocations:
|
||||
v, ok := value.(bool)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected type %T for field %s", value, name)
|
||||
}
|
||||
m.SetSyncChildItemsLocations(v)
|
||||
return nil
|
||||
case item.FieldSerialNumber:
|
||||
v, ok := value.(string)
|
||||
if !ok {
|
||||
@@ -6289,6 +6340,9 @@ func (m *ItemMutation) ResetField(name string) error {
|
||||
case item.FieldAssetID:
|
||||
m.ResetAssetID()
|
||||
return nil
|
||||
case item.FieldSyncChildItemsLocations:
|
||||
m.ResetSyncChildItemsLocations()
|
||||
return nil
|
||||
case item.FieldSerialNumber:
|
||||
m.ResetSerialNumber()
|
||||
return nil
|
||||
|
||||
@@ -259,36 +259,40 @@ func init() {
|
||||
itemDescAssetID := itemFields[5].Descriptor()
|
||||
// item.DefaultAssetID holds the default value on creation for the asset_id field.
|
||||
item.DefaultAssetID = itemDescAssetID.Default.(int)
|
||||
// itemDescSyncChildItemsLocations is the schema descriptor for sync_child_items_locations field.
|
||||
itemDescSyncChildItemsLocations := itemFields[6].Descriptor()
|
||||
// item.DefaultSyncChildItemsLocations holds the default value on creation for the sync_child_items_locations field.
|
||||
item.DefaultSyncChildItemsLocations = itemDescSyncChildItemsLocations.Default.(bool)
|
||||
// itemDescSerialNumber is the schema descriptor for serial_number field.
|
||||
itemDescSerialNumber := itemFields[6].Descriptor()
|
||||
itemDescSerialNumber := itemFields[7].Descriptor()
|
||||
// item.SerialNumberValidator is a validator for the "serial_number" field. It is called by the builders before save.
|
||||
item.SerialNumberValidator = itemDescSerialNumber.Validators[0].(func(string) error)
|
||||
// itemDescModelNumber is the schema descriptor for model_number field.
|
||||
itemDescModelNumber := itemFields[7].Descriptor()
|
||||
itemDescModelNumber := itemFields[8].Descriptor()
|
||||
// item.ModelNumberValidator is a validator for the "model_number" field. It is called by the builders before save.
|
||||
item.ModelNumberValidator = itemDescModelNumber.Validators[0].(func(string) error)
|
||||
// itemDescManufacturer is the schema descriptor for manufacturer field.
|
||||
itemDescManufacturer := itemFields[8].Descriptor()
|
||||
itemDescManufacturer := itemFields[9].Descriptor()
|
||||
// item.ManufacturerValidator is a validator for the "manufacturer" field. It is called by the builders before save.
|
||||
item.ManufacturerValidator = itemDescManufacturer.Validators[0].(func(string) error)
|
||||
// itemDescLifetimeWarranty is the schema descriptor for lifetime_warranty field.
|
||||
itemDescLifetimeWarranty := itemFields[9].Descriptor()
|
||||
itemDescLifetimeWarranty := itemFields[10].Descriptor()
|
||||
// item.DefaultLifetimeWarranty holds the default value on creation for the lifetime_warranty field.
|
||||
item.DefaultLifetimeWarranty = itemDescLifetimeWarranty.Default.(bool)
|
||||
// itemDescWarrantyDetails is the schema descriptor for warranty_details field.
|
||||
itemDescWarrantyDetails := itemFields[11].Descriptor()
|
||||
itemDescWarrantyDetails := itemFields[12].Descriptor()
|
||||
// item.WarrantyDetailsValidator is a validator for the "warranty_details" field. It is called by the builders before save.
|
||||
item.WarrantyDetailsValidator = itemDescWarrantyDetails.Validators[0].(func(string) error)
|
||||
// itemDescPurchasePrice is the schema descriptor for purchase_price field.
|
||||
itemDescPurchasePrice := itemFields[14].Descriptor()
|
||||
itemDescPurchasePrice := itemFields[15].Descriptor()
|
||||
// item.DefaultPurchasePrice holds the default value on creation for the purchase_price field.
|
||||
item.DefaultPurchasePrice = itemDescPurchasePrice.Default.(float64)
|
||||
// itemDescSoldPrice is the schema descriptor for sold_price field.
|
||||
itemDescSoldPrice := itemFields[17].Descriptor()
|
||||
itemDescSoldPrice := itemFields[18].Descriptor()
|
||||
// item.DefaultSoldPrice holds the default value on creation for the sold_price field.
|
||||
item.DefaultSoldPrice = itemDescSoldPrice.Default.(float64)
|
||||
// itemDescSoldNotes is the schema descriptor for sold_notes field.
|
||||
itemDescSoldNotes := itemFields[18].Descriptor()
|
||||
itemDescSoldNotes := itemFields[19].Descriptor()
|
||||
// item.SoldNotesValidator is a validator for the "sold_notes" field. It is called by the builders before save.
|
||||
item.SoldNotesValidator = itemDescSoldNotes.Validators[0].(func(string) error)
|
||||
// itemDescID is the schema descriptor for id field.
|
||||
|
||||
@@ -51,6 +51,8 @@ func (Item) Fields() []ent.Field {
|
||||
Default(false),
|
||||
field.Int("asset_id").
|
||||
Default(0),
|
||||
field.Bool("sync_child_items_locations").
|
||||
Default(false),
|
||||
|
||||
// ------------------------------------
|
||||
// item identification
|
||||
|
||||
@@ -55,11 +55,11 @@ type (
|
||||
}
|
||||
|
||||
ItemCreate struct {
|
||||
ImportRef string `json:"-"`
|
||||
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"`
|
||||
Name string `json:"name" validate:"required,min=1,max=255"`
|
||||
Description string `json:"description" validate:"max=1000"`
|
||||
AssetID AssetID `json:"-"`
|
||||
ImportRef string `json:"-"`
|
||||
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"`
|
||||
Name string `json:"name" validate:"required,min=1,max=255"`
|
||||
Description string `json:"description" validate:"max=1000"`
|
||||
AssetID AssetID `json:"-"`
|
||||
|
||||
// Edges
|
||||
LocationID uuid.UUID `json:"locationId"`
|
||||
@@ -67,14 +67,15 @@ type (
|
||||
}
|
||||
|
||||
ItemUpdate struct {
|
||||
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable,x-omitempty"`
|
||||
ID uuid.UUID `json:"id"`
|
||||
AssetID AssetID `json:"assetId" swaggertype:"string"`
|
||||
Name string `json:"name" validate:"required,min=1,max=255"`
|
||||
Description string `json:"description" validate:"max=1000"`
|
||||
Quantity int `json:"quantity"`
|
||||
Insured bool `json:"insured"`
|
||||
Archived bool `json:"archived"`
|
||||
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable,x-omitempty"`
|
||||
ID uuid.UUID `json:"id"`
|
||||
AssetID AssetID `json:"assetId" swaggertype:"string"`
|
||||
Name string `json:"name" validate:"required,min=1,max=255"`
|
||||
Description string `json:"description" validate:"max=1000"`
|
||||
Quantity int `json:"quantity"`
|
||||
Insured bool `json:"insured"`
|
||||
Archived bool `json:"archived"`
|
||||
SyncChildItemsLocations bool `json:"syncChildItemsLocations"`
|
||||
|
||||
// Edges
|
||||
LocationID uuid.UUID `json:"locationId"`
|
||||
@@ -137,6 +138,8 @@ type (
|
||||
ItemSummary
|
||||
AssetID AssetID `json:"assetId,string"`
|
||||
|
||||
SyncChildItemsLocations bool `json:"syncChildItemsLocations"`
|
||||
|
||||
SerialNumber string `json:"serialNumber"`
|
||||
ModelNumber string `json:"modelNumber"`
|
||||
Manufacturer string `json:"manufacturer"`
|
||||
@@ -248,12 +251,13 @@ func mapItemOut(item *ent.Item) ItemOut {
|
||||
}
|
||||
|
||||
return ItemOut{
|
||||
Parent: parent,
|
||||
AssetID: AssetID(item.AssetID),
|
||||
ItemSummary: mapItemSummary(item),
|
||||
LifetimeWarranty: item.LifetimeWarranty,
|
||||
WarrantyExpires: types.DateFromTime(item.WarrantyExpires),
|
||||
WarrantyDetails: item.WarrantyDetails,
|
||||
Parent: parent,
|
||||
AssetID: AssetID(item.AssetID),
|
||||
ItemSummary: mapItemSummary(item),
|
||||
LifetimeWarranty: item.LifetimeWarranty,
|
||||
WarrantyExpires: types.DateFromTime(item.WarrantyExpires),
|
||||
WarrantyDetails: item.WarrantyDetails,
|
||||
SyncChildItemsLocations: item.SyncChildItemsLocations,
|
||||
|
||||
// Identification
|
||||
SerialNumber: item.SerialNumber,
|
||||
@@ -606,7 +610,8 @@ func (e *ItemsRepository) UpdateByGroup(ctx context.Context, gid uuid.UUID, data
|
||||
SetWarrantyExpires(data.WarrantyExpires.Time()).
|
||||
SetWarrantyDetails(data.WarrantyDetails).
|
||||
SetQuantity(data.Quantity).
|
||||
SetAssetID(int(data.AssetID))
|
||||
SetAssetID(int(data.AssetID)).
|
||||
SetSyncChildItemsLocations(data.SyncChildItemsLocations)
|
||||
|
||||
currentLabels, err := e.db.Item.Query().Where(item.ID(data.ID)).QueryLabel().All(ctx)
|
||||
if err != nil {
|
||||
@@ -633,6 +638,28 @@ func (e *ItemsRepository) UpdateByGroup(ctx context.Context, gid uuid.UUID, data
|
||||
q.ClearParent()
|
||||
}
|
||||
|
||||
if data.SyncChildItemsLocations {
|
||||
children, err := e.db.Item.Query().Where(item.ID(data.ID)).QueryChildren().All(ctx)
|
||||
if err != nil {
|
||||
return ItemOut{}, err
|
||||
}
|
||||
location := data.LocationID
|
||||
|
||||
for _, child := range children {
|
||||
child_location, err := child.QueryLocation().First(ctx)
|
||||
if err != nil {
|
||||
return ItemOut{}, err
|
||||
}
|
||||
|
||||
if location != child_location.ID {
|
||||
err = child.Update().SetLocationID(location).Exec(ctx)
|
||||
if err != nil {
|
||||
return ItemOut{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = q.Exec(ctx)
|
||||
if err != nil {
|
||||
return ItemOut{}, err
|
||||
|
||||
36
frontend/components/Form/Toggle.vue
Normal file
36
frontend/components/Form/Toggle.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<div v-if="!inline" class="form-control w-full">
|
||||
<label class="label cursor-pointer">
|
||||
<input v-model="value" type="checkbox" class="toggle toggle-primary" />
|
||||
<span class="label-text"> {{ label }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div v-else class="label cursor-pointer sm:grid sm:grid-cols-4 sm:items-start sm:gap-4">
|
||||
<label>
|
||||
<span class="label-text">
|
||||
{{ label }}
|
||||
</span>
|
||||
</label>
|
||||
<input v-model="value" type="checkbox" class="toggle toggle-primary" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
inline: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
});
|
||||
|
||||
const value = useVModel(props, "modelValue");
|
||||
</script>
|
||||
|
||||
@@ -193,4 +193,72 @@ describe("user should be able to create an item and add an attachment", () => {
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test("child items sync their location to their parent", async () => {
|
||||
const api = await sharedUserClient();
|
||||
const [parentLocation, parentCleanup] = await useLocation(api);
|
||||
const [childsLocation, childsCleanup] = await useLocation(api);
|
||||
|
||||
const { response: parentResponse, data: parent } = await api.items.create({
|
||||
name: "parent-item",
|
||||
labelIds: [],
|
||||
description: "test-description",
|
||||
locationId: parentLocation.id,
|
||||
});
|
||||
expect(parentResponse.status).toBe(201);
|
||||
expect(parent.id).toBeTruthy();
|
||||
|
||||
const { response: child1Response, data: child1Item } = await api.items.create({
|
||||
name: "child1-item",
|
||||
labelIds: [],
|
||||
description: "test-description",
|
||||
locationId: childsLocation.id,
|
||||
});
|
||||
expect(child1Response.status).toBe(201);
|
||||
const child1ItemUpdate = {
|
||||
parentId: parent.id,
|
||||
...child1Item,
|
||||
locationId: child1Item.location?.id,
|
||||
labelIds: []
|
||||
};
|
||||
const { response: child1UpdatedResponse, data: child1UpdatedData } = await api.items.update(child1Item.id, child1ItemUpdate as ItemUpdate);
|
||||
expect(child1UpdatedResponse.status).toBe(200);
|
||||
|
||||
const { response: child2Response, data: child2Item } = await api.items.create({
|
||||
name: "child2-item",
|
||||
labelIds: [],
|
||||
description: "test-description",
|
||||
locationId: childsLocation.id,
|
||||
});
|
||||
expect(child2Response.status).toBe(201);
|
||||
const child2ItemUpdate = {
|
||||
parentId: parent.id,
|
||||
...child2Item,
|
||||
locationId: child2Item.location?.id,
|
||||
labelIds: []
|
||||
}
|
||||
const { response: child2UpdatedResponse, data: child2UpdatedData } = await api.items.update(child2Item.id, child2ItemUpdate as ItemUpdate);
|
||||
expect(child2UpdatedResponse.status).toBe(200);
|
||||
|
||||
const itemUpdate = {
|
||||
parentId: null,
|
||||
...parent,
|
||||
locationId: parentLocation.id,
|
||||
labelIds: [],
|
||||
syncChildItemsLocations: true
|
||||
};
|
||||
const { response: updateResponse, data: updateData } = await api.items.update(parent.id, itemUpdate)
|
||||
expect(updateResponse.status).toBe(200);
|
||||
|
||||
const { response: child1FinalResponse, data: child1FinalData } = await api.items.get(child1Item.id);
|
||||
expect(child1FinalResponse.status).toBe(200);
|
||||
expect(child1FinalData.location?.id).toBe(parentLocation.id);
|
||||
|
||||
const { response: child2FinalResponse, data: child2FinalData } = await api.items.get(child2Item.id);
|
||||
expect(child2FinalResponse.status).toBe(200);
|
||||
expect(child2FinalData.location?.id).toBe(parentLocation.id);
|
||||
|
||||
parentCleanup();
|
||||
childsCleanup();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -116,6 +116,7 @@ export interface ItemOut {
|
||||
/** Sold */
|
||||
soldTime: Date | string;
|
||||
soldTo: string;
|
||||
syncChildItemsLocations: boolean;
|
||||
updatedAt: Date | string;
|
||||
warrantyDetails: string;
|
||||
warrantyExpires: Date | string;
|
||||
@@ -190,6 +191,7 @@ export interface ItemUpdate {
|
||||
soldTime: Date | string;
|
||||
/** @maxLength 255 */
|
||||
soldTo: string;
|
||||
syncChildItemsLocations: boolean;
|
||||
warrantyDetails: string;
|
||||
warrantyExpires: Date | string;
|
||||
}
|
||||
|
||||
@@ -427,6 +427,63 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function maybeSyncWithParentLocation() {
|
||||
if (parent.value && parent.value.id) {
|
||||
const { data, error } = await api.items.get(parent.value.id);
|
||||
|
||||
if (error) {
|
||||
toast.error("Something went wrong trying to load parent data");
|
||||
} else {
|
||||
if (data.syncChildItemsLocations) {
|
||||
toast.info("Selected parent syncs its children's locations to its own. The location has been updated.");
|
||||
item.value.location = data.location
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function informAboutDesyncingLocationFromParent() {
|
||||
if (parent.value && parent.value.id) {
|
||||
const { data, error } = await api.items.get(parent.value.id);
|
||||
|
||||
if (error) {
|
||||
toast.error("Something went wrong trying to load parent data");
|
||||
}
|
||||
|
||||
if (data.syncChildItemsLocations) {
|
||||
toast.info("Changing location will de-sync it from the parent's location");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function syncChildItemsLocations() {
|
||||
if (!item.value.location?.id) {
|
||||
toast.error("Failed to save item: no location selected");
|
||||
return;
|
||||
}
|
||||
|
||||
const payload: ItemUpdate = {
|
||||
...item.value,
|
||||
locationId: item.value.location?.id,
|
||||
labelIds: item.value.labels.map(l => l.id),
|
||||
parentId: parent.value ? parent.value.id : null,
|
||||
assetId: item.value.assetId,
|
||||
};
|
||||
|
||||
const { error } = await api.items.update(itemId.value, payload);
|
||||
|
||||
if (error) {
|
||||
toast.error("Failed to save item");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item.value.syncChildItemsLocations) {
|
||||
toast.success("Child items' locations will no longer be synced with this item.")
|
||||
} else {
|
||||
toast.success("Child items' locations have been synced with this item");
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener("keydown", keyboardSave);
|
||||
});
|
||||
@@ -488,8 +545,9 @@
|
||||
<div class="mt-2 flex flex-wrap items-center justify-between gap-4"></div>
|
||||
</template>
|
||||
<div class="mb-6 grid gap-4 border-t px-5 pt-2 md:grid-cols-2">
|
||||
<LocationSelector v-model="item.location" />
|
||||
<LocationSelector v-model="item.location" @update:model-value="informAboutDesyncingLocationFromParent()" />
|
||||
<FormMultiselect v-model="item.labels" label="Labels" :items="labels ?? []" />
|
||||
<FormToggle v-model="item.syncChildItemsLocations" label="Sync child items' locations" inline @update:model-value="syncChildItemsLocations()" />
|
||||
<Autocomplete
|
||||
v-if="preferences.editorAdvancedView"
|
||||
v-model="parent"
|
||||
@@ -498,6 +556,7 @@
|
||||
item-text="name"
|
||||
label="Parent Item"
|
||||
no-results-text="Type to search..."
|
||||
@update:model-value="maybeSyncWithParentLocation()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user