diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 0000000..7748e23 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,13 @@ +## Change made + +- [ ]  New features +- [ ]  Bug fixes +- [ ]  Breaking changes +## Describe what you have done +- +### New Features +- +### Fix +- +### Others +- \ No newline at end of file diff --git a/go.mod b/go.mod index ade5ec4..80b2093 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.9 + github.com/isd-sgcu/johnjud-go-proto v0.3.0 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.31.0 github.com/spf13/viper v1.18.2 diff --git a/go.sum b/go.sum index fc7670b..7c1b4df 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.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.3.0 h1:UsAf2l06VypAp8nC5Ksru1QeoYwRjjxP/WKJwNOm1iY= +github.com/isd-sgcu/johnjud-go-proto v0.3.0/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/model/pet/pet.model.go b/src/app/model/pet/pet.model.go index 3c88a37..3b780cb 100644 --- a/src/app/model/pet/pet.model.go +++ b/src/app/model/pet/pet.model.go @@ -12,6 +12,8 @@ type Pet struct { Name string `json:"name" gorm:"tinytext"` Birthdate string `json:"birthdate" gorm:"tinytext"` Gender pet.Gender `json:"gender" gorm:"tinytext" example:"male"` + Color string `json:"color" gorm:"tinytext"` + Pattern string `json:"pattern" gorm:"tinytext"` Habit string `json:"habit" gorm:"mediumtext"` Caption string `json:"caption" gorm:"mediumtext"` Status pet.Status `json:"status" gorm:"mediumtext" example:"findhome"` @@ -19,7 +21,7 @@ type Pet struct { IsVaccinated bool `json:"is_vaccine"` IsVisible bool `json:"is_visible"` IsClubPet bool `json:"is_club_pet"` - Background string `json:"background" gorm:"tinytext"` + Origin string `json:"origin" 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/repository/pet/pet.repository.go b/src/app/repository/pet/pet.repository.go index 2ee80f1..0f72ae1 100644 --- a/src/app/repository/pet/pet.repository.go +++ b/src/app/repository/pet/pet.repository.go @@ -18,7 +18,7 @@ func (r *Repository) FindAll(result *[]*pet.Pet) error { } func (r *Repository) FindOne(id string, result *pet.Pet) error { - return r.db.Model(&pet.Pet{}).Find(result, "id = ?", id).Error + return r.db.Model(&pet.Pet{}).First(result, "id = ?", id).Error } func (r *Repository) Create(in *pet.Pet) error { diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 552f81b..7317841 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -66,9 +66,8 @@ func (s *Service) Update(_ context.Context, req *proto.UpdatePetRequest) (res *p if err != nil { return nil, status.Error(codes.Internal, "error querying image service") } - imageUrls := ExtractImageUrls(images) - return &proto.UpdatePetResponse{Pet: RawToDto(raw, imageUrls)}, nil + return &proto.UpdatePetResponse{Pet: RawToDto(raw, images)}, nil } func (s *Service) ChangeView(_ context.Context, req *proto.ChangeViewPetRequest) (res *proto.ChangeViewPetResponse, err error) { @@ -92,7 +91,7 @@ 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 + var imagesList [][]*image_proto.Image err = s.repository.FindAll(&pets) if err != nil { @@ -105,16 +104,15 @@ func (s *Service) FindAll(_ context.Context, req *proto.FindAllPetRequest) (res if err != nil { return nil, status.Error(codes.Internal, "error querying image service") } - imageUrls := ExtractImageUrls(images) - imageUrlsList = append(imageUrlsList, imageUrls) + imagesList = append(imagesList, images) } - petWithImageUrls, err := RawToDtoList(&pets, imageUrlsList) + petWithImages, err := RawToDtoList(&pets, imagesList) if err != nil { return nil, status.Error(codes.Internal, "error converting raw to dto list") } - return &proto.FindAllPetResponse{Pets: petWithImageUrls}, nil + return &proto.FindAllPetResponse{Pets: petWithImages}, nil } func (s Service) FindOne(_ context.Context, req *proto.FindOnePetRequest) (res *proto.FindOnePetResponse, err error) { @@ -131,9 +129,8 @@ func (s Service) FindOne(_ context.Context, req *proto.FindOnePetRequest) (res * if err != nil { return nil, status.Error(codes.Internal, "error querying image service") } - imageUrls := ExtractImageUrls(images) - return &proto.FindOnePetResponse{Pet: RawToDto(&pet, imageUrls)}, err + return &proto.FindOnePetResponse{Pet: RawToDto(&pet, images)}, err } func (s *Service) Create(_ context.Context, req *proto.CreatePetRequest) (res *proto.CreatePetResponse, err error) { @@ -142,14 +139,14 @@ func (s *Service) Create(_ context.Context, req *proto.CreatePetRequest) (res *p return nil, status.Error(codes.Internal, "error converting dto to raw: "+err.Error()) } - imgUrls := []string{} + images := []*image_proto.Image{} err = s.repository.Create(raw) if err != nil { return nil, status.Error(codes.Internal, "failed to create pet") } - return &proto.CreatePetResponse{Pet: RawToDto(raw, imgUrls)}, nil + return &proto.CreatePetResponse{Pet: RawToDto(raw, images)}, nil } func (s *Service) AdoptPet(ctx context.Context, req *proto.AdoptPetRequest) (res *proto.AdoptPetResponse, err error) { @@ -171,35 +168,37 @@ func (s *Service) AdoptPet(ctx context.Context, req *proto.AdoptPetRequest) (res return &proto.AdoptPetResponse{Success: true}, nil } -func RawToDtoList(in *[]*pet.Pet, imageUrls [][]string) ([]*proto.Pet, error) { +func RawToDtoList(in *[]*pet.Pet, images [][]*image_proto.Image) ([]*proto.Pet, error) { var result []*proto.Pet - if len(*in) != len(imageUrls) { + if len(*in) != len(images) { return nil, errors.New("length of in and imageUrls have to be the same") } for i, e := range *in { - result = append(result, RawToDto(e, imageUrls[i])) + result = append(result, RawToDto(e, images[i])) } return result, nil } -func RawToDto(in *pet.Pet, imgUrl []string) *proto.Pet { +func RawToDto(in *pet.Pet, images []*image_proto.Image) *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), + Gender: string(in.Gender), + Color: in.Color, + Pattern: in.Pattern, Habit: in.Habit, Caption: in.Caption, - Status: proto.PetStatus(in.Status), - ImageUrls: imgUrl, + Status: string(in.Status), + Images: images, IsSterile: in.IsSterile, IsVaccinated: in.IsVaccinated, IsVisible: in.IsVisible, IsClubPet: in.IsClubPet, - Background: in.Background, + Origin: in.Origin, Address: in.Address, Contact: in.Contact, AdoptBy: in.AdoptBy, @@ -219,16 +218,16 @@ func DtoToRaw(in *proto.Pet) (res *pet.Pet, err error) { } switch in.Gender { - case 0: + case string(petConst.MALE): gender = petConst.MALE - case 1: + case string(petConst.FEMALE): gender = petConst.FEMALE } switch in.Status { - case 0: + case string(petConst.ADOPTED): status = petConst.ADOPTED - case 1: + case string(petConst.FINDHOME): status = petConst.FINDHOME } @@ -244,6 +243,8 @@ func DtoToRaw(in *proto.Pet) (res *pet.Pet, err error) { Name: in.Name, Birthdate: in.Birthdate, Gender: gender, + Color: in.Color, + Pattern: in.Pattern, Habit: in.Habit, Caption: in.Caption, Status: status, @@ -251,7 +252,7 @@ func DtoToRaw(in *proto.Pet) (res *pet.Pet, err error) { IsVaccinated: in.IsVaccinated, IsVisible: in.IsVisible, IsClubPet: in.IsClubPet, - Background: in.Background, + Origin: in.Origin, Address: in.Address, Contact: in.Contact, AdoptBy: in.AdoptBy, diff --git a/src/app/service/pet/pet.service_test.go b/src/app/service/pet/pet.service_test.go index 04d36b9..a2167b9 100644 --- a/src/app/service/pet/pet.service_test.go +++ b/src/app/service/pet/pet.service_test.go @@ -37,9 +37,7 @@ type PetServiceTest struct { UpdatePetReqMock *proto.UpdatePetRequest ChangeViewPetReqMock *proto.ChangeViewPetRequest Images []*img_proto.Image - ImageUrls []string ImagesList [][]*img_proto.Image - ImageUrlsList [][]string ChangeAdoptBy *pet.Pet AdoptByReq *proto.AdoptPetRequest } @@ -50,6 +48,9 @@ func TestPetService(t *testing.T) { func (t *PetServiceTest) SetupTest() { var pets []*pet.Pet + genders := []petConst.Gender{petConst.MALE, petConst.FEMALE} + statuses := []petConst.Status{petConst.ADOPTED, petConst.FINDHOME} + for i := 0; i <= 3; i++ { pet := &pet.Pet{ Base: model.Base{ @@ -62,15 +63,17 @@ func (t *PetServiceTest) SetupTest() { Species: faker.Word(), Name: faker.Name(), Birthdate: faker.Word(), - Gender: petConst.Gender(rand.Intn(1) + 1), + Gender: genders[rand.Intn(2)], + Color: faker.Word(), + Pattern: faker.Word(), Habit: faker.Paragraph(), Caption: faker.Paragraph(), - Status: petConst.Status(rand.Intn(1) + 1), + Status: statuses[rand.Intn(2)], IsSterile: true, IsVaccinated: true, IsVisible: true, IsClubPet: true, - Background: faker.Paragraph(), + Origin: faker.Paragraph(), Address: faker.Paragraph(), Contact: faker.Paragraph(), AdoptBy: "", @@ -87,21 +90,12 @@ func (t *PetServiceTest) SetupTest() { imageUrls = append(imageUrls, url) } t.ImagesList = append(t.ImagesList, images) - t.ImageUrlsList = append(t.ImageUrlsList, imageUrls) pets = append(pets, pet) } t.Pets = pets t.Pet = pets[0] - - for _, images := range t.ImagesList { - for _, image := range images { - t.ImageUrls = append(t.ImageUrls, image.ImageUrl) - } - } - t.Images = t.ImagesList[0] - t.ImageUrls = t.ImageUrlsList[0] t.PetDto = &proto.Pet{ Id: t.Pet.ID.String(), @@ -109,18 +103,20 @@ func (t *PetServiceTest) SetupTest() { Species: t.Pet.Species, Name: t.Pet.Name, Birthdate: t.Pet.Birthdate, - Gender: proto.Gender(t.Pet.Gender), + Gender: string(t.Pet.Gender), + Color: t.Pet.Color, + Pattern: t.Pet.Pattern, Habit: t.Pet.Habit, Caption: t.Pet.Caption, - Status: proto.PetStatus(t.Pet.Status), + Status: string(t.Pet.Status), IsSterile: t.Pet.IsSterile, IsVaccinated: t.Pet.IsVaccinated, IsVisible: t.Pet.IsVisible, IsClubPet: t.Pet.IsClubPet, - Background: t.Pet.Background, + Origin: t.Pet.Origin, Address: t.Pet.Address, Contact: t.Pet.Contact, - ImageUrls: t.ImageUrls, + Images: t.Images, } t.UpdatePet = &pet.Pet{ @@ -135,6 +131,8 @@ func (t *PetServiceTest) SetupTest() { Name: t.Pet.Name, Birthdate: t.Pet.Birthdate, Gender: t.Pet.Gender, + Color: t.Pet.Color, + Pattern: t.Pet.Pattern, Habit: t.Pet.Habit, Caption: t.Pet.Caption, Status: t.Pet.Status, @@ -142,7 +140,7 @@ func (t *PetServiceTest) SetupTest() { IsVaccinated: t.Pet.IsVaccinated, IsVisible: t.Pet.IsVisible, IsClubPet: t.Pet.IsClubPet, - Background: t.Pet.Background, + Origin: t.Pet.Origin, Address: t.Pet.Address, Contact: t.Pet.Contact, } @@ -159,6 +157,8 @@ func (t *PetServiceTest) SetupTest() { Name: t.Pet.Name, Birthdate: t.Pet.Birthdate, Gender: t.Pet.Gender, + Color: t.Pet.Color, + Pattern: t.Pet.Pattern, Habit: t.Pet.Habit, Caption: t.Pet.Caption, Status: t.Pet.Status, @@ -166,7 +166,7 @@ func (t *PetServiceTest) SetupTest() { IsVaccinated: t.Pet.IsVaccinated, IsVisible: false, IsClubPet: t.Pet.IsClubPet, - Background: t.Pet.Background, + Origin: t.Pet.Origin, Address: t.Pet.Address, Contact: t.Pet.Contact, } @@ -177,16 +177,18 @@ func (t *PetServiceTest) SetupTest() { Species: t.Pet.Species, Name: t.Pet.Name, Birthdate: t.Pet.Birthdate, - Gender: proto.Gender(t.Pet.Gender), + Gender: string(t.Pet.Gender), + Color: t.Pet.Color, + Pattern: t.Pet.Pattern, Habit: t.Pet.Habit, Caption: t.Pet.Caption, - Status: proto.PetStatus(t.Pet.Status), - ImageUrls: t.ImageUrls, + Status: string(t.Pet.Status), + Images: t.Images, IsSterile: t.Pet.IsSterile, IsVaccinated: t.Pet.IsVaccinated, IsVisible: t.Pet.IsVaccinated, IsClubPet: t.Pet.IsClubPet, - Background: t.Pet.Background, + Origin: t.Pet.Origin, Address: t.Pet.Address, Contact: t.Pet.Contact, }, @@ -199,16 +201,18 @@ func (t *PetServiceTest) SetupTest() { Species: t.Pet.Species, Name: t.Pet.Name, Birthdate: t.Pet.Birthdate, - Gender: proto.Gender(t.Pet.Gender), + Gender: string(t.Pet.Gender), + Color: t.Pet.Color, + Pattern: t.Pet.Pattern, Habit: t.Pet.Habit, Caption: t.Pet.Caption, - Status: proto.PetStatus(t.Pet.Status), - ImageUrls: t.ImageUrls, + Status: string(t.Pet.Status), + Images: t.Images, IsSterile: t.Pet.IsSterile, IsVaccinated: t.Pet.IsVaccinated, IsVisible: t.Pet.IsVisible, IsClubPet: t.Pet.IsClubPet, - Background: t.Pet.Background, + Origin: t.Pet.Origin, Address: t.Pet.Address, Contact: t.Pet.Contact, }, @@ -231,6 +235,8 @@ func (t *PetServiceTest) SetupTest() { Name: t.Pet.Name, Birthdate: t.Pet.Birthdate, Gender: t.Pet.Gender, + Color: t.Pet.Color, + Pattern: t.Pet.Pattern, Habit: t.Pet.Habit, Caption: t.Pet.Caption, Status: t.Pet.Status, @@ -238,7 +244,7 @@ func (t *PetServiceTest) SetupTest() { IsVaccinated: t.Pet.IsVaccinated, IsVisible: t.Pet.IsVisible, IsClubPet: t.Pet.IsClubPet, - Background: t.Pet.Background, + Origin: t.Pet.Origin, Address: t.Pet.Address, Contact: t.Pet.Contact, AdoptBy: faker.UUIDDigit(), @@ -322,7 +328,7 @@ func (t *PetServiceTest) TestFindOneSuccess() { func (t *PetServiceTest) TestFindAllSuccess() { - want := &proto.FindAllPetResponse{Pets: t.createPetsDto(t.Pets, t.ImageUrlsList)} + want := &proto.FindAllPetResponse{Pets: t.createPetsDto(t.Pets, t.ImagesList)} var petsIn []*pet.Pet @@ -360,6 +366,8 @@ func (t *PetServiceTest) TestFindOneNotFound() { func createPets() []*pet.Pet { var result []*pet.Pet + genders := []petConst.Gender{petConst.MALE, petConst.FEMALE} + statuses := []petConst.Status{petConst.ADOPTED, petConst.FINDHOME} for i := 0; i < rand.Intn(4)+1; i++ { r := &pet.Pet{ @@ -373,15 +381,17 @@ func createPets() []*pet.Pet { Species: faker.Word(), Name: faker.Name(), Birthdate: faker.Word(), - Gender: petConst.Gender(rand.Intn(1) + 1), + Gender: genders[rand.Intn(2)], + Color: faker.Word(), + Pattern: faker.Word(), Habit: faker.Paragraph(), Caption: faker.Paragraph(), - Status: petConst.Status(rand.Intn(1) + 1), + Status: statuses[rand.Intn(2)], IsSterile: true, IsVaccinated: true, IsVisible: true, IsClubPet: true, - Background: faker.Paragraph(), + Origin: faker.Paragraph(), Address: faker.Paragraph(), Contact: faker.Paragraph(), } @@ -391,7 +401,7 @@ func createPets() []*pet.Pet { return result } -func (t *PetServiceTest) createPetsDto(in []*pet.Pet, imageUrlsList [][]string) []*proto.Pet { +func (t *PetServiceTest) createPetsDto(in []*pet.Pet, imagesList [][]*img_proto.Image) []*proto.Pet { var result []*proto.Pet for i, p := range in { @@ -401,16 +411,18 @@ func (t *PetServiceTest) createPetsDto(in []*pet.Pet, imageUrlsList [][]string) Species: p.Species, Name: p.Name, Birthdate: p.Birthdate, - Gender: proto.Gender(p.Gender), + Gender: string(p.Gender), + Color: p.Color, + Pattern: p.Pattern, Habit: p.Habit, Caption: p.Caption, - Status: proto.PetStatus(p.Status), - ImageUrls: imageUrlsList[i], + Status: string(p.Status), + Images: imagesList[i], IsSterile: p.IsSterile, IsVaccinated: p.IsVaccinated, IsVisible: p.IsVisible, IsClubPet: p.IsClubPet, - Background: p.Background, + Origin: p.Origin, Address: p.Address, Contact: p.Contact, } @@ -423,7 +435,7 @@ func (t *PetServiceTest) createPetsDto(in []*pet.Pet, imageUrlsList [][]string) func (t *PetServiceTest) TestCreateSuccess() { want := &proto.CreatePetResponse{Pet: t.PetDto} - want.Pet.ImageUrls = []string{} // when pet is first created, it has no images + want.Pet.Images = []*img_proto.Image{} // when pet is first created, it has no images repo := &mock.RepositoryMock{} @@ -433,6 +445,8 @@ func (t *PetServiceTest) TestCreateSuccess() { Name: t.Pet.Name, Birthdate: t.Pet.Birthdate, Gender: t.Pet.Gender, + Color: t.Pet.Color, + Pattern: t.Pet.Pattern, Habit: t.Pet.Habit, Caption: t.Pet.Caption, Status: t.Pet.Status, @@ -440,7 +454,7 @@ func (t *PetServiceTest) TestCreateSuccess() { IsVaccinated: t.Pet.IsVaccinated, IsVisible: t.Pet.IsVisible, IsClubPet: t.Pet.IsClubPet, - Background: t.Pet.Background, + Origin: t.Pet.Origin, Address: t.Pet.Address, Contact: t.Pet.Contact, } @@ -465,6 +479,8 @@ func (t *PetServiceTest) TestCreateInternalErr() { Name: t.Pet.Name, Birthdate: t.Pet.Birthdate, Gender: t.Pet.Gender, + Color: t.Pet.Color, + Pattern: t.Pet.Pattern, Habit: t.Pet.Habit, Caption: t.Pet.Caption, Status: t.Pet.Status, @@ -472,7 +488,7 @@ func (t *PetServiceTest) TestCreateInternalErr() { IsVaccinated: t.Pet.IsVaccinated, IsVisible: t.Pet.IsVisible, IsClubPet: t.Pet.IsClubPet, - Background: t.Pet.Background, + Origin: t.Pet.Origin, Address: t.Pet.Address, Contact: t.Pet.Contact, } diff --git a/src/constant/pet/pet.constant.go b/src/constant/pet/pet.constant.go index 577bed6..77e50c7 100644 --- a/src/constant/pet/pet.constant.go +++ b/src/constant/pet/pet.constant.go @@ -1,15 +1,15 @@ package pet -type Gender int +type Gender string const ( - MALE = 0 - FEMALE = 1 + MALE Gender = "male" + FEMALE Gender = "female" ) -type Status int +type Status string const ( - ADOPTED = 0 - FINDHOME = 1 + ADOPTED Status = "adopted" + FINDHOME Status = "findhome" ) diff --git a/src/mocks/image/image.mock.go b/src/mocks/image/image.mock.go index 19aba0d..d631497 100644 --- a/src/mocks/image/image.mock.go +++ b/src/mocks/image/image.mock.go @@ -32,6 +32,16 @@ func (c *ClientMock) FindByPetId(_ context.Context, in *proto.FindImageByPetIdRe return res, args.Error(1) } +func (c *ClientMock) AssignPet(_ context.Context, in *proto.AssignPetRequest, _ ...grpc.CallOption) (res *proto.AssignPetResponse, err error) { + args := c.Called(in) + + if args.Get(0) != nil { + res = args.Get(0).(*proto.AssignPetResponse) + } + + 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)