feat: add organisations as model

This commit is contained in:
Reto Aebersold 2023-11-14 17:13:27 +01:00 committed by Christian Cueni
parent 0f6232e6f4
commit 437ffde8b1
15 changed files with 245 additions and 138 deletions

View File

@ -14,18 +14,30 @@ import { profileNextRoute } from "@/services/onboarding";
const { t } = useTranslation(); const { t } = useTranslation();
type Organisation = { type Organisation = {
id: string; organisation_id: number;
name: string; name_de: string;
name_fr: string;
name_it: string;
}; };
const user = useUserStore(); const user = useUserStore();
const route = useRoute(); const route = useRoute();
const fetchResult = useFetch("/api/core/organisations/"); const fetchResult = useFetch("/api/core/organisations/");
const organisations: Ref<Organisation[] | null> = fetchResult.data; const organisationData: Ref<Organisation[] | null> = fetchResult.data;
const organisations = computed(() => {
if (organisationData.value) {
return organisationData.value.map((c) => ({
id: c.organisation_id,
name: c[`name_${user.language}`],
}));
}
return [];
});
const selectedOrganisation = ref({ const selectedOrganisation = ref({
id: "0", id: 0,
name: t("a.Auswählen"), name: t("a.Auswählen"),
}); });
@ -58,7 +70,6 @@ watch(avatarFileInfo, (info) => {
}); });
watch(selectedOrganisation, (organisation) => { watch(selectedOrganisation, (organisation) => {
console.log("organisation changed", organisation);
itPut("/api/core/me/", { itPut("/api/core/me/", {
organisation: organisation.id, organisation: organisation.id,
}); });
@ -82,7 +93,7 @@ const nextRoute = computed(() => {
</p> </p>
<ItDropdownSelect <ItDropdownSelect
v-if="organisations" v-if="organisationData"
v-model="selectedOrganisation" v-model="selectedOrganisation"
:items="organisations" :items="organisations"
/> />

View File

@ -25,7 +25,7 @@ export type UserState = {
email: string; email: string;
username: string; username: string;
avatar_url: string; avatar_url: string;
organisation: string; organisation: number;
is_superuser: boolean; is_superuser: boolean;
course_session_experts: string[]; course_session_experts: string[];
loggedIn: boolean; loggedIn: boolean;
@ -58,7 +58,7 @@ const initialUserState: UserState = {
username: "", username: "",
avatar_url: "", avatar_url: "",
is_superuser: false, is_superuser: false,
organisation: "", organisation: 0,
course_session_experts: [], course_session_experts: [],
loggedIn: false, loggedIn: false,
language: defaultLanguage, language: defaultLanguage,

View File

@ -13,6 +13,7 @@ from graphene_django.views import GraphQLView
from wagtail import urls as wagtail_urls from wagtail import urls as wagtail_urls
from wagtail.admin import urls as wagtailadmin_urls from wagtail.admin import urls as wagtailadmin_urls
from vbv_lernwelt.api.user import list_organisations, me_user_view
from vbv_lernwelt.assignment.views import request_assignment_completion_status from vbv_lernwelt.assignment.views import request_assignment_completion_status
from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
from vbv_lernwelt.core.schema import schema from vbv_lernwelt.core.schema import schema
@ -20,8 +21,6 @@ from vbv_lernwelt.core.views import (
check_rate_limit, check_rate_limit,
cypress_reset_view, cypress_reset_view,
generate_web_component_icons, generate_web_component_icons,
list_organisations,
me_user_view,
permission_denied_view, permission_denied_view,
rate_limit_exceeded_view, rate_limit_exceeded_view,
vue_home, vue_home,

View File

View File

@ -30,10 +30,10 @@ class MeUserViewTest(APITestCase):
url = reverse("me_user_view") # replace with your actual URL name url = reverse("me_user_view") # replace with your actual URL name
# WHEN # WHEN
response = self.client.put(url, {"organisation": "6"}) response = self.client.put(url, {"organisation": 6})
# THEN # THEN
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
updated_user = User.objects.get(username="testuser") updated_user = User.objects.get(username="testuser")
self.assertEquals(updated_user.organisation, "6") self.assertEquals(updated_user.organisation.organisation_id, 6)

View File

@ -3,7 +3,6 @@ from rest_framework import status
from rest_framework.test import APITestCase from rest_framework.test import APITestCase
from vbv_lernwelt.core.models import User from vbv_lernwelt.core.models import User
from vbv_lernwelt.core.organisations import ORGANISATIONS
class OrganisationViewTest(APITestCase): class OrganisationViewTest(APITestCase):
@ -23,5 +22,12 @@ class OrganisationViewTest(APITestCase):
# THEN # THEN
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
_id, name = ORGANISATIONS[0] self.assertEqual(
self.assertEqual(response.data[0], {"id": _id, "name": name}) response.data[0],
{
"organisation_id": 1,
"name_de": "andere Broker",
"name_fr": "autres Broker",
"name_it": "altre Broker",
},
)

View File

@ -0,0 +1,35 @@
from rest_framework.decorators import api_view
from rest_framework.response import Response
from vbv_lernwelt.core.models import Organisation
from vbv_lernwelt.core.serializers import OrganisationSerializer, UserSerializer
@api_view(["GET"])
def list_organisations(request):
if not request.user.is_authenticated:
return Response(status=403)
serializer = OrganisationSerializer(Organisation.objects.all(), many=True)
return Response(serializer.data)
@api_view(["GET", "PUT"])
def me_user_view(request):
if not request.user.is_authenticated:
return Response(status=403)
if request.method == "GET":
return Response(UserSerializer(request.user).data)
if request.method == "PUT":
serializer = UserSerializer(
request.user,
data=request.data,
partial=True,
)
if serializer.is_valid():
serializer.save()
return Response(UserSerializer(request.user).data)
return Response(status=400)

View File

@ -2,7 +2,7 @@ from django.contrib import admin
from django.contrib.auth import admin as auth_admin, get_user_model from django.contrib.auth import admin as auth_admin, get_user_model
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from vbv_lernwelt.core.models import JobLog from vbv_lernwelt.core.models import JobLog, Organisation
from vbv_lernwelt.core.utils import pretty_print_json from vbv_lernwelt.core.utils import pretty_print_json
User = get_user_model() User = get_user_model()
@ -78,3 +78,13 @@ class JobLogAdmin(LogAdmin):
if obj.ended: if obj.ended:
return (obj.ended - obj.started).seconds // 60 return (obj.ended - obj.started).seconds // 60
return None return None
@admin.register(Organisation)
class OrganisationAdmin(admin.ModelAdmin):
list_display = (
"organisation_id",
"name_de",
"name_fr",
"name_it",
)

View File

@ -0,0 +1,145 @@
import django.db.models.deletion
from django.db import migrations, models
orgs = {
1: {"de": "andere Broker", "fr": "autres Broker", "it": "altre Broker"},
2: {
"de": "andere Krankenversicherer",
"fr": "autres assureurs santé",
"it": "altre assicurazioni sanitarie",
},
3: {
"de": "andere Privatversicherer",
"fr": "autres Assurance privée",
"it": "altre Assicurazione privato",
},
4: {"de": "Allianz Suisse", "fr": "Allianz Suisse", "it": "Allianz Suisse"},
5: {"de": "AON", "fr": "AON", "it": "AON"},
6: {
"de": "AXA Winterthur",
"fr": "AXA Assurances SA",
"it": "AXA Assicurazioni SA",
},
7: {"de": "Baloise", "fr": "Baloise", "it": "Baloise"},
8: {
"de": "CAP Rechtsschutz",
"fr": "CAP Protection juridique",
"it": "CAP Protezione giuridica",
},
9: {
"de": "Coop Rechtsschutz",
"fr": "Coop Protection juridique",
"it": "Coop Protezione giuridica",
},
10: {"de": "CSS", "fr": "CSS", "it": "CSS"},
11: {"de": "Die Mobiliar", "fr": "La Mobilière", "it": "La Mobiliare"},
12: {
"de": "Emmental Versicherung",
"fr": "Emmental Assurance",
"it": "Emmental Assicurazione",
},
13: {
"de": "GENERALI Versicherungen",
"fr": "Generali Assurances",
"it": "Generali Assicurazioni",
},
14: {"de": "Groupe Mutuel", "fr": "GROUPE MUTUEL", "it": "GROUPE MUTUEL"},
15: {"de": "Helsana", "fr": "Helsana", "it": "Helsana"},
16: {"de": "Helvetia", "fr": "Helvetia", "it": "Helvetia"},
17: {"de": "Kessler & Co AG", "fr": "Kessler & Co AG", "it": "Kessler & Co AG"},
18: {
"de": "Orion Rechtsschutz Versicherung",
"fr": "Orion Protection juridique",
"it": "Orion Protezione giuridica",
},
19: {"de": "PAX", "fr": "PAX", "it": "PAX"},
20: {"de": "Sanitas", "fr": "Sanitas", "it": "Sanitas"},
21: {"de": "SUVA", "fr": "SUVA", "it": "SUVA"},
22: {"de": "Swica", "fr": "Swica", "it": "Swica"},
23: {"de": "Swiss Life", "fr": "Swiss Life", "it": "Swiss Life"},
24: {"de": "Swiss Re", "fr": "Swiss Re", "it": "Swiss Re"},
25: {
"de": "Visana Services AG",
"fr": "Visana Services SA",
"it": "Visana Services SA",
},
26: {
"de": "VZ VermögensZentrum AG",
"fr": "VZ VermögensZentrum AG",
"it": "VZ VermögensZentrum AG",
},
27: {
"de": "Würth Financial Services AG",
"fr": "Würth Financial Services SA",
"it": "Würth Financial Services SA",
},
28: {"de": "Zürich", "fr": "Zurich", "it": "Zurigo"},
29: {"de": "VBV", "fr": "AFA", "it": "AFA"},
30: {"de": "Vaudoise", "fr": "Vaudoise", "it": "Vaudoise"},
31: {
"de": "Keine Firmenzugehörigkeit",
"fr": "Pas d'appartenance à une entreprise",
"it": "Nessuna affiliazione aziendale",
},
}
def add_organisations(apps, schema_editor):
Organisation = apps.get_model("core", "Organisation")
for org_id, org_data in orgs.items():
Organisation.objects.create(
organisation_id=org_id,
name_de=org_data["de"],
name_fr=org_data["fr"],
name_it=org_data["it"],
)
def remove_organisations(apps, schema_editor):
Organisation = apps.get_model("core", "Organisation")
for org_id, org_data in orgs.items():
Organisation.objects.filter(
organisation_id=org_id,
name_de=org_data["de"],
name_fr=org_data["fr"],
name_it=org_data["it"],
).delete()
class Migration(migrations.Migration):
dependencies = [
("core", "0002_joblog"),
]
operations = [
migrations.CreateModel(
name="Organisation",
fields=[
(
"organisation_id",
models.IntegerField(primary_key=True, serialize=False),
),
("name_de", models.CharField(max_length=255)),
("name_fr", models.CharField(max_length=255)),
("name_it", models.CharField(max_length=255)),
],
options={
"verbose_name": "Organisation",
"verbose_name_plural": "Organisations",
"ordering": ["organisation_id"],
},
),
migrations.AddField(
model_name="user",
name="organisation",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="core.organisation",
),
),
migrations.RunPython(add_organisations, remove_organisations),
]

View File

@ -1,53 +0,0 @@
# Generated by Django 3.2.20 on 2023-11-13 13:23
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("core", "0002_joblog"),
]
operations = [
migrations.AddField(
model_name="user",
name="organisation",
field=models.CharField(
blank=True,
choices=[
("1", "Andere Broker"),
("2", "Andere Krankenversicherer"),
("3", "Andere Privatversicherer"),
("4", "Allianz Suisse"),
("5", "AON"),
("6", "AXA Winterthur"),
("7", "Baloise"),
("8", "CAP Rechtsschutz"),
("9", "Coop Rechtsschutz"),
("10", "CSS"),
("11", "Die Mobiliar"),
("12", "Emmental Versicherung"),
("13", "GENERALI Versicherungen"),
("14", "Groupe Mutuel"),
("15", "Helsana"),
("16", "Helvetia"),
("17", "Kessler & Co AG"),
("18", "Orion Rechtsschutz Versicherung"),
("19", "PAX"),
("20", "Sanitas"),
("21", "SUVA"),
("22", "Swica"),
("23", "Swiss Life"),
("24", "Swiss Re"),
("25", "Visana Services AG"),
("26", "VZ VermögensZentrum AG"),
("27", "Würth Financial Services AG"),
("28", "Zürich"),
("29", "VBV"),
("30", "Vaudoise"),
("31", "Keine Firmenzugehörigkeit"),
],
max_length=255,
),
),
]

View File

@ -4,7 +4,20 @@ from django.contrib.auth.models import AbstractUser
from django.db import models from django.db import models
from django.db.models import JSONField from django.db.models import JSONField
from vbv_lernwelt.core.organisations import ORGANISATIONS
class Organisation(models.Model):
organisation_id = models.IntegerField(primary_key=True)
name_de = models.CharField(max_length=255)
name_fr = models.CharField(max_length=255)
name_it = models.CharField(max_length=255)
def __str__(self):
return f"{self.name_de} ({self.organisation_id})"
class Meta:
verbose_name = "Organisation"
verbose_name_plural = "Organisations"
ordering = ["organisation_id"]
class User(AbstractUser): class User(AbstractUser):
@ -31,10 +44,8 @@ class User(AbstractUser):
additional_json_data = JSONField(default=dict, blank=True) additional_json_data = JSONField(default=dict, blank=True)
language = models.CharField(max_length=2, choices=LANGUAGE_CHOICES, default="de") language = models.CharField(max_length=2, choices=LANGUAGE_CHOICES, default="de")
organisation = models.CharField( organisation = models.ForeignKey(
max_length=255, Organisation, on_delete=models.SET_NULL, null=True, blank=True
choices=ORGANISATIONS,
blank=True,
) )

View File

@ -1,33 +0,0 @@
ORGANISATIONS = [
("1", "Andere Broker"),
("2", "Andere Krankenversicherer"),
("3", "Andere Privatversicherer"),
("4", "Allianz Suisse"),
("5", "AON"),
("6", "AXA Winterthur"),
("7", "Baloise"),
("8", "CAP Rechtsschutz"),
("9", "Coop Rechtsschutz"),
("10", "CSS"),
("11", "Die Mobiliar"),
("12", "Emmental Versicherung"),
("13", "GENERALI Versicherungen"),
("14", "Groupe Mutuel"),
("15", "Helsana"),
("16", "Helvetia"),
("17", "Kessler & Co AG"),
("18", "Orion Rechtsschutz Versicherung"),
("19", "PAX"),
("20", "Sanitas"),
("21", "SUVA"),
("22", "Swica"),
("23", "Swiss Life"),
("24", "Swiss Re"),
("25", "Visana Services AG"),
("26", "VZ VermögensZentrum AG"),
("27", "Würth Financial Services AG"),
("28", "Zürich"),
("29", "VBV"),
("30", "Vaudoise"),
("31", "Keine Firmenzugehörigkeit"),
]

View File

@ -3,7 +3,7 @@ from typing import List
from rest_framework import serializers from rest_framework import serializers
from rest_framework.renderers import JSONRenderer from rest_framework.renderers import JSONRenderer
from vbv_lernwelt.core.models import User from vbv_lernwelt.core.models import Organisation, User
from vbv_lernwelt.course.models import CourseSessionUser from vbv_lernwelt.course.models import CourseSessionUser
from vbv_lernwelt.course_session_group.models import CourseSessionGroup from vbv_lernwelt.course_session_group.models import CourseSessionGroup
@ -53,3 +53,9 @@ class UserSerializer(serializers.ModelSerializer):
) )
return [str(_id) for _id in (supervisor_in_session_ids | expert_in_session_ids)] return [str(_id) for _id in (supervisor_in_session_ids | expert_in_session_ids)]
class OrganisationSerializer(serializers.ModelSerializer):
class Meta:
model = Organisation
fields = "__all__"

View File

@ -27,7 +27,6 @@ from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response from rest_framework.response import Response
from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
from vbv_lernwelt.core.organisations import ORGANISATIONS
from vbv_lernwelt.core.serializers import UserSerializer from vbv_lernwelt.core.serializers import UserSerializer
logger = structlog.get_logger(__name__) logger = structlog.get_logger(__name__)
@ -91,35 +90,6 @@ def vue_login(request):
) )
@api_view(["GET"])
def list_organisations(request):
if not request.user.is_authenticated:
return Response(status=403)
return Response([{"id": _id, "name": name} for _id, name in ORGANISATIONS])
@api_view(["GET", "PUT"])
def me_user_view(request):
if not request.user.is_authenticated:
return Response(status=403)
if request.method == "GET":
return Response(UserSerializer(request.user).data)
if request.method == "PUT":
serializer = UserSerializer(
request.user,
data=request.data,
partial=True,
)
if serializer.is_valid():
serializer.save()
return Response(UserSerializer(request.user).data)
return Response(status=400)
@api_view(["POST"]) @api_view(["POST"])
def vue_logout(request): def vue_logout(request):
logout(request) logout(request)