Add a quantity field to the item create modal form. (#615)

* Add a quantity field to the item create modal form.

* Fix prettier code format complaint.

* Update en.json allowing the label of the field to be translated.

* Including changes generated by swag and typescript-types tasks.

* Fixed tests, item duplication and lint errors.

* Fix linter issues again and an error introduced in 912e5b2

* Fixed a test that creates an item through the go:coverage task
This commit is contained in:
EdWorth120
2025-04-30 20:42:24 -03:00
committed by GitHub
parent ebf42a754a
commit 60b2ffd023
13 changed files with 67 additions and 17 deletions

View File

@@ -4,14 +4,15 @@ import (
"bytes"
"context"
"fmt"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/sys/analytics"
"net/http"
"os"
"path/filepath"
"strings"
"time"
"github.com/google/uuid"
"github.com/sysadminsmedia/homebox/backend/internal/sys/analytics"
atlas "ariga.io/atlas/sql/migrate"
"entgo.io/ent/dialect/sql/schema"
"github.com/go-chi/chi/v5"
@@ -203,7 +204,7 @@ func run(cfg *config.Config) error {
currencies, err := currencies.CollectionCurrencies(collectFuncs...)
if err != nil {
go log.Error().
log.Error().
Err(err).
Msg("failed to collect currencies")
return err

View File

@@ -2241,6 +2241,9 @@ const docTemplate = `{
"parentId": {
"type": "string",
"x-nullable": true
},
"quantity": {
"type": "integer"
}
}
},
@@ -2466,6 +2469,10 @@ const docTemplate = `{
"quantity": {
"type": "integer"
},
"soldTime": {
"description": "Sale details",
"type": "string"
},
"updatedAt": {
"type": "string"
}

View File

@@ -2239,6 +2239,9 @@
"parentId": {
"type": "string",
"x-nullable": true
},
"quantity": {
"type": "integer"
}
}
},
@@ -2464,6 +2467,10 @@
"quantity": {
"type": "integer"
},
"soldTime": {
"description": "Sale details",
"type": "string"
},
"updatedAt": {
"type": "string"
}

View File

@@ -98,6 +98,8 @@ definitions:
parentId:
type: string
x-nullable: true
quantity:
type: integer
required:
- name
type: object
@@ -248,6 +250,9 @@ definitions:
type: number
quantity:
type: integer
soldTime:
description: Sale details
type: string
updatedAt:
type: string
type: object

View File

@@ -60,6 +60,7 @@ type (
ImportRef string `json:"-"`
ParentID uuid.UUID `json:"parentId" extensions:"x-nullable"`
Name string `json:"name" validate:"required,min=1,max=255"`
Quantity int `json:"quantity"`
Description string `json:"description" validate:"max=1000"`
AssetID AssetID `json:"-"`
@@ -575,6 +576,7 @@ func (e *ItemsRepository) Create(ctx context.Context, gid uuid.UUID, data ItemCr
q := e.db.Item.Create().
SetImportRef(data.ImportRef).
SetName(data.Name).
SetQuantity(data.Quantity).
SetDescription(data.Description).
SetGroupID(gid).
SetLocationID(data.LocationID).

View File

@@ -58,9 +58,10 @@ func TestLocationRepositoryGetAllWithCount(t *testing.T) {
ctx := context.Background()
result := useLocations(t, 1)[0]
_, err := tRepos.Items.Create(ctx, tGroup.ID, ItemCreate{
item, err := tRepos.Items.Create(ctx, tGroup.ID, ItemCreate{
Name: fk.Str(10),
Description: fk.Str(100),
Quantity: fk.Num(1, 10),
LocationID: result.ID,
})
@@ -71,7 +72,7 @@ func TestLocationRepositoryGetAllWithCount(t *testing.T) {
for _, loc := range results {
if loc.ID == result.ID {
assert.Equal(t, 1, loc.ItemCount)
assert.Equal(t, item.Quantity, loc.ItemCount)
}
}
}

View File

@@ -2239,6 +2239,9 @@
"parentId": {
"type": "string",
"x-nullable": true
},
"quantity": {
"type": "integer"
}
}
},
@@ -2464,6 +2467,10 @@
"quantity": {
"type": "integer"
},
"soldTime": {
"description": "Sale details",
"type": "string"
},
"updatedAt": {
"type": "string"
}

View File

@@ -98,6 +98,8 @@ definitions:
parentId:
type: string
x-nullable: true
quantity:
type: integer
required:
- name
type: object
@@ -248,6 +250,9 @@ definitions:
type: number
quantity:
type: integer
soldTime:
description: Sale details
type: string
updatedAt:
type: string
type: object

View File

@@ -11,6 +11,7 @@
:max-length="255"
:min-length="1"
/>
<FormTextField v-model="form.quantity" :label="$t('components.item.create_modal.item_quantity')" type="number" />
<FormTextArea
v-model="form.description"
:label="$t('components.item.create_modal.item_description')"
@@ -161,6 +162,7 @@
const form = reactive({
location: locations.value && locations.value.length > 0 ? locations.value[0] : ({} as LocationOut),
name: "",
quantity: 1,
description: "",
color: "",
labels: [] as string[],
@@ -238,6 +240,7 @@
const out: ItemCreate = {
parentId: null,
name: form.name,
quantity: form.quantity,
description: form.description,
locationId: form.location.id as string,
labelIds: form.labels,
@@ -278,6 +281,7 @@
}
form.name = "";
form.quantity = 1;
form.description = "";
form.color = "";
form.photos = [];

View File

@@ -38,6 +38,7 @@ describe("user should be able to create an item and add an attachment", () => {
name: "test-item",
labelIds: [],
description: "test-description",
quantity: 2,
locationId: location.id,
});
expect(response.status).toBe(201);
@@ -72,6 +73,7 @@ describe("user should be able to create an item and add an attachment", () => {
name: faker.vehicle.model(),
labelIds: [],
description: faker.lorem.paragraph(1),
quantity: 2,
locationId: location.id,
});
expect(response.status).toBe(201);
@@ -126,6 +128,7 @@ describe("user should be able to create an item and add an attachment", () => {
name: faker.vehicle.model(),
labelIds: [],
description: faker.lorem.paragraph(1),
quantity: 2,
locationId: location.id,
});
expect(response.status).toBe(201);
@@ -177,6 +180,7 @@ describe("user should be able to create an item and add an attachment", () => {
name: faker.vehicle.model(),
labelIds: [],
description: faker.lorem.paragraph(1),
quantity: 2,
locationId: lastLocationId,
});
expect(response.status).toBe(201);
@@ -201,6 +205,7 @@ describe("user should be able to create an item and add an attachment", () => {
name: "parent-item",
labelIds: [],
description: "test-description",
quantity: 2,
locationId: parentLocation.id,
});
expect(parentResponse.status).toBe(201);
@@ -210,6 +215,7 @@ describe("user should be able to create an item and add an attachment", () => {
name: "child1-item",
labelIds: [],
description: "test-description",
quantity: 2,
locationId: childsLocation.id,
});
expect(child1Response.status).toBe(201);
@@ -226,6 +232,7 @@ describe("user should be able to create an item and add an attachment", () => {
name: "child2-item",
labelIds: [],
description: "test-description",
quantity: 2,
locationId: childsLocation.id,
});
expect(child2Response.status).toBe(201);

View File

@@ -1,7 +1,6 @@
/* post-processed by ./scripts/process-types.go */
/* eslint-disable */
/* tslint:disable */
// @ts-nocheck
/*
* ---------------------------------------------------------------
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
@@ -11,17 +10,6 @@
* ---------------------------------------------------------------
*/
export enum MaintenanceFilterStatus {
MaintenanceFilterStatusScheduled = "scheduled",
MaintenanceFilterStatusCompleted = "completed",
MaintenanceFilterStatusBoth = "both",
}
export enum ItemType {
ItemTypeLocation = "location",
ItemTypeItem = "item",
}
export interface CurrenciesCurrency {
code: string;
local: string;
@@ -84,6 +72,7 @@ export interface ItemCreate {
*/
name: string;
parentId?: string | null;
quantity: number;
}
export interface ItemField {
@@ -160,9 +149,16 @@ export interface ItemSummary {
name: string;
purchasePrice: number;
quantity: number;
/** Sale details */
soldTime: Date | string;
updatedAt: Date | string;
}
export enum ItemType {
ItemTypeLocation = "location",
ItemTypeItem = "item",
}
export interface ItemUpdate {
archived: boolean;
assetId: string;
@@ -313,6 +309,12 @@ export interface MaintenanceEntryWithDetails {
scheduledDate: Date | string;
}
export enum MaintenanceFilterStatus {
MaintenanceFilterStatusScheduled = "scheduled",
MaintenanceFilterStatusCompleted = "completed",
MaintenanceFilterStatusBoth = "both",
}
export interface NotifierCreate {
isActive: boolean;
/**

View File

@@ -65,6 +65,7 @@
"create_modal": {
"item_description": "Item Description",
"item_name": "Item Name",
"item_quantity": "Item Quantity",
"item_photo": "Item Photo 📷",
"title": "Create Item",
"upload_photos": "Upload Photos"

View File

@@ -463,6 +463,7 @@
const { error, data } = await api.items.create({
name: `${item.value.name} Copy`,
description: item.value.description,
quantity: item.value.quantity,
locationId: item.value.location!.id,
parentId: item.value.parent?.id,
labelIds: item.value.labels.map(l => l.id),