diff --git a/backend/app/api/main.go b/backend/app/api/main.go index 0fd69187..245315b2 100644 --- a/backend/app/api/main.go +++ b/backend/app/api/main.go @@ -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 diff --git a/backend/app/api/static/docs/docs.go b/backend/app/api/static/docs/docs.go index ee155891..b8eb2883 100644 --- a/backend/app/api/static/docs/docs.go +++ b/backend/app/api/static/docs/docs.go @@ -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" } diff --git a/backend/app/api/static/docs/swagger.json b/backend/app/api/static/docs/swagger.json index 88fde4e7..8cca9565 100644 --- a/backend/app/api/static/docs/swagger.json +++ b/backend/app/api/static/docs/swagger.json @@ -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" } diff --git a/backend/app/api/static/docs/swagger.yaml b/backend/app/api/static/docs/swagger.yaml index 8e5c5bd6..9e377c6e 100644 --- a/backend/app/api/static/docs/swagger.yaml +++ b/backend/app/api/static/docs/swagger.yaml @@ -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 diff --git a/backend/internal/data/repo/repo_items.go b/backend/internal/data/repo/repo_items.go index 86180caa..04b7238b 100644 --- a/backend/internal/data/repo/repo_items.go +++ b/backend/internal/data/repo/repo_items.go @@ -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). diff --git a/backend/internal/data/repo/repo_locations_test.go b/backend/internal/data/repo/repo_locations_test.go index 4b3ab21a..940875e4 100644 --- a/backend/internal/data/repo/repo_locations_test.go +++ b/backend/internal/data/repo/repo_locations_test.go @@ -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) } } } diff --git a/docs/en/api/openapi-2.0.json b/docs/en/api/openapi-2.0.json index 88fde4e7..8cca9565 100644 --- a/docs/en/api/openapi-2.0.json +++ b/docs/en/api/openapi-2.0.json @@ -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" } diff --git a/docs/en/api/openapi-2.0.yaml b/docs/en/api/openapi-2.0.yaml index 8e5c5bd6..9e377c6e 100644 --- a/docs/en/api/openapi-2.0.yaml +++ b/docs/en/api/openapi-2.0.yaml @@ -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 diff --git a/frontend/components/Item/CreateModal.vue b/frontend/components/Item/CreateModal.vue index da65e1c5..fbc00a15 100644 --- a/frontend/components/Item/CreateModal.vue +++ b/frontend/components/Item/CreateModal.vue @@ -11,6 +11,7 @@ :max-length="255" :min-length="1" /> + 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 = []; diff --git a/frontend/lib/api/__test__/user/items.test.ts b/frontend/lib/api/__test__/user/items.test.ts index 196c6c51..5407d563 100644 --- a/frontend/lib/api/__test__/user/items.test.ts +++ b/frontend/lib/api/__test__/user/items.test.ts @@ -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); diff --git a/frontend/lib/api/types/data-contracts.ts b/frontend/lib/api/types/data-contracts.ts index e06fdd85..76cc94cc 100644 --- a/frontend/lib/api/types/data-contracts.ts +++ b/frontend/lib/api/types/data-contracts.ts @@ -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; /** diff --git a/frontend/locales/en.json b/frontend/locales/en.json index 30887583..48c6b11c 100644 --- a/frontend/locales/en.json +++ b/frontend/locales/en.json @@ -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" diff --git a/frontend/pages/item/[id]/index.vue b/frontend/pages/item/[id]/index.vue index c8fd697e..1fd38b09 100644 --- a/frontend/pages/item/[id]/index.vue +++ b/frontend/pages/item/[id]/index.vue @@ -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),