diff --git a/poetry.lock b/poetry.lock index a65627c..99cad6f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -296,6 +296,17 @@ ufo = ["fs (>=2.2.0,<3)"] unicode = ["unicodedata2 (>=14.0.0)"] woff = ["zopfli (>=0.1.4)", "brotlicffi (>=0.8.0)", "brotli (>=1.0.1)"] +[[package]] +name = "freezegun" +version = "1.2.1" +description = "Let your Python tests travel through time" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +python-dateutil = ">=2.7" + [[package]] name = "greenlet" version = "1.1.2" @@ -757,7 +768,7 @@ brotli = ["brotli"] [metadata] lock-version = "1.1" python-versions = "^3.10" -content-hash = "1e6949d15944eb22a11638e48f54f8a9400d7c39508ea6246ad3704c01e17450" +content-hash = "e4775458012aa94f4a84298e90e8133f85d38cccc0ddee6ecf8300ea2732a3a9" [metadata.files] asgiref = [ @@ -986,6 +997,10 @@ fonttools = [ {file = "fonttools-4.33.3-py3-none-any.whl", hash = "sha256:f829c579a8678fa939a1d9e9894d01941db869de44390adb49ce67055a06cc2a"}, {file = "fonttools-4.33.3.zip", hash = "sha256:c0fdcfa8ceebd7c1b2021240bd46ef77aa8e7408cf10434be55df52384865f8e"}, ] +freezegun = [ + {file = "freezegun-1.2.1-py3-none-any.whl", hash = "sha256:15103a67dfa868ad809a8f508146e396be2995172d25f927e48ce51c0bf5cb09"}, + {file = "freezegun-1.2.1.tar.gz", hash = "sha256:b4c64efb275e6bc68dc6e771b17ffe0ff0f90b81a2a5189043550b6519926ba4"}, +] greenlet = [ {file = "greenlet-1.1.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:58df5c2a0e293bf665a51f8a100d3e9956febfbf1d9aaf8c0677cf70218910c6"}, {file = "greenlet-1.1.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:aec52725173bd3a7b56fe91bc56eccb26fbdff1386ef123abb63c84c5b43b63a"}, diff --git a/pyproject.toml b/pyproject.toml index c212c6b..a85fab2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,7 @@ Pillow = "^9.1.0" django-crispy-forms = "^1.14.0" crispy-bootstrap5 = "^0.6" matplotlib = "^3.5.1" +freezegun = "^1.2.1" [tool.poetry.dev-dependencies] pre-commit = "^2.7" diff --git a/src/purchase/management/__init__.py b/src/purchase/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/purchase/management/commands/__init__.py b/src/purchase/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/purchase/management/commands/clear_all_data.py b/src/purchase/management/commands/clear_all_data.py new file mode 100644 index 0000000..0211bde --- /dev/null +++ b/src/purchase/management/commands/clear_all_data.py @@ -0,0 +1,17 @@ +from django.core.management.base import BaseCommand + +from purchase.models import Basket, BasketItem, PaymentMethod, Product + + +class Command(BaseCommand): + help = "Clear all data" # noqa: A003 + + def handle(self, *args, **options): + self.delete(BasketItem) + self.delete(Basket) + self.delete(Product) + self.delete(PaymentMethod) + + def delete(self, cls): + _, count = cls.objects.all().delete() + self.stdout.write(self.style.WARNING(f"Successfully deleted {count} {cls}.")) diff --git a/src/purchase/management/commands/generate_dummy_data.py b/src/purchase/management/commands/generate_dummy_data.py new file mode 100644 index 0000000..eca3258 --- /dev/null +++ b/src/purchase/management/commands/generate_dummy_data.py @@ -0,0 +1,66 @@ +import random +from datetime import timedelta + +import freezegun +from django.core.management.base import BaseCommand +from django.utils.timezone import now + +from purchase.models import Basket, BasketItem, PaymentMethod, Product + + +class Command(BaseCommand): + help = "Generates dummy data" # noqa: A003 + + def handle(self, *args, **options): + products = [ + Product(name="Clou", unit_price_cents=134), + Product(name="Villard'Ain", unit_price_cents=290), + Product(name="Herbier", unit_price_cents=330), + Product(name="Blanc vache", unit_price_cents=650), + ] + products = Product.objects.bulk_create(products) + self.stdout.write( + self.style.SUCCESS(f"Successfully created {len(products)} products.") + ) + + payment_methods = [ + PaymentMethod(name="Espèces"), + PaymentMethod(name="CB"), + PaymentMethod(name="Chèque"), + ] + payment_methods = PaymentMethod.objects.bulk_create(payment_methods) + self.stdout.write( + self.style.SUCCESS( + f"Successfully created {len(payment_methods)} payment methods." + ) + ) + + count = 0 + hours = list(range(-29, -20)) + hours += list(range(-10, -2)) + for hour in hours: + with freezegun.freeze_time(now() + timedelta(hours=hour)): + count += self.generate_baskets(payment_methods, products) + + self.stdout.write(self.style.SUCCESS(f"Successfully created {count} baskets.")) + + def delete(self, cls): + _, count = cls.objects.all().delete() + self.stdout.write(self.style.WARNING(f"Successfully deleted {count} {cls}.")) + + def generate_baskets(self, payment_methods, products): + count = int(random.normalvariate(20, 10)) + for _ in range(count): + method = random.choice(payment_methods) + basket = Basket.objects.create(payment_method=method) + items = [] + item_count = int(random.normalvariate(3, 2)) + for _ in range(item_count): + product = random.choice(products) + items.append( + BasketItem( + product=product, basket=basket, quantity=random.randint(1, 3) + ) + ) + BasketItem.objects.bulk_create(items) + return count