From eb23bcdb29c4979ab78fb24a29a07645f65a593a Mon Sep 17 00:00:00 2001 From: Sunioatm <104454675+Sunioatm@users.noreply.github.com> Date: Fri, 22 Dec 2023 03:21:59 +0700 Subject: [PATCH 01/48] feat: add delete pet --- go.mod | 26 ++++- go.sum | 46 ++++++++ src/app/service/pet/pet.service.go | 64 ++++++++++++ src/app/service/pet/pet.service_test.go | 133 ++++++++++++++++++++++++ src/mocks/pet/pet.mock.go | 46 ++++++++ 5 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 src/app/service/pet/pet.service.go create mode 100644 src/app/service/pet/pet.service_test.go create mode 100644 src/mocks/pet/pet.mock.go diff --git a/go.mod b/go.mod index a2fd7dc..ad5f36b 100644 --- a/go.mod +++ b/go.mod @@ -1,18 +1,41 @@ module github.com/isd-sgcu/johnjud-backend -go 1.21.0 +go 1.21.3 + +toolchain go1.21.5 require ( + github.com/bxcodec/faker/v3 v3.8.1 + github.com/go-playground/validator/v10 v10.16.0 github.com/google/uuid v1.5.0 github.com/pkg/errors v0.9.1 + github.com/rs/zerolog v1.31.0 github.com/spf13/viper v1.18.2 + google.golang.org/grpc v1.60.1 gorm.io/driver/postgres v1.5.4 gorm.io/gorm v1.25.5 ) +require ( + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/stretchr/objx v0.5.0 // indirect + golang.org/x/net v0.19.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect + google.golang.org/protobuf v1.31.0 // indirect +) + require ( github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/isd-sgcu/johnjud-go-proto v0.0.8 github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.4.3 // indirect @@ -27,6 +50,7 @@ require ( github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/testify v1.8.4 github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect diff --git a/go.sum b/go.sum index b753851..9501998 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,6 @@ +github.com/bxcodec/faker/v3 v3.8.1 h1:qO/Xq19V6uHt2xujwpaetgKhraGCapqY2CRWGD/SqcM= +github.com/bxcodec/faker/v3 v3.8.1/go.mod h1:DdSDccxF5msjFo5aO4vrobRQ8nIApg8kq3QWPEQD6+o= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -6,12 +9,29 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= +github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/isd-sgcu/johnjud-go-proto v0.0.8 h1:nIQBZgK2OFVrLjVtpeDgwows8poA7LhsIVE4hlbBC1o= +github.com/isd-sgcu/johnjud-go-proto v0.0.8/go.mod h1:HP0w9gC30b5WNnqeFBM9JJZud+pvyikz0+pGFSI/Wjw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= @@ -26,8 +46,15 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= @@ -39,6 +66,9 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= +github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -55,11 +85,13 @@ github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -72,10 +104,24 @@ golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go new file mode 100644 index 0000000..5636d59 --- /dev/null +++ b/src/app/service/pet/pet.service.go @@ -0,0 +1,64 @@ +package pet + +import ( + "context" + "errors" + + proto "github.com/isd-sgcu/johnjud-go-proto/johnjud/backend/pet/v1" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "gorm.io/gorm" +) + +type Service struct { + repo IRepository +} + +type IRepository interface { + FindAll() error + FindOne() error + Create() error + Update() error + ChangeView() error + Delete(string) error +} + +func NewService(repo IRepository) *Service { + return &Service{repo: repo} +} + +func (s *Service) Delete(ctx context.Context, req *proto.DeletePetRequest) (*proto.DeletePetResponse, error) { + err := s.repo.Delete(req.Id) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, status.Error(codes.NotFound, "pet not found") + } + return nil, status.Error(codes.Internal, "internal error") + } + return &proto.DeletePetResponse{Success: true}, nil +} + +// ChangeView implements v1.PetServiceServer. +func (*Service) ChangeView(context.Context, *proto.ChangeViewPetRequest) (*proto.ChangeViewPetResponse, error) { + panic("unimplemented") +} + +// Create implements v1.PetServiceServer. +func (*Service) Create(context.Context, *proto.CreatePetRequest) (*proto.CreatePetResponse, error) { + panic("unimplemented") +} + +// FindAll implements v1.PetServiceServer. +func (*Service) FindAll(context.Context, *proto.FindAllPetRequest) (*proto.FindAllPetResponse, error) { + panic("unimplemented") +} + +// FindOne implements v1.PetServiceServer. +func (*Service) FindOne(context.Context, *proto.FindOnePetRequest) (*proto.FindOnePetResponse, error) { + panic("unimplemented") +} + +// Update implements v1.PetServiceServer. +func (*Service) Update(context.Context, *proto.UpdatePetRequest) (*proto.UpdatePetResponse, error) { + panic("unimplemented") +} diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go new file mode 100644 index 0000000..db045ff --- /dev/null +++ b/src/app/service/pet/pet.service_test.go @@ -0,0 +1,133 @@ +package pet + +import ( + "context" + "errors" + "math/rand" + "os/user" + "testing" + "time" + + "github.com/bxcodec/faker/v3" + "github.com/google/uuid" + mock "github.com/isd-sgcu/johnjud-backend/src/mocks/pet" + "gorm.io/gorm" + + "github.com/isd-sgcu/johnjud-backend/src/app/model" + "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" + proto "github.com/isd-sgcu/johnjud-go-proto/johnjud/backend/pet/v1" + + petConst "github.com/isd-sgcu/johnjud-backend/src/constant/pet" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +type PetServiceTest struct { + suite.Suite + Pet *pet.Pet + UpdatePet *user.User + PetDto *proto.Pet + CreatePetReqMock *proto.CreatePetRequest + UpdatePetReqMock *proto.UpdatePetRequest +} + +func TestUserService(t *testing.T) { + suite.Run(t, new(PetServiceTest)) +} + +func (t *PetServiceTest) SetupTest() { + t.Pet = &pet.Pet{ + Base: model.Base{ + ID: uuid.New(), + CreatedAt: time.Time{}, + UpdatedAt: time.Time{}, + DeletedAt: gorm.DeletedAt{}, + }, + Type: faker.Word(), + Species: faker.Word(), + Name: faker.Name(), + Birthdate: faker.Word(), + Gender: petConst.Gender(rand.Intn(2) + 1), + Habit: faker.Paragraph(), + Caption: faker.Paragraph(), + Status: petConst.Status(rand.Intn(2) + 1), + IsSterile: true, + IsVaccinated: true, + IsVisible: true, + IsClubPet: true, + Background: faker.Paragraph(), + Address: faker.Paragraph(), + Contact: faker.Paragraph(), + } + + t.PetDto = &proto.Pet{ + Type: t.Pet.Type, + Species: t.Pet.Species, + Name: t.Pet.Name, + Birthdate: t.Pet.Birthdate, + Gender: proto.Gender(t.Pet.Gender), + Habit: t.Pet.Habit, + Caption: t.Pet.Caption, + Status: proto.PetStatus(t.Pet.Status), + IsSterile: t.Pet.IsSterile, + IsVaccinated: t.Pet.IsVaccinated, + IsVisible: t.Pet.IsVisible, + IsClubPet: t.Pet.IsClubPet, + Background: t.Pet.Background, + Address: t.Pet.Address, + Contact: t.Pet.Contact, + } +} +func (t *PetServiceTest) TestDeleteSuccess() { + want := &proto.DeletePetResponse{Success: true} + + repo := new(mock.RepositoryMock) + repo.On("Delete", t.Pet.ID.String()).Return(nil) + + srv := NewService(repo) + actual, err := srv.Delete(context.Background(), &proto.DeletePetRequest{Id: t.Pet.ID.String()}) + + assert.Nil(t.T(), err) + assert.Equal(t.T(), want, actual) + repo.AssertExpectations(t.T()) +} + +func (t *PetServiceTest) TestDeleteNotFound() { + repo := new(mock.RepositoryMock) + repo.On("Delete", t.Pet.ID.String()).Return(gorm.ErrRecordNotFound) + + srv := NewService(repo) + _, err := srv.Delete(context.Background(), &proto.DeletePetRequest{Id: t.Pet.ID.String()}) + + st, ok := status.FromError(err) + assert.True(t.T(), ok) + assert.Equal(t.T(), codes.NotFound, st.Code()) + repo.AssertExpectations(t.T()) +} + +func (t *PetServiceTest) TestDeleteWithDatabaseError() { + repo := new(mock.RepositoryMock) + repo.On("Delete", t.Pet.ID.String()).Return(errors.New("internal server error")) + + srv := NewService(repo) + _, err := srv.Delete(context.Background(), &proto.DeletePetRequest{Id: t.Pet.ID.String()}) + + st, ok := status.FromError(err) + assert.True(t.T(), ok) + assert.Equal(t.T(), codes.Internal, st.Code()) + repo.AssertExpectations(t.T()) +} + +func (t *PetServiceTest) TestDeleteWithUnexpectedError() { + repo := new(mock.RepositoryMock) + repo.On("Delete", t.Pet.ID.String()).Return(errors.New("unexpected error")) + + srv := NewService(repo) + _, err := srv.Delete(context.Background(), &proto.DeletePetRequest{Id: t.Pet.ID.String()}) + + assert.Error(t.T(), err) + repo.AssertExpectations(t.T()) +} diff --git a/src/mocks/pet/pet.mock.go b/src/mocks/pet/pet.mock.go new file mode 100644 index 0000000..19bae59 --- /dev/null +++ b/src/mocks/pet/pet.mock.go @@ -0,0 +1,46 @@ +package pet + +import ( + "github.com/stretchr/testify/mock" +) + +// RepositoryMock is a mock type for the IRepository interface +type RepositoryMock struct { + mock.Mock +} + +// FindAll mocks the FindAll method +func (r *RepositoryMock) FindAll() error { + // unimplemented for now + return nil +} + +// FindOne mocks the FindOne method +func (r *RepositoryMock) FindOne() error { + // unimplemented for now + return nil +} + +// Create mocks the Create method +func (r *RepositoryMock) Create() error { + // unimplemented for now + return nil +} + +// Update mocks the Update method +func (r *RepositoryMock) Update() error { + // unimplemented for now + return nil +} + +// ChangeView mocks the ChangeView method +func (r *RepositoryMock) ChangeView() error { + // unimplemented for now + return nil +} + +// Delete mocks the Delete method +func (r *RepositoryMock) Delete(id string) error { + args := r.Called(id) + return args.Error(0) +} From 48bf4568fb654415293fa8060e283692710f7f24 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Fri, 22 Dec 2023 13:42:31 +0700 Subject: [PATCH 02/48] feat: add workflow --- .github/workflows/run-unit-test.yaml | 38 ++++++++++++++++++++++++++++ .github/workflows/test-build.yaml | 35 +++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 .github/workflows/run-unit-test.yaml create mode 100644 .github/workflows/test-build.yaml diff --git a/.github/workflows/run-unit-test.yaml b/.github/workflows/run-unit-test.yaml new file mode 100644 index 0000000..d14323e --- /dev/null +++ b/.github/workflows/run-unit-test.yaml @@ -0,0 +1,38 @@ +name: 'Pull request/Push: Run unit test' + +on: + pull_request: + branches: + - dev + - master + - main + - beta + push: + branches: + - dev + - master + - main + - beta + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.21 + + - name: Download dependencies + run: go mod download + + - name: Vet + run: | + go vet ./... + + - name: Test + run: | + go test -v -coverpkg ./src/app/... -coverprofile coverage.out -covermode count ./src/app/... + go tool cover -func="./coverage.out" diff --git a/.github/workflows/test-build.yaml b/.github/workflows/test-build.yaml new file mode 100644 index 0000000..448e84c --- /dev/null +++ b/.github/workflows/test-build.yaml @@ -0,0 +1,35 @@ +name: 'Pull request/Push: Build test' + +on: + pull_request: + branches: + - dev + - master + - main + - beta + push: + branches: + - dev + - master + - main + - beta + +jobs: + docker-build: + name: 'Docker build and create an image' + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Build Docker image + id: docker_build + uses: docker/build-push-action@v2 + with: + context: . + push: false + tags: test \ No newline at end of file From f1996b216f5446e56502e02142a8dc625b7ba5a8 Mon Sep 17 00:00:00 2001 From: Sunioatm <104454675+Sunioatm@users.noreply.github.com> Date: Fri, 22 Dec 2023 14:04:43 +0700 Subject: [PATCH 03/48] made requested changes --- src/app/service/pet/pet.service.go | 29 ++++++++++------------------- src/mocks/pet/pet.mock.go | 21 +++++---------------- 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 5636d59..5ebd337 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -4,6 +4,7 @@ import ( "context" "errors" + "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" proto "github.com/isd-sgcu/johnjud-go-proto/johnjud/backend/pet/v1" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -11,24 +12,23 @@ import ( ) type Service struct { - repo IRepository + repository IRepository } type IRepository interface { - FindAll() error - FindOne() error - Create() error - Update() error - ChangeView() error - Delete(string) error + FindAll(result *[]*pet.Pet) error + FindOne(id string, result *[]*pet.Pet) error + Create(in *pet.Pet) error + Update(id string, result *pet.Pet) error + Delete(id string) error } -func NewService(repo IRepository) *Service { - return &Service{repo: repo} +func NewService(repository IRepository) *Service { + return &Service{repository: repository} } func (s *Service) Delete(ctx context.Context, req *proto.DeletePetRequest) (*proto.DeletePetResponse, error) { - err := s.repo.Delete(req.Id) + err := s.repository.Delete(req.Id) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, status.Error(codes.NotFound, "pet not found") @@ -38,27 +38,18 @@ func (s *Service) Delete(ctx context.Context, req *proto.DeletePetRequest) (*pro return &proto.DeletePetResponse{Success: true}, nil } -// ChangeView implements v1.PetServiceServer. -func (*Service) ChangeView(context.Context, *proto.ChangeViewPetRequest) (*proto.ChangeViewPetResponse, error) { - panic("unimplemented") -} - -// Create implements v1.PetServiceServer. func (*Service) Create(context.Context, *proto.CreatePetRequest) (*proto.CreatePetResponse, error) { panic("unimplemented") } -// FindAll implements v1.PetServiceServer. func (*Service) FindAll(context.Context, *proto.FindAllPetRequest) (*proto.FindAllPetResponse, error) { panic("unimplemented") } -// FindOne implements v1.PetServiceServer. func (*Service) FindOne(context.Context, *proto.FindOnePetRequest) (*proto.FindOnePetResponse, error) { panic("unimplemented") } -// Update implements v1.PetServiceServer. func (*Service) Update(context.Context, *proto.UpdatePetRequest) (*proto.UpdatePetResponse, error) { panic("unimplemented") } diff --git a/src/mocks/pet/pet.mock.go b/src/mocks/pet/pet.mock.go index 19bae59..c8c780d 100644 --- a/src/mocks/pet/pet.mock.go +++ b/src/mocks/pet/pet.mock.go @@ -1,45 +1,34 @@ package pet import ( + "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" "github.com/stretchr/testify/mock" ) -// RepositoryMock is a mock type for the IRepository interface type RepositoryMock struct { mock.Mock } -// FindAll mocks the FindAll method -func (r *RepositoryMock) FindAll() error { +func (r *RepositoryMock) FindAll(result *[]*pet.Pet) error { // unimplemented for now return nil } -// FindOne mocks the FindOne method -func (r *RepositoryMock) FindOne() error { +func (r *RepositoryMock) FindOne(id string, result *[]*pet.Pet) error { // unimplemented for now return nil } -// Create mocks the Create method -func (r *RepositoryMock) Create() error { +func (r *RepositoryMock) Create(in *pet.Pet) error { // unimplemented for now return nil } -// Update mocks the Update method -func (r *RepositoryMock) Update() error { +func (r *RepositoryMock) Update(id string, result *pet.Pet) error { // unimplemented for now return nil } -// ChangeView mocks the ChangeView method -func (r *RepositoryMock) ChangeView() error { - // unimplemented for now - return nil -} - -// Delete mocks the Delete method func (r *RepositoryMock) Delete(id string) error { args := r.Called(id) return args.Error(0) From d8457c9e8e2fe0099d839a2579ef1e675cc04d48 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Fri, 22 Dec 2023 14:06:23 +0700 Subject: [PATCH 04/48] fix: change docker port to 3003 --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index cb8a396..1301125 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,8 +36,8 @@ COPY --from=base /app/server ./ # Set ENV to production ENV GO_ENV production -# Expose port 3001 -EXPOSE 3001 +# Expose port 3003 +EXPOSE 3003 # Run the application CMD ["./server"] \ No newline at end of file From a3730897e2d39bc21daed2c4ddfdd28fc047d2e3 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Fri, 22 Dec 2023 14:40:17 +0700 Subject: [PATCH 05/48] feat: go mod tidy --- go.mod | 13 ------------- go.sum | 16 +++++++++++++--- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 0b3b04f..a519e39 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ toolchain go1.21.5 require ( github.com/bxcodec/faker/v3 v3.8.1 - github.com/go-playground/validator/v10 v10.16.0 github.com/google/uuid v1.5.0 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.31.0 @@ -18,11 +17,7 @@ require ( require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/gabriel-vasile/mimetype v1.4.2 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/leodido/go-urn v1.2.4 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect @@ -34,7 +29,6 @@ require ( require ( github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/isd-sgcu/johnjud-go-proto v0.0.8 github.com/jackc/pgpassfile v1.0.0 // indirect @@ -43,11 +37,8 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/rs/zerolog v1.31.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -60,12 +51,8 @@ require ( go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.19.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/grpc v1.60.1 // indirect - google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 4ea0d17..9366728 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/bxcodec/faker/v3 v3.8.1 h1:qO/Xq19V6uHt2xujwpaetgKhraGCapqY2CRWGD/SqcM= +github.com/bxcodec/faker/v3 v3.8.1/go.mod h1:DdSDccxF5msjFo5aO4vrobRQ8nIApg8kq3QWPEQD6+o= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -18,6 +20,8 @@ github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/isd-sgcu/johnjud-go-proto v0.0.8 h1:nIQBZgK2OFVrLjVtpeDgwows8poA7LhsIVE4hlbBC1o= +github.com/isd-sgcu/johnjud-go-proto v0.0.8/go.mod h1:HP0w9gC30b5WNnqeFBM9JJZud+pvyikz0+pGFSI/Wjw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= @@ -32,8 +36,6 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -77,7 +79,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -99,6 +100,15 @@ golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From ebc7b2af432ed432664d4be3d77f95d42e2d93fa Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Fri, 22 Dec 2023 15:45:43 +0700 Subject: [PATCH 06/48] fix: change makefile repo name --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 1dd22b2..bc834cc 100644 --- a/Makefile +++ b/Makefile @@ -3,8 +3,8 @@ proto: publish: cat ./token.txt | docker login --username isd-team-sgcu --password-stdin ghcr.io - docker build . -t ghcr.io/isd-sgcu/johnjud-gateway - docker push ghcr.io/isd-sgcu/johnjud-gateway + docker build . -t ghcr.io/isd-sgcu/johnjud-backend + docker push ghcr.io/isd-sgcu/johnjud-backend test: go vet ./... From d5b99e8c25b9c4092e75dd3691c532eaa3f64c4a Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Fri, 22 Dec 2023 15:46:29 +0700 Subject: [PATCH 07/48] feat: image service --- src/app/service/image/image.service.go | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/app/service/image/image.service.go diff --git a/src/app/service/image/image.service.go b/src/app/service/image/image.service.go new file mode 100644 index 0000000..0945ec5 --- /dev/null +++ b/src/app/service/image/image.service.go @@ -0,0 +1,34 @@ +package image + +import ( + "context" + "time" + + proto "github.com/isd-sgcu/johnjud-go-proto/johnjud/file/image/v1" + "github.com/rs/zerolog/log" +) + +type Service struct { + client proto.ImageServiceClient +} + +func NewService(client proto.ImageServiceClient) *Service { + return &Service{client: client} +} + +func (s *Service) FindByPetId(petId string) ([]*proto.Image, error) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + res, err := s.client.FindByPetId(ctx, &proto.FindImageByPetIdRequest{PetId: petId}) + if err != nil { + log.Error(). + Err(err). + Str("service", "image"). + Str("module", "find by petId"). + Msg("Error while connecting to service") + return nil, err + } + return res.Images, nil + +} From 5eabdeb54859da0d5a1df7edf2398c00f1f68591 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Fri, 22 Dec 2023 15:46:34 +0700 Subject: [PATCH 08/48] feat: image test --- src/app/service/image/image.service_test.go | 68 +++++++++++++++++++++ src/mocks/image/image.mock.go | 57 +++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 src/app/service/image/image.service_test.go create mode 100644 src/mocks/image/image.mock.go diff --git a/src/app/service/image/image.service_test.go b/src/app/service/image/image.service_test.go new file mode 100644 index 0000000..3effd29 --- /dev/null +++ b/src/app/service/image/image.service_test.go @@ -0,0 +1,68 @@ +package image + +import ( + "testing" + + "github.com/bxcodec/faker/v3" + mock "github.com/isd-sgcu/johnjud-backend/src/mocks/image" + proto "github.com/isd-sgcu/johnjud-go-proto/johnjud/file/image/v1" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" +) + +type ImageServiceTest struct { + suite.Suite + petId string + images []*proto.Image +} + +func TestImageService(t *testing.T) { + suite.Run(t, new(ImageServiceTest)) +} + +func (t *ImageServiceTest) SetupTest() { + t.petId = faker.UUIDDigit() + t.images = []*proto.Image{ + { + Id: faker.UUIDDigit(), + PetId: t.petId, + ImageUrl: faker.URL(), + }, + { + Id: faker.UUIDDigit(), + PetId: t.petId, + ImageUrl: faker.URL(), + }, + } +} + +func (t *ImageServiceTest) TestFindByPetIdSuccess() { + want := t.images + + c := mock.ClientMock{} + c.On("FindByPetId", &proto.FindImageByPetIdRequest{PetId: t.petId}). + Return(&proto.FindImageByPetIdResponse{Images: t.images}, nil) + + srv := NewService(&c) + actual, err := srv.FindByPetId(t.petId) + + assert.Nil(t.T(), err) + assert.Equal(t.T(), want, actual) +} + +func (t *ImageServiceTest) TestFindByPetIdError() { + c := mock.ClientMock{} + c.On("FindByPetId", &proto.FindImageByPetIdRequest{PetId: t.petId}). + Return(&proto.FindImageByPetIdResponse{Images: t.images}, status.Error(codes.Unavailable, "Connection Timeout")) + + srv := NewService(&c) + actual, err := srv.FindByPetId(t.petId) + + st, ok := status.FromError(err) + assert.True(t.T(), ok) + assert.Nil(t.T(), actual) + assert.Equal(t.T(), codes.Unavailable, st.Code()) +} diff --git a/src/mocks/image/image.mock.go b/src/mocks/image/image.mock.go new file mode 100644 index 0000000..19aba0d --- /dev/null +++ b/src/mocks/image/image.mock.go @@ -0,0 +1,57 @@ +package image + +import ( + "context" + + proto "github.com/isd-sgcu/johnjud-go-proto/johnjud/file/image/v1" + "github.com/stretchr/testify/mock" + "google.golang.org/grpc" +) + +type ClientMock struct { + mock.Mock +} + +func (c *ClientMock) Upload(_ context.Context, in *proto.UploadImageRequest, _ ...grpc.CallOption) (res *proto.UploadImageResponse, err error) { + args := c.Called(in) + + if args.Get(0) != nil { + res = args.Get(0).(*proto.UploadImageResponse) + } + + return res, args.Error(1) +} + +func (c *ClientMock) FindByPetId(_ context.Context, in *proto.FindImageByPetIdRequest, _ ...grpc.CallOption) (res *proto.FindImageByPetIdResponse, err error) { + args := c.Called(in) + + if args.Get(0) != nil { + res = args.Get(0).(*proto.FindImageByPetIdResponse) + } + + return res, args.Error(1) +} + +func (c *ClientMock) Delete(_ context.Context, in *proto.DeleteImageRequest, _ ...grpc.CallOption) (res *proto.DeleteImageResponse, err error) { + args := c.Called(in) + + if args.Get(0) != nil { + res = args.Get(0).(*proto.DeleteImageResponse) + } + + return res, args.Error(1) +} + +type ServiceMock struct { + mock.Mock +} + +func (c *ServiceMock) FindByPetId(petId string) (res []*proto.Image, err error) { + args := c.Called(petId) + + if args.Get(0) != nil { + res = args.Get(0).([]*proto.Image) + } + + return res, args.Error(1) +} From a9c369e795964fa15b4501a505bc2533a4a86668 Mon Sep 17 00:00:00 2001 From: Gear <84141000+macgeargear@users.noreply.github.com> Date: Thu, 21 Dec 2023 22:35:53 +0700 Subject: [PATCH 09/48] feat: pet service --- go.mod | 7 + src/app/service/pet/pet.service.go | 126 ++++++++++++++- src/app/service/pet/pet.service_test.go | 207 +++++++++++++++++++++++- src/mocks/pet/pet.mock.go | 33 ++-- 4 files changed, 354 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index a519e39..e7f3694 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ toolchain go1.21.5 require ( github.com/bxcodec/faker/v3 v3.8.1 github.com/google/uuid v1.5.0 + github.com/isd-sgcu/johnjud-go-proto v0.0.8 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.31.0 github.com/spf13/viper v1.18.2 @@ -29,6 +30,7 @@ require ( require ( github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/isd-sgcu/johnjud-go-proto v0.0.8 github.com/jackc/pgpassfile v1.0.0 // indirect @@ -37,6 +39,8 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect @@ -51,8 +55,11 @@ require ( go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/net v0.19.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 5ebd337..cd4c917 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -4,8 +4,14 @@ import ( "context" "errors" + "time" + + "github.com/google/uuid" + "github.com/isd-sgcu/johnjud-backend/src/app/model" "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" + petConst "github.com/isd-sgcu/johnjud-backend/src/constant/pet" proto "github.com/isd-sgcu/johnjud-go-proto/johnjud/backend/pet/v1" + "github.com/rs/zerolog/log" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "gorm.io/gorm" @@ -17,7 +23,7 @@ type Service struct { type IRepository interface { FindAll(result *[]*pet.Pet) error - FindOne(id string, result *[]*pet.Pet) error + FindOne(id string, result *pet.Pet) error Create(in *pet.Pet) error Update(id string, result *pet.Pet) error Delete(id string) error @@ -38,18 +44,122 @@ func (s *Service) Delete(ctx context.Context, req *proto.DeletePetRequest) (*pro return &proto.DeletePetResponse{Success: true}, nil } -func (*Service) Create(context.Context, *proto.CreatePetRequest) (*proto.CreatePetResponse, error) { +func (*Service) Update(context.Context, *proto.UpdatePetRequest) (*proto.UpdatePetResponse, error) { panic("unimplemented") } -func (*Service) FindAll(context.Context, *proto.FindAllPetRequest) (*proto.FindAllPetResponse, error) { - panic("unimplemented") +func (s *Service) FindAll(_ context.Context, req *proto.FindAllPetRequest) (res *proto.FindAllPetResponse, err error) { + var pets []*pet.Pet + + err = s.repository.FindAll(&pets) + if err != nil { + log.Error().Err(err).Str("service", "event").Str("module", "find all").Msg("Error while querying all events") + return nil, status.Error(codes.Unavailable, "Internal error") + } + return &proto.FindAllPetResponse{Pets: RawToDtoList(&pets)}, nil } -func (*Service) FindOne(context.Context, *proto.FindOnePetRequest) (*proto.FindOnePetResponse, error) { - panic("unimplemented") +func (s Service) FindOne(_ context.Context, req *proto.FindOnePetRequest) (res *proto.FindOnePetResponse, err error) { + var pet pet.Pet + + err = s.repository.FindOne(req.Id, &pet) + if err != nil { + log.Error().Err(err). + Str("service", "pet").Str("module", "find one").Str("id", req.Id).Msg("Not found") + return nil, status.Error(codes.NotFound, err.Error()) + } + return &proto.FindOnePetResponse{Pet: RawToDto(&pet, []string{})}, err } -func (*Service) Update(context.Context, *proto.UpdatePetRequest) (*proto.UpdatePetResponse, error) { - panic("unimplemented") +func (s *Service) Create(_ context.Context, req *proto.CreatePetRequest) (res *proto.CreatePetResponse, err error) { + raw, _ := DtoToRaw(req.Pet) + imgUrl := []string{} + + err = s.repository.Create(raw) + if err != nil { + return nil, status.Error(codes.Internal, "failed to create pet") + } + + return &proto.CreatePetResponse{Pet: RawToDto(raw, imgUrl)}, nil +} + +func RawToDto(in *pet.Pet, imgUrl []string) *proto.Pet { + return &proto.Pet{ + Id: in.ID.String(), + Type: in.Type, + Species: in.Species, + Name: in.Name, + Birthdate: in.Birthdate, + Gender: proto.Gender(in.Gender), + Habit: in.Habit, + Caption: in.Caption, + Status: proto.PetStatus(in.Status), + ImageUrls: imgUrl, + IsSterile: in.IsSterile, + IsVaccinated: in.IsVaccinated, + IsVisible: in.IsVisible, + IsClubPet: in.IsClubPet, + Background: in.Background, + Address: in.Address, + Contact: in.Contact, + } +} + +func DtoToRaw(in *proto.Pet) (res *pet.Pet, err error) { + var id uuid.UUID + var gender petConst.Gender + var status petConst.Status + + if in.Id != "" { + id, err = uuid.Parse(in.Id) + if err != nil { + return nil, err + } + } + + switch in.Gender { + case 1: + gender = petConst.MALE + case 2: + gender = petConst.FEMALE + } + + switch in.Status { + case 1: + status = petConst.ADOPTED + case 2: + status = petConst.FINDHOME + } + + return &pet.Pet{ + Base: model.Base{ + ID: id, + CreatedAt: time.Time{}, + UpdatedAt: time.Time{}, + DeletedAt: gorm.DeletedAt{}, + }, + Type: in.Type, + Species: in.Species, + Name: in.Name, + Birthdate: in.Birthdate, + Gender: gender, + Habit: in.Habit, + Caption: in.Caption, + Status: status, + IsSterile: in.IsSterile, + IsVaccinated: in.IsVaccinated, + IsVisible: in.IsVisible, + IsClubPet: in.IsClubPet, + Background: in.Background, + Address: in.Address, + Contact: in.Contact, + }, nil +} + +func RawToDtoList(in *[]*pet.Pet) []*proto.Pet { + var result []*proto.Pet + for _, e := range *in { + result = append(result, RawToDto(e, []string{})) + } + return result } diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index db045ff..4adf847 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -4,7 +4,6 @@ import ( "context" "errors" "math/rand" - "os/user" "testing" "time" @@ -28,7 +27,8 @@ import ( type PetServiceTest struct { suite.Suite Pet *pet.Pet - UpdatePet *user.User + Pets []*pet.Pet + UpdatePet *pet.Pet PetDto *proto.Pet CreatePetReqMock *proto.CreatePetRequest UpdatePetReqMock *proto.UpdatePetRequest @@ -64,6 +64,7 @@ func (t *PetServiceTest) SetupTest() { } t.PetDto = &proto.Pet{ + Id: t.Pet.ID.String(), Type: t.Pet.Type, Species: t.Pet.Species, Name: t.Pet.Name, @@ -79,6 +80,68 @@ func (t *PetServiceTest) SetupTest() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, + ImageUrls: []string{}, + } + + t.CreatePetReqMock = &proto.CreatePetRequest{ + Pet: &proto.Pet{ + Type: t.Pet.Type, + Species: t.Pet.Species, + Name: t.Pet.Name, + Birthdate: t.Pet.Birthdate, + Gender: proto.Gender(t.Pet.Gender), + Habit: t.Pet.Habit, + Caption: t.Pet.Caption, + Status: proto.PetStatus(t.Pet.Status), + ImageUrls: []string{}, + IsSterile: t.Pet.IsSterile, + IsVaccinated: t.Pet.IsVaccinated, + IsVisible: t.Pet.IsVaccinated, + IsClubPet: t.Pet.IsClubPet, + Background: t.Pet.Background, + Address: t.Pet.Address, + Contact: t.Pet.Contact, + }, + } + + t.UpdatePetReqMock = &proto.UpdatePetRequest{ + Pet: &proto.Pet{ + Id: t.Pet.ID.String(), + Type: t.Pet.Type, + Species: t.Pet.Species, + Name: t.Pet.Name, + Birthdate: t.Pet.Birthdate, + Gender: proto.Gender(t.Pet.Gender), + Habit: t.Pet.Habit, + Caption: t.Pet.Caption, + Status: proto.PetStatus(t.Pet.Status), + ImageUrls: []string{}, + IsSterile: t.Pet.IsSterile, + IsVaccinated: t.Pet.IsVaccinated, + IsVisible: t.Pet.IsVisible, + IsClubPet: t.Pet.IsClubPet, + Background: t.Pet.Background, + Address: t.Pet.Address, + Contact: t.Pet.Contact, + }, + } + + t.UpdatePet = &pet.Pet{ + Type: t.Pet.Type, + Species: t.Pet.Species, + Name: t.Pet.Name, + Birthdate: t.Pet.Birthdate, + Gender: t.Pet.Gender, + Habit: t.Pet.Habit, + Caption: t.Pet.Caption, + Status: t.Pet.Status, + IsSterile: t.Pet.IsSterile, + IsVaccinated: t.Pet.IsVaccinated, + IsVisible: t.Pet.IsVisible, + IsClubPet: t.Pet.IsClubPet, + Background: t.Pet.Background, + Address: t.Pet.Address, + Contact: t.Pet.Contact, } } func (t *PetServiceTest) TestDeleteSuccess() { @@ -131,3 +194,143 @@ func (t *PetServiceTest) TestDeleteWithUnexpectedError() { assert.Error(t.T(), err) repo.AssertExpectations(t.T()) } + +func (t *PetServiceTest) TestFindOneSuccess() { + t.PetDto.ImageUrls = []string{} + + want := &proto.FindOnePetResponse{Pet: t.PetDto} + + repo := &mock.RepositoryMock{} + repo.On("FindOne", t.Pet.ID.String(), &pet.Pet{}).Return(t.Pet, nil) + + srv := NewService(repo) + actual, err := srv.FindOne(context.Background(), &proto.FindOnePetRequest{Id: t.Pet.ID.String()}) + + assert.Nil(t.T(), err) + assert.Equal(t.T(), want, actual) +} + +func (t *PetServiceTest) TestFindAllSuccess() { + var pets []*pet.Pet + + want := &proto.FindAllPetResponse{Pets: createPetsDto(t.Pets)} + + r := mock.RepositoryMock{} + r.On("FindAll", pets).Return(&t.Pets, nil) + + srv := NewService(&r) + + actual, err := srv.FindAll(context.Background(), &proto.FindAllPetRequest{}) + + assert.Nil(t.T(), err) + assert.Equal(t.T(), want, actual) +} + +func (t *PetServiceTest) TestFindOneNotFound() { + repo := &mock.RepositoryMock{} + repo.On("FindOne", t.Pet.ID.String(), &pet.Pet{}).Return(nil, errors.New("Not found event")) + + srv := NewService(repo) + actual, err := srv.FindOne(context.Background(), &proto.FindOnePetRequest{Id: t.Pet.ID.String()}) + + st, ok := status.FromError(err) + + assert.True(t.T(), ok) + assert.Nil(t.T(), actual) + assert.Equal(t.T(), codes.NotFound, st.Code()) +} + +func createPetsDto(in []*pet.Pet) []*proto.Pet { + var result []*proto.Pet + + for _, p := range in { + r := &proto.Pet{ + Id: p.ID.String(), + Type: p.Type, + Species: p.Species, + Name: p.Name, + Birthdate: p.Birthdate, + Gender: proto.Gender(p.Gender), + Habit: p.Habit, + Caption: p.Caption, + Status: 0, + ImageUrls: []string{}, + IsSterile: p.IsSterile, + IsVaccinated: p.IsVaccinated, + IsVisible: p.IsVisible, + IsClubPet: p.IsClubPet, + Background: p.Background, + Address: p.Address, + Contact: p.Contact, + } + + result = append(result, r) + } + + return result +} + +func (t *PetServiceTest) TestCreateSuccess() { + want := &proto.CreatePetResponse{Pet: t.PetDto} + + repo := &mock.RepositoryMock{} + + in := &pet.Pet{ + Type: t.Pet.Type, + Species: t.Pet.Species, + Name: t.Pet.Name, + Birthdate: t.Pet.Birthdate, + Gender: t.Pet.Gender, + Habit: t.Pet.Habit, + Caption: t.Pet.Caption, + Status: t.Pet.Status, + IsSterile: t.Pet.IsSterile, + IsVaccinated: t.Pet.IsVaccinated, + IsVisible: t.Pet.IsVisible, + IsClubPet: t.Pet.IsClubPet, + Background: t.Pet.Background, + Address: t.Pet.Address, + Contact: t.Pet.Contact, + } + + repo.On("Create", in).Return(t.Pet, nil) + srv := NewService(repo) + + actual, err := srv.Create(context.Background(), t.CreatePetReqMock) + + assert.Nil(t.T(), err) + assert.Equal(t.T(), want, actual) +} + +func (t *PetServiceTest) TestCreateInternalErr() { + repo := &mock.RepositoryMock{} + + in := &pet.Pet{ + Type: t.Pet.Type, + Species: t.Pet.Species, + Name: t.Pet.Name, + Birthdate: t.Pet.Birthdate, + Gender: t.Pet.Gender, + Habit: t.Pet.Habit, + Caption: t.Pet.Caption, + Status: t.Pet.Status, + IsSterile: t.Pet.IsSterile, + IsVaccinated: t.Pet.IsVaccinated, + IsVisible: t.Pet.IsVisible, + IsClubPet: t.Pet.IsClubPet, + Background: t.Pet.Background, + Address: t.Pet.Address, + Contact: t.Pet.Contact, + } + + repo.On("Create", in).Return(nil, errors.New("something wrong")) + srv := NewService(repo) + + actual, err := srv.Create(context.Background(), t.CreatePetReqMock) + + st, ok := status.FromError(err) + + assert.True(t.T(), ok) + assert.Nil(t.T(), actual) + assert.Equal(t.T(), codes.Internal, st.Code()) +} diff --git a/src/mocks/pet/pet.mock.go b/src/mocks/pet/pet.mock.go index c8c780d..02b1194 100644 --- a/src/mocks/pet/pet.mock.go +++ b/src/mocks/pet/pet.mock.go @@ -9,19 +9,34 @@ type RepositoryMock struct { mock.Mock } -func (r *RepositoryMock) FindAll(result *[]*pet.Pet) error { - // unimplemented for now - return nil -} +func (r *RepositoryMock) FindOne(id string, result *pet.Pet) error { + args := r.Called(id, result) -func (r *RepositoryMock) FindOne(id string, result *[]*pet.Pet) error { - // unimplemented for now - return nil + if args.Get(0) != nil { + *result = *args.Get(0).(*pet.Pet) + } + + return args.Error(1) } func (r *RepositoryMock) Create(in *pet.Pet) error { - // unimplemented for now - return nil + args := r.Called(in) + + if args.Get(0) != nil { + *in = *args.Get(0).(*pet.Pet) + } + + return args.Error(1) +} + +func (r *RepositoryMock) FindAll(result *[]*pet.Pet) error { + args := r.Called(*result) + + if args.Get(0) != nil { + *result = *args.Get(0).(*[]*pet.Pet) + } + + return args.Error(1) } func (r *RepositoryMock) Update(id string, result *pet.Pet) error { From 7c473c22aceb4e9b78ae03614caa5fe1d2392151 Mon Sep 17 00:00:00 2001 From: Gear <84141000+macgeargear@users.noreply.github.com> Date: Fri, 22 Dec 2023 18:57:43 +0700 Subject: [PATCH 10/48] feat: FindOne FindAll PetService --- go.mod | 3 ++ src/app/service/pet/pet.service.go | 16 +++++----- src/app/service/pet/pet.service_test.go | 2 +- src/mock/pet/pet.mock.go | 40 +++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 src/mock/pet/pet.mock.go diff --git a/go.mod b/go.mod index e7f3694..4afd1ea 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.31.0 github.com/spf13/viper v1.18.2 + github.com/stretchr/testify v1.8.4 google.golang.org/grpc v1.60.1 gorm.io/driver/postgres v1.5.4 gorm.io/gorm v1.25.5 @@ -43,6 +44,7 @@ require ( github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -50,6 +52,7 @@ require ( github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.8.4 + github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index cd4c917..cc51005 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -83,6 +83,14 @@ func (s *Service) Create(_ context.Context, req *proto.CreatePetRequest) (res *p return &proto.CreatePetResponse{Pet: RawToDto(raw, imgUrl)}, nil } +func RawToDtoList(in *[]*pet.Pet) []*proto.Pet { + var result []*proto.Pet + for _, e := range *in { + result = append(result, RawToDto(e, []string{""})) + } + return result +} + func RawToDto(in *pet.Pet, imgUrl []string) *proto.Pet { return &proto.Pet{ Id: in.ID.String(), @@ -155,11 +163,3 @@ func DtoToRaw(in *proto.Pet) (res *pet.Pet, err error) { Contact: in.Contact, }, nil } - -func RawToDtoList(in *[]*pet.Pet) []*proto.Pet { - var result []*proto.Pet - for _, e := range *in { - result = append(result, RawToDto(e, []string{})) - } - return result -} diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index 4adf847..89ca8f1 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -34,7 +34,7 @@ type PetServiceTest struct { UpdatePetReqMock *proto.UpdatePetRequest } -func TestUserService(t *testing.T) { +func TestPetService(t *testing.T) { suite.Run(t, new(PetServiceTest)) } diff --git a/src/mock/pet/pet.mock.go b/src/mock/pet/pet.mock.go new file mode 100644 index 0000000..1f33c49 --- /dev/null +++ b/src/mock/pet/pet.mock.go @@ -0,0 +1,40 @@ +package mock + +import ( + "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" + "github.com/stretchr/testify/mock" +) + +type RepositoryMock struct { + mock.Mock +} + +func (r *RepositoryMock) FindOne(id string, result *pet.Pet) error { + args := r.Called(id, result) + + if args.Get(0) != nil { + *result = *args.Get(0).(*pet.Pet) + } + + return args.Error(1) +} + +func (r *RepositoryMock) Create(in *pet.Pet) error { + args := r.Called(in) + + if args.Get(0) != nil { + *in = *args.Get(0).(*pet.Pet) + } + + return args.Error(1) +} + +func (r *RepositoryMock) FindAll(result *[]*pet.Pet) error { + args := r.Called(*result) + + if args.Get(0) != nil { + *result = *args.Get(0).(*[]*pet.Pet) + } + + return args.Error(1) +} From 21944364d5315b94476d52a0aff1dc00a874c381 Mon Sep 17 00:00:00 2001 From: Gear <84141000+macgeargear@users.noreply.github.com> Date: Sat, 23 Dec 2023 03:02:53 +0700 Subject: [PATCH 11/48] feat: TestCreateSuccess TestCreatInternalErr --- src/app/service/pet/pet.service.go | 5 +- src/app/service/pet/pet.service_test.go | 63 ++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index cc51005..26c2902 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -3,6 +3,7 @@ package pet import ( "context" "errors" + "fmt" "time" @@ -80,13 +81,15 @@ func (s *Service) Create(_ context.Context, req *proto.CreatePetRequest) (res *p return nil, status.Error(codes.Internal, "failed to create pet") } + fmt.Println(RawToDto(raw, []string{})) + return &proto.CreatePetResponse{Pet: RawToDto(raw, imgUrl)}, nil } func RawToDtoList(in *[]*pet.Pet) []*proto.Pet { var result []*proto.Pet for _, e := range *in { - result = append(result, RawToDto(e, []string{""})) + result = append(result, RawToDto(e, []string{})) } return result } diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index 89ca8f1..b4792dc 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -27,8 +27,8 @@ import ( type PetServiceTest struct { suite.Suite Pet *pet.Pet - Pets []*pet.Pet UpdatePet *pet.Pet + Pets []*pet.Pet PetDto *proto.Pet CreatePetReqMock *proto.CreatePetRequest UpdatePetReqMock *proto.UpdatePetRequest @@ -143,6 +143,67 @@ func (t *PetServiceTest) SetupTest() { Address: t.Pet.Address, Contact: t.Pet.Contact, } + + t.CreatePetReqMock = &proto.CreatePetRequest{ + Pet: &proto.Pet{ + Type: t.Pet.Type, + Species: t.Pet.Species, + Name: t.Pet.Name, + Birthdate: t.Pet.Birthdate, + Gender: proto.Gender(t.Pet.Gender), + Habit: t.Pet.Habit, + Caption: t.Pet.Caption, + Status: proto.PetStatus(t.Pet.Status), + ImageUrls: []string{}, + IsSterile: t.Pet.IsSterile, + IsVaccinated: t.Pet.IsVaccinated, + IsVisible: t.Pet.IsVaccinated, + IsClubPet: t.Pet.IsClubPet, + Background: t.Pet.Background, + Address: t.Pet.Address, + Contact: t.Pet.Contact, + }, + } + + t.UpdatePetReqMock = &proto.UpdatePetRequest{ + Pet: &proto.Pet{ + Id: t.Pet.ID.String(), + Type: t.Pet.Type, + Species: t.Pet.Species, + Name: t.Pet.Name, + Birthdate: t.Pet.Birthdate, + Gender: proto.Gender(t.Pet.Gender), + Habit: t.Pet.Habit, + Caption: t.Pet.Caption, + Status: proto.PetStatus(t.Pet.Status), + ImageUrls: []string{}, + IsSterile: t.Pet.IsSterile, + IsVaccinated: t.Pet.IsVaccinated, + IsVisible: t.Pet.IsVisible, + IsClubPet: t.Pet.IsClubPet, + Background: t.Pet.Background, + Address: t.Pet.Address, + Contact: t.Pet.Contact, + }, + } + + t.UpdatePet = &pet.Pet{ + Type: t.Pet.Type, + Species: t.Pet.Species, + Name: t.Pet.Name, + Birthdate: t.Pet.Birthdate, + Gender: t.Pet.Gender, + Habit: t.Pet.Habit, + Caption: t.Pet.Caption, + Status: t.Pet.Status, + IsSterile: t.Pet.IsSterile, + IsVaccinated: t.Pet.IsVaccinated, + IsVisible: t.Pet.IsVisible, + IsClubPet: t.Pet.IsClubPet, + Background: t.Pet.Background, + Address: t.Pet.Address, + Contact: t.Pet.Contact, + } } func (t *PetServiceTest) TestDeleteSuccess() { want := &proto.DeletePetResponse{Success: true} From c1cf418a8e002e0d533a3f02fd07bccf151d0659 Mon Sep 17 00:00:00 2001 From: Gear <84141000+macgeargear@users.noreply.github.com> Date: Sat, 23 Dec 2023 15:40:06 +0700 Subject: [PATCH 12/48] fix(mocks): pet mock --- src/mock/pet/pet.mock.go | 40 ---------------------------------------- 1 file changed, 40 deletions(-) delete mode 100644 src/mock/pet/pet.mock.go diff --git a/src/mock/pet/pet.mock.go b/src/mock/pet/pet.mock.go deleted file mode 100644 index 1f33c49..0000000 --- a/src/mock/pet/pet.mock.go +++ /dev/null @@ -1,40 +0,0 @@ -package mock - -import ( - "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" - "github.com/stretchr/testify/mock" -) - -type RepositoryMock struct { - mock.Mock -} - -func (r *RepositoryMock) FindOne(id string, result *pet.Pet) error { - args := r.Called(id, result) - - if args.Get(0) != nil { - *result = *args.Get(0).(*pet.Pet) - } - - return args.Error(1) -} - -func (r *RepositoryMock) Create(in *pet.Pet) error { - args := r.Called(in) - - if args.Get(0) != nil { - *in = *args.Get(0).(*pet.Pet) - } - - return args.Error(1) -} - -func (r *RepositoryMock) FindAll(result *[]*pet.Pet) error { - args := r.Called(*result) - - if args.Get(0) != nil { - *result = *args.Get(0).(*[]*pet.Pet) - } - - return args.Error(1) -} From d3b7b79347fc02606ab5bee1513e4423f70ea8e7 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sun, 24 Dec 2023 13:40:05 +0700 Subject: [PATCH 13/48] feat: pet service update --- src/app/service/pet/pet.service.go | 11 ++- src/app/service/pet/pet.service_test.go | 94 +++++++++---------------- src/mocks/pet/pet.mock.go | 9 ++- 3 files changed, 49 insertions(+), 65 deletions(-) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 26c2902..6246194 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -45,8 +45,15 @@ func (s *Service) Delete(ctx context.Context, req *proto.DeletePetRequest) (*pro return &proto.DeletePetResponse{Success: true}, nil } -func (*Service) Update(context.Context, *proto.UpdatePetRequest) (*proto.UpdatePetResponse, error) { - panic("unimplemented") +func (s *Service) Update(_ context.Context, req *proto.UpdatePetRequest) (res *proto.UpdatePetResponse, err error) { + raw, _ := DtoToRaw(req.Pet) + + err = s.repository.Update(req.Pet.Id, raw) + if err != nil { + return nil, status.Error(codes.NotFound, "pet not found") + } + + return &proto.UpdatePetResponse{Pet: RawToDto(raw, []string{})}, nil } func (s *Service) FindAll(_ context.Context, req *proto.FindAllPetRequest) (res *proto.FindAllPetResponse, err error) { diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index b4792dc..ed6dcc5 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -83,50 +83,13 @@ func (t *PetServiceTest) SetupTest() { ImageUrls: []string{}, } - t.CreatePetReqMock = &proto.CreatePetRequest{ - Pet: &proto.Pet{ - Type: t.Pet.Type, - Species: t.Pet.Species, - Name: t.Pet.Name, - Birthdate: t.Pet.Birthdate, - Gender: proto.Gender(t.Pet.Gender), - Habit: t.Pet.Habit, - Caption: t.Pet.Caption, - Status: proto.PetStatus(t.Pet.Status), - ImageUrls: []string{}, - IsSterile: t.Pet.IsSterile, - IsVaccinated: t.Pet.IsVaccinated, - IsVisible: t.Pet.IsVaccinated, - IsClubPet: t.Pet.IsClubPet, - Background: t.Pet.Background, - Address: t.Pet.Address, - Contact: t.Pet.Contact, - }, - } - - t.UpdatePetReqMock = &proto.UpdatePetRequest{ - Pet: &proto.Pet{ - Id: t.Pet.ID.String(), - Type: t.Pet.Type, - Species: t.Pet.Species, - Name: t.Pet.Name, - Birthdate: t.Pet.Birthdate, - Gender: proto.Gender(t.Pet.Gender), - Habit: t.Pet.Habit, - Caption: t.Pet.Caption, - Status: proto.PetStatus(t.Pet.Status), - ImageUrls: []string{}, - IsSterile: t.Pet.IsSterile, - IsVaccinated: t.Pet.IsVaccinated, - IsVisible: t.Pet.IsVisible, - IsClubPet: t.Pet.IsClubPet, - Background: t.Pet.Background, - Address: t.Pet.Address, - Contact: t.Pet.Contact, - }, - } - t.UpdatePet = &pet.Pet{ + Base: model.Base{ + ID: t.Pet.Base.ID, + CreatedAt: t.Pet.Base.CreatedAt, + UpdatedAt: t.Pet.Base.UpdatedAt, + DeletedAt: t.Pet.Base.DeletedAt, + }, Type: t.Pet.Type, Species: t.Pet.Species, Name: t.Pet.Name, @@ -186,24 +149,6 @@ func (t *PetServiceTest) SetupTest() { Contact: t.Pet.Contact, }, } - - t.UpdatePet = &pet.Pet{ - Type: t.Pet.Type, - Species: t.Pet.Species, - Name: t.Pet.Name, - Birthdate: t.Pet.Birthdate, - Gender: t.Pet.Gender, - Habit: t.Pet.Habit, - Caption: t.Pet.Caption, - Status: t.Pet.Status, - IsSterile: t.Pet.IsSterile, - IsVaccinated: t.Pet.IsVaccinated, - IsVisible: t.Pet.IsVisible, - IsClubPet: t.Pet.IsClubPet, - Background: t.Pet.Background, - Address: t.Pet.Address, - Contact: t.Pet.Contact, - } } func (t *PetServiceTest) TestDeleteSuccess() { want := &proto.DeletePetResponse{Success: true} @@ -395,3 +340,30 @@ func (t *PetServiceTest) TestCreateInternalErr() { assert.Nil(t.T(), actual) assert.Equal(t.T(), codes.Internal, st.Code()) } + +func (t *PetServiceTest) TestUpdateSuccess() { + want := &proto.UpdatePetResponse{Pet: t.PetDto} + + repo := &mock.RepositoryMock{} + repo.On("Update", t.Pet.ID.String(), t.UpdatePet).Return(t.Pet, nil) + + srv := NewService(repo) + actual, err := srv.Update(context.Background(), t.UpdatePetReqMock) + + assert.Nil(t.T(), err) + assert.Equal(t.T(), want, actual) +} + +func (t *PetServiceTest) TestUpdateNotFound() { + repo := &mock.RepositoryMock{} + repo.On("Update", t.Pet.ID.String(), t.UpdatePet).Return(nil, errors.New("Not found pet")) + + srv := NewService(repo) + actual, err := srv.Update(context.Background(), t.UpdatePetReqMock) + + st, ok := status.FromError(err) + + assert.True(t.T(), ok) + assert.Nil(t.T(), actual) + assert.Equal(t.T(), codes.NotFound, st.Code()) +} diff --git a/src/mocks/pet/pet.mock.go b/src/mocks/pet/pet.mock.go index 02b1194..d1f5d87 100644 --- a/src/mocks/pet/pet.mock.go +++ b/src/mocks/pet/pet.mock.go @@ -40,8 +40,13 @@ func (r *RepositoryMock) FindAll(result *[]*pet.Pet) error { } func (r *RepositoryMock) Update(id string, result *pet.Pet) error { - // unimplemented for now - return nil + args := r.Called(id, result) + + if args.Get(0) != nil { + *result = *args.Get(0).(*pet.Pet) + } + + return args.Error(1) } func (r *RepositoryMock) Delete(id string) error { From 80e364ecaf070002108a2f1962112a2d4ab46412 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sun, 24 Dec 2023 14:28:16 +0700 Subject: [PATCH 14/48] feat: pet service add image service --- src/app/service/pet/pet.service.go | 35 +++++++++--- src/app/service/pet/pet.service_test.go | 75 +++++++++++++++++++------ 2 files changed, 84 insertions(+), 26 deletions(-) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 6246194..339910e 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -3,7 +3,6 @@ package pet import ( "context" "errors" - "fmt" "time" @@ -12,6 +11,7 @@ import ( "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" petConst "github.com/isd-sgcu/johnjud-backend/src/constant/pet" proto "github.com/isd-sgcu/johnjud-go-proto/johnjud/backend/pet/v1" + image_proto "github.com/isd-sgcu/johnjud-go-proto/johnjud/file/image/v1" "github.com/rs/zerolog/log" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -19,7 +19,8 @@ import ( ) type Service struct { - repository IRepository + repository IRepository + imageService ImageService } type IRepository interface { @@ -30,8 +31,12 @@ type IRepository interface { Delete(id string) error } -func NewService(repository IRepository) *Service { - return &Service{repository: repository} +type ImageService interface { + FindByPetId(petId string) ([]*image_proto.Image, error) +} + +func NewService(repository IRepository, imageService ImageService) *Service { + return &Service{repository, imageService} } func (s *Service) Delete(ctx context.Context, req *proto.DeletePetRequest) (*proto.DeletePetResponse, error) { @@ -53,7 +58,13 @@ func (s *Service) Update(_ context.Context, req *proto.UpdatePetRequest) (res *p return nil, status.Error(codes.NotFound, "pet not found") } - return &proto.UpdatePetResponse{Pet: RawToDto(raw, []string{})}, nil + images, err := s.imageService.FindByPetId(req.Pet.Id) + if err != nil { + return nil, status.Error(codes.Internal, "error querying image service") + } + imageUrls := ExtractImageUrls(images) + + return &proto.UpdatePetResponse{Pet: RawToDto(raw, imageUrls)}, nil } func (s *Service) FindAll(_ context.Context, req *proto.FindAllPetRequest) (res *proto.FindAllPetResponse, err error) { @@ -81,16 +92,14 @@ func (s Service) FindOne(_ context.Context, req *proto.FindOnePetRequest) (res * func (s *Service) Create(_ context.Context, req *proto.CreatePetRequest) (res *proto.CreatePetResponse, err error) { raw, _ := DtoToRaw(req.Pet) - imgUrl := []string{} + imgUrls := []string{} err = s.repository.Create(raw) if err != nil { return nil, status.Error(codes.Internal, "failed to create pet") } - fmt.Println(RawToDto(raw, []string{})) - - return &proto.CreatePetResponse{Pet: RawToDto(raw, imgUrl)}, nil + return &proto.CreatePetResponse{Pet: RawToDto(raw, imgUrls)}, nil } func RawToDtoList(in *[]*pet.Pet) []*proto.Pet { @@ -173,3 +182,11 @@ func DtoToRaw(in *proto.Pet) (res *pet.Pet, err error) { Contact: in.Contact, }, nil } + +func ExtractImageUrls(in []*image_proto.Image) []string { + var result []string + for _, e := range in { + result = append(result, e.ImageUrl) + } + return result +} diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index ed6dcc5..17c2354 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -9,12 +9,14 @@ import ( "github.com/bxcodec/faker/v3" "github.com/google/uuid" + img_mock "github.com/isd-sgcu/johnjud-backend/src/mocks/image" mock "github.com/isd-sgcu/johnjud-backend/src/mocks/pet" "gorm.io/gorm" "github.com/isd-sgcu/johnjud-backend/src/app/model" "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" proto "github.com/isd-sgcu/johnjud-go-proto/johnjud/backend/pet/v1" + img_proto "github.com/isd-sgcu/johnjud-go-proto/johnjud/file/image/v1" petConst "github.com/isd-sgcu/johnjud-backend/src/constant/pet" @@ -32,6 +34,8 @@ type PetServiceTest struct { PetDto *proto.Pet CreatePetReqMock *proto.CreatePetRequest UpdatePetReqMock *proto.UpdatePetRequest + Images []*img_proto.Image + ImageUrls []string } func TestPetService(t *testing.T) { @@ -63,6 +67,24 @@ func (t *PetServiceTest) SetupTest() { Contact: faker.Paragraph(), } + t.Images = []*img_proto.Image{ + { + Id: faker.UUIDDigit(), + PetId: t.Pet.ID.String(), + ImageUrl: faker.URL(), + }, + { + Id: faker.UUIDDigit(), + PetId: t.Pet.ID.String(), + ImageUrl: faker.URL(), + }, + } + + t.ImageUrls = []string{ + t.Images[0].ImageUrl, + t.Images[1].ImageUrl, + } + t.PetDto = &proto.Pet{ Id: t.Pet.ID.String(), Type: t.Pet.Type, @@ -80,7 +102,7 @@ func (t *PetServiceTest) SetupTest() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, - ImageUrls: []string{}, + ImageUrls: t.ImageUrls, } t.UpdatePet = &pet.Pet{ @@ -117,7 +139,7 @@ func (t *PetServiceTest) SetupTest() { Habit: t.Pet.Habit, Caption: t.Pet.Caption, Status: proto.PetStatus(t.Pet.Status), - ImageUrls: []string{}, + ImageUrls: t.ImageUrls, IsSterile: t.Pet.IsSterile, IsVaccinated: t.Pet.IsVaccinated, IsVisible: t.Pet.IsVaccinated, @@ -139,7 +161,7 @@ func (t *PetServiceTest) SetupTest() { Habit: t.Pet.Habit, Caption: t.Pet.Caption, Status: proto.PetStatus(t.Pet.Status), - ImageUrls: []string{}, + ImageUrls: t.ImageUrls, IsSterile: t.Pet.IsSterile, IsVaccinated: t.Pet.IsVaccinated, IsVisible: t.Pet.IsVisible, @@ -155,8 +177,9 @@ func (t *PetServiceTest) TestDeleteSuccess() { repo := new(mock.RepositoryMock) repo.On("Delete", t.Pet.ID.String()).Return(nil) + imgSrv := new(img_mock.ServiceMock) - srv := NewService(repo) + srv := NewService(repo, imgSrv) actual, err := srv.Delete(context.Background(), &proto.DeletePetRequest{Id: t.Pet.ID.String()}) assert.Nil(t.T(), err) @@ -167,8 +190,9 @@ func (t *PetServiceTest) TestDeleteSuccess() { func (t *PetServiceTest) TestDeleteNotFound() { repo := new(mock.RepositoryMock) repo.On("Delete", t.Pet.ID.String()).Return(gorm.ErrRecordNotFound) + imgSrv := new(img_mock.ServiceMock) - srv := NewService(repo) + srv := NewService(repo, imgSrv) _, err := srv.Delete(context.Background(), &proto.DeletePetRequest{Id: t.Pet.ID.String()}) st, ok := status.FromError(err) @@ -180,8 +204,9 @@ func (t *PetServiceTest) TestDeleteNotFound() { func (t *PetServiceTest) TestDeleteWithDatabaseError() { repo := new(mock.RepositoryMock) repo.On("Delete", t.Pet.ID.String()).Return(errors.New("internal server error")) + imgSrv := new(img_mock.ServiceMock) - srv := NewService(repo) + srv := NewService(repo, imgSrv) _, err := srv.Delete(context.Background(), &proto.DeletePetRequest{Id: t.Pet.ID.String()}) st, ok := status.FromError(err) @@ -193,8 +218,9 @@ func (t *PetServiceTest) TestDeleteWithDatabaseError() { func (t *PetServiceTest) TestDeleteWithUnexpectedError() { repo := new(mock.RepositoryMock) repo.On("Delete", t.Pet.ID.String()).Return(errors.New("unexpected error")) + imgSrv := new(img_mock.ServiceMock) - srv := NewService(repo) + srv := NewService(repo, imgSrv) _, err := srv.Delete(context.Background(), &proto.DeletePetRequest{Id: t.Pet.ID.String()}) assert.Error(t.T(), err) @@ -208,8 +234,10 @@ func (t *PetServiceTest) TestFindOneSuccess() { repo := &mock.RepositoryMock{} repo.On("FindOne", t.Pet.ID.String(), &pet.Pet{}).Return(t.Pet, nil) + imgSrv := new(img_mock.ServiceMock) + imgSrv.On("FindByPetId", t.Pet.ID.String()).Return(t.Images, nil) - srv := NewService(repo) + srv := NewService(repo, imgSrv) actual, err := srv.FindOne(context.Background(), &proto.FindOnePetRequest{Id: t.Pet.ID.String()}) assert.Nil(t.T(), err) @@ -221,10 +249,12 @@ func (t *PetServiceTest) TestFindAllSuccess() { want := &proto.FindAllPetResponse{Pets: createPetsDto(t.Pets)} - r := mock.RepositoryMock{} - r.On("FindAll", pets).Return(&t.Pets, nil) + repo := &mock.RepositoryMock{} + repo.On("FindAll", pets).Return(&t.Pets, nil) + imgSrv := new(img_mock.ServiceMock) + imgSrv.On("FindByPetId", t.Pet.ID.String()).Return(t.Images, nil) - srv := NewService(&r) + srv := NewService(repo, imgSrv) actual, err := srv.FindAll(context.Background(), &proto.FindAllPetRequest{}) @@ -234,9 +264,11 @@ func (t *PetServiceTest) TestFindAllSuccess() { func (t *PetServiceTest) TestFindOneNotFound() { repo := &mock.RepositoryMock{} - repo.On("FindOne", t.Pet.ID.String(), &pet.Pet{}).Return(nil, errors.New("Not found event")) + repo.On("FindOne", t.Pet.ID.String(), &pet.Pet{}).Return(nil, errors.New("Not found pet")) + imgSrv := new(img_mock.ServiceMock) + imgSrv.On("FindByPetId", t.Pet.ID.String()).Return(nil, nil) - srv := NewService(repo) + srv := NewService(repo, imgSrv) actual, err := srv.FindOne(context.Background(), &proto.FindOnePetRequest{Id: t.Pet.ID.String()}) st, ok := status.FromError(err) @@ -278,6 +310,7 @@ func createPetsDto(in []*pet.Pet) []*proto.Pet { func (t *PetServiceTest) TestCreateSuccess() { want := &proto.CreatePetResponse{Pet: t.PetDto} + want.Pet.ImageUrls = []string{} // when pet is first created, it has no images repo := &mock.RepositoryMock{} @@ -300,7 +333,9 @@ func (t *PetServiceTest) TestCreateSuccess() { } repo.On("Create", in).Return(t.Pet, nil) - srv := NewService(repo) + imgSrv := new(img_mock.ServiceMock) + + srv := NewService(repo, imgSrv) actual, err := srv.Create(context.Background(), t.CreatePetReqMock) @@ -330,7 +365,9 @@ func (t *PetServiceTest) TestCreateInternalErr() { } repo.On("Create", in).Return(nil, errors.New("something wrong")) - srv := NewService(repo) + imgSrv := new(img_mock.ServiceMock) + + srv := NewService(repo, imgSrv) actual, err := srv.Create(context.Background(), t.CreatePetReqMock) @@ -346,8 +383,10 @@ func (t *PetServiceTest) TestUpdateSuccess() { repo := &mock.RepositoryMock{} repo.On("Update", t.Pet.ID.String(), t.UpdatePet).Return(t.Pet, nil) + imgSrv := new(img_mock.ServiceMock) + imgSrv.On("FindByPetId", t.Pet.ID.String()).Return(t.Images, nil) - srv := NewService(repo) + srv := NewService(repo, imgSrv) actual, err := srv.Update(context.Background(), t.UpdatePetReqMock) assert.Nil(t.T(), err) @@ -357,8 +396,10 @@ func (t *PetServiceTest) TestUpdateSuccess() { func (t *PetServiceTest) TestUpdateNotFound() { repo := &mock.RepositoryMock{} repo.On("Update", t.Pet.ID.String(), t.UpdatePet).Return(nil, errors.New("Not found pet")) + imgSrv := new(img_mock.ServiceMock) + imgSrv.On("FindByPetId", t.Pet.ID.String()).Return(nil, errors.New("No images with this pet id")) - srv := NewService(repo) + srv := NewService(repo, imgSrv) actual, err := srv.Update(context.Background(), t.UpdatePetReqMock) st, ok := status.FromError(err) From 3260f02fb9588335eb7abe996d282cec85b08642 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sun, 24 Dec 2023 15:00:16 +0700 Subject: [PATCH 15/48] feat: pet changeview --- src/app/service/pet/pet.service.go | 16 +++++ src/app/service/pet/pet.service_test.go | 78 ++++++++++++++++++++++--- 2 files changed, 86 insertions(+), 8 deletions(-) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 339910e..a756ed8 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -67,6 +67,22 @@ func (s *Service) Update(_ context.Context, req *proto.UpdatePetRequest) (res *p return &proto.UpdatePetResponse{Pet: RawToDto(raw, imageUrls)}, nil } +func (s *Service) ChangeView(_ context.Context, req *proto.ChangeViewPetRequest) (res *proto.ChangeViewPetResponse, err error) { + petData, err := s.FindOne(context.Background(), &proto.FindOnePetRequest{Id: req.Id}) + if err != nil { + return nil, status.Error(codes.NotFound, "pet not found") + } + pet, _ := DtoToRaw(petData.Pet) + pet.IsVisible = req.Visible + + err = s.repository.Update(req.Id, pet) + if err != nil { + return nil, status.Error(codes.NotFound, "pet not found") + } + + return &proto.ChangeViewPetResponse{Success: true}, nil +} + func (s *Service) FindAll(_ context.Context, req *proto.FindAllPetRequest) (res *proto.FindAllPetResponse, err error) { var pets []*pet.Pet diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index 17c2354..77aff95 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -28,14 +28,16 @@ import ( type PetServiceTest struct { suite.Suite - Pet *pet.Pet - UpdatePet *pet.Pet - Pets []*pet.Pet - PetDto *proto.Pet - CreatePetReqMock *proto.CreatePetRequest - UpdatePetReqMock *proto.UpdatePetRequest - Images []*img_proto.Image - ImageUrls []string + Pet *pet.Pet + UpdatePet *pet.Pet + ChangeViewPet *pet.Pet + Pets []*pet.Pet + PetDto *proto.Pet + CreatePetReqMock *proto.CreatePetRequest + UpdatePetReqMock *proto.UpdatePetRequest + ChangeViewPetReqMock *proto.ChangeViewPetRequest + Images []*img_proto.Image + ImageUrls []string } func TestPetService(t *testing.T) { @@ -129,6 +131,30 @@ func (t *PetServiceTest) SetupTest() { Contact: t.Pet.Contact, } + t.ChangeViewPet = &pet.Pet{ + Base: model.Base{ + ID: t.Pet.Base.ID, + CreatedAt: t.Pet.Base.CreatedAt, + UpdatedAt: t.Pet.Base.UpdatedAt, + DeletedAt: t.Pet.Base.DeletedAt, + }, + Type: t.Pet.Type, + Species: t.Pet.Species, + Name: t.Pet.Name, + Birthdate: t.Pet.Birthdate, + Gender: t.Pet.Gender, + Habit: t.Pet.Habit, + Caption: t.Pet.Caption, + Status: t.Pet.Status, + IsSterile: t.Pet.IsSterile, + IsVaccinated: t.Pet.IsVaccinated, + IsVisible: false, + IsClubPet: t.Pet.IsClubPet, + Background: t.Pet.Background, + Address: t.Pet.Address, + Contact: t.Pet.Contact, + } + t.CreatePetReqMock = &proto.CreatePetRequest{ Pet: &proto.Pet{ Type: t.Pet.Type, @@ -171,6 +197,11 @@ func (t *PetServiceTest) SetupTest() { Contact: t.Pet.Contact, }, } + + t.ChangeViewPetReqMock = &proto.ChangeViewPetRequest{ + Id: t.Pet.ID.String(), + Visible: false, + } } func (t *PetServiceTest) TestDeleteSuccess() { want := &proto.DeletePetResponse{Success: true} @@ -408,3 +439,34 @@ func (t *PetServiceTest) TestUpdateNotFound() { assert.Nil(t.T(), actual) assert.Equal(t.T(), codes.NotFound, st.Code()) } + +func (t *PetServiceTest) TestChangeViewSuccess() { + want := &proto.ChangeViewPetResponse{Success: true} + + repo := &mock.RepositoryMock{} + repo.On("FindOne", t.Pet.ID.String(), &pet.Pet{}).Return(t.Pet, nil) + repo.On("Update", t.Pet.ID.String(), t.ChangeViewPet).Return(t.ChangeViewPet, nil) + imgSrv := new(img_mock.ServiceMock) + + srv := NewService(repo, imgSrv) + actual, err := srv.ChangeView(context.Background(), t.ChangeViewPetReqMock) + + assert.Nil(t.T(), err) + assert.Equal(t.T(), want, actual) +} + +func (t *PetServiceTest) TestChangeViewNotFound() { + repo := &mock.RepositoryMock{} + repo.On("FindOne", t.Pet.ID.String(), &pet.Pet{}).Return(nil, errors.New("Not found pet")) + repo.On("Update", t.Pet.ID.String(), t.UpdatePet).Return(nil, errors.New("Not found pet")) + imgSrv := new(img_mock.ServiceMock) + + srv := NewService(repo, imgSrv) + actual, err := srv.ChangeView(context.Background(), t.ChangeViewPetReqMock) + + st, ok := status.FromError(err) + + assert.True(t.T(), ok) + assert.Nil(t.T(), actual) + assert.Equal(t.T(), codes.NotFound, st.Code()) +} From 1adb79a659d81f42faa845e195fa9fdb02f364d9 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sun, 24 Dec 2023 15:58:00 +0700 Subject: [PATCH 16/48] fix: change pet enum number to match proto --- src/app/service/pet/pet.service.go | 8 ++++---- src/constant/pet/pet.constant.go | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 26c2902..b98cf48 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -129,16 +129,16 @@ func DtoToRaw(in *proto.Pet) (res *pet.Pet, err error) { } switch in.Gender { - case 1: + case 0: gender = petConst.MALE - case 2: + case 1: gender = petConst.FEMALE } switch in.Status { - case 1: + case 0: status = petConst.ADOPTED - case 2: + case 1: status = petConst.FINDHOME } diff --git a/src/constant/pet/pet.constant.go b/src/constant/pet/pet.constant.go index 34f4dc4..577bed6 100644 --- a/src/constant/pet/pet.constant.go +++ b/src/constant/pet/pet.constant.go @@ -3,13 +3,13 @@ package pet type Gender int const ( - MALE = 1 - FEMALE = 2 + MALE = 0 + FEMALE = 1 ) type Status int const ( - ADOPTED = 1 - FINDHOME = 2 + ADOPTED = 0 + FINDHOME = 1 ) From 69bb4a9422ea91e27c8633b117cf1c128af8d99c Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sun, 24 Dec 2023 20:58:50 +0700 Subject: [PATCH 17/48] fix: test pet update not found --- src/app/service/pet/pet.service_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index 77aff95..0368d19 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -428,7 +428,7 @@ func (t *PetServiceTest) TestUpdateNotFound() { repo := &mock.RepositoryMock{} repo.On("Update", t.Pet.ID.String(), t.UpdatePet).Return(nil, errors.New("Not found pet")) imgSrv := new(img_mock.ServiceMock) - imgSrv.On("FindByPetId", t.Pet.ID.String()).Return(nil, errors.New("No images with this pet id")) + imgSrv.On("FindByPetId", t.Pet.ID.String()).Return(t.Images, nil) srv := NewService(repo, imgSrv) actual, err := srv.Update(context.Background(), t.UpdatePetReqMock) From 6854ed921ab05fa6b1146ddac259e59fbe0d12d0 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sun, 24 Dec 2023 21:07:43 +0700 Subject: [PATCH 18/48] fix: gender, status number range --- src/app/service/pet/pet.service_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index 0368d19..4235945 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -56,10 +56,10 @@ func (t *PetServiceTest) SetupTest() { Species: faker.Word(), Name: faker.Name(), Birthdate: faker.Word(), - Gender: petConst.Gender(rand.Intn(2) + 1), + Gender: petConst.Gender(rand.Intn(1) + 1), Habit: faker.Paragraph(), Caption: faker.Paragraph(), - Status: petConst.Status(rand.Intn(2) + 1), + Status: petConst.Status(rand.Intn(1) + 1), IsSterile: true, IsVaccinated: true, IsVisible: true, From 38b89e3b1e120d36b840248d49b3741f4480edca Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Sun, 24 Dec 2023 21:18:43 +0700 Subject: [PATCH 19/48] fix: add if error for DtoToRaw in pet srv --- src/app/service/pet/pet.service.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index a756ed8..11ceb70 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -51,7 +51,10 @@ func (s *Service) Delete(ctx context.Context, req *proto.DeletePetRequest) (*pro } func (s *Service) Update(_ context.Context, req *proto.UpdatePetRequest) (res *proto.UpdatePetResponse, err error) { - raw, _ := DtoToRaw(req.Pet) + raw, err := DtoToRaw(req.Pet) + if err != nil { + return nil, status.Error(codes.Internal, "error converting dto to raw") + } err = s.repository.Update(req.Pet.Id, raw) if err != nil { @@ -72,7 +75,10 @@ func (s *Service) ChangeView(_ context.Context, req *proto.ChangeViewPetRequest) if err != nil { return nil, status.Error(codes.NotFound, "pet not found") } - pet, _ := DtoToRaw(petData.Pet) + pet, err := DtoToRaw(petData.Pet) + if err != nil { + return nil, status.Error(codes.Internal, "error converting dto to raw") + } pet.IsVisible = req.Visible err = s.repository.Update(req.Id, pet) @@ -107,7 +113,11 @@ func (s Service) FindOne(_ context.Context, req *proto.FindOnePetRequest) (res * } func (s *Service) Create(_ context.Context, req *proto.CreatePetRequest) (res *proto.CreatePetResponse, err error) { - raw, _ := DtoToRaw(req.Pet) + raw, err := DtoToRaw(req.Pet) + if err != nil { + return nil, status.Error(codes.Internal, "error converting dto to raw") + } + imgUrls := []string{} err = s.repository.Create(raw) From bda42e80521815f247931503ac1689e303cdbe7c Mon Sep 17 00:00:00 2001 From: Sunioatm <104454675+Sunioatm@users.noreply.github.com> Date: Tue, 26 Dec 2023 00:37:13 +0700 Subject: [PATCH 20/48] feat : adopt pet and adoptby field --- go.mod | 14 ++------------ go.sum | 8 ++++---- src/app/model/pet/pet.model.go | 1 + src/app/service/pet/pet.service.go | 21 +++++++++++++++++++++ 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 4afd1ea..ade5ec4 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ toolchain go1.21.5 require ( github.com/bxcodec/faker/v3 v3.8.1 github.com/google/uuid v1.5.0 - github.com/isd-sgcu/johnjud-go-proto v0.0.8 + github.com/isd-sgcu/johnjud-go-proto v0.0.9 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.31.0 github.com/spf13/viper v1.18.2 @@ -26,43 +26,33 @@ require ( github.com/stretchr/objx v0.5.0 // indirect golang.org/x/net v0.19.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect ) require ( github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/isd-sgcu/johnjud-go-proto v0.0.8 github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.4.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.8.4 - github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.19.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9366728..fc7670b 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/isd-sgcu/johnjud-go-proto v0.0.8 h1:nIQBZgK2OFVrLjVtpeDgwows8poA7LhsIVE4hlbBC1o= -github.com/isd-sgcu/johnjud-go-proto v0.0.8/go.mod h1:HP0w9gC30b5WNnqeFBM9JJZud+pvyikz0+pGFSI/Wjw= +github.com/isd-sgcu/johnjud-go-proto v0.0.9 h1:cFfZ2JSpW0jg94Iv5zHQJGnoekj0eCQe42SJaTpnp3c= +github.com/isd-sgcu/johnjud-go-proto v0.0.9/go.mod h1:1OK6aiCgtXQiLhxp0r6iLEejYIRpckWQZDrCZ9Trbo4= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= @@ -107,8 +107,8 @@ google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/src/app/model/pet/pet.model.go b/src/app/model/pet/pet.model.go index d6b916a..3c88a37 100644 --- a/src/app/model/pet/pet.model.go +++ b/src/app/model/pet/pet.model.go @@ -22,4 +22,5 @@ type Pet struct { Background string `json:"background" gorm:"tinytext"` Address string `json:"address" gorm:"tinytext"` Contact string `json:"contact" gorm:"tinytext"` + AdoptBy string `json:"adopt_by" gorm:"tinytext"` } diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 310f6f9..8936fa4 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -128,6 +128,25 @@ func (s *Service) Create(_ context.Context, req *proto.CreatePetRequest) (res *p return &proto.CreatePetResponse{Pet: RawToDto(raw, imgUrls)}, nil } +func (s *Service) AdoptPet(ctx context.Context, req *proto.AdoptPetRequest) (res *proto.AdoptPetResponse, err error) { + dtoPet, err := s.FindOne(context.Background(), &proto.FindOnePetRequest{Id: req.PetId}) + if err != nil { + return nil, status.Error(codes.NotFound, "pet not found") + } + pet, err := DtoToRaw(dtoPet.Pet) + if err != nil { + return nil, status.Error(codes.Internal, "error converting dto to raw") + } + pet.AdoptBy = req.UserId + + err = s.repository.Update(req.PetId, pet) + if err != nil { + return nil, status.Error(codes.NotFound, "pet not found") + } + + return &proto.AdoptPetResponse{Success: true}, nil +} + func RawToDtoList(in *[]*pet.Pet) []*proto.Pet { var result []*proto.Pet for _, e := range *in { @@ -155,6 +174,7 @@ func RawToDto(in *pet.Pet, imgUrl []string) *proto.Pet { Background: in.Background, Address: in.Address, Contact: in.Contact, + AdoptBy: in.AdoptBy, } } @@ -206,6 +226,7 @@ func DtoToRaw(in *proto.Pet) (res *pet.Pet, err error) { Background: in.Background, Address: in.Address, Contact: in.Contact, + AdoptBy: in.AdoptBy, }, nil } From 10ae40c39b8471dc52489d3c7932444f187bb2f7 Mon Sep 17 00:00:00 2001 From: Gear <84141000+macgeargear@users.noreply.github.com> Date: Tue, 26 Dec 2023 00:44:14 +0700 Subject: [PATCH 21/48] fix: all image to FindOne pet --- src/app/service/pet/pet.service.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 310f6f9..25c3044 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -109,7 +109,14 @@ func (s Service) FindOne(_ context.Context, req *proto.FindOnePetRequest) (res * Str("service", "pet").Str("module", "find one").Str("id", req.Id).Msg("Not found") return nil, status.Error(codes.NotFound, err.Error()) } - return &proto.FindOnePetResponse{Pet: RawToDto(&pet, []string{})}, err + + images, err := s.imageService.FindByPetId(req.Id) + if err != nil { + return nil, status.Error(codes.Internal, "error querying image service") + } + imageUrls := ExtractImageUrls(images) + + return &proto.FindOnePetResponse{Pet: RawToDto(&pet, imageUrls)}, err } func (s *Service) Create(_ context.Context, req *proto.CreatePetRequest) (res *proto.CreatePetResponse, err error) { From 92a2c9d37340765a429841e2faad67dd3f72fcf8 Mon Sep 17 00:00:00 2001 From: Gear <84141000+macgeargear@users.noreply.github.com> Date: Tue, 26 Dec 2023 00:52:32 +0700 Subject: [PATCH 22/48] fix: remove unnecessary code in TestFindOneSuccess --- src/app/service/pet/pet.service_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index 4235945..c15fafd 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -3,6 +3,7 @@ package pet import ( "context" "errors" + "fmt" "math/rand" "testing" "time" @@ -259,8 +260,6 @@ func (t *PetServiceTest) TestDeleteWithUnexpectedError() { } func (t *PetServiceTest) TestFindOneSuccess() { - t.PetDto.ImageUrls = []string{} - want := &proto.FindOnePetResponse{Pet: t.PetDto} repo := &mock.RepositoryMock{} @@ -270,6 +269,7 @@ func (t *PetServiceTest) TestFindOneSuccess() { srv := NewService(repo, imgSrv) actual, err := srv.FindOne(context.Background(), &proto.FindOnePetRequest{Id: t.Pet.ID.String()}) + fmt.Println(want, actual) assert.Nil(t.T(), err) assert.Equal(t.T(), want, actual) From 2d0a6c77d7fa0006b1e91fa48fcd319a21a5b6f7 Mon Sep 17 00:00:00 2001 From: Gear <84141000+macgeargear@users.noreply.github.com> Date: Tue, 26 Dec 2023 23:20:18 +0700 Subject: [PATCH 23/48] fix: setup test & findAllSuccess --- src/app/service/pet/pet.service.go | 30 ++++- src/app/service/pet/pet.service_test.go | 167 +++++++++++++++++------- 2 files changed, 146 insertions(+), 51 deletions(-) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 25c3044..4b021b5 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -91,13 +91,29 @@ func (s *Service) ChangeView(_ context.Context, req *proto.ChangeViewPetRequest) func (s *Service) FindAll(_ context.Context, req *proto.FindAllPetRequest) (res *proto.FindAllPetResponse, err error) { var pets []*pet.Pet + var imageUrlsList [][]string err = s.repository.FindAll(&pets) if err != nil { log.Error().Err(err).Str("service", "event").Str("module", "find all").Msg("Error while querying all events") return nil, status.Error(codes.Unavailable, "Internal error") } - return &proto.FindAllPetResponse{Pets: RawToDtoList(&pets)}, nil + + for _, pet := range pets { + images, err := s.imageService.FindByPetId(pet.ID.String()) + if err != nil { + return nil, status.Error(codes.Internal, "error querying image service") + } + imageUrls := ExtractImageUrls(images) + imageUrlsList = append(imageUrlsList, imageUrls) + } + + petWithImageUrls, err := RawToDtoList(&pets, imageUrlsList) + if err != nil { + return nil, status.Error(codes.Internal, "error converting raw to dto list") + } + + return &proto.FindAllPetResponse{Pets: petWithImageUrls}, nil } func (s Service) FindOne(_ context.Context, req *proto.FindOnePetRequest) (res *proto.FindOnePetResponse, err error) { @@ -135,12 +151,16 @@ func (s *Service) Create(_ context.Context, req *proto.CreatePetRequest) (res *p return &proto.CreatePetResponse{Pet: RawToDto(raw, imgUrls)}, nil } -func RawToDtoList(in *[]*pet.Pet) []*proto.Pet { +func RawToDtoList(in *[]*pet.Pet, imageUrls [][]string) ([]*proto.Pet, error) { var result []*proto.Pet - for _, e := range *in { - result = append(result, RawToDto(e, []string{})) + if len(*in) != len(imageUrls) { + return nil, errors.New("length of in and imageUrls have to be the same") } - return result + + for i, e := range *in { + result = append(result, RawToDto(e, imageUrls[i])) + } + return result, nil } func RawToDto(in *pet.Pet, imgUrl []string) *proto.Pet { diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index c15fafd..fa5f611 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -39,6 +39,8 @@ type PetServiceTest struct { ChangeViewPetReqMock *proto.ChangeViewPetRequest Images []*img_proto.Image ImageUrls []string + ImagesList [][]*img_proto.Image + ImageUrlsList [][]string } func TestPetService(t *testing.T) { @@ -46,48 +48,78 @@ func TestPetService(t *testing.T) { } func (t *PetServiceTest) SetupTest() { - t.Pet = &pet.Pet{ - Base: model.Base{ - ID: uuid.New(), - CreatedAt: time.Time{}, - UpdatedAt: time.Time{}, - DeletedAt: gorm.DeletedAt{}, - }, - Type: faker.Word(), - Species: faker.Word(), - Name: faker.Name(), - Birthdate: faker.Word(), - Gender: petConst.Gender(rand.Intn(1) + 1), - Habit: faker.Paragraph(), - Caption: faker.Paragraph(), - Status: petConst.Status(rand.Intn(1) + 1), - IsSterile: true, - IsVaccinated: true, - IsVisible: true, - IsClubPet: true, - Background: faker.Paragraph(), - Address: faker.Paragraph(), - Contact: faker.Paragraph(), + var pets []*pet.Pet + for i := 0; i <= 3; i++ { + pet := &pet.Pet{ + Base: model.Base{ + ID: uuid.New(), + CreatedAt: time.Time{}, + UpdatedAt: time.Time{}, + DeletedAt: gorm.DeletedAt{}, + }, + Type: faker.Word(), + Species: faker.Word(), + Name: faker.Name(), + Birthdate: faker.Word(), + Gender: petConst.Gender(rand.Intn(1) + 1), + Habit: faker.Paragraph(), + Caption: faker.Paragraph(), + Status: petConst.Status(rand.Intn(1) + 1), + IsSterile: true, + IsVaccinated: true, + IsVisible: true, + IsClubPet: true, + Background: faker.Paragraph(), + Address: faker.Paragraph(), + Contact: faker.Paragraph(), + } + var images []*img_proto.Image + var imageUrls []string + for i := 0; i < 3; i++ { + url := fmt.Sprintf("http://www.image.pet.%v", i) + images = append(images, &img_proto.Image{ + Id: faker.UUIDDigit(), + PetId: pet.ID.String(), + ImageUrl: url, + }) + imageUrls = append(imageUrls, url) + } + t.ImagesList = append(t.ImagesList, images) + t.ImageUrlsList = append(t.ImageUrlsList, imageUrls) + pets = append(pets, pet) } - t.Images = []*img_proto.Image{ - { - Id: faker.UUIDDigit(), - PetId: t.Pet.ID.String(), - ImageUrl: faker.URL(), - }, - { - Id: faker.UUIDDigit(), - PetId: t.Pet.ID.String(), - ImageUrl: faker.URL(), - }, - } + t.Pets = pets + t.Pet = pets[0] - t.ImageUrls = []string{ - t.Images[0].ImageUrl, - t.Images[1].ImageUrl, + for _, images := range t.ImagesList { + for _, image := range images { + t.ImageUrls = append(t.ImageUrls, image.ImageUrl) + } } + // for _, image := t.ImagesList + + // t.Images = []*img_proto.Image{ + // { + // Id: faker.UUIDDigit(), + // PetId: t.Pet.ID.String(), + // ImageUrl: faker.URL(), + // }, + // { + // Id: faker.UUIDDigit(), + // PetId: t.Pet.ID.String(), + // ImageUrl: faker.URL(), + // }, + // } + + // t.ImageUrls = []string{ + // t.Images[0].ImageUrl, + // t.Images[1].ImageUrl, + // } + t.Images = t.ImagesList[0] + t.ImageUrls = t.ImageUrlsList[0] + t.PetDto = &proto.Pet{ Id: t.Pet.ID.String(), Type: t.Pet.Type, @@ -203,6 +235,7 @@ func (t *PetServiceTest) SetupTest() { Id: t.Pet.ID.String(), Visible: false, } + } func (t *PetServiceTest) TestDeleteSuccess() { want := &proto.DeletePetResponse{Success: true} @@ -269,21 +302,25 @@ func (t *PetServiceTest) TestFindOneSuccess() { srv := NewService(repo, imgSrv) actual, err := srv.FindOne(context.Background(), &proto.FindOnePetRequest{Id: t.Pet.ID.String()}) - fmt.Println(want, actual) assert.Nil(t.T(), err) assert.Equal(t.T(), want, actual) } func (t *PetServiceTest) TestFindAllSuccess() { - var pets []*pet.Pet - want := &proto.FindAllPetResponse{Pets: createPetsDto(t.Pets)} + want := &proto.FindAllPetResponse{Pets: t.createPetsDto(t.Pets, t.ImageUrlsList)} + + var petsIn []*pet.Pet repo := &mock.RepositoryMock{} - repo.On("FindAll", pets).Return(&t.Pets, nil) + repo.On("FindAll", petsIn).Return(&t.Pets, nil) + imgSrv := new(img_mock.ServiceMock) - imgSrv.On("FindByPetId", t.Pet.ID.String()).Return(t.Images, nil) + for i, pet := range t.Pets { + imgSrv.On("FindByPetId", pet.ID.String()).Return(t.ImagesList[i], nil) + fmt.Println(len(t.ImageUrlsList[i])) + } srv := NewService(repo, imgSrv) @@ -309,10 +346,48 @@ func (t *PetServiceTest) TestFindOneNotFound() { assert.Equal(t.T(), codes.NotFound, st.Code()) } -func createPetsDto(in []*pet.Pet) []*proto.Pet { +func createPets() []*pet.Pet { + var result []*pet.Pet + + for i := 0; i < rand.Intn(4)+1; i++ { + r := &pet.Pet{ + Base: model.Base{ + ID: uuid.New(), + CreatedAt: time.Time{}, + UpdatedAt: time.Time{}, + DeletedAt: gorm.DeletedAt{}, + }, + Type: faker.Word(), + Species: faker.Word(), + Name: faker.Name(), + Birthdate: faker.Word(), + Gender: petConst.Gender(rand.Intn(1) + 1), + Habit: faker.Paragraph(), + Caption: faker.Paragraph(), + Status: petConst.Status(rand.Intn(1) + 1), + IsSterile: true, + IsVaccinated: true, + IsVisible: true, + IsClubPet: true, + Background: faker.Paragraph(), + Address: faker.Paragraph(), + Contact: faker.Paragraph(), + } + result = append(result, r) + } + + return result +} + +// TODO: test find one invalid ID +func (t *PetServiceTest) TestFindOneInvalidID() { + +} + +func (t *PetServiceTest) createPetsDto(in []*pet.Pet, imageUrlsList [][]string) []*proto.Pet { var result []*proto.Pet - for _, p := range in { + for i, p := range in { r := &proto.Pet{ Id: p.ID.String(), Type: p.Type, @@ -322,8 +397,8 @@ func createPetsDto(in []*pet.Pet) []*proto.Pet { Gender: proto.Gender(p.Gender), Habit: p.Habit, Caption: p.Caption, - Status: 0, - ImageUrls: []string{}, + Status: proto.PetStatus(p.Status), + ImageUrls: imageUrlsList[i], IsSterile: p.IsSterile, IsVaccinated: p.IsVaccinated, IsVisible: p.IsVisible, From a789156511416b0baaeaf675bd5def6dea6561e4 Mon Sep 17 00:00:00 2001 From: Gear <84141000+macgeargear@users.noreply.github.com> Date: Tue, 26 Dec 2023 23:29:03 +0700 Subject: [PATCH 24/48] fix: remove find one with invalid id --- src/app/service/pet/pet.service_test.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index fa5f611..162c848 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -379,11 +379,6 @@ func createPets() []*pet.Pet { return result } -// TODO: test find one invalid ID -func (t *PetServiceTest) TestFindOneInvalidID() { - -} - func (t *PetServiceTest) createPetsDto(in []*pet.Pet, imageUrlsList [][]string) []*proto.Pet { var result []*proto.Pet From 8d7d7e58d496a600565b725ce8639cce2617f6e1 Mon Sep 17 00:00:00 2001 From: Gear <84141000+macgeargear@users.noreply.github.com> Date: Tue, 26 Dec 2023 23:34:23 +0700 Subject: [PATCH 25/48] fix: call imgSrv FindByPetId on TestChangeViewSuccess --- src/app/service/pet/pet.service_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index 162c848..d4366da 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -3,7 +3,6 @@ package pet import ( "context" "errors" - "fmt" "math/rand" "testing" "time" @@ -76,7 +75,7 @@ func (t *PetServiceTest) SetupTest() { var images []*img_proto.Image var imageUrls []string for i := 0; i < 3; i++ { - url := fmt.Sprintf("http://www.image.pet.%v", i) + url := faker.URL() images = append(images, &img_proto.Image{ Id: faker.UUIDDigit(), PetId: pet.ID.String(), @@ -319,7 +318,6 @@ func (t *PetServiceTest) TestFindAllSuccess() { imgSrv := new(img_mock.ServiceMock) for i, pet := range t.Pets { imgSrv.On("FindByPetId", pet.ID.String()).Return(t.ImagesList[i], nil) - fmt.Println(len(t.ImageUrlsList[i])) } srv := NewService(repo, imgSrv) @@ -517,6 +515,7 @@ func (t *PetServiceTest) TestChangeViewSuccess() { repo.On("FindOne", t.Pet.ID.String(), &pet.Pet{}).Return(t.Pet, nil) repo.On("Update", t.Pet.ID.String(), t.ChangeViewPet).Return(t.ChangeViewPet, nil) imgSrv := new(img_mock.ServiceMock) + imgSrv.On("FindByPetId", t.Pet.ID.String()).Return(t.Images, nil) srv := NewService(repo, imgSrv) actual, err := srv.ChangeView(context.Background(), t.ChangeViewPetReqMock) From 8ea07a0d70018bbb959a448f8d2dd27fcf4c88ed Mon Sep 17 00:00:00 2001 From: Sunioatm <104454675+Sunioatm@users.noreply.github.com> Date: Wed, 27 Dec 2023 01:35:24 +0700 Subject: [PATCH 26/48] test : add adopt pet test - make test func - add ChangeAdoptBy and AdoptByReq - add AdoptBy feild in SetupTest --- src/app/service/pet/pet.service_test.go | 91 +++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index 4235945..f7c678f 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -38,6 +38,8 @@ type PetServiceTest struct { ChangeViewPetReqMock *proto.ChangeViewPetRequest Images []*img_proto.Image ImageUrls []string + ChangeAdoptBy *pet.Pet + AdoptByReq *proto.AdoptPetRequest } func TestPetService(t *testing.T) { @@ -67,6 +69,7 @@ func (t *PetServiceTest) SetupTest() { Background: faker.Paragraph(), Address: faker.Paragraph(), Contact: faker.Paragraph(), + AdoptBy: "", } t.Images = []*img_proto.Image{ @@ -105,6 +108,7 @@ func (t *PetServiceTest) SetupTest() { Address: t.Pet.Address, Contact: t.Pet.Contact, ImageUrls: t.ImageUrls, + AdoptBy: t.Pet.AdoptBy, } t.UpdatePet = &pet.Pet{ @@ -129,6 +133,7 @@ func (t *PetServiceTest) SetupTest() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, + AdoptBy: t.Pet.AdoptBy, } t.ChangeViewPet = &pet.Pet{ @@ -153,6 +158,7 @@ func (t *PetServiceTest) SetupTest() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, + AdoptBy: t.Pet.AdoptBy, } t.CreatePetReqMock = &proto.CreatePetRequest{ @@ -173,6 +179,7 @@ func (t *PetServiceTest) SetupTest() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, + AdoptBy: t.Pet.AdoptBy, }, } @@ -195,6 +202,7 @@ func (t *PetServiceTest) SetupTest() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, + AdoptBy: t.Pet.AdoptBy, }, } @@ -202,6 +210,36 @@ func (t *PetServiceTest) SetupTest() { Id: t.Pet.ID.String(), Visible: false, } + + t.ChangeAdoptBy = &pet.Pet{ + Base: model.Base{ + ID: t.Pet.Base.ID, + CreatedAt: t.Pet.Base.CreatedAt, + UpdatedAt: t.Pet.Base.UpdatedAt, + DeletedAt: t.Pet.Base.DeletedAt, + }, + Type: t.Pet.Type, + Species: t.Pet.Species, + Name: t.Pet.Name, + Birthdate: t.Pet.Birthdate, + Gender: t.Pet.Gender, + Habit: t.Pet.Habit, + Caption: t.Pet.Caption, + Status: t.Pet.Status, + IsSterile: t.Pet.IsSterile, + IsVaccinated: t.Pet.IsVaccinated, + IsVisible: t.Pet.IsVisible, + IsClubPet: t.Pet.IsClubPet, + Background: t.Pet.Background, + Address: t.Pet.Address, + Contact: t.Pet.Contact, + AdoptBy: faker.UUIDDigit(), + } + + t.AdoptByReq = &proto.AdoptPetRequest{ + PetId: t.ChangeAdoptBy.ID.String(), + UserId: t.ChangeAdoptBy.AdoptBy, + } } func (t *PetServiceTest) TestDeleteSuccess() { want := &proto.DeletePetResponse{Success: true} @@ -361,6 +399,7 @@ func (t *PetServiceTest) TestCreateSuccess() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, + AdoptBy: t.Pet.AdoptBy, } repo.On("Create", in).Return(t.Pet, nil) @@ -393,6 +432,7 @@ func (t *PetServiceTest) TestCreateInternalErr() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, + AdoptBy: t.Pet.AdoptBy, } repo.On("Create", in).Return(nil, errors.New("something wrong")) @@ -470,3 +510,54 @@ func (t *PetServiceTest) TestChangeViewNotFound() { assert.Nil(t.T(), actual) assert.Equal(t.T(), codes.NotFound, st.Code()) } + +func (t *PetServiceTest) TestAdoptBySuccess() { + want := &proto.AdoptPetResponse{Success: true} + repo := &mock.RepositoryMock{} + + repo.On("FindOne", t.AdoptByReq.PetId, &pet.Pet{}).Return(t.Pet, nil) + repo.On("Update", t.AdoptByReq.PetId, t.ChangeAdoptBy).Return(t.ChangeAdoptBy, nil) + + imgSrv := new(img_mock.ServiceMock) + srv := NewService(repo, imgSrv) + + actual, err := srv.AdoptPet(context.Background(), t.AdoptByReq) + + assert.Nil(t.T(), err) + assert.Equal(t.T(), want, actual) +} + +func (t *PetServiceTest) TestAdoptByPetNotFound() { + wantError := status.Error(codes.NotFound, "pet not found") + repo := &mock.RepositoryMock{} + + repo.On("FindOne", t.AdoptByReq.PetId, &pet.Pet{}).Return(nil, wantError) + + imgSrv := new(img_mock.ServiceMock) + srv := NewService(repo, imgSrv) + + actual, err := srv.AdoptPet(context.Background(), t.AdoptByReq) + + assert.NotNil(t.T(), err) + assert.Equal(t.T(), wantError, err) + assert.Nil(t.T(), actual) + + repo.AssertNotCalled(t.T(), "Update", t.AdoptByReq.PetId, t.ChangeAdoptBy) +} + +func (t *PetServiceTest) TestAdoptByUpdateError() { + wantError := status.Error(codes.NotFound, "pet not found") + repo := &mock.RepositoryMock{} + + repo.On("FindOne", t.AdoptByReq.PetId, &pet.Pet{}).Return(t.Pet, nil) + repo.On("Update", t.AdoptByReq.PetId, t.ChangeAdoptBy).Return(nil, errors.New("update error")) + + imgSrv := new(img_mock.ServiceMock) + srv := NewService(repo, imgSrv) + + actual, err := srv.AdoptPet(context.Background(), t.AdoptByReq) + + assert.NotNil(t.T(), err) + assert.Equal(t.T(), wantError, err) + assert.Nil(t.T(), actual) +} From 282ce441815dcba723b14c53e597ad711924332c Mon Sep 17 00:00:00 2001 From: Sunioatm <104454675+Sunioatm@users.noreply.github.com> Date: Wed, 27 Dec 2023 02:52:48 +0700 Subject: [PATCH 27/48] fix: remove AdoptBy field remove AdoptBy field that not relevant --- src/app/service/pet/pet.service_test.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index f7c678f..f55abd8 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -108,7 +108,6 @@ func (t *PetServiceTest) SetupTest() { Address: t.Pet.Address, Contact: t.Pet.Contact, ImageUrls: t.ImageUrls, - AdoptBy: t.Pet.AdoptBy, } t.UpdatePet = &pet.Pet{ @@ -133,7 +132,6 @@ func (t *PetServiceTest) SetupTest() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, - AdoptBy: t.Pet.AdoptBy, } t.ChangeViewPet = &pet.Pet{ @@ -158,7 +156,6 @@ func (t *PetServiceTest) SetupTest() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, - AdoptBy: t.Pet.AdoptBy, } t.CreatePetReqMock = &proto.CreatePetRequest{ @@ -179,7 +176,6 @@ func (t *PetServiceTest) SetupTest() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, - AdoptBy: t.Pet.AdoptBy, }, } @@ -202,7 +198,6 @@ func (t *PetServiceTest) SetupTest() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, - AdoptBy: t.Pet.AdoptBy, }, } @@ -399,7 +394,6 @@ func (t *PetServiceTest) TestCreateSuccess() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, - AdoptBy: t.Pet.AdoptBy, } repo.On("Create", in).Return(t.Pet, nil) @@ -432,7 +426,6 @@ func (t *PetServiceTest) TestCreateInternalErr() { Background: t.Pet.Background, Address: t.Pet.Address, Contact: t.Pet.Contact, - AdoptBy: t.Pet.AdoptBy, } repo.On("Create", in).Return(nil, errors.New("something wrong")) From 10dcce92990130bfe1e8b7c47eb3fa3efd773de5 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 16:47:01 +0700 Subject: [PATCH 28/48] fix: remove unused code --- src/app/service/pet/pet.service_test.go | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index d4366da..664d1b6 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -97,25 +97,6 @@ func (t *PetServiceTest) SetupTest() { } } - // for _, image := t.ImagesList - - // t.Images = []*img_proto.Image{ - // { - // Id: faker.UUIDDigit(), - // PetId: t.Pet.ID.String(), - // ImageUrl: faker.URL(), - // }, - // { - // Id: faker.UUIDDigit(), - // PetId: t.Pet.ID.String(), - // ImageUrl: faker.URL(), - // }, - // } - - // t.ImageUrls = []string{ - // t.Images[0].ImageUrl, - // t.Images[1].ImageUrl, - // } t.Images = t.ImagesList[0] t.ImageUrls = t.ImageUrlsList[0] From cb62e7e660810b699b5b6fae1d253979db877c41 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 21:51:45 +0700 Subject: [PATCH 29/48] feat: main init db, conf, net --- src/main.go | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/main.go b/src/main.go index 70b6c9a..0b4100e 100644 --- a/src/main.go +++ b/src/main.go @@ -1,5 +1,36 @@ package main +import ( + "fmt" + "net" + + "github.com/isd-sgcu/johnjud-backend/src/config" + "github.com/isd-sgcu/johnjud-backend/src/database" + "github.com/rs/zerolog/log" +) + func main() { - // Code + conf, err := config.LoadConfig() + if err != nil { + log.Fatal(). + Err(err). + Str("service", "backend load config"). + Msg("Failed to start service") + } + + db, err := database.InitPostgresDatabase(&conf.Database, conf.App.Debug) + if err != nil { + log.Fatal(). + Err(err). + Str("service", "backend database"). + Msg("Failed to start service") + } + + lis, err := net.Listen("tcp", fmt.Sprintf(":%v", conf.App.Port)) + if err != nil { + log.Fatal(). + Err(err). + Str("service", "backend server"). + Msg("Failed to start service") + } } From e0a450c313b8626889642e981571a82e7f71ed75 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:15:29 +0700 Subject: [PATCH 30/48] feat: config add file service --- config/config.example.yaml | 3 +++ src/config/config.go | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/config/config.example.yaml b/config/config.example.yaml index a413180..f4c5111 100644 --- a/config/config.example.yaml +++ b/config/config.example.yaml @@ -8,3 +8,6 @@ database: name: johnjud_db username: root password: root + +service: + file: localhost:3003 \ No newline at end of file diff --git a/src/config/config.go b/src/config/config.go index c526550..fc6876a 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -19,9 +19,14 @@ type App struct { Debug bool `mapstructure:"debug"` } +type Service struct { + File string `mapstructure:"file"` +} + type Config struct { App App `mapstructure:"app"` Database Database `mapstructure:"database"` + Service Service `mapstructure:"service"` } func LoadConfig() (config *Config, err error) { From c0c0c831d39b5de2e0cb565b2f540142be41c9f0 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:19:54 +0700 Subject: [PATCH 31/48] feat: service add proto.UnimplementedLikeServiceServer --- src/app/service/like/like.service.go | 1 + src/app/service/pet/pet.service.go | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/service/like/like.service.go b/src/app/service/like/like.service.go index 064558b..1d111fc 100644 --- a/src/app/service/like/like.service.go +++ b/src/app/service/like/like.service.go @@ -15,6 +15,7 @@ import ( ) type Service struct { + proto.UnimplementedLikeServiceServer repository IRepository } diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 4b021b5..d71c292 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -19,6 +19,7 @@ import ( ) type Service struct { + proto.UnimplementedPetServiceServer repository IRepository imageService ImageService } @@ -36,7 +37,7 @@ type ImageService interface { } func NewService(repository IRepository, imageService ImageService) *Service { - return &Service{repository, imageService} + return &Service{repository: repository, imageService: imageService} } func (s *Service) Delete(ctx context.Context, req *proto.DeletePetRequest) (*proto.DeletePetResponse, error) { From f24b4cf3edc2991693f86cd6e0a49cf6049c5d59 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:20:28 +0700 Subject: [PATCH 32/48] feat: main graceful shutdown, repo, srv --- go.mod | 14 +----- go.sum | 4 ++ src/main.go | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 140 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 4afd1ea..ade5ec4 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ toolchain go1.21.5 require ( github.com/bxcodec/faker/v3 v3.8.1 github.com/google/uuid v1.5.0 - github.com/isd-sgcu/johnjud-go-proto v0.0.8 + github.com/isd-sgcu/johnjud-go-proto v0.0.9 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.31.0 github.com/spf13/viper v1.18.2 @@ -26,43 +26,33 @@ require ( github.com/stretchr/objx v0.5.0 // indirect golang.org/x/net v0.19.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect ) require ( github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/isd-sgcu/johnjud-go-proto v0.0.8 github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.4.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.8.4 - github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.19.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9366728..cc506c7 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/isd-sgcu/johnjud-go-proto v0.0.8 h1:nIQBZgK2OFVrLjVtpeDgwows8poA7LhsIVE4hlbBC1o= github.com/isd-sgcu/johnjud-go-proto v0.0.8/go.mod h1:HP0w9gC30b5WNnqeFBM9JJZud+pvyikz0+pGFSI/Wjw= +github.com/isd-sgcu/johnjud-go-proto v0.0.9 h1:cFfZ2JSpW0jg94Iv5zHQJGnoekj0eCQe42SJaTpnp3c= +github.com/isd-sgcu/johnjud-go-proto v0.0.9/go.mod h1:1OK6aiCgtXQiLhxp0r6iLEejYIRpckWQZDrCZ9Trbo4= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= @@ -109,6 +111,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/src/main.go b/src/main.go index 0b4100e..e23b1b4 100644 --- a/src/main.go +++ b/src/main.go @@ -1,36 +1,165 @@ package main import ( + "context" "fmt" "net" + "os" + "os/signal" + "sync" + "syscall" + "time" + likeRepo "github.com/isd-sgcu/johnjud-backend/src/app/repository/like" + petRepo "github.com/isd-sgcu/johnjud-backend/src/app/repository/pet" + imageSrv "github.com/isd-sgcu/johnjud-backend/src/app/service/image" + likeSrv "github.com/isd-sgcu/johnjud-backend/src/app/service/like" + petSrv "github.com/isd-sgcu/johnjud-backend/src/app/service/pet" "github.com/isd-sgcu/johnjud-backend/src/config" "github.com/isd-sgcu/johnjud-backend/src/database" + likePb "github.com/isd-sgcu/johnjud-go-proto/johnjud/backend/like/v1" + petPb "github.com/isd-sgcu/johnjud-go-proto/johnjud/backend/pet/v1" + imagePb "github.com/isd-sgcu/johnjud-go-proto/johnjud/file/image/v1" "github.com/rs/zerolog/log" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/health" + "google.golang.org/grpc/health/grpc_health_v1" + "google.golang.org/grpc/reflection" ) +type operation func(ctx context.Context) error + +func gracefulShutdown(ctx context.Context, timeout time.Duration, ops map[string]operation) <-chan struct{} { + wait := make(chan struct{}) + go func() { + s := make(chan os.Signal, 1) + + signal.Notify(s, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) + sig := <-s + + log.Info(). + Str("service", "graceful shutdown"). + Msgf("got signal \"%v\" shutting down service", sig) + + timeoutFunc := time.AfterFunc(timeout, func() { + log.Error(). + Str("service", "graceful shutdown"). + Msgf("timeout %v ms has been elapsed, force exit", timeout.Milliseconds()) + os.Exit(0) + }) + + defer timeoutFunc.Stop() + + var wg sync.WaitGroup + + for key, op := range ops { + wg.Add(1) + innerOp := op + innerKey := key + go func() { + defer wg.Done() + + log.Info(). + Str("service", "graceful shutdown"). + Msgf("cleaning up: %v", innerKey) + if err := innerOp(ctx); err != nil { + log.Error(). + Str("service", "graceful shutdown"). + Err(err). + Msgf("%v: clean up failed: %v", innerKey, err.Error()) + return + } + + log.Info(). + Str("service", "graceful shutdown"). + Msgf("%v was shutdown gracefully", innerKey) + }() + } + + wg.Wait() + close(wait) + }() + + return wait +} + func main() { conf, err := config.LoadConfig() if err != nil { log.Fatal(). Err(err). - Str("service", "backend load config"). - Msg("Failed to start service") + Str("service", "backend"). + Msg("Failed to load config") } db, err := database.InitPostgresDatabase(&conf.Database, conf.App.Debug) if err != nil { log.Fatal(). Err(err). - Str("service", "backend database"). - Msg("Failed to start service") + Str("service", "backend"). + Msg("Failed to init postgres connection") + } + + fileConn, err := grpc.Dial(conf.Service.File, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + log.Fatal(). + Err(err). + Str("service", "johnjud-file"). + Msg("Cannot connect to service") } lis, err := net.Listen("tcp", fmt.Sprintf(":%v", conf.App.Port)) if err != nil { log.Fatal(). Err(err). - Str("service", "backend server"). + Str("service", "backend"). Msg("Failed to start service") } + + grpcServer := grpc.NewServer() + + likeRepo := likeRepo.NewRepository(db) + likeService := likeSrv.NewService(likeRepo) + + imageClient := imagePb.NewImageServiceClient(fileConn) + imageService := imageSrv.NewService(imageClient) + petRepo := petRepo.NewRepository(db) + petService := petSrv.NewService(petRepo, imageService) + + grpc_health_v1.RegisterHealthServer(grpcServer, health.NewServer()) + likePb.RegisterLikeServiceServer(grpcServer, likeService) + petPb.RegisterPetServiceServer(grpcServer, petService) + + reflection.Register(grpcServer) + go func() { + log.Info(). + Str("service", "backend"). + Msgf("JohnJud backend starting at port %v", conf.App.Port) + + if err := grpcServer.Serve(lis); err != nil { + log.Fatal(). + Err(err). + Str("service", "backend"). + Msg("Failed to start service") + } + }() + + wait := gracefulShutdown(context.Background(), 2*time.Second, map[string]operation{ + "server": func(ctx context.Context) error { + grpcServer.GracefulStop() + return nil + }, + }) + + <-wait + + grpcServer.GracefulStop() + log.Info(). + Str("service", "backend"). + Msg("Closing the listener") + lis.Close() + log.Info(). + Str("service", "backend"). + Msg("End the program") } From 9dfd0262690db418420f2b1528e01408d9e59201 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:28:48 +0700 Subject: [PATCH 33/48] fix: dokcer port typo --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 7c2ad2e..2ddebae 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -12,7 +12,7 @@ services: volumes: - postgres:/var/lib/postgresql/data ports: - - "5433:5432" + - "5432:5432" volumes: postgres: \ No newline at end of file From f568f0e6f248fa72ea32d77943ebc9c9d134382d Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:33:06 +0700 Subject: [PATCH 34/48] feat: postgres init table --- src/database/postgresql.connection.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/database/postgresql.connection.go b/src/database/postgresql.connection.go index 098b96b..95a0006 100644 --- a/src/database/postgresql.connection.go +++ b/src/database/postgresql.connection.go @@ -4,6 +4,8 @@ import ( "fmt" "strconv" + "github.com/isd-sgcu/johnjud-backend/src/app/model/like" + "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" "github.com/isd-sgcu/johnjud-backend/src/config" "gorm.io/driver/postgres" "gorm.io/gorm" @@ -24,5 +26,10 @@ func InitPostgresDatabase(conf *config.Database, isDebug bool) (db *gorm.DB, err return nil, err } + err = db.AutoMigrate(&like.Like{}, &pet.Pet{}) + if err != nil { + return nil, err + } + return } From 92990f907b9bf390b6dc5236de906cfad9911161 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:39:41 +0700 Subject: [PATCH 35/48] fix: gorm postgres model --- src/app/model/common.model.go | 8 ++++---- src/app/model/user/user.model.go | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/app/model/common.model.go b/src/app/model/common.model.go index 682db1c..1ab9cd8 100644 --- a/src/app/model/common.model.go +++ b/src/app/model/common.model.go @@ -8,10 +8,10 @@ import ( ) type Base struct { - ID uuid.UUID `json:"id" gorm:"primaryKey;size:191"` - CreatedAt time.Time `json:"created_at" gorm:"type:datetime;autoCreateTime:nano"` - UpdatedAt time.Time `json:"updated_at" gorm:"type:datetime;autoUpdateTime:nano"` - DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index;type:datetime"` + ID uuid.UUID `json:"id" gorm:"primary_key"` + CreatedAt time.Time `json:"created_at" gorm:"type:timestamp;autoCreateTime:nano"` + UpdatedAt time.Time `json:"updated_at" gorm:"type:timestamp;autoUpdateTime:nano"` + DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index;type:timestamp"` } func (m *Base) BeforeCreate(_ *gorm.DB) error { diff --git a/src/app/model/user/user.model.go b/src/app/model/user/user.model.go index e93dae0..332db06 100644 --- a/src/app/model/user/user.model.go +++ b/src/app/model/user/user.model.go @@ -4,9 +4,9 @@ import "github.com/isd-sgcu/johnjud-backend/src/app/model" type User struct { model.Base - Email string `json:"email" gorm:"type:tinytext"` - Password string `json:"password" gorm:"type:tinytext"` - Firstname string `json:"firstname" gorm:"type:tinytext"` - Lastname string `json:"lastname" gorm:"type:tinytext"` - Role string `json:"role" gorm:"type:tinytext"` + Email string `json:"email" gorm:"tinytext"` + Password string `json:"password" gorm:"tinytext"` + Firstname string `json:"firstname" gorm:"tinytext"` + Lastname string `json:"lastname" gorm:"tinytext"` + Role string `json:"role" gorm:"tinytext"` } From 1b393778deb3236c7b113e74a385fc6bee57c4e8 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:39:53 +0700 Subject: [PATCH 36/48] fix: db init also make user table --- src/database/postgresql.connection.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/database/postgresql.connection.go b/src/database/postgresql.connection.go index 95a0006..8369137 100644 --- a/src/database/postgresql.connection.go +++ b/src/database/postgresql.connection.go @@ -6,6 +6,7 @@ import ( "github.com/isd-sgcu/johnjud-backend/src/app/model/like" "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" + "github.com/isd-sgcu/johnjud-backend/src/app/model/user" "github.com/isd-sgcu/johnjud-backend/src/config" "gorm.io/driver/postgres" "gorm.io/gorm" @@ -26,7 +27,7 @@ func InitPostgresDatabase(conf *config.Database, isDebug bool) (db *gorm.DB, err return nil, err } - err = db.AutoMigrate(&like.Like{}, &pet.Pet{}) + err = db.AutoMigrate(&user.User{}, &like.Like{}, &pet.Pet{}) if err != nil { return nil, err } From c0d0177c5dc3e3618c3965e2cd3e54af5ec980de Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 23:25:25 +0700 Subject: [PATCH 37/48] feat: pet model add adoptBy --- src/app/model/pet/pet.model.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/model/pet/pet.model.go b/src/app/model/pet/pet.model.go index d6b916a..3c88a37 100644 --- a/src/app/model/pet/pet.model.go +++ b/src/app/model/pet/pet.model.go @@ -22,4 +22,5 @@ type Pet struct { Background string `json:"background" gorm:"tinytext"` Address string `json:"address" gorm:"tinytext"` Contact string `json:"contact" gorm:"tinytext"` + AdoptBy string `json:"adopt_by" gorm:"tinytext"` } From e4d0ee64a29e057e03332a53d394af944e24fbf3 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 23:28:12 +0700 Subject: [PATCH 38/48] feat: add adoptby in pet service --- src/app/service/pet/pet.service.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index d71c292..f7f0748 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -139,7 +139,7 @@ func (s Service) FindOne(_ context.Context, req *proto.FindOnePetRequest) (res * func (s *Service) Create(_ context.Context, req *proto.CreatePetRequest) (res *proto.CreatePetResponse, err error) { raw, err := DtoToRaw(req.Pet) if err != nil { - return nil, status.Error(codes.Internal, "error converting dto to raw") + return nil, status.Error(codes.Internal, "error converting dto to raw: "+err.Error()) } imgUrls := []string{} @@ -183,6 +183,7 @@ func RawToDto(in *pet.Pet, imgUrl []string) *proto.Pet { Background: in.Background, Address: in.Address, Contact: in.Contact, + AdoptBy: in.AdoptBy, } } @@ -234,6 +235,7 @@ func DtoToRaw(in *proto.Pet) (res *pet.Pet, err error) { Background: in.Background, Address: in.Address, Contact: in.Contact, + AdoptBy: in.AdoptBy, }, nil } From d6ded3d8b731a0141574102b7f0bc4961950d92a Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Thu, 28 Dec 2023 00:21:19 +0700 Subject: [PATCH 39/48] fix: config file port to 3004 --- config/config.example.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.example.yaml b/config/config.example.yaml index f4c5111..34bc114 100644 --- a/config/config.example.yaml +++ b/config/config.example.yaml @@ -10,4 +10,4 @@ database: password: root service: - file: localhost:3003 \ No newline at end of file + file: localhost:3004 \ No newline at end of file From 61480ff6e51b293fdc2e4f83698a0b61db927b43 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Thu, 28 Dec 2023 00:22:44 +0700 Subject: [PATCH 40/48] fix: remove adopt model, repo --- src/app/model/adopt/adopt.model.go | 16 ------------ src/app/repository/adopt/adopt.repository.go | 26 -------------------- 2 files changed, 42 deletions(-) delete mode 100644 src/app/model/adopt/adopt.model.go delete mode 100644 src/app/repository/adopt/adopt.repository.go diff --git a/src/app/model/adopt/adopt.model.go b/src/app/model/adopt/adopt.model.go deleted file mode 100644 index 24a8a86..0000000 --- a/src/app/model/adopt/adopt.model.go +++ /dev/null @@ -1,16 +0,0 @@ -package adopt - -import ( - "github.com/google/uuid" - "github.com/isd-sgcu/johnjud-backend/src/app/model" - "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" - "github.com/isd-sgcu/johnjud-backend/src/app/model/user" -) - -type Adopt struct { - model.Base - PetID *uuid.UUID `json:"pet_id" gorm:"index:idx_name,unique"` - Pet *pet.Pet `json:"pet" gorm:"foreignKey:PetID;constraint:OnUpdate:CASCADE;OnDelete:SET NULL;"` - UserID *uuid.UUID `json:"user_id" gorm:"index:idx_name,unique"` - User *user.User `json:"user" gorm:"foreignKey:UserID;constraint:OnUpdate:CASCADE;OnDelete:SET NULL;"` -} diff --git a/src/app/repository/adopt/adopt.repository.go b/src/app/repository/adopt/adopt.repository.go deleted file mode 100644 index 2acc99b..0000000 --- a/src/app/repository/adopt/adopt.repository.go +++ /dev/null @@ -1,26 +0,0 @@ -package adopt - -import ( - "github.com/isd-sgcu/johnjud-backend/src/app/model/adopt" - "gorm.io/gorm" -) - -type Repository struct { - db *gorm.DB -} - -func NewRepository(db *gorm.DB) *Repository { - return &Repository{db: db} -} - -func (r *Repository) FindAll(result *[]*adopt.Adopt) error { - return r.db.Model(&adopt.Adopt{}).Find(result).Error -} - -func (r *Repository) Create(in *adopt.Adopt) error { - return r.db.Create(&in).Error -} - -func (r *Repository) Delete(id string) error { - return r.db.Where("id = ?", id).Delete(&adopt.Adopt{}).Error -} From b695aa94c43fd8b691b02f12485c781e7e86b13f Mon Sep 17 00:00:00 2001 From: Sunioatm <104454675+Sunioatm@users.noreply.github.com> Date: Mon, 1 Jan 2024 13:01:42 +0700 Subject: [PATCH 41/48] feat: add adopt by add adopt by fix adopt by test --- go.sum | 2 -- src/app/service/pet/pet.service.go | 19 ------------------- src/app/service/pet/pet.service_test.go | 8 ++++++-- 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/go.sum b/go.sum index 3b4b7f5..fc7670b 100644 --- a/go.sum +++ b/go.sum @@ -22,8 +22,6 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/isd-sgcu/johnjud-go-proto v0.0.9 h1:cFfZ2JSpW0jg94Iv5zHQJGnoekj0eCQe42SJaTpnp3c= github.com/isd-sgcu/johnjud-go-proto v0.0.9/go.mod h1:1OK6aiCgtXQiLhxp0r6iLEejYIRpckWQZDrCZ9Trbo4= -github.com/isd-sgcu/johnjud-go-proto v0.0.9 h1:cFfZ2JSpW0jg94Iv5zHQJGnoekj0eCQe42SJaTpnp3c= -github.com/isd-sgcu/johnjud-go-proto v0.0.9/go.mod h1:1OK6aiCgtXQiLhxp0r6iLEejYIRpckWQZDrCZ9Trbo4= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 8f1fc77..552f81b 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -171,25 +171,6 @@ func (s *Service) AdoptPet(ctx context.Context, req *proto.AdoptPetRequest) (res return &proto.AdoptPetResponse{Success: true}, nil } -func (s *Service) AdoptPet(ctx context.Context, req *proto.AdoptPetRequest) (res *proto.AdoptPetResponse, err error) { - dtoPet, err := s.FindOne(context.Background(), &proto.FindOnePetRequest{Id: req.PetId}) - if err != nil { - return nil, status.Error(codes.NotFound, "pet not found") - } - pet, err := DtoToRaw(dtoPet.Pet) - if err != nil { - return nil, status.Error(codes.Internal, "error converting dto to raw") - } - pet.AdoptBy = req.UserId - - err = s.repository.Update(req.PetId, pet) - if err != nil { - return nil, status.Error(codes.NotFound, "pet not found") - } - - return &proto.AdoptPetResponse{Success: true}, nil -} - func RawToDtoList(in *[]*pet.Pet, imageUrls [][]string) ([]*proto.Pet, error) { var result []*proto.Pet if len(*in) != len(imageUrls) { diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index b499185..04d36b9 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -38,10 +38,10 @@ type PetServiceTest struct { ChangeViewPetReqMock *proto.ChangeViewPetRequest Images []*img_proto.Image ImageUrls []string - ChangeAdoptBy *pet.Pet - AdoptByReq *proto.AdoptPetRequest ImagesList [][]*img_proto.Image ImageUrlsList [][]string + ChangeAdoptBy *pet.Pet + AdoptByReq *proto.AdoptPetRequest } func TestPetService(t *testing.T) { @@ -562,6 +562,8 @@ func (t *PetServiceTest) TestAdoptBySuccess() { repo.On("Update", t.AdoptByReq.PetId, t.ChangeAdoptBy).Return(t.ChangeAdoptBy, nil) imgSrv := new(img_mock.ServiceMock) + imgSrv.On("FindByPetId", t.Pet.ID.String()).Return(t.Images, nil) + srv := NewService(repo, imgSrv) actual, err := srv.AdoptPet(context.Background(), t.AdoptByReq) @@ -596,6 +598,8 @@ func (t *PetServiceTest) TestAdoptByUpdateError() { repo.On("Update", t.AdoptByReq.PetId, t.ChangeAdoptBy).Return(nil, errors.New("update error")) imgSrv := new(img_mock.ServiceMock) + imgSrv.On("FindByPetId", t.Pet.ID.String()).Return(nil, errors.New("pet not found")) + srv := NewService(repo, imgSrv) actual, err := srv.AdoptPet(context.Background(), t.AdoptByReq) From 22d1c717d2cd160ee81d10b486f50298ee809171 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Thu, 4 Jan 2024 19:21:03 +0700 Subject: [PATCH 42/48] feat: build workflow --- .github/workflows/build.yml | 54 +++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..e8796d6 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,54 @@ +name: Build + +on: + workflow_dispatch: + push: + branches: + - main + - beta + - dev + - master + +env: + IMAGE_NAME: ghcr.io/${{ github.repository }} + IMAGE_TAG: ${{ github.sha }} + +jobs: + build: + name: Build + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + outputs: + BRANCH: ${{ steps.branch.outputs.BRANCH }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Set branch + id: branch + run: | + echo "::set-output name=BRANCH::${GITHUB_REF#refs/heads/}" + + - name: Log in to the Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and Push Docker Image + uses: docker/build-push-action@v2 + with: + context: . + push: true + tags: ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }},${{ env.IMAGE_NAME }}:latest + cache-from: type=registry,ref=${{ env.IMAGE_NAME }}:buildcache + cache-to: type=registry,ref=${{ env.IMAGE_NAME }}:buildcache,mode=max \ No newline at end of file From 53305dfcb3efbd3cb2d2d8f0e14f27de5114ec1a Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Thu, 4 Jan 2024 19:28:05 +0700 Subject: [PATCH 43/48] feat: update readme --- README.md | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ad50fd8..d808198 100644 --- a/README.md +++ b/README.md @@ -1 +1,43 @@ -# johnjud-backend +# Johnjud-backend + +Johnjud-backend handles data management and business logic for the Johnjud project. + +### What is Johnjud? +Johnjud is a pet adoption web application of the [CUVET For Animal Welfare Club](https://www.facebook.com/CUVETforAnimalWelfareClub) + +## Stack + +- golang +- gRPC +- go-fiber + +## Getting Started + +### Prerequisites + +- golang 1.21 or [later](https://go.dev) +- docker +- makefile + +### Installation + +1. Clone this repo +2. Copy `config.example.yaml` in `config` and paste it in the same directory with `.example` removed from its name. + +3. Run `go mod download` to download all the dependencies. + +### Running +1. Run `docker-compose up -d` +2. Run `make server` or `go run ./src/.` + +### Testing +1. Run `make test` or `go test -v -coverpkg ./... -coverprofile coverage.out -covermode count ./...` + +## Other microservices/repositories of Johnjud +- [Johnjud-gateway](https://github.com/isd-sgcu/johnjud-gateway): Routing and request handling +- [Johnjud-auth](https://github.com/isd-sgcu/johnjud-auth): Authentication and authorization +- [Johnjud-backend](https://github.com/isd-sgcu/johnjud-backend): Main business logic +- [Johnjud-file](https://github.com/isd-sgcu/johnjud-file): File management service +- [Johnjud-proto](https://github.com/isd-sgcu/johnjud-proto): Protobuf files generator +- [Johnjud-go-proto](https://github.com/isd-sgcu/johnjud-go-proto): Generated protobuf files for golang +- [Johnjud-frontend](https://github.com/isd-sgcu/johnjud-frontend): Frontend web application From 53d4d13ab8aae1055a69e3d3fb56b1bf422c188f Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Thu, 4 Jan 2024 19:29:45 +0700 Subject: [PATCH 44/48] feat: file config --- config/file/config.example.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 config/file/config.example.yaml diff --git a/config/file/config.example.yaml b/config/file/config.example.yaml new file mode 100644 index 0000000..f1ecd10 --- /dev/null +++ b/config/file/config.example.yaml @@ -0,0 +1,14 @@ +app: + port: 3004 + debug: true + +database: + host: local-db + port: 5432 + name: johnjud_db + username: root + password: root + +s3: + bucket_name: + region: \ No newline at end of file From c2cc6f520e1803bd583153a7fad35da2ccb032cb Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Thu, 4 Jan 2024 19:30:52 +0700 Subject: [PATCH 45/48] feat: compose add file srv --- docker-compose.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docker-compose.yaml b/docker-compose.yaml index 2ddebae..ee154f3 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,6 +1,18 @@ version: "3.9" services: + local-file: + image: ghcr.io/isd-sgcu/johnjud-file + platform: linux/amd64 + container_name: file + depends_on: + - local-db + restart: unless-stopped + volumes: + - ./config/file:/app/config + ports: + - "3004:3004" + local-db: image: postgres:15.1-alpine3.17 container_name: johnjud-local-db From b535a8913f7d504919c92521a38e18ca1f9f6aab Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Thu, 4 Jan 2024 19:37:04 +0700 Subject: [PATCH 46/48] fix: readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d808198..c65e037 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Johnjud is a pet adoption web application of the [CUVET For Animal Welfare Club] ### Installation 1. Clone this repo -2. Copy `config.example.yaml` in `config` and paste it in the same directory with `.example` removed from its name. +2. Copy every `config.example.yaml` in `config` and paste it in the same directory with `.example` removed from its name. 3. Run `go mod download` to download all the dependencies. From e77e8fc46ed5f5b58810d4d92b27e885c9de0db7 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Thu, 4 Jan 2024 20:51:11 +0700 Subject: [PATCH 47/48] fix: readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c65e037..f813ad7 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Johnjud is a pet adoption web application of the [CUVET For Animal Welfare Club] - golang - gRPC -- go-fiber +- postgresql ## Getting Started From d0ad27bf6a6849c33eedc676911b99a08641d32f Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Thu, 4 Jan 2024 21:06:24 +0700 Subject: [PATCH 48/48] fix: remove linux/amd64 --- docker-compose.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index ee154f3..707a72e 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -3,7 +3,6 @@ version: "3.9" services: local-file: image: ghcr.io/isd-sgcu/johnjud-file - platform: linux/amd64 container_name: file depends_on: - local-db