Refactor country handling code
This commit is contained in:
parent
8ce7f9935e
commit
2646b072ee
|
|
@ -141,7 +141,11 @@ const orgAddress = computed({
|
|||
autocomplete="country-name"
|
||||
class="block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
>
|
||||
<option v-for="country in countries" :key="country.id" :value="country.id">
|
||||
<option
|
||||
v-for="country in countries"
|
||||
:key="country.country_code"
|
||||
:value="country.country_code"
|
||||
>
|
||||
{{ country.name }}
|
||||
</option>
|
||||
</select>
|
||||
|
|
|
|||
|
|
@ -153,7 +153,11 @@ const address = computed({
|
|||
autocomplete="country-name"
|
||||
class="block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
>
|
||||
<option v-for="country in countries" :key="country.id" :value="country.id">
|
||||
<option
|
||||
v-for="country in countries"
|
||||
:key="country.country_code"
|
||||
:value="country.country_code"
|
||||
>
|
||||
{{ country.name }}
|
||||
</option>
|
||||
</select>
|
||||
|
|
|
|||
|
|
@ -20,23 +20,25 @@ const formData = ref({
|
|||
street_number: user.street_number,
|
||||
postal_code: user.postal_code,
|
||||
city: user.city,
|
||||
country_id: user.country?.id,
|
||||
country_code: user.country?.country_code,
|
||||
organisation: user.organisation,
|
||||
organisation_street: user.organisation_street,
|
||||
organisation_street_number: user.organisation_street_number,
|
||||
organisation_postal_code: user.organisation_postal_code,
|
||||
organisation_city: user.organisation_city,
|
||||
organisation_country_id: user.organisation_country?.id,
|
||||
organisation_country_code: user.organisation_country?.country_code,
|
||||
invoice_address: user.invoice_address,
|
||||
});
|
||||
|
||||
async function save() {
|
||||
const { country_id, organisation_country_id, ...profileData } = formData.value;
|
||||
const { country_code, organisation_country_code, ...profileData } = formData.value;
|
||||
const typedProfileData: Partial<User> = { ...profileData };
|
||||
|
||||
typedProfileData.country = countries.value.find((c) => c.id === country_id);
|
||||
typedProfileData.country = countries.value.find(
|
||||
(c) => c.country_code === country_code
|
||||
);
|
||||
typedProfileData.organisation_country = countries.value.find(
|
||||
(c) => c.id === organisation_country_id
|
||||
(c) => c.country_code === organisation_country_code
|
||||
);
|
||||
|
||||
await user.updateUserProfile(typedProfileData);
|
||||
|
|
@ -219,12 +221,16 @@ async function avatarUpload(e: Event) {
|
|||
|
||||
<select
|
||||
id="country"
|
||||
v-model="formData.country_id"
|
||||
v-model="formData.country_code"
|
||||
name="country"
|
||||
autocomplete="country-name"
|
||||
class="disabled:bg-gray-50 mb-4 block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 disabled:cursor-not-allowed disabled:text-gray-500 disabled:ring-gray-200 sm:max-w-sm sm:text-sm sm:leading-6"
|
||||
>
|
||||
<option v-for="country in countries" :key="country.id" :value="country.id">
|
||||
<option
|
||||
v-for="country in countries"
|
||||
:key="country.country_code"
|
||||
:value="country.country_code"
|
||||
>
|
||||
{{ country.name }}
|
||||
</option>
|
||||
</select>
|
||||
|
|
@ -325,13 +331,17 @@ async function avatarUpload(e: Event) {
|
|||
|
||||
<select
|
||||
id="org-country"
|
||||
v-model="formData.organisation_country_id"
|
||||
v-model="formData.organisation_country_code"
|
||||
required
|
||||
name="org-country"
|
||||
autocomplete="country-name"
|
||||
class="disabled:bg-gray-50 mb-4 block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 disabled:cursor-not-allowed disabled:text-gray-500 disabled:ring-gray-200 sm:max-w-sm sm:text-sm sm:leading-6"
|
||||
>
|
||||
<option v-for="country in countries" :key="country.id" :value="country.id">
|
||||
<option
|
||||
v-for="country in countries"
|
||||
:key="country.country_code"
|
||||
:value="country.country_code"
|
||||
>
|
||||
{{ country.name }}
|
||||
</option>
|
||||
</select>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ export type Organisation = {
|
|||
};
|
||||
|
||||
export type Country = {
|
||||
id: number;
|
||||
country_code: string;
|
||||
vbv_country_id: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@ from dotenv import dotenv_values
|
|||
script_path = os.path.abspath(__file__)
|
||||
script_dir = os.path.dirname(script_path)
|
||||
|
||||
dev_env = dotenv_values(
|
||||
f"{script_dir}/../../../env_secrets/caprover_vbv-develop.env"
|
||||
)
|
||||
dev_env = dotenv_values(f"{script_dir}/../../../env_secrets/caprover_vbv-develop.env")
|
||||
|
||||
os.environ["IT_APP_ENVIRONMENT"] = "local"
|
||||
|
||||
|
|
|
|||
|
|
@ -42,58 +42,32 @@ class EntitiesViewTest(APITestCase):
|
|||
},
|
||||
)
|
||||
|
||||
countries = response.data["countries"]
|
||||
|
||||
self.assertEqual(
|
||||
countries[0],
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Afghanistan",
|
||||
},
|
||||
)
|
||||
|
||||
def test_list_country_entities_ordered_by_country_id(self) -> None:
|
||||
# GIVEN
|
||||
url = reverse("list_entities")
|
||||
|
||||
first_country = Country.objects.get(country_id=1)
|
||||
|
||||
# WHEN
|
||||
response = self.client.get(url)
|
||||
|
||||
# THEN
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
countries = response.data["countries"]
|
||||
|
||||
self.assertEqual(
|
||||
countries[0],
|
||||
{
|
||||
"id": first_country.country_id,
|
||||
"name": first_country.name_de,
|
||||
},
|
||||
)
|
||||
|
||||
def test_list_country_entities_ordered_by_order_id(self) -> None:
|
||||
# GIVEN
|
||||
url = reverse("list_entities")
|
||||
|
||||
switzerland = Country.objects.get(name_de="Schweiz")
|
||||
switzerland.order_id = 1
|
||||
switzerland.save()
|
||||
|
||||
# WHEN
|
||||
response = self.client.get(url)
|
||||
|
||||
# THEN
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
countries = response.data["countries"]
|
||||
|
||||
self.assertEqual(
|
||||
countries[0],
|
||||
{
|
||||
"id": switzerland.country_id,
|
||||
"name": switzerland.name_de,
|
||||
"country_code": "CH",
|
||||
"vbv_country_id": 209,
|
||||
"name": "Schweiz",
|
||||
},
|
||||
)
|
||||
|
||||
usa = Country.objects.get(country_code="US")
|
||||
usa.order_id = 0.5
|
||||
usa.save()
|
||||
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
countries = response.data["countries"]
|
||||
self.assertEqual(
|
||||
countries[0],
|
||||
{
|
||||
"country_code": "US",
|
||||
"vbv_country_id": usa.vbv_country_id,
|
||||
"name": usa.name_de,
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ class OrganisationAdmin(admin.ModelAdmin):
|
|||
class CountryAdmin(admin.ModelAdmin):
|
||||
list_display = (
|
||||
"order_id",
|
||||
"country_id",
|
||||
"country_code",
|
||||
"vbv_country_id",
|
||||
"name_de",
|
||||
"name_fr",
|
||||
"name_it",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,15 @@
|
|||
|
||||
from django.db import migrations, models
|
||||
|
||||
from vbv_lernwelt.core.model_utils import countries
|
||||
|
||||
|
||||
def populate_country_order_id(apps, schema_editor):
|
||||
Country = apps.get_model("core", "Country")
|
||||
for country in Country.objects.all():
|
||||
country.order_id = countries[country.country_id].get("order_id", 20.0)
|
||||
country.save(update_fields=["order_id"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
|
|
@ -22,4 +31,5 @@ class Migration(migrations.Migration):
|
|||
name="order_id",
|
||||
field=models.FloatField(default=20),
|
||||
),
|
||||
migrations.RunPython(populate_country_order_id),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -4,15 +4,14 @@ from django.db import migrations, models
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0007_auto_20240220_1058'),
|
||||
("core", "0007_auto_20240220_1058"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='abacus_debitor_number',
|
||||
model_name="user",
|
||||
name="abacus_debitor_number",
|
||||
field=models.BigIntegerField(blank=True, null=True, unique=True),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
# Generated by Django 3.2.20 on 2024-05-30 10:34
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
from vbv_lernwelt.core.model_utils import countries
|
||||
|
||||
|
||||
def populate_country_code(apps, schema_editor):
|
||||
Country = apps.get_model("core", "Country")
|
||||
for country in Country.objects.all():
|
||||
country.country_code = countries[country.country_id]["country_code"]
|
||||
country.save(update_fields=["country_code"])
|
||||
|
||||
|
||||
def migrate_user_country(apps, schema_editor):
|
||||
User = apps.get_model("core", "User")
|
||||
Country = apps.get_model("core", "Country")
|
||||
for user in User.objects.all():
|
||||
if user.old_country:
|
||||
country = Country.objects.get(vbv_country_id=user.old_country)
|
||||
user.country = country
|
||||
if user.old_organisation_country:
|
||||
country = Country.objects.get(vbv_country_id=user.old_organisation_country)
|
||||
user.organisation_country = country
|
||||
user.save(update_fields=["country", "organisation_country"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("core", "0008_user_abacus_debitor_number"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="country",
|
||||
field=models.IntegerField(null=True, blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="organisation_country",
|
||||
field=models.IntegerField(null=True, blank=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="country",
|
||||
name="country_code",
|
||||
field=models.CharField(max_length=2, null=True),
|
||||
),
|
||||
migrations.RunPython(populate_country_code),
|
||||
migrations.AlterField(
|
||||
model_name="country",
|
||||
name="country_id",
|
||||
field=models.IntegerField(),
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name="country", old_name="country_id", new_name="vbv_country_id"
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="country",
|
||||
name="country_code",
|
||||
field=models.CharField(max_length=2, primary_key=True, serialize=False),
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name="user",
|
||||
old_name="country",
|
||||
new_name="old_country",
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name="user",
|
||||
old_name="organisation_country",
|
||||
new_name="old_organisation_country",
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="user",
|
||||
name="country",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=models.deletion.SET_NULL,
|
||||
related_name="user_country",
|
||||
to="core.country",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="user",
|
||||
name="organisation_country",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=models.deletion.SET_NULL,
|
||||
related_name="organisation_country",
|
||||
to="core.country",
|
||||
),
|
||||
),
|
||||
migrations.RunPython(migrate_user_country),
|
||||
migrations.RemoveField(
|
||||
model_name="user",
|
||||
name="old_country",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="user",
|
||||
name="old_organisation_country",
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name="country",
|
||||
options={
|
||||
"ordering": ["order_id", "vbv_country_id"],
|
||||
"verbose_name": "Country",
|
||||
"verbose_name_plural": "Countries",
|
||||
},
|
||||
),
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -25,19 +25,20 @@ class Organisation(models.Model):
|
|||
|
||||
|
||||
class Country(models.Model):
|
||||
country_id = models.IntegerField(primary_key=True)
|
||||
country_code = models.CharField(max_length=2, primary_key=True)
|
||||
vbv_country_id = models.IntegerField(primary_key=False)
|
||||
name_de = models.CharField(max_length=255)
|
||||
name_fr = models.CharField(max_length=255)
|
||||
name_it = models.CharField(max_length=255)
|
||||
order_id = models.FloatField(default=20)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name_de} ({self.country_id})"
|
||||
return f"{self.name_de} ({self.country_code}) ({self.vbv_country_id})"
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Country"
|
||||
verbose_name_plural = "Countries"
|
||||
ordering = ["order_id", "country_id"]
|
||||
ordering = ["order_id", "vbv_country_id"]
|
||||
|
||||
|
||||
class User(AbstractUser):
|
||||
|
|
|
|||
|
|
@ -14,12 +14,11 @@ def create_json_from_objects(objects, serializer_class, many=True) -> str:
|
|||
|
||||
|
||||
class CountrySerializer(serializers.ModelSerializer):
|
||||
id = serializers.IntegerField(source="country_id", read_only=True)
|
||||
name = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Country
|
||||
fields = ["id", "name"]
|
||||
fields = ["country_code", "vbv_country_id", "name"]
|
||||
|
||||
def get_name(self, obj):
|
||||
language = self.context.get("langauge")
|
||||
|
|
@ -32,11 +31,15 @@ class CountrySerializer(serializers.ModelSerializer):
|
|||
return obj.name_de
|
||||
|
||||
def to_internal_value(self, data):
|
||||
country_id = data.get("id")
|
||||
if country_id is not None:
|
||||
country_code = data.get("country_code")
|
||||
if country_code is not None:
|
||||
try:
|
||||
country = Country.objects.get(country_id=country_id)
|
||||
return {"id": country.country_id, "name": self.get_name(country)}
|
||||
country = Country.objects.get(country_code=country_code)
|
||||
return {
|
||||
"country_code": country.country_code,
|
||||
"vbv_country_id": country.vbv_country_id,
|
||||
"name": self.get_name(country),
|
||||
}
|
||||
except Country.DoesNotExist:
|
||||
raise serializers.ValidationError({"id": "Invalid country ID"})
|
||||
return super().to_internal_value(data)
|
||||
|
|
@ -105,14 +108,14 @@ class UserSerializer(serializers.ModelSerializer):
|
|||
setattr(instance, attr, value)
|
||||
|
||||
if country_data is not None:
|
||||
country_id = country_data.get("id")
|
||||
country_instance = Country.objects.filter(country_id=country_id).first()
|
||||
country_code = country_data.get("country_code")
|
||||
country_instance = Country.objects.filter(country_code=country_code).first()
|
||||
instance.country = country_instance
|
||||
|
||||
if organisation_country_data is not None:
|
||||
organisation_country_id = organisation_country_data.get("id")
|
||||
organisation_country_code = organisation_country_data.get("country_code")
|
||||
organisation_country_instance = Country.objects.filter(
|
||||
country_id=organisation_country_id
|
||||
country_code=organisation_country_code
|
||||
).first()
|
||||
instance.organisation_country = organisation_country_instance
|
||||
|
||||
|
|
|
|||
|
|
@ -74,3 +74,6 @@ After everything runs fine, we should be able to remove the following deprecated
|
|||
8. `IT_OAUTH_SCOPE`
|
||||
|
||||
|
||||
### Datatrans Test Credit Card
|
||||
|
||||
5100 0010 0000 0014 06/25 123
|
||||
|
|
|
|||
|
|
@ -3,6 +3,16 @@
|
|||
from django.db import migrations, models
|
||||
|
||||
|
||||
def add_default_shop_product(apps, schema_editor):
|
||||
Product = apps.get_model("shop", "Product")
|
||||
Product.objects.create(
|
||||
sku="vv-de",
|
||||
name="Versicherungsvermittler/-in VBV",
|
||||
description="Versicherungsvermittler/-in VBV DE",
|
||||
price=324_00,
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("shop", "0008_auto_20231117_0905"),
|
||||
|
|
@ -16,4 +26,5 @@ class Migration(migrations.Migration):
|
|||
help_text="The total price of the product in centimes -> 1000 = 10.00 CHF"
|
||||
),
|
||||
),
|
||||
migrations.RunPython(add_default_shop_product),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -4,15 +4,14 @@ from django.db import migrations, models
|
|||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('shop', '0012_delete_country'),
|
||||
("shop", "0012_delete_country"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='checkoutinformation',
|
||||
name='abacus_order_id',
|
||||
model_name="checkoutinformation",
|
||||
name="abacus_order_id",
|
||||
field=models.BigIntegerField(blank=True, null=True, unique=True),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ from vbv_lernwelt.core.admin import User
|
|||
from vbv_lernwelt.core.create_default_users import create_default_users
|
||||
from vbv_lernwelt.shop.invoice.abacus import (
|
||||
AbacusInvoiceCreator,
|
||||
render_invoice_xml,
|
||||
render_customer_xml,
|
||||
create_invoice_xml,
|
||||
create_customer_xml,
|
||||
create_invoice_xml,
|
||||
render_customer_xml,
|
||||
render_invoice_xml,
|
||||
)
|
||||
from vbv_lernwelt.shop.invoice.repositories import InvoiceRepository
|
||||
from vbv_lernwelt.shop.models import CheckoutInformation
|
||||
|
|
|
|||
|
|
@ -275,7 +275,9 @@ def update_user_address(user: User, checkout_info: CheckoutInformation):
|
|||
user.city = checkout_info.city
|
||||
|
||||
if checkout_info.country:
|
||||
user.country = Country.objects.filter(country_id=checkout_info.country).first()
|
||||
user.country = Country.objects.filter(
|
||||
country_code=checkout_info.country
|
||||
).first()
|
||||
|
||||
if (
|
||||
checkout_info.company_name
|
||||
|
|
@ -292,7 +294,7 @@ def update_user_address(user: User, checkout_info: CheckoutInformation):
|
|||
user.organisation_city = checkout_info.company_city
|
||||
|
||||
user.organisation_country = Country.objects.filter(
|
||||
country_id=checkout_info.company_country
|
||||
country_code=checkout_info.company_country
|
||||
).first()
|
||||
|
||||
user.invoice_address = User.INVOICE_ADDRESS_ORGANISATION
|
||||
|
|
|
|||
Loading…
Reference in New Issue