Sort person by paid year
This commit is contained in:
parent
c65c1be0a8
commit
0a4bbb0df7
|
|
@ -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<MenuItem>(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<MenuItem>(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
|
||||
></ItDropdownSelect>
|
||||
|
||||
<ItDropdownSelect
|
||||
v-if="paidYears.length > 2"
|
||||
v-model="selectedPaidYear"
|
||||
data-cy="select-paid-year"
|
||||
:items="paidYears"
|
||||
borderless
|
||||
></ItDropdownSelect>
|
||||
</section>
|
||||
<div
|
||||
v-for="person in filteredPersons"
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import type {
|
|||
XlsExportRequestData,
|
||||
XlsExportResponseData,
|
||||
} from "@/types";
|
||||
import type dayjs from "dayjs";
|
||||
|
||||
export type DashboardPersonRoleType =
|
||||
| "SUPERVISOR"
|
||||
|
|
@ -78,11 +79,12 @@ export type DashboardPersonType = {
|
|||
course_sessions: DashboardPersonCourseSessionType[];
|
||||
avatar_url: string;
|
||||
avatar_url_small: string;
|
||||
chosen_profile: string;
|
||||
competence_metrics?: {
|
||||
passed_count: number;
|
||||
failed_count: number;
|
||||
};
|
||||
chosen_profile: string;
|
||||
paid_date?: string;
|
||||
};
|
||||
|
||||
export type DashboardCourseConfigType = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import uuid
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
from django.db import models
|
||||
|
|
@ -13,6 +14,7 @@ from vbv_lernwelt.core.model_utils import find_available_slug
|
|||
from vbv_lernwelt.core.models import User
|
||||
from vbv_lernwelt.course.serializer_helpers import get_course_serializer_class
|
||||
from vbv_lernwelt.files.models import UploadFile
|
||||
from vbv_lernwelt.shop.models import CheckoutState
|
||||
|
||||
|
||||
class CircleContactType(Enum):
|
||||
|
|
@ -301,6 +303,16 @@ class CourseSessionUser(models.Model):
|
|||
]
|
||||
ordering = ["user__last_name", "user__first_name", "user__email"]
|
||||
|
||||
@property
|
||||
def paid_date(self) -> 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})"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue