From a7cf8fd062c31766fcc474af006d87019caedd2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Murta?= Date: Sat, 1 Jun 2024 09:11:42 +0100 Subject: [PATCH] ongoing --- docs/openapi.yaml | 15 ++++++++++ internal/api/impl.go | 39 +++++++++++++++++++++++-- internal/api/impl_test.go | 60 ++++++++++++++++++++++++++++++++++++++ internal/api/server.gen.go | 58 ++++++++++++++++++++++++++---------- internal/dal/dal.go | 2 ++ 5 files changed, 156 insertions(+), 18 deletions(-) diff --git a/docs/openapi.yaml b/docs/openapi.yaml index 28e7587..30c617c 100644 --- a/docs/openapi.yaml +++ b/docs/openapi.yaml @@ -73,6 +73,21 @@ paths: $ref: "#/components/schemas/Transaction" "400": description: Transaction not created + put: + summary: Update an existing transaction + operationId: updateTransaction + requestBody: + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/Transaction" + - required: + - id + + responses: + "204": + description: Transaction updated successfully /transaction/{transactionId}: get: diff --git a/internal/api/impl.go b/internal/api/impl.go index 7484a84..a1d832b 100644 --- a/internal/api/impl.go +++ b/internal/api/impl.go @@ -83,11 +83,46 @@ func (server *ServerImpl) CreateTransaction(ctx echo.Context) error { return ctx.NoContent(http.StatusBadRequest) } - ans, err := server.Dal.InsertTransaction(transaction2entity(*t)) + transaction, err := server.Dal.InsertTransaction(transaction2entity(*t)) if err != nil { log.Printf("%v", err) return ctx.NoContent(http.StatusInternalServerError) } - return ctx.JSON(http.StatusCreated, entity2transaction(ans)) + return ctx.JSON(http.StatusCreated, entity2transaction(transaction)) +} + +func (server *ServerImpl) UpdateTransaction(ctx echo.Context) error { + t := new(Transaction) + if err := ctx.Bind(t); err != nil { + log.Printf("%v", err) + return ctx.NoContent(http.StatusBadRequest) + } + + transaction := transaction2entity(*t) + + exists, err := server.Dal.TransactionExists(transaction.Id) + if err != nil { + log.Printf("%v", err) + return ctx.NoContent(http.StatusInternalServerError) + } + + if !exists { + transaction, err := server.Dal.InsertTransaction(transaction) + if err != nil { + log.Printf("%v", err) + return ctx.NoContent(http.StatusInternalServerError) + } + + return ctx.JSON(http.StatusCreated, entity2transaction(transaction)) + + } else { + transaction, err := server.Dal.UpdateTransaction(transaction) + if err != nil { + log.Printf("%v", err) + return ctx.NoContent(http.StatusInternalServerError) + } + + return ctx.JSON(http.StatusOK, entity2transaction(transaction)) + } } diff --git a/internal/api/impl_test.go b/internal/api/impl_test.go index 367303e..9d223cf 100644 --- a/internal/api/impl_test.go +++ b/internal/api/impl_test.go @@ -286,3 +286,63 @@ func TestServerImpl_CreateTransaction(t *testing.T) { }) } } + +func TestServerImpl_UpdateTransaction(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + mock_dal := mock.NewMockDAL(ctrl) + + date, _ := time.Parse(time.DateOnly, "1974-04-25") + + type fields struct { + Dal dal.DAL + } + type args struct { + request string + } + type want struct { + entity entity.Transaction + response string + } + tests := []struct { + name string + fields fields + args args + want want + wantErr bool + }{ + { + "201", + fields{mock_dal}, + args{`{"date": "1974-04-25", "description": "freedom", "value": 9000}`}, + want{ + entity.Transaction{Id: 1, Date: date, Description: "freedom", Value: decimal.New(9000, 0)}, + `{"date":"1974-04-25","description":"freedom","id":1,"value":9000}`, + }, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := &ServerImpl{Dal: tt.fields.Dal} + + req := httptest.NewRequest(http.MethodPost, "/transactions", strings.NewReader(tt.args.request)) + req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) + rec := httptest.NewRecorder() + e := echo.New() + ctx := e.NewContext(req, rec) + + inserted := tt.want.entity + inserted.Id = entity.InvalidId + mock_dal.EXPECT().InsertTransaction(gomock.AssignableToTypeOf(reflect.TypeOf(tt.want.entity))).Return(tt.want.entity, nil).Times(1) + + if err := s.UpdateTransaction(ctx); (err != nil) != tt.wantErr { + t.Errorf("ServerImpl.GetTransactionById() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(strings.TrimSpace(rec.Body.String()), tt.want.response) { + t.Errorf("DalImpl.InsertTransaction() = %v, want %v", rec.Body.String(), tt.want.response) + } + }) + } +} diff --git a/internal/api/server.gen.go b/internal/api/server.gen.go index 927fd40..0670ce5 100644 --- a/internal/api/server.gen.go +++ b/internal/api/server.gen.go @@ -59,9 +59,21 @@ type GetTransactionsParams struct { Sort *string `form:"sort,omitempty" json:"sort,omitempty"` } +// UpdateTransactionJSONBody defines parameters for UpdateTransaction. +type UpdateTransactionJSONBody struct { + Category *string `json:"category,omitempty"` + Date openapi_types.Date `json:"date"` + Description string `json:"description"` + Id int64 `json:"id"` + Value float32 `json:"value"` +} + // CreateTransactionJSONRequestBody defines body for CreateTransaction for application/json ContentType. type CreateTransactionJSONRequestBody = Transaction +// UpdateTransactionJSONRequestBody defines body for UpdateTransaction for application/json ContentType. +type UpdateTransactionJSONRequestBody UpdateTransactionJSONBody + // ServerInterface represents all server handlers. type ServerInterface interface { // Find bank by ID @@ -79,6 +91,9 @@ type ServerInterface interface { // Create a new transaction // (POST /transactions) CreateTransaction(ctx echo.Context) error + // Update an existing transaction + // (PUT /transactions) + UpdateTransaction(ctx echo.Context) error } // ServerInterfaceWrapper converts echo contexts to parameters. @@ -182,6 +197,15 @@ func (w *ServerInterfaceWrapper) CreateTransaction(ctx echo.Context) error { return err } +// UpdateTransaction converts echo context to params. +func (w *ServerInterfaceWrapper) UpdateTransaction(ctx echo.Context) error { + var err error + + // Invoke the callback with all the unmarshaled arguments + err = w.Handler.UpdateTransaction(ctx) + return err +} + // This is a simple interface which specifies echo.Route addition functions which // are present on both echo.Echo and echo.Group, since we want to allow using // either of them for path registration @@ -215,28 +239,30 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL router.GET(baseURL+"/transaction/:transactionId", wrapper.GetTransactionById) router.GET(baseURL+"/transactions", wrapper.GetTransactions) router.POST(baseURL+"/transactions", wrapper.CreateTransaction) + router.PUT(baseURL+"/transactions", wrapper.UpdateTransaction) } // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/8RWTW/jNhD9KwTboyIpcdCDTm0abGCg2Abd9rTdAy2NbO5SpJYc2jUM//diKMWmPhKn", - "QLN7cSRxOPPmzeNjDrw0TWs0aHS8OHBXbqAR4fFO6C/0t7WmBYsSwldZ0S/uW+AFd2ilXvNjwrVoYH7B", - "2EquQS/DvtrYRiAvuPey4sk4/JhwC1+9tFDx4iMPISHzp1OoWX2GEikz4esgITTh4UcLNS/4D9m5p6xv", - "KAvdHE9phLViT+9/WqGdKFEaPW22FAhrY/eznVUCYdBT+JDMBIIrrWyfSkzW5ZAaqfGnW57wRmrZ+IYX", - "+Smn1AhrsLRpK5Qflq+VEXiur32zotARpz3IGNNTsjmSI3pez3XM6YRyAiR1bQK/RqMokR6hEVJRF1IL", - "XcLPjbco0gq2Ewb5I1hntFDsXRfLPoDdgv2bOlGyBO0CMZ0k+cP7v9gDaLBCsUe/UrJkv3VBbLtIc2Ys", - "UwLB8oR7Swg2iK0rsmy326Vr7VNj11mf1mXrVl0t0vzKodCVUEZDusFGhTYlKpiDd8V+b0H/8rhkizQn", - "tsG6rpM8zdNr2mta0KKVvOCLNE8XPOGtwE0gOlsJ/SU70O+yOtKXNQTGSKiCKKGjxR8ASeJ3+2UVdlvR", - "AIJ1vPh4GPG3vGemZpSQoWEW0FuiTtIalX06dAXvivJYQWg9JL1NzKj5+ImCXWuILVq/yfOnSYMOuEXb", - "KlkG5Nln152Jc77LZ/g4EcQHX5bgXO0VO5FCrN52tUfd661QsmLLe+Y8QYGqi72dxlJBpg2y2nhdhbPk", - "fNMIcgT+TuqqY3G1Z8v7sBqG5S4NyfE3Jsn9F5Zu5jp/b9iqTxT3/AeglbAFBv9Ih1Kvo6gMz8c+O0Qv", - "F2QbucXr1RulvyTiAZIXtTyx4LHtvqm6B675DUUe1X1Z6zHnkeRxdEW8Ys7u0pBrqRAsVYmLnq7jfs5f", - "PYSXftDR8plx7ZUSKzLmbtqT/zjGpbt7c6QxNxXZqLiSjcRB5Qpq4RXy4jrPk4G2FjcXrvcpKlPXDpDV", - "1jRstwELPaDuNOKQ2jl8XYJ5gFfXM/guY+pP4gaCCTxTt196/sJIprMHVTHaTvPfbWS5oWadsfhMjX7p", - "+1xKA1n/D7aLw3wvu+8wOOGtcTOH71cLAiH2l84FweGdqfZv5WDHCevX38osY08rQ/fVs1459r9T/ID7", - "jkMmmIZdTHto9N8AAAD//+YRCdlGDQAA", + "H4sIAAAAAAAC/8RXTW/jNhD9KwTboyIpcdCDTm0abGCg2A263dM2B1oc2dylSC05tGsY/u/FUIqjr8Qp", + "sNleZEkczsebN4/ygZe2bqwBg54XB+7LDdQi3t4I85V+G2cbcKggvlWSrrhvgBfco1NmzY8JN6KG+QXr", + "pFqDWcZ9lXW1QF7wEJTkydj8mHAH34JyIHnxmUeT6PnhZGpXX6BE8kz5tSkh1PHmZwcVL/hP2VNNWVdQ", + "Fqs5ntwI58Senv9ywnhRorJmWmwpENbW7WcrkwJhUFN8kcwYgi+dah5DTNbVEBpl8JdrnvBaGVWHmhf5", + "yacyCGtwtGkrdBiGr7QV+BTfhHpFpiNMuyT7OT06mwO5B8/rse5jOoGcElKmshFfa1CUSLdQC6WpCmWE", + "KeHXOjgUqYTtBEF+D85bIzR719qyj+C24P6mSrQqwfgITEtJfvf+E7sDA05odh9WWpXsj9aIbRdpzqxj", + "WiA4nvDgKIMNYuOLLNvtdunahNS6dda59dm60ReLNL/wKIwU2hpIN1jrWKZCDXPpXbAPDZjf7pdskeaE", + "NjjfVpKneXpJe20DRjSKF3yR5umCJ7wRuIlAZythvmYHui7lkd6sISJGRBUECY0WvwMkit/slzLudqIG", + "BOd58fkwwm95y2zFyCFDyxxgcASdojUK+zh0BW+D8j6D0AVIOpmYYfPxgYx9YwktWr/K88dOg4l5i6bR", + "qoyZZ198OxNP/s7P8HFCiI+hLMH7Kmh2AoVQvW5jj6o3W6GVZMtb5gOlArK1vZ7aUkBmLLLKBiPjLPlQ", + "14IUgb9TRrYorvZseRtXY7P8uSZ5/sYg+f+C0tVc5e8tW3WO+jX/CegUbIHBP8qjMuueVYZPY58deg9n", + "aNtTi9ezt+f+HIkHmbzI5YkEj2X3Tdk9UM0fSPJe3Je53se8R3kcHRGv6LM/1+RKaQRHUfpBT8dx1+dv", + "AeJD1+je8hPiJmgtViTMbbcnXxzj0O25OeKYn5JsFFyrWuEgsoRKBI28uMzzZMCtxdWZ432ala0qD8gq", + "Z2u224CDLqF2GnEI7Vx+rYP5BC8uZ/I7n1M3iRuIIvBM3G7p+QMjmfYetGS0nfq/26hyQ8V66/CZGN3S", + "/3MoDWj9HWQXh/5eVt+hccIb62eG73cHAqGvL60KgscbK/dvpWDHCeqXP0os+5pWxurls1o51r+T/QD7", + "FkMmmIFdH/aIepgB/VMjvxvoQusPVZTJ1392H8Z/pR6OD7NNOXMkhFiHZP7EY70fYdOWyoSZJWakwr8B", + "AAD//5ap8eBoDgAA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/dal/dal.go b/internal/dal/dal.go index fdea783..e2d747e 100644 --- a/internal/dal/dal.go +++ b/internal/dal/dal.go @@ -6,6 +6,8 @@ type DAL interface { Transaction(transactionId int64) (*entity.Transaction, error) Transactions() (entity.Transactions, error) InsertTransaction(entity.Transaction) (entity.Transaction, error) + UpdateTransaction(entity.Transaction) (entity.Transaction, error) + TransactionExists(uint64) (bool, error) Bank(bankId string) (*entity.Bank, error) Banks() (entity.Banks, error) }