From 6a399d913c6b1a340eff0ca43820993f40ee44f1 Mon Sep 17 00:00:00 2001 From: Raphael Odini Date: Sat, 28 Sep 2024 10:00:09 +0200 Subject: [PATCH] Properties to update these stats --- open_prices/stats/models.py | 55 ++++++++++++++++++++ open_prices/stats/tests.py | 101 ++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 open_prices/stats/tests.py diff --git a/open_prices/stats/models.py b/open_prices/stats/models.py index e94ca09c..ce55a2f1 100644 --- a/open_prices/stats/models.py +++ b/open_prices/stats/models.py @@ -4,6 +4,12 @@ class TotalStats(SingletonModel): + PRICE_COUNT_FIELDS = ["price_count", "price_barcode_count", "price_category_count"] + PRODUCT_COUNT_FIELDS = ["product_count", "product_with_price_count"] + LOCATION_COUNT_FIELDS = ["location_count", "location_with_price_count"] + PROOF_COUNT_FIELDS = ["proof_count", "proof_with_price_count"] + USER_COUNT_FIELDS = ["user_count", "user_with_price_count"] + price_count = models.PositiveIntegerField(default=0) price_barcode_count = models.PositiveIntegerField(default=0) price_category_count = models.PositiveIntegerField(default=0) @@ -22,3 +28,52 @@ class TotalStats(SingletonModel): class Meta: verbose_name = "Total Stats" verbose_name_plural = "Total Stats" + + def update_price_stats(self): + from open_prices.prices.models import Price + + self.price_count = Price.objects.count() + self.price_barcode_count = Price.objects.filter( + product_code__isnull=False + ).count() + self.price_category_count = Price.objects.filter( + category_tag__isnull=False + ).count() + self.save( + update_fields=self.PRICE_COUNT_FIELDS + + [ + "updated", + ] + ) + + def update_product_stats(self): + from open_prices.products.models import Product + + self.product_count = Product.objects.count() + self.product_with_price_count = Product.objects.has_prices().count() + # self.product_with_price_count = User.objects.values_list("product_id", flat=True).distinct().count() # noqa + self.save(update_fields=self.PRODUCT_COUNT_FIELDS + ["updated"]) + + def update_location_stats(self): + from open_prices.locations.models import Location + + self.location_count = Location.objects.count() + self.location_with_price_count = Location.objects.has_prices().count() + # self.location_with_price_count = User.objects.values_list("location_id", flat=True).distinct().count() # noqa + self.save(update_fields=self.LOCATION_COUNT_FIELDS + ["updated"]) + + def update_proof_stats(self): + from open_prices.proofs.models import Proof + + self.proof_count = Proof.objects.count() + self.proof_with_price_count = Proof.objects.has_prices().count() + # self.proof_with_price_count = User.objects.values_list("proof_id", flat=True).distinct().count() # noqa + self.save(update_fields=self.PROOF_COUNT_FIELDS + ["updated"]) + + def update_user_stats(self): + from open_prices.users.models import User + + self.user_count = User.objects.count() + self.user_with_price_count = User.objects.has_prices().count() + # self.user_with_price_count = User.objects.values_list("owner", flat=True).distinct().count() # noqa + self.save(update_fields=self.USER_COUNT_FIELDS + ["updated"]) diff --git a/open_prices/stats/tests.py b/open_prices/stats/tests.py new file mode 100644 index 00000000..d4b21cfb --- /dev/null +++ b/open_prices/stats/tests.py @@ -0,0 +1,101 @@ +from django.db import IntegrityError +from django.test import TestCase + +from open_prices.locations.factories import LocationFactory +from open_prices.prices.factories import PriceFactory +from open_prices.proofs.factories import ProofFactory +from open_prices.stats.models import TotalStats +from open_prices.users.factories import UserFactory + +LOCATION_NODE_652825274 = { + "osm_id": 652825274, + "osm_type": "NODE", + "osm_name": "Monoprix", +} + + +class TotalStatsSaveTest(TestCase): + @classmethod + def setUpTestData(cls): + cls.total_stats = TotalStats.get_solo() + + def test_total_stats_singleton(self): + # cannot create another TotalStats instance + self.assertRaises(IntegrityError, TotalStats.objects.create) + + +class TotalStatsTest(TestCase): + @classmethod + def setUpTestData(cls): + cls.total_stats = TotalStats.get_solo() + cls.user = UserFactory() + cls.user_2 = UserFactory() + cls.location = LocationFactory(**LOCATION_NODE_652825274) + cls.location_2 = LocationFactory() + cls.proof = ProofFactory( + location_osm_id=cls.location.osm_id, + location_osm_type=cls.location.osm_type, + owner=cls.user.user_id, + ) + cls.proof_2 = ProofFactory( + location_osm_id=cls.location_2.osm_id, + location_osm_type=cls.location_2.osm_type, + owner=cls.user_2.user_id, + ) + PriceFactory( + product_code="0123456789100", + location_osm_id=cls.location.osm_id, + location_osm_type=cls.location.osm_type, + proof_id=cls.proof.id, + price=1.0, + owner=cls.user.user_id, + ) + PriceFactory( + product_code="0123456789101", + location_osm_id=cls.location.osm_id, + location_osm_type=cls.location.osm_type, + price=2.0, + owner=cls.user_2.user_id, + ) + + def test_update_price_stats(self): + self.assertEqual(self.total_stats.price_count, 0) + self.assertEqual(self.total_stats.price_barcode_count, 0) + self.assertEqual(self.total_stats.price_category_count, 0) + # update_price_stats() will update price_counts + self.total_stats.update_price_stats() + self.assertEqual(self.total_stats.price_count, 2) + self.assertEqual(self.total_stats.price_barcode_count, 2) + self.assertEqual(self.total_stats.price_category_count, 0) + + def test_update_product_stats(self): + self.assertEqual(self.total_stats.product_count, 0) + self.assertEqual(self.total_stats.product_with_price_count, 0) + # update_product_stats() will update product_counts + self.total_stats.update_product_stats() + self.assertEqual(self.total_stats.product_count, 2) + self.assertEqual(self.total_stats.product_with_price_count, 2) + + def test_update_location_stats(self): + self.assertEqual(self.total_stats.location_count, 0) + self.assertEqual(self.total_stats.location_with_price_count, 0) + # update_location_stats() will update location_counts + self.total_stats.update_location_stats() + self.assertEqual(self.total_stats.location_count, 2) + self.assertEqual(self.total_stats.location_with_price_count, 1) + + def test_update_proof_stats(self): + self.assertEqual(self.total_stats.proof_count, 0) + self.assertEqual(self.total_stats.proof_with_price_count, 0) + # update_proof_stats() will update proof_counts + self.total_stats.update_proof_stats() + self.assertEqual(self.total_stats.proof_count, 2) + self.assertEqual(self.total_stats.proof_with_price_count, 1) + + def test_update_user_stats(self): + self.assertEqual(self.total_stats.user_count, 0) + self.assertEqual(self.total_stats.user_with_price_count, 0) + # update_user_stats() will update user_counts + self.total_stats.update_user_stats() + self.assertEqual(self.total_stats.user_count, 2) + self.assertEqual(self.total_stats.user_with_price_count, 2)