From 0a4bbb0df74a086406c2ebf2110b8583e67d8c8b Mon Sep 17 00:00:00 2001 From: Elia Bieri Date: Thu, 12 Sep 2024 17:07:52 +0200 Subject: [PATCH] Sort person by paid year --- .../pages/dashboard/DashboardPersonsPage.vue | 49 +++++++++++++++++-- client/src/services/dashboard.ts | 4 +- server/vbv_lernwelt/course/models.py | 12 +++++ server/vbv_lernwelt/dashboard/utils.py | 1 + .../0020_alter_checkoutinformation_user.py | 24 +++++++++ server/vbv_lernwelt/shop/models.py | 4 +- 6 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 server/vbv_lernwelt/shop/migrations/0020_alter_checkoutinformation_user.py diff --git a/client/src/pages/dashboard/DashboardPersonsPage.vue b/client/src/pages/dashboard/DashboardPersonsPage.vue index 706f9018..457b75f5 100644 --- a/client/src/pages/dashboard/DashboardPersonsPage.vue +++ b/client/src/pages/dashboard/DashboardPersonsPage.vue @@ -10,6 +10,7 @@ import { useUserStore } from "@/stores/user"; import type { DashboardPersonsPageMode, StatisticsFilterItem } from "@/types"; import { exportDataAsXls } from "@/utils/export"; import { useRouteQuery } from "@vueuse/router"; +import dayjs from "dayjs"; import { useTranslation } from "i18next-vue"; import _ from "lodash"; import log from "loglevel"; @@ -160,7 +161,7 @@ const roles = computed(() => { return [ { - id: "", + id: UNFILTERED, name: `${t("Rolle")}: ${t("a.Alle")}`, }, ...values, @@ -191,6 +192,30 @@ const chosenProfiles = computed(() => { }); const selectedChosenProfile = ref(chosenProfiles.value[0]); +const paidYears = computed(() => { + const values = _(dashboardPersons.value) + .filter((cs) => dayjs(cs.paid_date).isValid()) + .map((cs) => { + const paidYear = dayjs(cs.paid_date).format("YYYY"); + return Object.assign({}, cs, { + name: paidYear, + id: paidYear, + }); + }) + .uniqBy("id") + .orderBy("name") + .value(); + + return [ + { + id: UNFILTERED, + name: `${t("Jahr")}: ${t("a.Alle")}`, + }, + ...values, + ]; +}); +const selectedPaidYear = ref(paidYears.value[0]); + const filteredPersons = computed(() => { return _.orderBy( dashboardPersons.value @@ -225,7 +250,7 @@ const filteredPersons = computed(() => { ); }) .filter((person) => { - if (selectedRole.value.id === "") { + if (selectedRole.value.id === UNFILTERED) { return true; } return person.course_sessions.some( @@ -233,10 +258,17 @@ const filteredPersons = computed(() => { ); }) .filter((person) => { - if (selectedChosenProfile.value.id === "") { + if (selectedChosenProfile.value.id === UNFILTERED) { return true; } return person.chosen_profile === selectedChosenProfile.value.id; + }) + .filter((person) => { + if (selectedPaidYear.value.id === UNFILTERED) { + return true; + } + const paidYear = dayjs(person.paid_date).format("YYYY"); + return paidYear == selectedPaidYear.value.id; }), ["last_name", "first_name"] ); @@ -249,7 +281,8 @@ const filtersVisible = computed(() => { regions.value.length > 2 || generations.value.length > 2 || roles.value.length > 2 || - chosenProfiles.value.length > 2 + chosenProfiles.value.length > 2 || + paidYears.value.length > 2 ); }); @@ -380,6 +413,14 @@ watch(selectedRegion, () => { :items="chosenProfiles" borderless > + +
datetime | None: + """ + Returns the date when the user paid for the course session + """ + checkout = self.user.checkout_information.filter(state=CheckoutState.PAID) + if checkout: + return checkout.first().created_at + return None + def __str__(self): return f"{self.user} ({self.course_session.title})" diff --git a/server/vbv_lernwelt/dashboard/utils.py b/server/vbv_lernwelt/dashboard/utils.py index a9247d73..8c5e2ffd 100644 --- a/server/vbv_lernwelt/dashboard/utils.py +++ b/server/vbv_lernwelt/dashboard/utils.py @@ -109,6 +109,7 @@ def create_person_list_with_roles( "avatar_url": user_object.avatar_url, "course_sessions": [], "chosen_profile": csu.chosen_profile.code if csu.chosen_profile else "all", + "paid_date": csu.paid_date.isoformat() if csu.paid_date else None, } if include_private_data: user_data["phone_number"] = user_object.phone_number diff --git a/server/vbv_lernwelt/shop/migrations/0020_alter_checkoutinformation_user.py b/server/vbv_lernwelt/shop/migrations/0020_alter_checkoutinformation_user.py new file mode 100644 index 00000000..008bf864 --- /dev/null +++ b/server/vbv_lernwelt/shop/migrations/0020_alter_checkoutinformation_user.py @@ -0,0 +1,24 @@ +# Generated by Django 4.2.13 on 2024-09-12 13:40 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("shop", "0019_alter_checkoutinformation_refno2"), + ] + + operations = [ + migrations.AlterField( + model_name="checkoutinformation", + name="user", + field=models.ForeignKey( + on_delete=django.db.models.deletion.PROTECT, + related_name="checkout_information", + to=settings.AUTH_USER_MODEL, + ), + ), + ] diff --git a/server/vbv_lernwelt/shop/models.py b/server/vbv_lernwelt/shop/models.py index 34be44bb..e6db05ff 100644 --- a/server/vbv_lernwelt/shop/models.py +++ b/server/vbv_lernwelt/shop/models.py @@ -43,7 +43,9 @@ class CheckoutInformation(models.Model): (INVOICE_ADDRESS_ORGANISATION, "Organisation"), ) - user = models.ForeignKey("core.User", on_delete=models.PROTECT) + user = models.ForeignKey( + "core.User", on_delete=models.PROTECT, related_name="checkout_information" + ) product_sku = models.CharField(max_length=255) product_name = models.CharField(max_length=255)