diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92254c6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +.env \ No newline at end of file diff --git a/client.go b/client.go index b78df39..651955e 100644 --- a/client.go +++ b/client.go @@ -1,7 +1,9 @@ package mpsdkgo import ( + "encoding/json" "fmt" + "io" "log" "net/http" "net/http/httputil" @@ -10,6 +12,7 @@ import ( type ApiClient struct { cfg *Config Store *StoreService + Pos *PosService BaseURL string } @@ -24,6 +27,7 @@ func NewApiClient(cfg *Config) *ApiClient { } client.Store = NewStoreService(client) + client.Pos = NewPosService(client) return client @@ -56,3 +60,19 @@ func (c *ApiClient) callAPI(request *http.Request) (*http.Response, error) { } return resp, err } + +func (c *ApiClient) DeserializeBody(body io.Reader, obj any) error { + + b, err := io.ReadAll(body) + if err != nil { + return err + } + + err = json.Unmarshal(b, obj) + if err != nil { + return err + } + + return nil + +} diff --git a/go.mod b/go.mod index 061b7cc..d3057ab 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/vudu-people/mp-sdk-go go 1.20 + +require github.com/joho/godotenv v1.5.1 diff --git a/model/pos.go b/model/pos.go new file mode 100644 index 0000000..b7d225c --- /dev/null +++ b/model/pos.go @@ -0,0 +1,42 @@ +package model + +type QR struct { + Image string `json:"image"` + TemplateDocument string `json:"template_document"` + TemplateImage string `json:"template_image"` +} + +type Pos struct { + ID int `json:"id"` + QR QR `json:"qr"` + Status string `json:"status"` + DateCreated string `json:"date_created"` + DateLastUpdated string `json:"date_last_updated"` + UUID string `json:"uuid"` + UserID int `json:"user_id"` + Name string `json:"name"` + FixedAmount bool `json:"fixed_amount"` + Category int `json:"category"` + StoreID string `json:"store_id"` + ExternalID string `json:"external_id"` + Site string `json:"site"` + QrCode string `json:"qr_code"` +} + +type CreatePosRequest struct { + StoreID int `json:"store_id"` + Name string `json:"name"` + FixedAmount bool `json:"fixed_amount"` + Category int `json:"category"` + ExternalStoreID string `json:"external_store_id,omitempty"` + ExternalID string `json:"external_id,omitempty"` +} + +type GetAllPosResponse struct { + Paging struct { + Total int `json:"total"` + Offset int `json:"offset"` + Limit int `json:"limit"` + } `json:"paging"` + Results []Pos `json:"results"` +} diff --git a/model/store.go b/model/store.go index f9cd238..ccf249f 100644 --- a/model/store.go +++ b/model/store.go @@ -2,52 +2,38 @@ package model import "time" +type BusinessHourPair struct { + Open string `json:"open"` + Close string `json:"close"` +} + +type BusinessHours struct { + Monday []BusinessHourPair `json:"monday,omitempty"` + Tuesday []BusinessHourPair `json:"tuesday,omitempty"` + Wednesday []BusinessHourPair `json:"wednesday,omitempty"` + Thursday []BusinessHourPair `json:"thursday,omitempty"` + Friday []BusinessHourPair `json:"friday,omitempty"` + Saturday []BusinessHourPair `json:"saturday,omitempty"` + Sunday []BusinessHourPair `json:"sunday,omitempty"` +} + type CreateStoreRequest struct { - Name string `json:"name"` - BusinessHours struct { - Monday []struct { - Open string `json:"open"` - Close string `json:"close"` - } `json:"monday,omitempty"` - Tuesday []struct { - Open string `json:"open"` - Close string `json:"close"` - } `json:"tuesday,omitempty"` - Wednesday []struct { - Open string `json:"open"` - Close string `json:"close"` - } `json:"wednesday,omitempty"` - Thursday []struct { - Open string `json:"open"` - Close string `json:"close"` - } `json:"thursday,omitempty"` - Friday []struct { - Open string `json:"open"` - Close string `json:"close"` - } `json:"friday,omitempty"` - Saturday []struct { - Open string `json:"open"` - Close string `json:"close"` - } `json:"saturday,omitempty"` - Sunday []struct { - Open string `json:"open"` - Close string `json:"close"` - } `json:"sunday,omitempty"` - } `json:"business_hours"` - Location struct { - StreetNumber string `json:"street_number"` - StreetName string `json:"street_name"` - CityName string `json:"city_name"` - StateName string `json:"state_name"` - Latitude float64 `json:"latitude"` - Longitude float64 `json:"longitude"` - Reference string `json:"reference"` - } `json:"location"` - ExternalID string `json:"external_id"` + Name string `json:"name,omitempty"` + BusinessHours BusinessHours `json:"business_hours"` + Location struct { + StreetNumber string `json:"street_number,omitempty"` + StreetName string `json:"street_name,omitempty"` + CityName string `json:"city_name,omitempty"` + StateName string `json:"state_name,omitempty"` + Latitude float64 `json:"latitude,omitempty"` + Longitude float64 `json:"longitude,omitempty"` + Reference string `json:"reference,omitempty"` + } `json:"location,omitempty"` + ExternalID string `json:"external_id,omitempty"` } -type CreateStoreResponse struct { - ID int `json:"id"` +type Store struct { + ID string `json:"id"` Name string `json:"name"` DateCreated time.Time `json:"date_created"` BusinessHours struct { @@ -70,7 +56,7 @@ type CreateStoreResponse struct { } type GetStoreResponse struct { - CreateStoreResponse + Store } type UpdateStoreRequest struct { @@ -83,5 +69,5 @@ type GetStoresResponse struct { Offset int `json:"offset"` Limit int `json:"limit"` } `json:"paging"` - Results []CreateStoreResponse `json:"results"` + Results []Store `json:"results"` } diff --git a/pos_service.go b/pos_service.go new file mode 100644 index 0000000..daab5eb --- /dev/null +++ b/pos_service.go @@ -0,0 +1,185 @@ +package mpsdkgo + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + + "github.com/vudu-people/mp-sdk-go/model" +) + +type PosService struct { + client *ApiClient +} + +type IPosService interface { + CreatePos(request model.CreatePosRequest) (model.Pos, error) + GetPos(posID string) (model.Pos, error) + GetPosByExternalID(externalID string) (model.GetAllPosResponse, error) + GetAllPos(limit int) (model.GetAllPosResponse, error) + UpdatePos(posID string, request model.CreatePosRequest) (model.Pos, error) + DeletePos(posID string) error +} + +func NewPosService(client *ApiClient) *PosService { + return &PosService{client} +} + +func (s *PosService) CreatePos(body model.CreatePosRequest) (model.Pos, error) { + var ( + path = "%s/pos" + ) + + postBody, err := json.Marshal(body) + if err != nil { + return model.Pos{}, err + } + + url := fmt.Sprintf(path, s.client.BaseURL) + + req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(postBody)) + if err != nil { + return model.Pos{}, err + } + + r, err := s.client.callAPI(req) + if err != nil { + return model.Pos{}, err + } + + defer r.Body.Close() + + var response model.Pos + s.client.DeserializeBody(r.Body, &response) + + return response, nil + +} + +func (s *PosService) GetPos(posID string) (model.Pos, error) { + var ( + path = "%s/pos/%s" + ) + + url := fmt.Sprintf(path, s.client.BaseURL, posID) + + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return model.Pos{}, err + } + + r, err := s.client.callAPI(req) + if err != nil { + return model.Pos{}, err + } + + defer r.Body.Close() + + var response model.Pos + s.client.DeserializeBody(r.Body, &response) + + return response, nil +} + +func (s *PosService) GetPosByExternalID(externalID string) (model.GetAllPosResponse, error) { + var ( + path = "%s/pos?external_id=%s" + ) + + url := fmt.Sprintf(path, s.client.BaseURL, externalID) + + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return model.GetAllPosResponse{}, err + } + + r, err := s.client.callAPI(req) + if err != nil { + return model.GetAllPosResponse{}, err + } + + defer r.Body.Close() + + var response model.GetAllPosResponse + s.client.DeserializeBody(r.Body, &response) + + return response, nil +} + +func (s *PosService) GetAllPos(limit int) (model.GetAllPosResponse, error) { + var ( + path = "%s/pos?limit=%d" + ) + + url := fmt.Sprintf(path, s.client.BaseURL, limit) + + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return model.GetAllPosResponse{}, err + } + + r, err := s.client.callAPI(req) + if err != nil { + return model.GetAllPosResponse{}, err + } + + defer r.Body.Close() + + var response model.GetAllPosResponse + s.client.DeserializeBody(r.Body, &response) + + return response, nil +} + +func (s *PosService) UpdatePos(posID string, body model.CreatePosRequest) (model.Pos, error) { + + var ( + path = "%s/pos/%s" + ) + + postBody, err := json.Marshal(body) + if err != nil { + return model.Pos{}, err + } + + url := fmt.Sprintf(path, s.client.BaseURL, posID) + + req, err := http.NewRequest(http.MethodPut, url, bytes.NewReader(postBody)) + if err != nil { + return model.Pos{}, err + } + + r, err := s.client.callAPI(req) + if err != nil { + return model.Pos{}, err + } + + defer r.Body.Close() + + var response model.Pos + s.client.DeserializeBody(r.Body, &response) + + return response, nil + +} + +func (s *PosService) DeletePos(posID string) error { + var ( + path = "%s/pos/%s" + ) + + url := fmt.Sprintf(path, s.client.BaseURL, posID) + + req, err := http.NewRequest(http.MethodDelete, url, nil) + if err != nil { + return err + } + + _, err = s.client.callAPI(req) + if err != nil { + return err + } + + return nil +} diff --git a/store_service.go b/store_service.go index fc39987..36be8ed 100644 --- a/store_service.go +++ b/store_service.go @@ -15,6 +15,15 @@ type StoreService struct { client *ApiClient } +type IStoreService interface { + CreateStore(userID string, body model.CreateStoreRequest) (model.Store, error) + GetStore(storeID string) (model.GetStoreResponse, error) + GetStoreByExternalID(userID string, externalID string) (model.GetStoresResponse, error) + GetStores(userID string, limit int) (model.GetStoresResponse, error) + UpdateStore(userID string, storeID string, body model.UpdateStoreRequest) (model.Store, error) + DeleteStore(userID string, storeID string) error +} + func NewStoreService(client *ApiClient) *StoreService { return &StoreService{ client: client, @@ -22,27 +31,27 @@ func NewStoreService(client *ApiClient) *StoreService { } // CreateStore Create a store -func (s *StoreService) CreateStore(body model.CreateStoreRequest) (model.CreateStoreResponse, error) { +func (s *StoreService) CreateStore(userID string, body model.CreateStoreRequest) (model.Store, error) { var ( - path = "/stores" + path = "%s/users/%s/stores" ) postBody, err := json.Marshal(body) if err != nil { - return model.CreateStoreResponse{}, err + return model.Store{}, err } - url := fmt.Sprintf("%s%s", s.client.BaseURL, path) + url := fmt.Sprintf(path, s.client.BaseURL, userID) req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(postBody)) if err != nil { - return model.CreateStoreResponse{}, err + return model.Store{}, err } // request url r, err := s.client.callAPI(req) if err != nil { - return model.CreateStoreResponse{}, err + return model.Store{}, err } defer r.Body.Close() b, err := io.ReadAll(r.Body) @@ -50,7 +59,7 @@ func (s *StoreService) CreateStore(body model.CreateStoreRequest) (model.CreateS log.Fatalln(err) } - var response model.CreateStoreResponse + var response model.Store json.Unmarshal(b, &response) return response, nil @@ -77,43 +86,33 @@ func (s *StoreService) GetStore(storeID string) (model.GetStoreResponse, error) return model.GetStoreResponse{}, err } defer r.Body.Close() - b, err := io.ReadAll(r.Body) - if err != nil { - log.Fatalln(err) - } + var response model.GetStoreResponse - json.Unmarshal(b, &response) + s.client.DeserializeBody(r.Body, &response) return response, nil } // GetStore By External ID Get a store by external ID -func (s *StoreService) GetStoreByExternalID(userID string, externalID string) (model.GetStoreResponse, error) { +func (s *StoreService) GetStoreByExternalID(userID string, externalID string) (model.GetStoresResponse, error) { - var ( - path = "/stores/search?external_id=" - ) - - url := fmt.Sprintf("%susers/%s/%s/search?external_id=%s", s.client.BaseURL, userID, path, externalID) + url := fmt.Sprintf("%susers/%s/stores/search?external_id=%s", s.client.BaseURL, userID, externalID) req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { - return model.GetStoreResponse{}, err + return model.GetStoresResponse{}, err } // request url r, err := s.client.callAPI(req) if err != nil { - return model.GetStoreResponse{}, err + return model.GetStoresResponse{}, err } + defer r.Body.Close() - b, err := io.ReadAll(r.Body) - if err != nil { - log.Fatalln(err) - } - var response model.GetStoreResponse - json.Unmarshal(b, &response) + var response model.GetStoresResponse + s.client.DeserializeBody(r.Body, &response) return response, nil @@ -139,16 +138,67 @@ func (s *StoreService) GetStores(userID string, limit int) (model.GetStoresRespo return model.GetStoresResponse{}, err } - // read response body + var response model.GetStoresResponse + err = s.client.DeserializeBody(r.Body, &response) + if err != nil { + return model.GetStoresResponse{}, err + } defer r.Body.Close() - b, err := io.ReadAll(r.Body) + + return response, nil + +} + +func (s *StoreService) UpdateStore(userID string, storeID string, body model.UpdateStoreRequest) (model.Store, error) { + + var ( + path = "%s/users/%s/stores/%s" + ) + + url := fmt.Sprintf(path, s.client.BaseURL, userID, storeID) + + postBody, err := json.Marshal(body) if err != nil { - log.Fatalln(err) + return model.Store{}, err } - var response model.GetStoresResponse - json.Unmarshal(b, &response) + req, err := http.NewRequest(http.MethodPut, url, bytes.NewReader(postBody)) + if err != nil { + return model.Store{}, err + } + + r, err := s.client.callAPI(req) + if err != nil { + return model.Store{}, err + } + + defer r.Body.Close() + var response model.Store + s.client.DeserializeBody(r.Body, &response) return response, nil } + +func (s *StoreService) DeleteStore(userID string, storeID string) error { + + var ( + path = "%s/users/%s/stores/%s" + ) + + url := fmt.Sprintf(path, s.client.BaseURL, userID, storeID) + + req, err := http.NewRequest(http.MethodDelete, url, nil) + if err != nil { + return err + } + + // request url + _, err = s.client.callAPI(req) + if err != nil { + return err + } + + return nil + +}