diff --git a/.env.example b/.env.example
index 855246ae4..4667e35fc 100644
--- a/.env.example
+++ b/.env.example
@@ -80,7 +80,7 @@ ALLOW_REMOTE_USER_AUTH=False
LOCATIONS_SEARCH_API="https://api3.geo.admin.ch/rest/services/api/SearchServer"
LOCATIONS_SEARCH_API_DETAILS="https://api3.geo.admin.ch/rest/services/api/MapServer/ch.bfs.gebaeude_wohnungs_register/"
# Local directory on docker host for temporary storage of archive folders
-ARCHIVE_DIR=
+ARCHIVE_DIR=archive
# Isolated network for print service
# This has to be unique for multiple instance on same docker host
ISOLATED_NETWORK_NAME=geocity_isolated_1
diff --git a/README.md b/README.md
index a052bcfbe..6c41457e2 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
**[What is Geocity ?](https://geocity-asso.ch)**
-**[Features and user guide](https://github.com/yverdon/geocity/wiki)**
+**[Features and user guide](https://gitlab.com/geocity/geocity/-/wikis/home)**
## Setting up full Docker non persistent demo
diff --git a/geocity/apps/accounts/dootix/adapter.py b/geocity/apps/accounts/dootix/adapter.py
index 420e73581..328813581 100644
--- a/geocity/apps/accounts/dootix/adapter.py
+++ b/geocity/apps/accounts/dootix/adapter.py
@@ -41,6 +41,7 @@ def save_user(self, request, sociallogin: SocialLogin, form=None):
address=form.cleaned_data["address"],
zipcode=form.cleaned_data["zipcode"],
city=form.cleaned_data["city"],
+ country=form.cleaned_data["country"],
phone_first=form.cleaned_data["phone_first"],
phone_second=form.cleaned_data["phone_second"],
company_name=form.cleaned_data["company_name"],
diff --git a/geocity/apps/accounts/forms.py b/geocity/apps/accounts/forms.py
index f4161a006..678a4215e 100644
--- a/geocity/apps/accounts/forms.py
+++ b/geocity/apps/accounts/forms.py
@@ -5,8 +5,9 @@
from django.conf import settings
from django.contrib.auth import authenticate
from django.contrib.auth.forms import AuthenticationForm, BaseUserCreationForm
-from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
+from django.core.validators import MinValueValidator, RegexValidator
from django.utils.translation import gettext_lazy as _
+from django_countries.fields import CountryField
from geocity.fields import AddressWidget
@@ -226,8 +227,8 @@ def __init__(self, *args, **kwargs):
)
zipcode = forms.IntegerField(
- label=_("NPA"),
- validators=[MinValueValidator(1000), MaxValueValidator(9999)],
+ label=_("Code postal"),
+ validators=[MinValueValidator(1)],
widget=forms.NumberInput(attrs={"required": "required"}),
)
city = forms.CharField(
@@ -245,6 +246,7 @@ class Meta:
"address",
"zipcode",
"city",
+ "country",
"phone_first",
"phone_second",
"company_name",
@@ -295,11 +297,11 @@ class SocialSignupForm(SignupForm):
)
zipcode = forms.IntegerField(
- label=_("NPA"),
- min_value=1000,
- max_value=9999,
+ label=_("Code postal"),
+ min_value=1,
widget=forms.NumberInput(attrs={"required": "required"}),
)
+
city = forms.CharField(
max_length=100,
label=_("Ville"),
@@ -307,6 +309,9 @@ class SocialSignupForm(SignupForm):
attrs={"placeholder": "ex: Yverdon", "required": "required"}
),
)
+
+ country = CountryField().formfield(initial="CH")
+
phone_first = forms.CharField(
label=_("Téléphone principal"),
max_length=20,
@@ -314,7 +319,7 @@ class SocialSignupForm(SignupForm):
widget=forms.TextInput(attrs={"placeholder": "ex: 024 111 22 22"}),
validators=[
RegexValidator(
- regex=r"^(((\+41)\s?)|(0))?(\d{2})\s?(\d{3})\s?(\d{2})\s?(\d{2})$",
+ regex=r"^(?:\+(?:[0-9] ?){6,14}[0-9]|0\d(?: ?\d){8,13})$",
message="Seuls les chiffres et les espaces sont autorisés.",
)
],
diff --git a/geocity/apps/accounts/geomapfish/adapter.py b/geocity/apps/accounts/geomapfish/adapter.py
index 1a0672514..9ad43c4d0 100644
--- a/geocity/apps/accounts/geomapfish/adapter.py
+++ b/geocity/apps/accounts/geomapfish/adapter.py
@@ -42,6 +42,7 @@ def save_user(self, request, sociallogin: SocialLogin, form=None):
address=form.cleaned_data["address"],
zipcode=form.cleaned_data["zipcode"],
city=form.cleaned_data["city"],
+ country=form.cleaned_data["country"],
phone_first=form.cleaned_data["phone_first"],
phone_second=form.cleaned_data["phone_second"],
company_name=form.cleaned_data["company_name"],
diff --git a/geocity/apps/accounts/migrations/0020_historicaluserprofile_country_userprofile_country.py b/geocity/apps/accounts/migrations/0020_historicaluserprofile_country_userprofile_country.py
new file mode 100644
index 000000000..5a6314239
--- /dev/null
+++ b/geocity/apps/accounts/migrations/0020_historicaluserprofile_country_userprofile_country.py
@@ -0,0 +1,38 @@
+# Generated by Django 4.2.11 on 2024-05-29 09:09
+
+import django_countries.fields
+from django.db import migrations
+
+
+def set_country_to_null(apps, schema_editor):
+ UserProfile = apps.get_model("accounts", "UserProfile")
+ HistoricalUserProfile = apps.get_model("accounts", "HistoricalUserProfile")
+
+ UserProfile.objects.all().update(country=None)
+ HistoricalUserProfile.objects.all().update(country=None)
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("accounts", "0019_administrativeentity_agenda_domain"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="historicaluserprofile",
+ name="country",
+ field=django_countries.fields.CountryField(
+ default="CH", max_length=2, null=True, verbose_name="Pays"
+ ),
+ ),
+ migrations.AddField(
+ model_name="userprofile",
+ name="country",
+ field=django_countries.fields.CountryField(
+ default="CH", max_length=2, null=True, verbose_name="Pays"
+ ),
+ ),
+ # Dont add the default value to the existing users
+ migrations.RunPython(set_country_to_null),
+ ]
diff --git a/geocity/apps/accounts/migrations/0021_alter_administrativeentity_phone_and_more.py b/geocity/apps/accounts/migrations/0021_alter_administrativeentity_phone_and_more.py
new file mode 100644
index 000000000..8267468f2
--- /dev/null
+++ b/geocity/apps/accounts/migrations/0021_alter_administrativeentity_phone_and_more.py
@@ -0,0 +1,97 @@
+# Generated by Django 4.2.11 on 2024-05-30 08:58
+
+import django.core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("accounts", "0020_historicaluserprofile_country_userprofile_country"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="administrativeentity",
+ name="phone",
+ field=models.CharField(
+ blank=True,
+ max_length=20,
+ validators=[
+ django.core.validators.RegexValidator(
+ message="Seuls les chiffres et les espaces sont autorisés.",
+ regex="^(?:\\+(?:[0-9] ?){6,14}[0-9]|0\\d(?: ?\\d){8,13})$",
+ )
+ ],
+ verbose_name="Téléphone",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="historicaluserprofile",
+ name="phone_first",
+ field=models.CharField(
+ max_length=20,
+ validators=[
+ django.core.validators.RegexValidator(
+ message="Seuls les chiffres et les espaces sont autorisés.",
+ regex="^(?:\\+(?:[0-9] ?){6,14}[0-9]|0\\d(?: ?\\d){8,13})$",
+ )
+ ],
+ verbose_name="Téléphone principal",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="historicaluserprofile",
+ name="phone_second",
+ field=models.CharField(
+ blank=True,
+ max_length=20,
+ validators=[
+ django.core.validators.RegexValidator(
+ message="Seuls les chiffres et les espaces sont autorisés.",
+ regex="^(?:\\+(?:[0-9] ?){6,14}[0-9]|0\\d(?: ?\\d){8,13})$",
+ )
+ ],
+ verbose_name="Téléphone secondaire",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="historicaluserprofile",
+ name="zipcode",
+ field=models.PositiveIntegerField(verbose_name="Code postal"),
+ ),
+ migrations.AlterField(
+ model_name="userprofile",
+ name="phone_first",
+ field=models.CharField(
+ max_length=20,
+ validators=[
+ django.core.validators.RegexValidator(
+ message="Seuls les chiffres et les espaces sont autorisés.",
+ regex="^(?:\\+(?:[0-9] ?){6,14}[0-9]|0\\d(?: ?\\d){8,13})$",
+ )
+ ],
+ verbose_name="Téléphone principal",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="userprofile",
+ name="phone_second",
+ field=models.CharField(
+ blank=True,
+ max_length=20,
+ validators=[
+ django.core.validators.RegexValidator(
+ message="Seuls les chiffres et les espaces sont autorisés.",
+ regex="^(?:\\+(?:[0-9] ?){6,14}[0-9]|0\\d(?: ?\\d){8,13})$",
+ )
+ ],
+ verbose_name="Téléphone secondaire",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="userprofile",
+ name="zipcode",
+ field=models.PositiveIntegerField(verbose_name="Code postal"),
+ ),
+ ]
diff --git a/geocity/apps/accounts/models.py b/geocity/apps/accounts/models.py
index 0f1ad8aa7..a1239a217 100644
--- a/geocity/apps/accounts/models.py
+++ b/geocity/apps/accounts/models.py
@@ -3,12 +3,7 @@
from django.contrib.gis.db import models as geomodels
from django.contrib.sites.models import Site
from django.core.exceptions import ObjectDoesNotExist, ValidationError
-from django.core.validators import (
- FileExtensionValidator,
- MaxValueValidator,
- MinValueValidator,
- RegexValidator,
-)
+from django.core.validators import FileExtensionValidator, RegexValidator
from django.db import models
from django.db.models import BooleanField, Count, ExpressionWrapper, Q, UniqueConstraint
from django.db.models.signals import post_save
@@ -17,6 +12,7 @@
from django.utils.functional import cached_property
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
+from django_countries.fields import CountryField
from simple_history.models import HistoricalRecords
from taggit.managers import TaggableManager
@@ -293,7 +289,7 @@ class AdministrativeEntity(models.Model):
max_length=20,
validators=[
RegexValidator(
- regex=r"^(((\+41)\s?)|(0))?(\d{2})\s?(\d{3})\s?(\d{2})\s?(\d{2})$",
+ regex=r"^(?:\+(?:[0-9] ?){6,14}[0-9]|0\d(?: ?\d){8,13})$",
message="Seuls les chiffres et les espaces sont autorisés.",
)
],
@@ -583,19 +579,24 @@ class UserProfile(models.Model):
max_length=100,
)
zipcode = models.PositiveIntegerField(
- _("NPA"),
- validators=[MinValueValidator(1000), MaxValueValidator(9999)],
+ _("Code postal"),
)
city = models.CharField(
_("Ville"),
max_length=100,
)
+ country = CountryField(
+ _("Pays"),
+ null=True,
+ blank=False,
+ default="CH",
+ )
phone_first = models.CharField(
_("Téléphone principal"),
max_length=20,
validators=[
RegexValidator(
- regex=r"^(((\+41)\s?)|(0))?(\d{2})\s?(\d{3})\s?(\d{2})\s?(\d{2})$",
+ regex=r"^(?:\+(?:[0-9] ?){6,14}[0-9]|0\d(?: ?\d){8,13})$",
message="Seuls les chiffres et les espaces sont autorisés.",
)
],
@@ -606,7 +607,7 @@ class UserProfile(models.Model):
max_length=20,
validators=[
RegexValidator(
- regex=r"^(((\+41)\s?)|(0))?(\d{2})\s?(\d{3})\s?(\d{2})\s?(\d{2})$",
+ regex=r"^(?:\+(?:[0-9] ?){6,14}[0-9]|0\d(?: ?\d){8,13})$",
message="Seuls les chiffres et les espaces sont autorisés.",
)
],
diff --git a/geocity/apps/api/serializers.py b/geocity/apps/api/serializers.py
index 9a165860f..94c9566fe 100644
--- a/geocity/apps/api/serializers.py
+++ b/geocity/apps/api/serializers.py
@@ -451,6 +451,7 @@ class Meta:
"zipcode",
"user_id",
"city",
+ "country",
"company_name",
"vat_number",
"iban",
diff --git a/geocity/apps/api/services.py b/geocity/apps/api/services.py
index a5e0d6451..75de5266b 100644
--- a/geocity/apps/api/services.py
+++ b/geocity/apps/api/services.py
@@ -3,6 +3,7 @@
from io import BytesIO
from django.conf import settings
+from django.core.exceptions import SuspiciousOperation
from django.db.models import Q
from django.utils.text import get_valid_filename
from PIL import Image
@@ -22,7 +23,11 @@ def get_mime_type(content):
"""
Used to retrieve mime type in response.content of request
"""
- image = Image.open(BytesIO(content))
+ try:
+ image = Image.open(BytesIO(content))
+ except:
+ raise SuspiciousOperation
+
image_format = image.format
mime_type = "image/" + image_format.lower()
return mime_type
diff --git a/geocity/apps/core/static/css/contactform.css b/geocity/apps/core/static/css/contactform.css
index 94ce36ce7..b4c9831c8 100644
--- a/geocity/apps/core/static/css/contactform.css
+++ b/geocity/apps/core/static/css/contactform.css
@@ -11,3 +11,8 @@ select[readonly] {
border: 0;
font-weight: bold;
}
+
+.disabled-dropdown {
+ background-color: #e9ecef;
+ pointer-events: none;
+}
diff --git a/geocity/apps/core/static/js/submission_contacts.js b/geocity/apps/core/static/js/submission_contacts.js
index adc69c206..adbb68bfd 100644
--- a/geocity/apps/core/static/js/submission_contacts.js
+++ b/geocity/apps/core/static/js/submission_contacts.js
@@ -1,15 +1,30 @@
let update_form_value = function(item, userprofile) {
-
if (document.getElementById(`self_contact_${parseInt(item) + 1}`).checked == true) {
document.getElementById(`id_form-${item}-first_name`).value = userprofile.first_name;
for (const [key, value] of Object.entries(userprofile)) {
- document.getElementById(`id_form-${item}-${key}`).value = value;
- document.getElementById(`id_form-${item}-${key}`).readOnly = true;
+ let element = document.getElementById(`id_form-${item}-${key}`);
+ if (element !== null) {
+ element.value = value;
+ // Pseudo disable the dropdown with CSS instead of setting it read-only
+ if (key === "country") {
+ element.classList.add("disabled-dropdown");
+ } else {
+ element.readOnly = true;
+ }
+ }
}
} else {
for (const [key, value] of Object.entries(userprofile)) {
- document.getElementById(`id_form-${item}-${key}`).value = '';
- document.getElementById(`id_form-${item}-${key}`).readOnly = false;
+ let element = document.getElementById(`id_form-${item}-${key}`);
+ if (element !== null) {
+ element.value = '';
+ element.readOnly = false;
+ if (key === "country") {
+ element.classList.remove("disabled-dropdown");
+ } else {
+ element.readOnly = false;
+ }
+ }
}
}
}
@@ -17,7 +32,11 @@ let update_form_value = function(item, userprofile) {
// Create a label to replace .form-control without .extra-form in classes inside of forms-container
window.addEventListener('load', function () {
var forms_control = document.querySelectorAll("[id=forms-container] select[class*=form-control]");
- for (form_control of forms_control) {
+ for (let form_control of forms_control) {
+ // Skip the country select field
+ if (form_control.classList.contains("country")) {
+ continue;
+ }
let elem = document.createElement('label');
let text = form_control.querySelector("option[selected]").text
let div = form_control.closest('.col-md-9');
diff --git a/geocity/apps/forms/migrations/0036_alter_formcategory_meta_type.py b/geocity/apps/forms/migrations/0036_alter_formcategory_meta_type.py
new file mode 100644
index 000000000..82ee85ae3
--- /dev/null
+++ b/geocity/apps/forms/migrations/0036_alter_formcategory_meta_type.py
@@ -0,0 +1,31 @@
+# Generated by Django 4.2.11 on 2024-06-03 06:35
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("forms", "0035_service_fee"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="formcategory",
+ name="meta_type",
+ field=models.IntegerField(
+ choices=[
+ (0, "Autres"),
+ (1, "Chantier"),
+ (2, "Construction"),
+ (3, "Événement sportif"),
+ (4, "Événement culturel"),
+ (5, "Événement commercial"),
+ (6, "Dispositif de police"),
+ ],
+ default=0,
+ help_text="Utilisé dans le calendrier afin de filtrer par type d'événement",
+ verbose_name="Type générique",
+ ),
+ ),
+ ]
diff --git a/geocity/apps/forms/models.py b/geocity/apps/forms/models.py
index 3d58c8a44..e69a98661 100644
--- a/geocity/apps/forms/models.py
+++ b/geocity/apps/forms/models.py
@@ -60,7 +60,10 @@ class FormCategory(models.Model):
limit_choices_to={"permit_department__is_integrator_admin": True},
)
meta_type = models.IntegerField(
- _("Type générique"), choices=META_TYPE_CHOICES, default=META_TYPE_OTHER
+ _("Type générique"),
+ choices=META_TYPE_CHOICES,
+ default=META_TYPE_OTHER,
+ help_text="Utilisé dans le calendrier afin de filtrer par type d'événement",
)
tags = TaggableManager(
blank=True,
diff --git a/geocity/apps/reports/templates/reports/sections/sectionauthor.html b/geocity/apps/reports/templates/reports/sections/sectionauthor.html
index 725123cdd..2d44d7d4a 100644
--- a/geocity/apps/reports/templates/reports/sections/sectionauthor.html
+++ b/geocity/apps/reports/templates/reports/sections/sectionauthor.html
@@ -18,11 +18,14 @@
Adresse : {{submission.author.userprofile.address}}
{% endif %}
{% if submission.author.userprofile.zipcode %}
- NPA : {{submission.author.userprofile.zipcode}}
+ Code postal : {{submission.author.userprofile.zipcode}}
{% endif %}
{% if submission.author.userprofile.city %}
Localité : {{submission.author.userprofile.city}}
{% endif %}
+ {% if submission.author.userprofile.country %}
+ Pays : {{submission.author.userprofile.country.name}}
+ {% endif %}
{% if submission.author.userprofile.company_name %}
Raison sociale : {{submission.author.userprofile.company_name}}
{% endif %}
diff --git a/geocity/apps/reports/templates/reports/sections/sectioncontact.html b/geocity/apps/reports/templates/reports/sections/sectioncontact.html
index d5d959e06..89d1eec45 100644
--- a/geocity/apps/reports/templates/reports/sections/sectioncontact.html
+++ b/geocity/apps/reports/templates/reports/sections/sectioncontact.html
@@ -23,11 +23,14 @@
Adresse : {{contact.address}}
{% endif %}
{% if contact.zipcode %}
- NPA : {{contact.zipcode}}
+ Code postal : {{contact.zipcode}}
{% endif %}
{% if contact.city %}
Localité : {{contact.city}}
{% endif %}
+ {% if contact.country %}
+ Pays : {{contact.country.name}}
+ {% endif %}
{% if contact.company_name %}
Raison sociale : {{contact.company_name}}
{% endif %}
diff --git a/geocity/apps/reports/templates/reports/sections/sectionrecipient.html b/geocity/apps/reports/templates/reports/sections/sectionrecipient.html
index ff316c27b..25453b243 100644
--- a/geocity/apps/reports/templates/reports/sections/sectionrecipient.html
+++ b/geocity/apps/reports/templates/reports/sections/sectionrecipient.html
@@ -13,6 +13,9 @@
{{recipient.last_name}} {{recipient.first_name}}
{{recipient.address}}
{{recipient.zipcode}} {{recipient.city}}
+ {% if recipient.country %}
+
{{recipient.country.name}}
+ {% endif %}
{% endblock %}
diff --git a/geocity/apps/submissions/forms.py b/geocity/apps/submissions/forms.py
index 903150034..f6fbd939e 100644
--- a/geocity/apps/submissions/forms.py
+++ b/geocity/apps/submissions/forms.py
@@ -18,15 +18,15 @@
from django.contrib.gis import forms as geoforms
from django.core.exceptions import ValidationError
from django.core.files import File
-from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
+from django.core.validators import MinValueValidator, RegexValidator
from django.db import transaction
from django.db.models import Max, Q
from django.forms import modelformset_factory
from django.urls import reverse
from django.utils import timezone
-from django.utils.safestring import mark_safe
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
+from django_countries.fields import CountryField
from django_select2.forms import Select2MultipleWidget, Select2Widget
from geocity.apps.accounts.models import (
@@ -898,8 +898,8 @@ class SubmissionContactForm(forms.ModelForm):
"company_name",
"vat_number",
"address",
- "address",
"city",
+ "country",
"phone",
"zipcode",
"email",
@@ -934,10 +934,8 @@ class SubmissionContactForm(forms.ModelForm):
),
validators=[
RegexValidator(
- regex=r"^(((\+41)\s?)|(0))?(\d{2})\s?(\d{3})\s?(\d{2})\s?(\d{2})$",
- message=mark_safe(
- 'Veuillez saisir un numéro de téléphone suisse valide.'
- ),
+ regex=r"^(?:\+(?:[0-9] ?){6,14}[0-9]|0\d(?: ?\d){8,13})$",
+ message="Seuls les chiffres et les espaces sont autorisés.",
)
],
)
@@ -962,8 +960,8 @@ class SubmissionContactForm(forms.ModelForm):
)
zipcode = forms.IntegerField(
- label=_("NPA"),
- validators=[MinValueValidator(1000), MaxValueValidator(9999)],
+ label=_("Code postal"),
+ validators=[MinValueValidator(1)],
widget=forms.NumberInput(),
)
city = forms.CharField(
@@ -975,6 +973,10 @@ class SubmissionContactForm(forms.ModelForm):
}
),
)
+ country = CountryField().formfield(
+ label=_("Pays"),
+ widget=forms.Select(attrs={"class": "country"}),
+ )
company_name = forms.CharField(
required=False,
label=_("Raison sociale"),
diff --git a/geocity/apps/submissions/migrations/0031_contact_country_historicalcontact_country.py b/geocity/apps/submissions/migrations/0031_contact_country_historicalcontact_country.py
new file mode 100644
index 000000000..3193e7aeb
--- /dev/null
+++ b/geocity/apps/submissions/migrations/0031_contact_country_historicalcontact_country.py
@@ -0,0 +1,28 @@
+# Generated by Django 4.2.11 on 2024-05-29 15:04
+
+import django_countries.fields
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("submissions", "0030_alter_servicefeetype_fix_price_editable"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="contact",
+ name="country",
+ field=django_countries.fields.CountryField(
+ max_length=2, null=True, verbose_name="Pays"
+ ),
+ ),
+ migrations.AddField(
+ model_name="historicalcontact",
+ name="country",
+ field=django_countries.fields.CountryField(
+ max_length=2, null=True, verbose_name="Pays"
+ ),
+ ),
+ ]
diff --git a/geocity/apps/submissions/migrations/0032_alter_contact_zipcode_and_more.py b/geocity/apps/submissions/migrations/0032_alter_contact_zipcode_and_more.py
new file mode 100644
index 000000000..65621c86c
--- /dev/null
+++ b/geocity/apps/submissions/migrations/0032_alter_contact_zipcode_and_more.py
@@ -0,0 +1,23 @@
+# Generated by Django 4.2.11 on 2024-05-30 08:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("submissions", "0031_contact_country_historicalcontact_country"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="contact",
+ name="zipcode",
+ field=models.PositiveIntegerField(verbose_name="Code postal"),
+ ),
+ migrations.AlterField(
+ model_name="historicalcontact",
+ name="zipcode",
+ field=models.PositiveIntegerField(verbose_name="Code postal"),
+ ),
+ ]
diff --git a/geocity/apps/submissions/models.py b/geocity/apps/submissions/models.py
index 209c54941..d7e85b386 100644
--- a/geocity/apps/submissions/models.py
+++ b/geocity/apps/submissions/models.py
@@ -39,6 +39,7 @@
from django.utils.functional import cached_property
from django.utils.html import escape, format_html
from django.utils.translation import gettext_lazy as _
+from django_countries.fields import CountryField
from pdf2image import convert_from_path
from PIL import Image
from simple_history.models import HistoricalRecords
@@ -1461,12 +1462,17 @@ class Contact(models.Model):
max_length=100,
)
zipcode = models.PositiveIntegerField(
- _("NPA"),
+ _("Code postal"),
)
city = models.CharField(
_("Ville"),
max_length=100,
)
+ country = CountryField(
+ _("Pays"),
+ null=True,
+ blank=False,
+ )
phone = models.CharField(
_("Téléphone"),
max_length=20,
diff --git a/geocity/apps/submissions/templates/submissions/_submission_actions.html b/geocity/apps/submissions/templates/submissions/_submission_actions.html
index 0cc78aef9..4c89d7415 100644
--- a/geocity/apps/submissions/templates/submissions/_submission_actions.html
+++ b/geocity/apps/submissions/templates/submissions/_submission_actions.html
@@ -18,7 +18,7 @@