From e051c0d2ee232d5214b78dfae0d3cfe42f84917a Mon Sep 17 00:00:00 2001 From: FaisalIqbal211 Date: Thu, 22 Feb 2024 20:36:33 +0500 Subject: [PATCH 1/3] added provider queries --- db/metrics.go | 18 +++++- db/structs.go | 1 + handlers/metrics.go | 8 +++ handlers/metrics_test.go | 134 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 158 insertions(+), 3 deletions(-) diff --git a/db/metrics.go b/db/metrics.go index 8e75479e6..827ea9b38 100644 --- a/db/metrics.go +++ b/db/metrics.go @@ -193,7 +193,14 @@ func (db database) GetBountiesByDateRange(r PaymentDateRange, re *http.Request) limitQuery = fmt.Sprintf("LIMIT %d OFFSET %d", limit, offset) } - query := `SELECT * FROM public.bounty WHERE created >= '` + r.StartDate + `' AND created <= '` + r.EndDate + `'` + var providerCondition string + if len(r.Providers) > 0 { + providerCondition = " AND owner_id IN ('" + strings.Join(r.Providers, "','") + "')" + } else { + providerCondition = "" + } + + query := `SELECT * FROM public.bounty WHERE created >= '` + r.StartDate + `' AND created <= '` + r.EndDate + `'` + providerCondition allQuery := query + " " + statusQuery + " " + orderQuery + " " + limitQuery b := []Bounty{} @@ -226,9 +233,16 @@ func (db database) GetBountiesByDateRangeCount(r PaymentDateRange, re *http.Requ statusQuery = "" } + var providerCondition string + if len(r.Providers) > 0 { + providerCondition = " AND owner_id IN ('" + strings.Join(r.Providers, "','") + "')" + } else { + providerCondition = "" + } + var count int64 - query := `SELECT COUNT(*) FROM public.bounty WHERE created >= '` + r.StartDate + `' AND created <= '` + r.EndDate + `'` + query := `SELECT COUNT(*) FROM public.bounty WHERE created >= '` + r.StartDate + `' AND created <= '` + r.EndDate + `'` + providerCondition allQuery := query + " " + statusQuery db.db.Raw(allQuery).Scan(&count) return count diff --git a/db/structs.go b/db/structs.go index 479548717..18997f43d 100644 --- a/db/structs.go +++ b/db/structs.go @@ -611,6 +611,7 @@ type PaymentDateRange struct { StartDate string `json:"start_date"` EndDate string `json:"end_date"` PaymentType PaymentType `json:"payment_type,omitempty"` + Providers []string `json:"providers,omitempty"` } type MemeChallenge struct { diff --git a/handlers/metrics.go b/handlers/metrics.go index e5b91d87e..286ee8de6 100644 --- a/handlers/metrics.go +++ b/handlers/metrics.go @@ -188,6 +188,8 @@ func (mh *metricHandler) MetricsBounties(w http.ResponseWriter, r *http.Request) return } + providers := r.URL.Query()["provider"] + request := db.PaymentDateRange{} body, err := io.ReadAll(r.Body) r.Body.Close() @@ -199,6 +201,8 @@ func (mh *metricHandler) MetricsBounties(w http.ResponseWriter, r *http.Request) return } + request.Providers = providers + metricBounties := mh.db.GetBountiesByDateRange(request, r) metricBountiesData := mh.GetMetricsBountiesData(metricBounties) @@ -216,6 +220,8 @@ func (mh *metricHandler) MetricsBountiesCount(w http.ResponseWriter, r *http.Req return } + providers := r.URL.Query()["provider"] + request := db.PaymentDateRange{} body, err := io.ReadAll(r.Body) r.Body.Close() @@ -227,6 +233,8 @@ func (mh *metricHandler) MetricsBountiesCount(w http.ResponseWriter, r *http.Req return } + request.Providers = providers + MetricsBountiesCount := mh.db.GetBountiesByDateRangeCount(request, r) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(MetricsBountiesCount) diff --git a/handlers/metrics_test.go b/handlers/metrics_test.go index 85eeb4dee..a69756ce1 100644 --- a/handlers/metrics_test.go +++ b/handlers/metrics_test.go @@ -10,11 +10,12 @@ import ( "testing" "fmt" + "time" + "github.com/stakwork/sphinx-tribes/auth" "github.com/stakwork/sphinx-tribes/db" mocks "github.com/stakwork/sphinx-tribes/mocks" "github.com/stretchr/testify/assert" - "time" ) func TestBountyMetrics(t *testing.T) { @@ -173,6 +174,109 @@ func TestMetricsBounties(t *testing.T) { assert.Equal(t, res[0].BountyDescription, "test bounty") assert.Equal(t, res[0].BountyCreated, int64(1112)) }) + + t.Run("should fetch bounties from db for selected providers", func(t *testing.T) { + db.RedisError = errors.New("redis not initialized") + rr := httptest.NewRecorder() + handler := http.HandlerFunc(mh.MetricsBounties) + dateRange := db.PaymentDateRange{ + StartDate: "1111", + EndDate: "2222", + Providers: []string{"provider1", "provider2", "provider3"}, + } + body, _ := json.Marshal(dateRange) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, "/boutnies", bytes.NewReader(body)) + if err != nil { + t.Fatal(err) + } + + // Provide multiple provider IDs in the request query parameters + req.URL.RawQuery = "provider=provider1&provider=provider2&provider=provider3" + + // Mock bounties data for multiple providers + bounties := []db.Bounty{ + { + ID: 1, + OwnerID: "provider1", + Price: 100, + Title: "bounty 1", + Description: "test bounty", + Created: 1112, + }, + { + ID: 2, + OwnerID: "provider1", + Price: 100, + Title: "bounty 2", + Description: "test bounty", + Created: 1112, + }, + { + ID: 3, + OwnerID: "provider2", + Price: 200, + Title: "bounty 3", + Description: "test bounty", + Created: 1113, + }, + { + ID: 4, + OwnerID: "provider2", + Price: 200, + Title: "bounty 4", + Description: "test bounty", + Created: 1113, + }, + { + ID: 5, + OwnerID: "provider3", + Price: 200, + Title: "bounty 5", + Description: "test bounty", + Created: 1113, + }, + { + ID: 6, + OwnerID: "provider3", + Price: 200, + Title: "bounty 6", + Description: "test bounty", + Created: 1113, + }, + } + // Mock the database call to return bounties for the selected providers + mockDb.On("GetBountiesByDateRange", dateRange, req).Return(bounties).Once() + mockDb.On("GetPersonByPubkey", "provider1").Return(db.Person{ID: 1}).Once() + mockDb.On("GetPersonByPubkey", "").Return(db.Person{}).Once() + mockDb.On("GetOrganizationByUuid", "").Return(db.Organization{}).Once() + mockDb.On("GetPersonByPubkey", "provider1").Return(db.Person{ID: 1}).Once() + mockDb.On("GetPersonByPubkey", "").Return(db.Person{}).Once() + mockDb.On("GetOrganizationByUuid", "").Return(db.Organization{}).Once() + mockDb.On("GetPersonByPubkey", "provider2").Return(db.Person{ID: 1}).Once() + mockDb.On("GetPersonByPubkey", "").Return(db.Person{}).Once() + mockDb.On("GetOrganizationByUuid", "").Return(db.Organization{}).Once() + mockDb.On("GetPersonByPubkey", "provider2").Return(db.Person{ID: 1}).Once() + mockDb.On("GetPersonByPubkey", "").Return(db.Person{}).Once() + mockDb.On("GetOrganizationByUuid", "").Return(db.Organization{}).Once() + mockDb.On("GetPersonByPubkey", "provider3").Return(db.Person{ID: 1}).Once() + mockDb.On("GetPersonByPubkey", "").Return(db.Person{}).Once() + mockDb.On("GetOrganizationByUuid", "").Return(db.Organization{}).Once() + mockDb.On("GetPersonByPubkey", "provider3").Return(db.Person{ID: 1}).Once() + mockDb.On("GetPersonByPubkey", "").Return(db.Person{}).Once() + mockDb.On("GetOrganizationByUuid", "").Return(db.Organization{}).Once() + + handler.ServeHTTP(rr, req) + + var res []db.BountyData + _ = json.Unmarshal(rr.Body.Bytes(), &res) + + assert.Equal(t, http.StatusOK, rr.Code) + + // Assert that the response contains bounties only from the selected providers + for _, bounty := range res { + assert.Contains(t, []string{"provider1", "provider2", "provider3"}, bounty.OwnerID) + } + }) } func TestMetricsBountiesCount(t *testing.T) { @@ -233,6 +337,34 @@ func TestMetricsBountiesCount(t *testing.T) { assert.Equal(t, http.StatusOK, rr.Code) assert.Equal(t, res, int64(100)) }) + + t.Run("should fetch bounties count within specified date range for selected providers", func(t *testing.T) { + db.RedisError = errors.New("redis not initialized") + rr := httptest.NewRecorder() + handler := http.HandlerFunc(mh.MetricsBountiesCount) + dateRange := db.PaymentDateRange{ + StartDate: "1111", + EndDate: "2222", + Providers: []string{"provider1"}, + } + body, _ := json.Marshal(dateRange) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, "/boutnies/count", bytes.NewReader(body)) + if err != nil { + t.Fatal(err) + } + + // Provide provider IDs in the request query parameters + req.URL.RawQuery = "provider=provider1" + + mockDb.On("GetBountiesByDateRangeCount", dateRange, req).Return(int64(50)).Once() + handler.ServeHTTP(rr, req) + + var res int64 + _ = json.Unmarshal(rr.Body.Bytes(), &res) + + assert.Equal(t, http.StatusOK, rr.Code) + assert.Equal(t, res, int64(50)) + }) } func TestConvertMetricsToCSV(t *testing.T) { From 6df920863f3398746c43be6bf94cdeb8a66ecf91 Mon Sep 17 00:00:00 2001 From: FaisalIqbal211 Date: Thu, 22 Feb 2024 22:28:26 +0500 Subject: [PATCH 2/3] Changes Addressed --- db/metrics.go | 20 ++++++++-------- db/structs.go | 1 - handlers/metrics.go | 8 ------- handlers/metrics_test.go | 52 +++------------------------------------- 4 files changed, 13 insertions(+), 68 deletions(-) diff --git a/db/metrics.go b/db/metrics.go index 827ea9b38..9a33bdbbe 100644 --- a/db/metrics.go +++ b/db/metrics.go @@ -161,6 +161,7 @@ func (db database) GetBountiesByDateRange(r PaymentDateRange, re *http.Request) open := keys.Get("Open") assingned := keys.Get("Assigned") paid := keys.Get("Paid") + providers := keys.Get("provider") orderQuery := "" limitQuery := "" @@ -193,11 +194,10 @@ func (db database) GetBountiesByDateRange(r PaymentDateRange, re *http.Request) limitQuery = fmt.Sprintf("LIMIT %d OFFSET %d", limit, offset) } - var providerCondition string - if len(r.Providers) > 0 { - providerCondition = " AND owner_id IN ('" + strings.Join(r.Providers, "','") + "')" - } else { - providerCondition = "" + providerCondition := "" + if len(providers) > 0 { + providerSlice := strings.Split(providers, ",") + providerCondition = " AND owner_id IN ('" + strings.Join(providerSlice, "','") + "')" } query := `SELECT * FROM public.bounty WHERE created >= '` + r.StartDate + `' AND created <= '` + r.EndDate + `'` + providerCondition @@ -213,6 +213,7 @@ func (db database) GetBountiesByDateRangeCount(r PaymentDateRange, re *http.Requ open := keys.Get("Open") assingned := keys.Get("Assigned") paid := keys.Get("Paid") + providers := keys.Get("provider") var statusConditions []string @@ -233,11 +234,10 @@ func (db database) GetBountiesByDateRangeCount(r PaymentDateRange, re *http.Requ statusQuery = "" } - var providerCondition string - if len(r.Providers) > 0 { - providerCondition = " AND owner_id IN ('" + strings.Join(r.Providers, "','") + "')" - } else { - providerCondition = "" + providerCondition := "" + if len(providers) > 0 { + providerSlice := strings.Split(providers, ",") + providerCondition = " AND owner_id IN ('" + strings.Join(providerSlice, "','") + "')" } var count int64 diff --git a/db/structs.go b/db/structs.go index 18997f43d..479548717 100644 --- a/db/structs.go +++ b/db/structs.go @@ -611,7 +611,6 @@ type PaymentDateRange struct { StartDate string `json:"start_date"` EndDate string `json:"end_date"` PaymentType PaymentType `json:"payment_type,omitempty"` - Providers []string `json:"providers,omitempty"` } type MemeChallenge struct { diff --git a/handlers/metrics.go b/handlers/metrics.go index 286ee8de6..e5b91d87e 100644 --- a/handlers/metrics.go +++ b/handlers/metrics.go @@ -188,8 +188,6 @@ func (mh *metricHandler) MetricsBounties(w http.ResponseWriter, r *http.Request) return } - providers := r.URL.Query()["provider"] - request := db.PaymentDateRange{} body, err := io.ReadAll(r.Body) r.Body.Close() @@ -201,8 +199,6 @@ func (mh *metricHandler) MetricsBounties(w http.ResponseWriter, r *http.Request) return } - request.Providers = providers - metricBounties := mh.db.GetBountiesByDateRange(request, r) metricBountiesData := mh.GetMetricsBountiesData(metricBounties) @@ -220,8 +216,6 @@ func (mh *metricHandler) MetricsBountiesCount(w http.ResponseWriter, r *http.Req return } - providers := r.URL.Query()["provider"] - request := db.PaymentDateRange{} body, err := io.ReadAll(r.Body) r.Body.Close() @@ -233,8 +227,6 @@ func (mh *metricHandler) MetricsBountiesCount(w http.ResponseWriter, r *http.Req return } - request.Providers = providers - MetricsBountiesCount := mh.db.GetBountiesByDateRangeCount(request, r) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(MetricsBountiesCount) diff --git a/handlers/metrics_test.go b/handlers/metrics_test.go index a69756ce1..eab6706a1 100644 --- a/handlers/metrics_test.go +++ b/handlers/metrics_test.go @@ -182,7 +182,6 @@ func TestMetricsBounties(t *testing.T) { dateRange := db.PaymentDateRange{ StartDate: "1111", EndDate: "2222", - Providers: []string{"provider1", "provider2", "provider3"}, } body, _ := json.Marshal(dateRange) req, err := http.NewRequestWithContext(ctx, http.MethodPost, "/boutnies", bytes.NewReader(body)) @@ -205,63 +204,19 @@ func TestMetricsBounties(t *testing.T) { }, { ID: 2, - OwnerID: "provider1", + OwnerID: "provider2", Price: 100, Title: "bounty 2", Description: "test bounty", Created: 1112, }, - { - ID: 3, - OwnerID: "provider2", - Price: 200, - Title: "bounty 3", - Description: "test bounty", - Created: 1113, - }, - { - ID: 4, - OwnerID: "provider2", - Price: 200, - Title: "bounty 4", - Description: "test bounty", - Created: 1113, - }, - { - ID: 5, - OwnerID: "provider3", - Price: 200, - Title: "bounty 5", - Description: "test bounty", - Created: 1113, - }, - { - ID: 6, - OwnerID: "provider3", - Price: 200, - Title: "bounty 6", - Description: "test bounty", - Created: 1113, - }, } // Mock the database call to return bounties for the selected providers mockDb.On("GetBountiesByDateRange", dateRange, req).Return(bounties).Once() mockDb.On("GetPersonByPubkey", "provider1").Return(db.Person{ID: 1}).Once() mockDb.On("GetPersonByPubkey", "").Return(db.Person{}).Once() mockDb.On("GetOrganizationByUuid", "").Return(db.Organization{}).Once() - mockDb.On("GetPersonByPubkey", "provider1").Return(db.Person{ID: 1}).Once() - mockDb.On("GetPersonByPubkey", "").Return(db.Person{}).Once() - mockDb.On("GetOrganizationByUuid", "").Return(db.Organization{}).Once() - mockDb.On("GetPersonByPubkey", "provider2").Return(db.Person{ID: 1}).Once() - mockDb.On("GetPersonByPubkey", "").Return(db.Person{}).Once() - mockDb.On("GetOrganizationByUuid", "").Return(db.Organization{}).Once() - mockDb.On("GetPersonByPubkey", "provider2").Return(db.Person{ID: 1}).Once() - mockDb.On("GetPersonByPubkey", "").Return(db.Person{}).Once() - mockDb.On("GetOrganizationByUuid", "").Return(db.Organization{}).Once() - mockDb.On("GetPersonByPubkey", "provider3").Return(db.Person{ID: 1}).Once() - mockDb.On("GetPersonByPubkey", "").Return(db.Person{}).Once() - mockDb.On("GetOrganizationByUuid", "").Return(db.Organization{}).Once() - mockDb.On("GetPersonByPubkey", "provider3").Return(db.Person{ID: 1}).Once() + mockDb.On("GetPersonByPubkey", "provider2").Return(db.Person{ID: 2}).Once() mockDb.On("GetPersonByPubkey", "").Return(db.Person{}).Once() mockDb.On("GetOrganizationByUuid", "").Return(db.Organization{}).Once() @@ -274,7 +229,7 @@ func TestMetricsBounties(t *testing.T) { // Assert that the response contains bounties only from the selected providers for _, bounty := range res { - assert.Contains(t, []string{"provider1", "provider2", "provider3"}, bounty.OwnerID) + assert.Contains(t, []string{"provider1", "provider2"}, bounty.OwnerID) } }) } @@ -345,7 +300,6 @@ func TestMetricsBountiesCount(t *testing.T) { dateRange := db.PaymentDateRange{ StartDate: "1111", EndDate: "2222", - Providers: []string{"provider1"}, } body, _ := json.Marshal(dateRange) req, err := http.NewRequestWithContext(ctx, http.MethodPost, "/boutnies/count", bytes.NewReader(body)) From 3de4da074a172ec188191684dacb257579267ded Mon Sep 17 00:00:00 2001 From: FaisalIqbal211 Date: Mon, 26 Feb 2024 19:29:42 +0500 Subject: [PATCH 3/3] accepted, comma-separated provider in UT --- handlers/metrics_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/handlers/metrics_test.go b/handlers/metrics_test.go index eab6706a1..7fc0de3f4 100644 --- a/handlers/metrics_test.go +++ b/handlers/metrics_test.go @@ -190,7 +190,7 @@ func TestMetricsBounties(t *testing.T) { } // Provide multiple provider IDs in the request query parameters - req.URL.RawQuery = "provider=provider1&provider=provider2&provider=provider3" + req.URL.RawQuery = "provider=provider1,provider2" // Mock bounties data for multiple providers bounties := []db.Bounty{