From 7bfd9f0fa816b86662ed422ae8c8b0607426176a Mon Sep 17 00:00:00 2001 From: Hayden <64056131+hay-kot@users.noreply.github.com> Date: Mon, 5 Dec 2022 18:30:00 -0900 Subject: [PATCH] routes --- .../api/handlers/v1/v1_ctrl_maint_entry.go | 125 ++++++++++++ backend/app/api/routes.go | 5 + backend/app/api/static/docs/docs.go | 188 ++++++++++++++++++ backend/app/api/static/docs/swagger.json | 188 ++++++++++++++++++ backend/app/api/static/docs/swagger.yaml | 117 +++++++++++ .../data/repo/repo_maintenance_entry.go | 35 +++- .../data/repo/repo_maintenance_entry_test.go | 3 +- 7 files changed, 650 insertions(+), 11 deletions(-) create mode 100644 backend/app/api/handlers/v1/v1_ctrl_maint_entry.go diff --git a/backend/app/api/handlers/v1/v1_ctrl_maint_entry.go b/backend/app/api/handlers/v1/v1_ctrl_maint_entry.go new file mode 100644 index 0000000..3f3f1a1 --- /dev/null +++ b/backend/app/api/handlers/v1/v1_ctrl_maint_entry.go @@ -0,0 +1,125 @@ +package v1 + +import ( + "net/http" + + "github.com/hay-kot/homebox/backend/internal/core/services" + "github.com/hay-kot/homebox/backend/internal/data/repo" + "github.com/hay-kot/homebox/backend/internal/sys/validate" + "github.com/hay-kot/homebox/backend/pkgs/server" + "github.com/rs/zerolog/log" +) + +// HandleMaintenanceGetLog godoc +// @Summary Get Maintenance Log +// @Tags Maintenance +// @Produce json +// @Success 200 {object} repo.MaintenanceLog +// @Router /v1/items/{id}/maintenance [GET] +// @Security Bearer +func (ctrl *V1Controller) HandleMaintenanceLogGet() server.HandlerFunc { + return ctrl.handleMaintenanceLog() +} + +// HandleMaintenanceEntryCreate godoc +// @Summary Create Maintenance Entry +// @Tags Maintenance +// @Produce json +// @Param payload body repo.MaintenanceEntryCreate true "Entry Data" +// @Success 200 {object} repo.MaintenanceEntry +// @Router /v1/items/{id}/maintenance [POST] +// @Security Bearer +func (ctrl *V1Controller) HandleMaintenanceEntryCreate() server.HandlerFunc { + return ctrl.handleMaintenanceLog() +} + +// HandleMaintenanceEntryDelete godoc +// @Summary Delete Maintenance Entry +// @Tags Maintenance +// @Produce json +// @Success 204 +// @Router /v1/items/{id}/maintenance/{entry_id} [DELETE] +// @Security Bearer +func (ctrl *V1Controller) HandleMaintenanceEntryDelete() server.HandlerFunc { + return ctrl.handleMaintenanceLog() +} + +// HandleMaintenanceEntryUpdate godoc +// @Summary Update Maintenance Entry +// @Tags Maintenance +// @Produce json +// @Param payload body repo.MaintenanceEntryUpdate true "Entry Data" +// @Success 200 {object} repo.MaintenanceEntry +// @Router /v1/items/{id}/maintenance/{entry_id} [PUT] +// @Security Bearer +func (ctrl *V1Controller) HandleMaintenanceEntryUpdate() server.HandlerFunc { + return ctrl.handleMaintenanceLog() +} + +func (ctrl *V1Controller) handleMaintenanceLog() server.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) error { + ctx := services.NewContext(r.Context()) + itemID, err := ctrl.routeID(r) + if err != nil { + return err + } + + switch r.Method { + case http.MethodGet: + mlog, err := ctrl.repo.MaintEntry.GetLog(ctx, itemID) + if err != nil { + log.Err(err).Msg("failed to get items") + return validate.NewRequestError(err, http.StatusInternalServerError) + } + return server.Respond(w, http.StatusOK, mlog) + case http.MethodPost: + var create repo.MaintenanceEntryCreate + err := server.Decode(r, &create) + if err != nil { + return validate.NewRequestError(err, http.StatusBadRequest) + } + + entry, err := ctrl.repo.MaintEntry.Create(ctx, itemID, create) + if err != nil { + log.Err(err).Msg("failed to create item") + return validate.NewRequestError(err, http.StatusInternalServerError) + } + + return server.Respond(w, http.StatusCreated, entry) + case http.MethodPut: + entryID, err := ctrl.routeUUID(r, "entry_id") + if err != nil { + return err + } + + var update repo.MaintenanceEntryUpdate + err = server.Decode(r, &update) + if err != nil { + return validate.NewRequestError(err, http.StatusBadRequest) + } + + entry, err := ctrl.repo.MaintEntry.Update(ctx, entryID, update) + if err != nil { + log.Err(err).Msg("failed to update item") + return validate.NewRequestError(err, http.StatusInternalServerError) + } + + return server.Respond(w, http.StatusOK, entry) + case http.MethodDelete: + entryID, err := ctrl.routeUUID(r, "entry_id") + if err != nil { + return err + } + + err = ctrl.repo.MaintEntry.Delete(ctx, entryID) + if err != nil { + log.Err(err).Msg("failed to delete item") + return validate.NewRequestError(err, http.StatusInternalServerError) + } + + return server.Respond(w, http.StatusNoContent, nil) + } + + return nil + } +} diff --git a/backend/app/api/routes.go b/backend/app/api/routes.go index 1a42aeb..61e13d4 100644 --- a/backend/app/api/routes.go +++ b/backend/app/api/routes.go @@ -112,6 +112,11 @@ func (a *app) mountRoutes(repos *repo.AllRepos) { a.server.Put(v1Base("/items/{id}/attachments/{attachment_id}"), v1Ctrl.HandleItemAttachmentUpdate(), userMW...) a.server.Delete(v1Base("/items/{id}/attachments/{attachment_id}"), v1Ctrl.HandleItemAttachmentDelete(), userMW...) + a.server.Get(v1Base("/items/{id}/maintenance"), v1Ctrl.HandleMaintenanceEntryCreate(), userMW...) + a.server.Post(v1Base("/items/{id}/maintenance"), v1Ctrl.HandleMaintenanceEntryCreate(), userMW...) + a.server.Put(v1Base("/items/{id}/maintenance/{entry_id}"), v1Ctrl.HandleMaintenanceEntryUpdate(), userMW...) + a.server.Delete(v1Base("/items/{id}/maintenance/{entry_id}"), v1Ctrl.HandleMaintenanceEntryDelete(), userMW...) + a.server.Get( v1Base("/items/{id}/attachments/{attachment_id}"), v1Ctrl.HandleItemAttachmentGet(), diff --git a/backend/app/api/static/docs/docs.go b/backend/app/api/static/docs/docs.go index 632b9e5..06cb95c 100644 --- a/backend/app/api/static/docs/docs.go +++ b/backend/app/api/static/docs/docs.go @@ -657,6 +657,117 @@ const docTemplate = `{ } } }, + "/v1/items/{id}/maintenance": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Maintenance" + ], + "summary": "Get Maintenance Log", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/repo.MaintenanceLog" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Maintenance" + ], + "summary": "Create Maintenance Entry", + "parameters": [ + { + "description": "Entry Data", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/repo.MaintenanceEntryCreate" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/repo.MaintenanceEntry" + } + } + } + } + }, + "/v1/items/{id}/maintenance/{entry_id}": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Maintenance" + ], + "summary": "Update Maintenance Entry", + "parameters": [ + { + "description": "Entry Data", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/repo.MaintenanceEntryUpdate" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/repo.MaintenanceEntry" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Maintenance" + ], + "summary": "Delete Maintenance Entry", + "responses": { + "204": { + "description": "No Content" + } + } + } + }, "/v1/labels": { "get": { "security": [ @@ -1825,6 +1936,83 @@ const docTemplate = `{ } } }, + "repo.MaintenanceEntry": { + "type": "object", + "properties": { + "cost": { + "type": "string", + "example": "0" + }, + "date": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "repo.MaintenanceEntryCreate": { + "type": "object", + "properties": { + "cost": { + "type": "string", + "example": "0" + }, + "date": { + "type": "string" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "repo.MaintenanceEntryUpdate": { + "type": "object", + "properties": { + "cost": { + "type": "string", + "example": "0" + }, + "date": { + "type": "string" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "repo.MaintenanceLog": { + "type": "object", + "properties": { + "costAverage": { + "type": "number" + }, + "costTotal": { + "type": "number" + }, + "entries": { + "type": "array", + "items": { + "$ref": "#/definitions/repo.MaintenanceEntry" + } + }, + "itemId": { + "type": "string" + } + } + }, "repo.PaginationResult-repo_ItemSummary": { "type": "object", "properties": { diff --git a/backend/app/api/static/docs/swagger.json b/backend/app/api/static/docs/swagger.json index 69ba931..7e5ec85 100644 --- a/backend/app/api/static/docs/swagger.json +++ b/backend/app/api/static/docs/swagger.json @@ -649,6 +649,117 @@ } } }, + "/v1/items/{id}/maintenance": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Maintenance" + ], + "summary": "Get Maintenance Log", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/repo.MaintenanceLog" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Maintenance" + ], + "summary": "Create Maintenance Entry", + "parameters": [ + { + "description": "Entry Data", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/repo.MaintenanceEntryCreate" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/repo.MaintenanceEntry" + } + } + } + } + }, + "/v1/items/{id}/maintenance/{entry_id}": { + "put": { + "security": [ + { + "Bearer": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Maintenance" + ], + "summary": "Update Maintenance Entry", + "parameters": [ + { + "description": "Entry Data", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/repo.MaintenanceEntryUpdate" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/repo.MaintenanceEntry" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Maintenance" + ], + "summary": "Delete Maintenance Entry", + "responses": { + "204": { + "description": "No Content" + } + } + } + }, "/v1/labels": { "get": { "security": [ @@ -1817,6 +1928,83 @@ } } }, + "repo.MaintenanceEntry": { + "type": "object", + "properties": { + "cost": { + "type": "string", + "example": "0" + }, + "date": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "repo.MaintenanceEntryCreate": { + "type": "object", + "properties": { + "cost": { + "type": "string", + "example": "0" + }, + "date": { + "type": "string" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "repo.MaintenanceEntryUpdate": { + "type": "object", + "properties": { + "cost": { + "type": "string", + "example": "0" + }, + "date": { + "type": "string" + }, + "description": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "repo.MaintenanceLog": { + "type": "object", + "properties": { + "costAverage": { + "type": "number" + }, + "costTotal": { + "type": "number" + }, + "entries": { + "type": "array", + "items": { + "$ref": "#/definitions/repo.MaintenanceEntry" + } + }, + "itemId": { + "type": "string" + } + } + }, "repo.PaginationResult-repo_ItemSummary": { "type": "object", "properties": { diff --git a/backend/app/api/static/docs/swagger.yaml b/backend/app/api/static/docs/swagger.yaml index 802fdf8..3d2fe2a 100644 --- a/backend/app/api/static/docs/swagger.yaml +++ b/backend/app/api/static/docs/swagger.yaml @@ -383,6 +383,57 @@ definitions: type: string x-nullable: true type: object + repo.MaintenanceEntry: + properties: + cost: + example: "0" + type: string + date: + type: string + description: + type: string + id: + type: string + name: + type: string + type: object + repo.MaintenanceEntryCreate: + properties: + cost: + example: "0" + type: string + date: + type: string + description: + type: string + name: + type: string + type: object + repo.MaintenanceEntryUpdate: + properties: + cost: + example: "0" + type: string + date: + type: string + description: + type: string + name: + type: string + type: object + repo.MaintenanceLog: + properties: + costAverage: + type: number + costTotal: + type: number + entries: + items: + $ref: '#/definitions/repo.MaintenanceEntry' + type: array + itemId: + type: string + type: object repo.PaginationResult-repo_ItemSummary: properties: items: @@ -938,6 +989,72 @@ paths: summary: retrieves an attachment for an item tags: - Items Attachments + /v1/items/{id}/maintenance: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/repo.MaintenanceLog' + security: + - Bearer: [] + summary: Get Maintenance Log + tags: + - Maintenance + post: + parameters: + - description: Entry Data + in: body + name: payload + required: true + schema: + $ref: '#/definitions/repo.MaintenanceEntryCreate' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/repo.MaintenanceEntry' + security: + - Bearer: [] + summary: Create Maintenance Entry + tags: + - Maintenance + /v1/items/{id}/maintenance/{entry_id}: + delete: + produces: + - application/json + responses: + "204": + description: No Content + security: + - Bearer: [] + summary: Delete Maintenance Entry + tags: + - Maintenance + put: + parameters: + - description: Entry Data + in: body + name: payload + required: true + schema: + $ref: '#/definitions/repo.MaintenanceEntryUpdate' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/repo.MaintenanceEntry' + security: + - Bearer: [] + summary: Update Maintenance Entry + tags: + - Maintenance /v1/items/import: post: parameters: diff --git a/backend/internal/data/repo/repo_maintenance_entry.go b/backend/internal/data/repo/repo_maintenance_entry.go index 70f554e..d59469e 100644 --- a/backend/internal/data/repo/repo_maintenance_entry.go +++ b/backend/internal/data/repo/repo_maintenance_entry.go @@ -17,11 +17,10 @@ type MaintenanceEntryRepository struct { } type ( MaintenanceEntryCreate struct { - ItemID uuid.UUID `json:"itemId"` Date time.Time `json:"date"` Name string `json:"name"` Description string `json:"description"` - Cost float64 `json:"cost"` + Cost float64 `json:"cost,string"` } MaintenanceEntry struct { @@ -29,14 +28,21 @@ type ( Date time.Time `json:"date"` Name string `json:"name"` Description string `json:"description"` - Cost float64 `json:"cost"` + Cost float64 `json:"cost,string"` + } + + MaintenanceEntryUpdate struct { + Date time.Time `json:"date"` + Name string `json:"name"` + Description string `json:"description"` + Cost float64 `json:"cost,string"` } MaintenanceLog struct { - ItemID uuid.UUID `json:"itemId"` - CostAverage float64 `json:"costAverage"` - CostTotal float64 `json:"costTotal"` - Entries []MaintenanceEntry + ItemID uuid.UUID `json:"itemId"` + CostAverage float64 `json:"costAverage"` + CostTotal float64 `json:"costTotal"` + Entries []MaintenanceEntry `json:"entries"` } ) @@ -55,9 +61,20 @@ func mapMaintenanceEntry(entry *ent.MaintenanceEntry) MaintenanceEntry { } } -func (r *MaintenanceEntryRepository) Create(ctx context.Context, input MaintenanceEntryCreate) (MaintenanceEntry, error) { +func (r *MaintenanceEntryRepository) Create(ctx context.Context, itemID uuid.UUID, input MaintenanceEntryCreate) (MaintenanceEntry, error) { item, err := r.db.MaintenanceEntry.Create(). - SetItemID(input.ItemID). + SetItemID(itemID). + SetDate(input.Date). + SetName(input.Name). + SetDescription(input.Description). + SetCost(input.Cost). + Save(ctx) + + return mapMaintenanceEntryErr(item, err) +} + +func (r *MaintenanceEntryRepository) Update(ctx context.Context, ID uuid.UUID, input MaintenanceEntryUpdate) (MaintenanceEntry, error) { + item, err := r.db.MaintenanceEntry.UpdateOneID(ID). SetDate(input.Date). SetName(input.Name). SetDescription(input.Description). diff --git a/backend/internal/data/repo/repo_maintenance_entry_test.go b/backend/internal/data/repo/repo_maintenance_entry_test.go index a1ad51b..8babefc 100644 --- a/backend/internal/data/repo/repo_maintenance_entry_test.go +++ b/backend/internal/data/repo/repo_maintenance_entry_test.go @@ -24,7 +24,6 @@ func TestMaintenanceEntryRepository_GetLog(t *testing.T) { } created[i] = MaintenanceEntryCreate{ - ItemID: item.ID, Date: dt, Name: "Maintenance", Description: "Maintenance description", @@ -33,7 +32,7 @@ func TestMaintenanceEntryRepository_GetLog(t *testing.T) { } for _, entry := range created { - _, err := tRepos.MaintEntry.Create(context.Background(), entry) + _, err := tRepos.MaintEntry.Create(context.Background(), item.ID, entry) if err != nil { t.Fatalf("failed to create maintenance entry: %v", err) }