diff --git a/endpoint/phonebook.go b/endpoint/phonebook.go index 01dce31..e0fdebf 100644 --- a/endpoint/phonebook.go +++ b/endpoint/phonebook.go @@ -180,3 +180,19 @@ func MakeCheckReadiness(ctx context.Context, usecase usecase.Provider) endpoint. }, nil } } + +// MakeIsExistPhoneNumber ... +func MakeIsExistPhoneNumber(ctx context.Context, usecase usecase.Provider) endpoint.Endpoint { + return func(ctx context.Context, request interface{}) (response interface{}, err error) { + req := request.(*IsExistPhoneNumber) + + isExist, err := usecase.IsExistPhoneNumber(ctx, req.PhoneNumber) + if err != nil { + return nil, err + } + + return map[string]map[string]interface{}{ + "data": {"exist": isExist}, + }, nil + } +} diff --git a/endpoint/request.go b/endpoint/request.go index f0ae8ed..853c386 100644 --- a/endpoint/request.go +++ b/endpoint/request.go @@ -56,3 +56,8 @@ type PhoneNumber struct { PhoneNumber string `json:"phone_number"` Type string `json:"type"` } + +// IsExistPhoneNumber ... +type IsExistPhoneNumber struct { + PhoneNumber string `httpquery:"phone_number"` +} diff --git a/mocks/mock_phonebook.go b/mocks/mock_phonebook.go index 9567d43..d3c8c8d 100644 --- a/mocks/mock_phonebook.go +++ b/mocks/mock_phonebook.go @@ -182,6 +182,21 @@ func (mr *MockPhoneBookIMockRecorder) Insert(ctx, params interface{}) *gomock.Ca return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Insert", reflect.TypeOf((*MockPhoneBookI)(nil).Insert), ctx, params) } +// IsExistPhoneNumber mocks base method. +func (m *MockPhoneBookI) IsExistPhoneNumber(ctx context.Context, phone string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsExistPhoneNumber", ctx, phone) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsExistPhoneNumber indicates an expected call of IsExistPhoneNumber. +func (mr *MockPhoneBookIMockRecorder) IsExistPhoneNumber(ctx, phone interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsExistPhoneNumber", reflect.TypeOf((*MockPhoneBookI)(nil).IsExistPhoneNumber), ctx, phone) +} + // Update mocks base method. func (m *MockPhoneBookI) Update(ctx context.Context, params *model.UpdatePhonebook) error { m.ctrl.T.Helper() diff --git a/mocks/testcases/is_exist_phone_number.go b/mocks/testcases/is_exist_phone_number.go new file mode 100644 index 0000000..50477f1 --- /dev/null +++ b/mocks/testcases/is_exist_phone_number.go @@ -0,0 +1,56 @@ +package testcases + +import "errors" + +// ReponseIsExistPhone ... +type ReponseIsExistPhone struct { + Result bool + Error error +} + +// IsExistPhoneNumber ... +type IsExistPhoneNumber struct { + Description string + UsecaseParams string + RepositoryParams string + UsecaseResponse ReponseIsExistPhone + RepositoryResponse ReponseIsExistPhone +} + +// IsExistPhoneNumberData ... +var IsExistPhoneNumberData = []IsExistPhoneNumber{ + { + Description: "success_get_check_phone_number", + UsecaseParams: "022-1234", + RepositoryParams: "022-1234", + UsecaseResponse: ReponseIsExistPhone{ + Result: true, + Error: nil, + }, + RepositoryResponse: ReponseIsExistPhone{ + Result: true, + Error: nil, + }, + }, { + Description: "failed_check_phone_number", + UsecaseParams: "sample", + RepositoryParams: "sample", + UsecaseResponse: ReponseIsExistPhone{ + Result: false, + Error: errors.New("failed_check"), + }, + RepositoryResponse: ReponseIsExistPhone{ + Result: false, + Error: errors.New("failed_check"), + }, + }, +} + +// IsExistDescription ... +func IsExistDescription() []string { + var arr = []string{} + for _, data := range IsExistPhoneNumberData { + arr = append(arr, data.Description) + } + return arr +} diff --git a/repository/mysql/mysql.go b/repository/mysql/mysql.go index 1395a12..65ea8c9 100644 --- a/repository/mysql/mysql.go +++ b/repository/mysql/mysql.go @@ -238,3 +238,29 @@ func (r *PhonebookRepository) Delete(ctx context.Context, id int64) error { return nil } + +// IsExistPhoneNumber ... +func (r *PhonebookRepository) IsExistPhoneNumber(ctx context.Context, phone string) (bool, error) { + var query bytes.Buffer + var count int + var err error + + query.WriteString(` SELECT count(1) FROM sapawarga_db_development.phonebooks + WHERE JSON_CONTAINS(phone_numbers->'$[*].phone_number', json_array(?))`) + + if ctx != nil { + err = r.conn.GetContext(ctx, count, query.String(), phone) + } else { + err = r.conn.Get(count, query.String(), phone) + } + + if err != nil { + return false, err + } + + if count == 0 || err == sql.ErrNoRows { + return false, nil + } + + return true, nil +} diff --git a/repository/repository_interface.go b/repository/repository_interface.go index 48000ed..298ecd8 100644 --- a/repository/repository_interface.go +++ b/repository/repository_interface.go @@ -16,6 +16,7 @@ type PhoneBookI interface { GetLocationByID(ctx context.Context, id int64) (*model.Location, error) GetListPhonebookByLongLat(ctx context.Context, params *model.GetListRequest) ([]*model.PhoneBookResponse, error) GetListPhonebookByLongLatMeta(ctx context.Context, params *model.GetListRequest) (int64, error) + IsExistPhoneNumber(ctx context.Context, phone string) (bool, error) // Create section Insert(ctx context.Context, params *model.AddPhonebook) error // Update section diff --git a/transport/http/handler.go b/transport/http/handler.go index 50bcf53..9a1eceb 100644 --- a/transport/http/handler.go +++ b/transport/http/handler.go @@ -42,6 +42,7 @@ func MakeHTTPHandler(ctx context.Context, fs usecase.Provider, logger kitlog.Log processAdd := kithttp.NewServer(endpoint.MakeAddPhonebook(ctx, fs), decodeCreateRequest, encodeResponse, opts...) processUpdate := kithttp.NewServer(endpoint.MakeUpdatePhonebook(ctx, fs), decodeUpdateRequest, encodeResponse, opts...) processDelete := kithttp.NewServer(endpoint.MakeDeletePhonebook(ctx, fs), decodeGetByID, encodeResponse, opts...) + processIsExist := kithttp.NewServer(endpoint.MakeIsExistPhoneNumber(ctx, fs), decodeIsExist, encodeResponse, opts...) r := mux.NewRouter() @@ -51,6 +52,7 @@ func MakeHTTPHandler(ctx context.Context, fs usecase.Provider, logger kitlog.Log r.Handle("/phone-books/", processAdd).Methods(helper.HTTP_POST) r.Handle("/phone-books/{id}", processUpdate).Methods(helper.HTTP_PUT) r.Handle("/phone-books/{id}", processDelete).Methods(helper.HTTP_DELETE) + r.Handle("/phone-books/check-exist", processIsExist).Methods(helper.HTTP_GET) return r } @@ -122,6 +124,13 @@ func decodeUpdateRequest(ctx context.Context, r *http.Request) (interface{}, err return reqBody, nil } +func decodeIsExist(ctx context.Context, r *http.Request) (interface{}, error) { + phone := r.URL.Query().Get("phone_number") + + reqBody := &endpoint.IsExistPhoneNumber{PhoneNumber: phone} + return reqBody, nil +} + func decodeNoRequest(ctx context.Context, r *http.Request) (interface{}, error) { return r, nil } diff --git a/usecase/phonebook.go b/usecase/phonebook.go index bf66a20..368ace5 100644 --- a/usecase/phonebook.go +++ b/usecase/phonebook.go @@ -150,6 +150,18 @@ func (pb *PhoneBook) Delete(ctx context.Context, id int64) error { return nil } +// IsExistPhoneNumber ... +func (pb *PhoneBook) IsExistPhoneNumber(ctx context.Context, phone string) (bool, error) { + logger := kitlog.With(pb.logger, "method", "IsExistPhoneNumber") + isExist, err := pb.repo.IsExistPhoneNumber(ctx, phone) + if err != nil { + level.Error(logger).Log("error_is_exist", err) + return false, err + } + + return isExist, nil +} + // CheckHealthReadiness ... func (pb *PhoneBook) CheckHealthReadiness(ctx context.Context) error { logger := kitlog.With(pb.logger, "method", "CheckHealthReadiness") diff --git a/usecase/usecase_interface.go b/usecase/usecase_interface.go index 662c3f0..49067df 100644 --- a/usecase/usecase_interface.go +++ b/usecase/usecase_interface.go @@ -10,6 +10,7 @@ import ( type Provider interface { GetList(ctx context.Context, params *model.ParamsPhoneBook) (*model.PhoneBookWithMeta, error) GetDetail(ctx context.Context, id int64) (*model.PhonebookDetail, error) + IsExistPhoneNumber(ctx context.Context, phone string) (bool, error) Insert(ctx context.Context, params *model.AddPhonebook) error Update(ctx context.Context, params *model.UpdatePhonebook) error Delete(ctx context.Context, id int64) error diff --git a/usecase/usecase_test.go b/usecase/usecase_test.go index df6f506..8dec6aa 100644 --- a/usecase/usecase_test.go +++ b/usecase/usecase_test.go @@ -117,6 +117,7 @@ var _ = Describe("Phone Book", func() { } } + // CheckReadinessLogic ... var CheckReadinessLogic = func(idx int) { ctx := context.Background() data := testcases.CheckReadinessData[idx] @@ -128,14 +129,29 @@ var _ = Describe("Phone Book", func() { } } + // IsExistPhoneNumberLogic ... + var IsExistPhoneNumberLogic = func(idx int) { + ctx := context.Background() + data := testcases.IsExistPhoneNumberData[idx] + mockPhoneBookRepo.EXPECT().IsExistPhoneNumber(ctx, data.RepositoryParams).Return(data.RepositoryResponse.Result, data.RepositoryResponse.Error).Times(1) + isExist, err := phonebook.IsExistPhoneNumber(ctx, data.UsecaseParams) + if err != nil { + Expect(err).NotTo(BeNil()) + } else { + Expect(isExist).To(Equal(data.UsecaseResponse.Result)) + Expect(err).To(BeNil()) + } + } + // sort all function names var unitTestLogic = map[string]map[string]interface{}{ - "GetList": {"func": GetListLogic, "test_case_count": len(testcases.GetPhoneBookData), "desc": testcases.ListPhonebookDescription()}, - "GetDetail": {"func": GetDetailPhonebookLogic, "test_case_count": len(testcases.GetDetailPhonebookData), "desc": testcases.DetailPhonebookDescription()}, - "Insert": {"func": InsertPhonebookLogic, "test_case_count": len(testcases.InsertPhonebookTestcases), "desc": testcases.InsertPhonebookDescription()}, - "Update": {"func": UpdatePhonebookLogic, "test_case_count": len(testcases.UpdatePhonebookTestcases), "desc": testcases.UpdatePhonebookDescription()}, - "Delete": {"func": DeletePhonebookLogic, "test_case_count": len(testcases.DeletePhonebookTestcases), "desc": testcases.DeletePhonebookDescription()}, - "CheckReadiness": {"func": CheckReadinessLogic, "test_case_count": len(testcases.CheckReadinessData), "desc": testcases.CheckReadinessDescription()}, + "GetList": {"func": GetListLogic, "test_case_count": len(testcases.GetPhoneBookData), "desc": testcases.ListPhonebookDescription()}, + "GetDetail": {"func": GetDetailPhonebookLogic, "test_case_count": len(testcases.GetDetailPhonebookData), "desc": testcases.DetailPhonebookDescription()}, + "Insert": {"func": InsertPhonebookLogic, "test_case_count": len(testcases.InsertPhonebookTestcases), "desc": testcases.InsertPhonebookDescription()}, + "Update": {"func": UpdatePhonebookLogic, "test_case_count": len(testcases.UpdatePhonebookTestcases), "desc": testcases.UpdatePhonebookDescription()}, + "Delete": {"func": DeletePhonebookLogic, "test_case_count": len(testcases.DeletePhonebookTestcases), "desc": testcases.DeletePhonebookDescription()}, + "CheckReadiness": {"func": CheckReadinessLogic, "test_case_count": len(testcases.CheckReadinessData), "desc": testcases.CheckReadinessDescription()}, + "IsExistPhoneNumber": {"func": IsExistPhoneNumberLogic, "test_case_count": len(testcases.IsExistPhoneNumberData), "desc": testcases.IsExistDescription()}, } for _, val := range unitTestLogic {