From d332cdecacaf6259ac89d7d0a6bdf85be342e9f6 Mon Sep 17 00:00:00 2001 From: dhanushcrueiso Date: Sun, 23 Feb 2025 11:47:46 +0530 Subject: [PATCH 1/4] cli started ,service layer logics needed to be added --- go.mod | 3 ++ internal/models/cahceinitialisor.go | 18 ++++++++ internal/models/distributor.go | 22 +++++++++ internal/service/interface.go | 9 ++++ internal/service/service.go | 1 + internal/store/interface.go | 11 +++++ internal/store/store.go | 70 +++++++++++++++++++++++++++++ internal/utils/csvreader.go | 58 ++++++++++++++++++++++++ main.go | 67 +++++++++++++++++++++++++++ 9 files changed, 259 insertions(+) create mode 100644 go.mod create mode 100644 internal/models/cahceinitialisor.go create mode 100644 internal/models/distributor.go create mode 100644 internal/service/interface.go create mode 100644 internal/service/service.go create mode 100644 internal/store/interface.go create mode 100644 internal/store/store.go create mode 100644 internal/utils/csvreader.go create mode 100644 main.go diff --git a/go.mod b/go.mod new file mode 100644 index 000000000..3f6099e06 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module challange2016 + +go 1.23.3 diff --git a/internal/models/cahceinitialisor.go b/internal/models/cahceinitialisor.go new file mode 100644 index 000000000..532ea651e --- /dev/null +++ b/internal/models/cahceinitialisor.go @@ -0,0 +1,18 @@ +package models + +type DistributionMaps struct { + CityMap map[string]*Location + ProvinceMap map[string]*Location + CountryMap map[string]*Location + Distributor map[string]*Distributor +} + +// factory function +func NewDistributionMaps() *DistributionMaps { + return &DistributionMaps{ + CityMap: make(map[string]*Location), + ProvinceMap: make(map[string]*Location), + CountryMap: make(map[string]*Location), + Distributor: make(map[string]*Distributor), + } +} diff --git a/internal/models/distributor.go b/internal/models/distributor.go new file mode 100644 index 000000000..08e275e9f --- /dev/null +++ b/internal/models/distributor.go @@ -0,0 +1,22 @@ +package models + +type Distributor struct { + Name string + Include []Location + Exclude []Location + ParentDistributor *string +} + +type Location struct { + City string + CityCode string + Province string + ProvinceCode string + Country string + CountryCode string +} + +type CheckPermission struct { + DistributorName *string + Loc *Location +} diff --git a/internal/service/interface.go b/internal/service/interface.go new file mode 100644 index 000000000..4b61f3c8b --- /dev/null +++ b/internal/service/interface.go @@ -0,0 +1,9 @@ +package service + +import "challange2016/internal/models" + +type Service interface { + AddDistributor(reqBody *models.Distributor) (*models.Distributor, error) + GetDistributorByName(distributorName *string) (*models.Distributor, error) + CheckDistributorPermission(reqBody models.CheckPermission) bool +} diff --git a/internal/service/service.go b/internal/service/service.go new file mode 100644 index 000000000..6d43c3366 --- /dev/null +++ b/internal/service/service.go @@ -0,0 +1 @@ +package service diff --git a/internal/store/interface.go b/internal/store/interface.go new file mode 100644 index 000000000..171a705b6 --- /dev/null +++ b/internal/store/interface.go @@ -0,0 +1,11 @@ +package store + +import "challange2016/internal/models" + +type Store interface { + AddDistributor(obj *models.Distributor) *models.Distributor + GetDistributorByName(distributorName string) *models.Distributor + GetLocationDetailsByCity(cityName string) *models.Location + GetLocationDetailsByProvince(province string) *models.Location + GetLocationDetailsByCountry(countryName string) *models.Location +} diff --git a/internal/store/store.go b/internal/store/store.go new file mode 100644 index 000000000..49f8db697 --- /dev/null +++ b/internal/store/store.go @@ -0,0 +1,70 @@ +package store + +import ( + "strings" + + "github.com/challenge2016/models" +) + +type store struct { + dMap *models.DistributionMaps +} + +func NewStore(dMap *models.DistributionMaps) *store { + return &store{ + dMap: dMap, + } +} + +func (s *store) AddDistributor(obj *models.Distributor) *models.Distributor { + // storing a distributor in a map + s.dMap.Distributor[obj.Name] = obj + + // get call + + return s.GetDistributorByName(ctx, reqBody.Name) +} + +func (s *store) GetDistributorByName(distributorName string) *models.Distributor { + distributorName = strings.ToUpper(distributorName) + + distributor, ok := s.dMap.Distributor[distributorName] + if !ok { + return nil + } + + return distributor +} + +func (s *store) GetLocationDetailsByCity(cityName string) *models.Location { + cityName = strings.ToUpper(cityName) + + loc, ok := s.dMap.CityMap[cityName] + if !ok { + return nil + } + + return loc +} + +func (s *store) GetLocationDetailsByProvince(province string) *models.Location { + province = strings.ToUpper(province) + + loc, ok := s.dMap.ProvinceMap[province] + if !ok { + return nil + } + + return loc +} + +func (s *store) GetLocationDetailsByCountry(countryName string) *models.Location { + countryName = strings.ToUpper(countryName) + + loc, ok := s.dMap.CountryMap[countryName] + if !ok { + return nil + } + + return loc +} diff --git a/internal/utils/csvreader.go b/internal/utils/csvreader.go new file mode 100644 index 000000000..dd394cb98 --- /dev/null +++ b/internal/utils/csvreader.go @@ -0,0 +1,58 @@ +package utils + +import ( + "challange2016/internal/models" + "encoding/csv" + "io" + "log" + "os" + "strings" +) + +func LoadCsvIntoLocalStores(storeMap *models.DistributionMaps, fileName string) error { + + // reading the csv file + reader, err := os.OpenFile(fileName, os.O_RDONLY, 0777) + if err != nil { + log.Println("Error in opening file, Err", err) + return err + } + + csvReader := csv.NewReader(reader) + + for { + record, err := csvReader.Read() + if err == io.EOF { + break + } + + if err != nil { + log.Printf("Err :%v", err) + return err + } + + if len(record) != 6 { + log.Println("Record length is less than 6") + } + + loc := models.Location{ + CityCode: record[0], + ProvinceCode: record[1], + CountryCode: record[2], + City: record[3], + Province: record[4], + Country: record[5], + } + + storeMap.CityMap[strings.ToUpper(loc.City)] = &loc + loc.City = "ALL" + loc.CityCode = "ALL" + storeMap.ProvinceMap[strings.ToUpper(loc.Province)] = &loc + loc.Province = "ALL" + loc.ProvinceCode = "ALL" + storeMap.CountryMap[strings.ToUpper(loc.Country)] = &loc + + } + + return nil +} diff --git a/main.go b/main.go new file mode 100644 index 000000000..edb2e020d --- /dev/null +++ b/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "bufio" + "challange2016/internal/models" + "challange2016/internal/store" + "challange2016/internal/utils" + "fmt" + "os" + "strings" +) + +func main() { + + storeMap := models.NewDistributionMaps() + + //pushing daat to cache + utils.LoadCsvIntoLocalStores(storeMap, "cities.csv") + + store := store.NewStore(storeMap) + svc := service.New(store) + + //cli inputs + scanner := bufio.NewScanner(os.Stdin) + + for { + fmt.Println("Choose an option:") + fmt.Println("1. Add new permission") + fmt.Println("2. Check permission") + fmt.Println("3. Exit") + + var option int + fmt.Scan(&option) + + switch option { + case 1: + var input, distributor string + var permissionType string + + fmt.Print("Enter distributor: ") + scanner.Scan() + distributor = scanner.Text() + var distributorobj models.Distributor + if strings.Contains(distributor, "<") { + + } + dList := strings.Split(distributor, "<") + + distributorobj.Name = dList[0] + distributorobj.ParentDistributor = dList[1] + // log.Println(awsutil.Prettify(distributor)) + + response, err := h.svc.AddDistributor(ctx, &distributorobj) + if err != nil { + ctx.JSON(httpPkg.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + + return + } + + case 2: + case 3: + os.Exit() + } + } +} From b9f62b6313f317901dc74bee5f56e62ddb672ae5 Mon Sep 17 00:00:00 2001 From: dhanushcrueiso Date: Sun, 23 Feb 2025 14:45:21 +0530 Subject: [PATCH 2/4] basic flow working --- internal/service/service.go | 157 ++++++++++++++++++++++++++++++++++++ internal/store/store.go | 5 +- main.go | 130 ++++++++++++++++++++++++----- 3 files changed, 270 insertions(+), 22 deletions(-) diff --git a/internal/service/service.go b/internal/service/service.go index 6d43c3366..af0a28b57 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -1 +1,158 @@ package service + +import ( + "challange2016/internal/models" + "challange2016/internal/store" + "errors" + "fmt" + "strings" +) + +type service struct { + store store.Store +} + +func New(store store.Store) *service { + return &service{ + store: store, + } +} + +func (s *service) AddDistributor(reqBody *models.Distributor) (*models.Distributor, error) { + fmt.Println("checking pas throgugh one") + reqBody.Name = strings.ToUpper(reqBody.Name) + + // check whether distributor already exist or not + distributor := s.store.GetDistributorByName(reqBody.Name) + if distributor != nil { + return nil, errors.New("distributor already exist") + } + + // initilise include fields + reqBody.Include = s.autoInitialiseFields(reqBody.Include) + + // initialise exclude fields + reqBody.Exclude = s.autoInitialiseFields(reqBody.Exclude) + + // if parentDistributor exist, assign exclude fields also + if reqBody.ParentDistributor != nil { + isAllowed := s.checkParentDistributorPermissions(reqBody) + if !isAllowed { + return nil, errors.New("Parent Distributor doesn't have permission to distribute these location") + } + + upperCaseName := strings.ToUpper(*reqBody.ParentDistributor) + reqBody.ParentDistributor = &upperCaseName + } + + // store layer call + response := s.store.AddDistributor(reqBody) + + return response, nil +} + +func (s *service) checkParentDistributorPermissions(distributor *models.Distributor) bool { + parentDistributor := s.store.GetDistributorByName(strings.ToUpper(*distributor.ParentDistributor)) + if parentDistributor == nil { + return false + } + + // check for include/exclude permission + for _, loc := range distributor.Include { + isIncludeAllowed := checkPermission(parentDistributor.Include, loc) + isExcludeAllowed := checkPermission(parentDistributor.Exclude, loc) + + if isExcludeAllowed || !isIncludeAllowed { + return false + } + } + + return true +} + +func (s *service) GetDistributorByName(distributorName *string) (*models.Distributor, error) { + if distributorName == nil || *distributorName == "" { + return nil, errors.New("empty distributor name value") + } + + *distributorName = strings.ToUpper(*distributorName) + + distributor := s.store.GetDistributorByName(*distributorName) + if distributor == nil { + return nil, errors.New("entity not found") + } + + return distributor, nil +} + +func (s *service) CheckDistributorPermission(reqBody models.CheckPermission) bool { + switch { + case reqBody.DistributorName == nil: + return false + case reqBody.Loc == nil: + return false + case reqBody.Loc.City == "" || reqBody.Loc.Province == "" || reqBody.Loc.Country == "": + return false + + } + + // retrive the distributor details + distributor := s.store.GetDistributorByName(strings.ToUpper(*reqBody.DistributorName)) + if distributor == nil { + return false + } + + // check for include location + isIncludeLoc := checkPermission(distributor.Include, *reqBody.Loc) + if !isIncludeLoc { + // return false - as it does have have permission to distribute + + return false + } + + // check for exclude permission + for { + isExcludeLoc := checkPermission(distributor.Exclude, *reqBody.Loc) + if isExcludeLoc { + return false + } + + // check for exlude permission + if distributor.ParentDistributor != nil { + distributor = s.store.GetDistributorByName(strings.ToUpper(*distributor.ParentDistributor)) + } else { + break + } + } + + return true +} + +func checkPermission(distributorLoc []models.Location, loc models.Location) bool { + // check for country + for _, dLoc := range distributorLoc { + if strings.EqualFold(dLoc.Country, loc.Country) { + if strings.EqualFold(dLoc.Province, loc.Province) || strings.EqualFold(dLoc.Province, "ALL") { + if strings.EqualFold(dLoc.City, loc.City) || strings.EqualFold(dLoc.City, "ALL") { + return true + } + } + } + } + + return false +} + +func (s *service) autoInitialiseFields(loc []models.Location) []models.Location { + for i := range loc { + if loc[i].City != "" { + loc[i] = *s.store.GetLocationDetailsByCity(loc[i].City) + } else if loc[i].Province != "" { + loc[i] = *s.store.GetLocationDetailsByProvince(loc[i].Province) + } else if loc[i].Country != "" { + loc[i] = *s.store.GetLocationDetailsByCountry(loc[i].Country) + } + } + + return loc +} diff --git a/internal/store/store.go b/internal/store/store.go index 49f8db697..2e4988146 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -1,9 +1,8 @@ package store import ( + "challange2016/internal/models" "strings" - - "github.com/challenge2016/models" ) type store struct { @@ -22,7 +21,7 @@ func (s *store) AddDistributor(obj *models.Distributor) *models.Distributor { // get call - return s.GetDistributorByName(ctx, reqBody.Name) + return s.GetDistributorByName(obj.Name) } func (s *store) GetDistributorByName(distributorName string) *models.Distributor { diff --git a/main.go b/main.go index edb2e020d..c9ac882aa 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "bufio" "challange2016/internal/models" + "challange2016/internal/service" "challange2016/internal/store" "challange2016/internal/utils" "fmt" @@ -30,38 +31,129 @@ func main() { fmt.Println("3. Exit") var option int - fmt.Scan(&option) - + _, err := fmt.Scan(&option) + if err != nil { + fmt.Println("Error reading option:", err) + continue + } + scanner.Scan() switch option { case 1: - var input, distributor string - var permissionType string + fmt.Println("reached check one") + var dist string + //var permissionType string + //var input string fmt.Print("Enter distributor: ") - scanner.Scan() - distributor = scanner.Text() + scanner.Scan() // This waits for the user input + dist = scanner.Text() + dist = strings.TrimSpace(dist) var distributorobj models.Distributor - if strings.Contains(distributor, "<") { + if strings.Contains(dist, "<") { + dList := strings.Split(dist, "<") + + distributorobj.Name = dList[0] + distributorobj.ParentDistributor = &dList[1] + + } else { + distributorobj.Name = dist } - dList := strings.Split(distributor, "<") - distributorobj.Name = dList[0] - distributorobj.ParentDistributor = dList[1] - // log.Println(awsutil.Prettify(distributor)) + fmt.Print("Enter Inclisions and Exclusions and EXIT for exiting the input loop: ") + var includes []models.Location + var excludes []models.Location + for { + var permission string + scanner.Scan() // This waits for the user input + permission = scanner.Text() + permission = strings.TrimSpace(permission) + if permission == "EXIT" { + distributorobj.Include = includes + distributorobj.Exclude = excludes + break + } + partspermission := strings.Split(permission, ":") + if len(partspermission) != 2 { + fmt.Println("Invalid input format. Please use the format 'INCLUDE: COUNTRY-PROVINCE-CITY EXCLUDE: COUNTRY-PROVINCE-CITY'.") + continue + } + permissionTypeStr := strings.TrimSpace(partspermission[0]) + input := strings.TrimSpace(partspermission[1]) + parts := strings.Split(input, "-") + if len(parts) == 1 { + fmt.Println("checking pas throgugh one") + country := strings.ToUpper(parts[0]) + tempLocation := models.Location{ + Country: country, + } - response, err := h.svc.AddDistributor(ctx, &distributorobj) - if err != nil { - ctx.JSON(httpPkg.StatusBadRequest, gin.H{ - "error": err.Error(), - }) + if permissionTypeStr == "INCLUDE" { + fmt.Println("checking pas throgugh one") + includes = append(includes, tempLocation) + } else if permissionTypeStr == "EXCLUDE" { + excludes = append(excludes, tempLocation) + } - return - } + } else if len(parts) == 2 { + province, country := strings.ToUpper(parts[0]), strings.ToUpper(parts[1]) + tempLocation := models.Location{ + Country: country, + Province: province, + } + + if permissionTypeStr == "INCLUDE" { + includes = append(includes, tempLocation) + } else if permissionTypeStr == "EXCLUDE" { + excludes = append(excludes, tempLocation) + } + + } else if len(parts) == 3 { + city, province, country := strings.ToUpper(parts[0]), strings.ToUpper(parts[1]), strings.ToUpper(parts[2]) + tempLocation := models.Location{ + Country: country, + Province: province, + City: city, + } + + if permissionTypeStr == "INCLUDE" { + includes = append(includes, tempLocation) + } else if permissionTypeStr == "EXCLUDE" { + excludes = append(excludes, tempLocation) + } + } else { + fmt.Println("Invalid String. Please enter this way country, province-country, city-province-country") + continue + } + } + fmt.Println("obj", distributorobj) + response, err := svc.AddDistributor(&distributorobj) + if err != nil { + fmt.Println(err) + } + fmt.Println("response", response) case 2: + var distributorName string + _, err := fmt.Scan(&distributorName) + if err != nil { + fmt.Println("Error reading option:", err) + continue + } + distributor, err := svc.GetDistributorByName(&distributorName) + if err != nil && err.Error() == "entity not found" { + return + } + fmt.Println("distributor name", distributor) case 3: - os.Exit() + for k, v := range storeMap.Distributor { + fmt.Println("distributor maps", k) + fmt.Println("distributor maps", v) + } + + os.Exit(0) + default: + fmt.Println("Invalid option. Please choose 1, 2, or 3.") } } } From da4c8bbaa98ea96c073addf105860327a11248db Mon Sep 17 00:00:00 2001 From: dhanushcrueiso Date: Sun, 23 Feb 2025 23:50:02 +0530 Subject: [PATCH 3/4] tested all --- internal/service/service.go | 21 ++++++++++++------- internal/store/store.go | 2 -- internal/utils/csvreader.go | 36 ++++++++++++++++++++++++------- main.go | 42 ++++++++++++++++++++++++++++++------- 4 files changed, 77 insertions(+), 24 deletions(-) diff --git a/internal/service/service.go b/internal/service/service.go index af0a28b57..abfc356ad 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -27,26 +27,28 @@ func (s *service) AddDistributor(reqBody *models.Distributor) (*models.Distribut if distributor != nil { return nil, errors.New("distributor already exist") } - + fmt.Println("checking pas throgugh two", reqBody.Include) // initilise include fields - reqBody.Include = s.autoInitialiseFields(reqBody.Include) - + reqBody.Include = s.AutoInitialiseFields(reqBody.Include) + fmt.Println("checking pas throgugh three", reqBody.Exclude) // initialise exclude fields - reqBody.Exclude = s.autoInitialiseFields(reqBody.Exclude) - + reqBody.Exclude = s.AutoInitialiseFields(reqBody.Exclude) + fmt.Println("checking pas throgugh four") // if parentDistributor exist, assign exclude fields also if reqBody.ParentDistributor != nil { + fmt.Println("checking pas throgugh four-1") isAllowed := s.checkParentDistributorPermissions(reqBody) if !isAllowed { return nil, errors.New("Parent Distributor doesn't have permission to distribute these location") } - + fmt.Println("checking pas throgugh four-2") upperCaseName := strings.ToUpper(*reqBody.ParentDistributor) reqBody.ParentDistributor = &upperCaseName } - + fmt.Println("checking pas throgugh five") // store layer call response := s.store.AddDistributor(reqBody) + fmt.Println("checking pas throgugh six") return response, nil } @@ -143,13 +145,16 @@ func checkPermission(distributorLoc []models.Location, loc models.Location) bool return false } -func (s *service) autoInitialiseFields(loc []models.Location) []models.Location { +func (s *service) AutoInitialiseFields(loc []models.Location) []models.Location { for i := range loc { + if loc[i].City != "" { loc[i] = *s.store.GetLocationDetailsByCity(loc[i].City) } else if loc[i].Province != "" { + loc[i] = *s.store.GetLocationDetailsByProvince(loc[i].Province) } else if loc[i].Country != "" { + loc[i] = *s.store.GetLocationDetailsByCountry(loc[i].Country) } } diff --git a/internal/store/store.go b/internal/store/store.go index 2e4988146..3768809bb 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -48,12 +48,10 @@ func (s *store) GetLocationDetailsByCity(cityName string) *models.Location { func (s *store) GetLocationDetailsByProvince(province string) *models.Location { province = strings.ToUpper(province) - loc, ok := s.dMap.ProvinceMap[province] if !ok { return nil } - return loc } diff --git a/internal/utils/csvreader.go b/internal/utils/csvreader.go index dd394cb98..535cdd858 100644 --- a/internal/utils/csvreader.go +++ b/internal/utils/csvreader.go @@ -44,15 +44,37 @@ func LoadCsvIntoLocalStores(storeMap *models.DistributionMaps, fileName string) Country: record[5], } - storeMap.CityMap[strings.ToUpper(loc.City)] = &loc - loc.City = "ALL" - loc.CityCode = "ALL" - storeMap.ProvinceMap[strings.ToUpper(loc.Province)] = &loc - loc.Province = "ALL" - loc.ProvinceCode = "ALL" - storeMap.CountryMap[strings.ToUpper(loc.Country)] = &loc + //was not settting it prooperly + // storeMap.CityMap[strings.ToUpper(loc.City)] = &loc + // loc.City = "ALL" + // loc.CityCode = "ALL" + // storeMap.ProvinceMap[strings.ToUpper(loc.Province)] = &loc + // loc.Province = "ALL" + // loc.ProvinceCode = "ALL" + // storeMap.CountryMap[strings.ToUpper(loc.Country)] = &loc + setCityMap(storeMap, loc) + setProvinceMap(storeMap, loc) + setCountryMap(storeMap, loc) } return nil } + +func setCityMap(dMap *models.DistributionMaps, loc models.Location) { + dMap.CityMap[strings.ToUpper(loc.City)] = &loc +} + +func setProvinceMap(dMap *models.DistributionMaps, loc models.Location) { + loc.City = "ALL" + loc.CityCode = "ALL" + dMap.ProvinceMap[strings.ToUpper(loc.Province)] = &loc +} + +func setCountryMap(dMap *models.DistributionMaps, loc models.Location) { + loc.City = "ALL" + loc.CityCode = "ALL" + loc.Province = "ALL" + loc.ProvinceCode = "ALL" + dMap.CountryMap[strings.ToUpper(loc.Country)] = &loc +} diff --git a/main.go b/main.go index c9ac882aa..f53781a12 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "challange2016/internal/store" "challange2016/internal/utils" "fmt" + "log" "os" "strings" ) @@ -27,8 +28,9 @@ func main() { for { fmt.Println("Choose an option:") fmt.Println("1. Add new permission") - fmt.Println("2. Check permission") - fmt.Println("3. Exit") + fmt.Println("2. Get Distributor With Name") + fmt.Println("3. Check Distributor Permission") + fmt.Println("4. Exit") var option int _, err := fmt.Scan(&option) @@ -60,10 +62,11 @@ func main() { } - fmt.Print("Enter Inclisions and Exclusions and EXIT for exiting the input loop: ") var includes []models.Location var excludes []models.Location for { + fmt.Println("Enter Inclisions and Exclusions : ") + fmt.Println("Enter Exit to exit") var permission string scanner.Scan() // This waits for the user input permission = scanner.Text() @@ -106,6 +109,7 @@ func main() { includes = append(includes, tempLocation) } else if permissionTypeStr == "EXCLUDE" { excludes = append(excludes, tempLocation) + log.Println("check", excludes) } } else if len(parts) == 3 { @@ -127,11 +131,12 @@ func main() { } } - fmt.Println("obj", distributorobj) + fmt.Println("obj") response, err := svc.AddDistributor(&distributorobj) if err != nil { fmt.Println(err) } + fmt.Println("checking pas throgugh seven") fmt.Println("response", response) case 2: var distributorName string @@ -146,11 +151,34 @@ func main() { } fmt.Println("distributor name", distributor) case 3: - for k, v := range storeMap.Distributor { - fmt.Println("distributor maps", k) - fmt.Println("distributor maps", v) + var permission string + scanner.Scan() // This waits for the user input + permission = scanner.Text() + permission = strings.TrimSpace(permission) + partspermission := strings.Split(permission, ":") + if len(partspermission) != 2 { + fmt.Println("Invalid input format. Please use the format 'NAME: City-PROVINCE-Country.") + continue + } + name := partspermission[0] + parts := strings.Split(partspermission[1], "-") + if len(parts) != 3 { + fmt.Println("invallid input format") + break + } + loc := models.Location{ + City: parts[0], + Country: parts[2], + Province: parts[1], + } + checkPermission := models.CheckPermission{ + DistributorName: &name, + Loc: &loc, } + response := svc.CheckDistributorPermission(checkPermission) + fmt.Println("response", response) + case 4: os.Exit(0) default: fmt.Println("Invalid option. Please choose 1, 2, or 3.") From 2e2d6a903245d0976030b3d664597f112ec99216 Mon Sep 17 00:00:00 2001 From: dhanushcrueiso Date: Wed, 26 Feb 2025 19:46:22 +0530 Subject: [PATCH 4/4] missing tests --- HowToRun.md | 27 +++++++++++++++++++++++++ internal/service/interface.go | 2 +- internal/service/service.go | 26 +++++++++--------------- main.go | 37 +++++++++++++++++++++++------------ 4 files changed, 61 insertions(+), 31 deletions(-) create mode 100644 HowToRun.md diff --git a/HowToRun.md b/HowToRun.md new file mode 100644 index 000000000..3e021adf3 --- /dev/null +++ b/HowToRun.md @@ -0,0 +1,27 @@ +Find the Below Example Commands For Each of the Following : + +User Flow + +Choose an option: +1. Add new permission +2. Get Distributor With Name +3. Check Distributor Permission +4. Exit + +Addding single distributor: + +1. slect option one after initial promt (1) +2. Add distributor name and click enter(distributor1) +3. Add permissions as many as you want and if you want to exit enter EXIT(EXIT) +4. then you can check the distributor by selecting option 2 (2) +5. enter the distributor name and it will fetch all the details +6. checking individual region permissions select option (3) +7. Enter Distributor Name +8. enter the permissons with format (NAME : CITY-PROVINCE_COUNTRY)exqample (distributor1) + + +For Adding PArent Child Distributor: + +All the things follow same flow +only while adding names : Child < Parent +this is the only change diff --git a/internal/service/interface.go b/internal/service/interface.go index 4b61f3c8b..272e57e10 100644 --- a/internal/service/interface.go +++ b/internal/service/interface.go @@ -5,5 +5,5 @@ import "challange2016/internal/models" type Service interface { AddDistributor(reqBody *models.Distributor) (*models.Distributor, error) GetDistributorByName(distributorName *string) (*models.Distributor, error) - CheckDistributorPermission(reqBody models.CheckPermission) bool + CheckDistributorPermission(distributorName *string, reqBody models.CheckPermission) bool } diff --git a/internal/service/service.go b/internal/service/service.go index abfc356ad..a390a5959 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -4,7 +4,6 @@ import ( "challange2016/internal/models" "challange2016/internal/store" "errors" - "fmt" "strings" ) @@ -19,7 +18,6 @@ func New(store store.Store) *service { } func (s *service) AddDistributor(reqBody *models.Distributor) (*models.Distributor, error) { - fmt.Println("checking pas throgugh one") reqBody.Name = strings.ToUpper(reqBody.Name) // check whether distributor already exist or not @@ -27,28 +25,21 @@ func (s *service) AddDistributor(reqBody *models.Distributor) (*models.Distribut if distributor != nil { return nil, errors.New("distributor already exist") } - fmt.Println("checking pas throgugh two", reqBody.Include) // initilise include fields reqBody.Include = s.AutoInitialiseFields(reqBody.Include) - fmt.Println("checking pas throgugh three", reqBody.Exclude) // initialise exclude fields reqBody.Exclude = s.AutoInitialiseFields(reqBody.Exclude) - fmt.Println("checking pas throgugh four") // if parentDistributor exist, assign exclude fields also if reqBody.ParentDistributor != nil { - fmt.Println("checking pas throgugh four-1") isAllowed := s.checkParentDistributorPermissions(reqBody) if !isAllowed { return nil, errors.New("Parent Distributor doesn't have permission to distribute these location") } - fmt.Println("checking pas throgugh four-2") upperCaseName := strings.ToUpper(*reqBody.ParentDistributor) reqBody.ParentDistributor = &upperCaseName } - fmt.Println("checking pas throgugh five") // store layer call response := s.store.AddDistributor(reqBody) - fmt.Println("checking pas throgugh six") return response, nil } @@ -58,8 +49,6 @@ func (s *service) checkParentDistributorPermissions(distributor *models.Distribu if parentDistributor == nil { return false } - - // check for include/exclude permission for _, loc := range distributor.Include { isIncludeAllowed := checkPermission(parentDistributor.Include, loc) isExcludeAllowed := checkPermission(parentDistributor.Exclude, loc) @@ -87,7 +76,7 @@ func (s *service) GetDistributorByName(distributorName *string) (*models.Distrib return distributor, nil } -func (s *service) CheckDistributorPermission(reqBody models.CheckPermission) bool { +func (s *service) CheckDistributorPermission(distributorName *string, reqBody models.CheckPermission) bool { switch { case reqBody.DistributorName == nil: return false @@ -98,13 +87,16 @@ func (s *service) CheckDistributorPermission(reqBody models.CheckPermission) boo } - // retrive the distributor details - distributor := s.store.GetDistributorByName(strings.ToUpper(*reqBody.DistributorName)) - if distributor == nil { + if distributorName == nil || *distributorName == "" { return false } - // check for include location + *distributorName = strings.ToUpper(*distributorName) + + distributor := s.store.GetDistributorByName(*distributorName) + if distributor == nil { + return false + } isIncludeLoc := checkPermission(distributor.Include, *reqBody.Loc) if !isIncludeLoc { // return false - as it does have have permission to distribute @@ -116,6 +108,7 @@ func (s *service) CheckDistributorPermission(reqBody models.CheckPermission) boo for { isExcludeLoc := checkPermission(distributor.Exclude, *reqBody.Loc) if isExcludeLoc { + return false } @@ -131,7 +124,6 @@ func (s *service) CheckDistributorPermission(reqBody models.CheckPermission) boo } func checkPermission(distributorLoc []models.Location, loc models.Location) bool { - // check for country for _, dLoc := range distributorLoc { if strings.EqualFold(dLoc.Country, loc.Country) { if strings.EqualFold(dLoc.Province, loc.Province) || strings.EqualFold(dLoc.Province, "ALL") { diff --git a/main.go b/main.go index f53781a12..bdf082116 100644 --- a/main.go +++ b/main.go @@ -71,7 +71,7 @@ func main() { scanner.Scan() // This waits for the user input permission = scanner.Text() permission = strings.TrimSpace(permission) - if permission == "EXIT" { + if strings.ToUpper(permission) == "EXIT" { distributorobj.Include = includes distributorobj.Exclude = excludes break @@ -151,6 +151,19 @@ func main() { } fmt.Println("distributor name", distributor) case 3: + var distributorName string + _, err := fmt.Scan(&distributorName) + if err != nil { + fmt.Println("Error reading option:", err) + + } + //distributor, _ := svc.GetDistributorByName(&distributorName) + + bufio.NewReader(os.Stdin).ReadString('\n') + fmt.Println("Enter Distributor Name to Check Permissions") + scanner := bufio.NewScanner(os.Stdin) + //fmt.Println("distributor name", distributor) + var permission string scanner.Scan() // This waits for the user input permission = scanner.Text() @@ -166,18 +179,16 @@ func main() { fmt.Println("invallid input format") break } - loc := models.Location{ - City: parts[0], - Country: parts[2], - Province: parts[1], - } - checkPermission := models.CheckPermission{ - DistributorName: &name, - Loc: &loc, - } - - response := svc.CheckDistributorPermission(checkPermission) - fmt.Println("response", response) + var loc models.Location + + loc.City = parts[0] + loc.Province = parts[1] + loc.Country = parts[2] + var checkPermission models.CheckPermission + checkPermission.DistributorName = &name + checkPermission.Loc = &loc + response := svc.CheckDistributorPermission(&distributorName, checkPermission) + fmt.Println("Can Distribute", response) case 4: os.Exit(0) default: