Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Operational learning stats API #2335

Merged

Conversation

sudip-khanal
Copy link
Contributor

@sudip-khanal sudip-khanal commented Dec 9, 2024

Addresses

Changes

  • Add ops-learning stats api
  • Add unit test

Checklist

Things that should succeed before merging.

  • Updated/ran unit tests
  • Updated CHANGELOG.md

Release

If there is a version update, make sure to tag the repository with the latest version.

@sudip-khanal sudip-khanal marked this pull request as draft December 9, 2024 06:27
@sudip-khanal sudip-khanal marked this pull request as ready for review December 9, 2024 06:36
@sudip-khanal sudip-khanal marked this pull request as draft December 9, 2024 08:06
Copy link

@sudan45 sudan45 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor Changes

per/test_views.py Outdated Show resolved Hide resolved
per/drf_views.py Outdated Show resolved Hide resolved
@samshara samshara changed the title Feature/ops learning stat api Operational learning stats API Dec 10, 2024
Copy link
Member

@susilnem susilnem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's Check the queries and remove duplicated queries.
mostly for country and region.

per/drf_views.py Outdated Show resolved Hide resolved
@sudip-khanal sudip-khanal force-pushed the feature/ops-learning-stat-api branch 2 times, most recently from 3e73ced to 4d61d3d Compare December 11, 2024 17:36
Copy link
Member

@susilnem susilnem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add some filter on it

per/drf_views.py Outdated Show resolved Hide resolved
per/drf_views.py Outdated Show resolved Hide resolved
per/drf_views.py Outdated Show resolved Hide resolved
per/drf_views.py Outdated Show resolved Hide resolved
per/drf_views.py Outdated Show resolved Hide resolved
@sudip-khanal sudip-khanal force-pushed the feature/ops-learning-stat-api branch from ad5e19a to c1245a6 Compare December 13, 2024 01:36
Add validated filter
@sudip-khanal sudip-khanal force-pushed the feature/ops-learning-stat-api branch from c1245a6 to 2a6d79f Compare December 16, 2024 03:23
per/test_views.py Outdated Show resolved Hide resolved
per/drf_views.py Outdated Show resolved Hide resolved
per/test_views.py Outdated Show resolved Hide resolved
per/test_views.py Outdated Show resolved Hide resolved
per/drf_views.py Outdated Show resolved Hide resolved
@susilnem susilnem force-pushed the feature/ops-learning-stat-api branch from 3c9dda6 to ca1c3d3 Compare December 17, 2024 10:39


class LearningSourcesOvertimeSerializer(serializers.Serializer):
type = serializers.IntegerField()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@susilnem Do we return type as integer or get display name for type? If no may be we need to do type = serializers.CharField(source='get_type_display', read_only=True) to get the type name.

Copy link
Member

@susilnem susilnem Dec 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, for now it's not required as it should be managed by the client side

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure about this? It will be complicated for the client side to do this mapping.

source='get_type_display' can't be used here, as the object will be a dict instead of a proper object. We could use serializer_method or do the enum->label in the views.

@susilnem susilnem force-pushed the feature/ops-learning-stat-api branch from 32c4d62 to afff697 Compare December 17, 2024 14:02
@susilnem susilnem self-assigned this Dec 17, 2024
@susilnem susilnem marked this pull request as ready for review December 18, 2024 04:34
Copy link
Member

@thenav56 thenav56 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Few integration required

per/drf_views.py Outdated
learning_by_sector = (
SectorTag.objects.filter(validated_sectors__in=queryset, title__isnull=False)
.annotate(count=Count("validated_sectors", distinct=True))
.values("title", "count")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to add 'id', this will be used by client as unique key

date=F("start_date"),
count=Count("appealdocument", distinct=True),
)
.values("type", "date", "count")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to add 'id', this will be used by client as unique key

per/drf_views.py Outdated
source_used=Count("appeal_code__appealdocument", distinct=True),
)

learning_by_sector = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add _qs as postfix (learning_by_sector_qs) for all querysets variables

per/drf_views.py Outdated
region_name=F("label"),
count=Count("appeal__opslearning", distinct=True),
)
.values("region_name", "count")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to add 'id', this will be used by client as unique key

country_name=F("name"),
count=Count("appeal__opslearning", distinct=True),
)
.values("country_id", "country_name", "count")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to add 'id', this will be used by client as unique key



class LearningSourcesOvertimeSerializer(serializers.Serializer):
type = serializers.IntegerField()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure about this? It will be complicated for the client side to do this mapping.

source='get_type_display' can't be used here, as the object will be a dict instead of a proper object. We could use serializer_method or do the enum->label in the views.

per/factories.py Outdated
class Meta:
model = Appeal

country = factory.SubFactory(CountryFactory)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not use factory.SubFactory, this will create objects without developer knowledge which can have weird confusing related to data generation, and it's effect.

per/factories.py Outdated
class OpsLearningFactory(factory.django.DjangoModelFactory):
learning = fuzzy.FuzzyText(length=50)

class Meta:
model = OpsLearning

appeal_code = factory.SubFactory(AppealFactory)
is_validated = fuzzy.FuzzyChoice([True, False])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not use fuzzy choice for is_validated, we should manually define in the test cases as lots of endpoints depends on this

Comment on lines +1286 to +1289
learning_by_region = LearningByRegionSerializer(many=True)
learning_by_country = LearningByCountrySerializer(many=True)
learning_by_sector = LearningBySectorSerializer(many=True)
sources_overtime = LearningSourcesOvertimeSerializer(many=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's explicitly define required=True for all fields

url = "/api/v2/ops-learning/stats/"
response = self.client.get(url)

self.assert_200(response)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are comparing all fields data, it will be better to just use basic dict assert instead.

assert response.data == expected_data

@susilnem susilnem merged commit 0777e4e into project/operational-learning2.0 Dec 18, 2024
3 checks passed
@susilnem susilnem deleted the feature/ops-learning-stat-api branch December 18, 2024 06:30
susilnem added a commit that referenced this pull request Jan 7, 2025
* Add Opslearning stats

Add validated filter

* Refactor ops learning stat api

* Change in source over time

* Add filter check for validated opslearning

* fix test cases and refactor queryset

* Add start date field in appeal serailizer

* Change filter queryset and add label for appealtype

* Define required field in serializers

* Remove subfactories and id in appeal queryset

---------

Co-authored-by: Sushil Tiwari <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants