diff --git a/.dockerignore b/.dockerignore index 0168e414..c481dce0 100644 --- a/.dockerignore +++ b/.dockerignore @@ -26,11 +26,4 @@ secrets/ db_backups/ services_data/ static/ -media/ -node_modules//geo/data/admin1CodesASCII.txt -/geo/data/admin2Codes.txt -/geo/data/allCountries.zip -/geo/data/alternateNames.zip -/geo/data/cities5000.zip -/geo/data/countryInfo.txt -/geo/data/hierarchy.zip \ No newline at end of file +media/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index 93451de8..55e4d31b 100644 --- a/.gitignore +++ b/.gitignore @@ -81,7 +81,6 @@ services_data/postgres/* services_data/redis/* static !core/static -!geo/static !payments/static !vibes_auth/static media diff --git a/core/admin.py b/core/admin.py index 5a7d9cd5..4af6a812 100644 --- a/core/admin.py +++ b/core/admin.py @@ -3,6 +3,7 @@ from constance.admin import ConstanceAdmin as BaseConstanceAdmin from django.apps import apps from django.contrib import admin from django.contrib.admin import ModelAdmin, TabularInline +from django.contrib.gis.admin import GISModelAdmin from django.urls import path from django.utils.translation import gettext_lazy as _ from mptt.admin import DraggableMPTTAdmin @@ -11,6 +12,7 @@ from evibes.settings import CONSTANCE_CONFIG, LANGUAGES from .forms import OrderForm, OrderProductForm, VendorForm from .models import ( + Address, Attribute, AttributeGroup, AttributeValue, @@ -360,6 +362,21 @@ class ProductImageAdmin(BasicModelAdmin): autocomplete_fields = ("product",) +@admin.register(Address) +class AddressAdmin(GISModelAdmin): + list_display = ("street", "city", "region", "country", "user") + list_filter = ("country", "region") + search_fields = ("raw_data", "street", "city", "postal_code", "user__email") + + gis_widget_kwargs = { + "attrs": { + "default_lon": 37.61556, + "default_lat": 55.75222, + "default_zoom": 6, + } + } + + class ConstanceAdmin(BaseConstanceAdmin): def get_urls(self): info = f"{self.model._meta.app_label}_{self.model._meta.model_name}" diff --git a/core/docs/drf/viewsets.py b/core/docs/drf/viewsets.py index 28365600..693d4a53 100644 --- a/core/docs/drf/viewsets.py +++ b/core/docs/drf/viewsets.py @@ -5,6 +5,9 @@ from rest_framework import status from core.docs.drf import BASE_ERRORS from core.serializers import ( AddOrderProductSerializer, + AddressAutocompleteInputSerializer, + AddressSerializer, + AddressSuggestionSerializer, AddWishlistProductSerializer, AttributeDetailSerializer, AttributeGroupDetailSerializer, @@ -438,3 +441,59 @@ PRODUCT_SCHEMA = { }, ), } + +ADDRESS_SCHEMA = { + "list": extend_schema( + summary=_("list all addresses"), + responses={ + status.HTTP_200_OK: AddressSerializer(many=True), + **BASE_ERRORS, + }, + ), + "retrieve": extend_schema( + summary=_("retrieve a single address"), + responses={ + status.HTTP_200_OK: AddressSerializer, + **BASE_ERRORS, + }, + ), + "create": extend_schema( + summary=_("create a new address"), + request=AddressSerializer, + responses={ + status.HTTP_201_CREATED: AddressSerializer, + **BASE_ERRORS, + }, + ), + "destroy": extend_schema( + summary=_("delete an address"), + responses={ + status.HTTP_204_NO_CONTENT: {}, + **BASE_ERRORS, + }, + ), + "update": extend_schema( + summary=_("update an entire address"), + request=AddressSerializer, + responses={ + status.HTTP_200_OK: AddressSerializer, + **BASE_ERRORS, + }, + ), + "partial_update": extend_schema( + summary=_("partially update an address"), + request=AddressSerializer, + responses={ + status.HTTP_200_OK: AddressSerializer, + **BASE_ERRORS, + }, + ), + "autocomplete": extend_schema( + summary=_("autocomplete address suggestions"), + request=AddressAutocompleteInputSerializer, + responses={ + status.HTTP_200_OK: AddressSuggestionSerializer(many=True), + **BASE_ERRORS, + }, + ), +} diff --git a/core/graphene/mutations.py b/core/graphene/mutations.py index 55295f27..3c4b7232 100644 --- a/core/graphene/mutations.py +++ b/core/graphene/mutations.py @@ -11,12 +11,13 @@ from graphene_django.utils import camelize from core.elasticsearch import process_query from core.graphene import BaseMutation -from core.graphene.object_types import OrderType, ProductType, SearchResultsType, WishlistType -from core.models import Category, Order, Product, Wishlist +from core.graphene.object_types import AddressType, OrderType, ProductType, SearchResultsType, WishlistType +from core.models import Address, Category, Order, Product, Wishlist from core.utils import format_attributes, is_url_safe from core.utils.caching import web_cache from core.utils.emailing import contact_us_email from core.utils.messages import permission_denied_message +from core.utils.nominatim import fetch_address_suggestions from payments.graphene.object_types import TransactionType logger = logging.getLogger(__name__) @@ -455,6 +456,70 @@ class DeleteProduct(BaseMutation): return DeleteProduct(ok=True) +class CreateAddress(BaseMutation): + class Arguments: + raw_data = String( + required=True, + description=_("original address string provided by the user") + ) + + address = Field(AddressType) + + @staticmethod + def mutate(_parent, info, raw_data): + user = info.context.user if info.context.user.is_authenticated else None + + address = Address.objects.create( + raw_data=raw_data, + user=user + ) + return CreateAddress(address=address) + + +class DeleteAddress(BaseMutation): + class Arguments: + uuid = UUID(required=True) + + success = Boolean() + + @staticmethod + def mutate(_parent, info, uuid): + try: + address = Address.objects.get(uuid=uuid) + if ( + info.context.user.is_superuser + or info.context.user.has_perm("core.delete_address") + or info.context.user == address.user + ): + address.delete() + return DeleteAddress(success=True) + + raise PermissionDenied(permission_denied_message) + + except Address.DoesNotExist: + name = "Address" + raise Http404(_(f"{name} does not exist: {uuid}")) + + +class AutocompleteAddress(BaseMutation): + class Arguments: + q = String() + limit = Int() + + suggestions = GenericScalar() + + @staticmethod + def mutate(_parent, info, q, limit): + if 1 > limit > 10: + raise BadRequest(_("limit must be between 1 and 10")) + try: + suggestions = fetch_address_suggestions(query=q, limit=limit) + except Exception as e: + raise BadRequest(f"geocoding error: {e!s}") from e + + return AutocompleteAddress(suggestions=suggestions) + + class ContactUs(BaseMutation): class Arguments: email = String(required=True) diff --git a/core/graphene/object_types.py b/core/graphene/object_types.py index bebc6603..a51023ed 100644 --- a/core/graphene/object_types.py +++ b/core/graphene/object_types.py @@ -24,9 +24,8 @@ from core.models import ( Promotion, Stock, Vendor, - Wishlist, + Wishlist, Address, ) -from geo.graphene.object_types import AddressType logger = __import__("logging").getLogger(__name__) @@ -359,6 +358,33 @@ class ProductType(DjangoObjectType): return self.quantity or 0 +class AddressType(DjangoObjectType): + latitude = Float(description=_("Latitude (Y coordinate)")) + longitude = Float(description=_("Longitude (X coordinate)")) + + class Meta: + model = Address + fields = ( + "uuid", + "street", + "district", + "city", + "region", + "postal_code", + "country", + "raw_data", + "api_response", + "user", + ) + read_only_fields = ("api_response",) + + def resolve_latitude(self, info): + return self.location.y if self.location else None + + def resolve_longitude(self, info): + return self.location.x if self.location else None + + class AttributeValueType(DjangoObjectType): value = String(description=_("attribute value")) diff --git a/core/graphene/schema.py b/core/graphene/schema.py index efea2f33..87d40517 100644 --- a/core/graphene/schema.py +++ b/core/graphene/schema.py @@ -18,12 +18,15 @@ from core.filters import ( from core.graphene.mutations import ( AddOrderProduct, AddWishlistProduct, + AutocompleteAddress, BuyOrder, BuyProduct, BuyWishlist, CacheOperator, ContactUs, + CreateAddress, CreateProduct, + DeleteAddress, DeleteProduct, RemoveAllOrderProducts, RemoveAllWishlistProducts, @@ -70,7 +73,6 @@ from core.utils import get_project_parameters from core.utils.languages import get_flag_by_language from core.utils.messages import permission_denied_message from evibes.settings import LANGUAGES -from geo.graphene.mutations import AutocompleteAddress, CreateAddress, DeleteAddress from payments.graphene.mutations import Deposit from vibes_auth.filters import UserFilter from vibes_auth.graphene.mutations import ( diff --git a/core/management/commands/deepl_translate.py b/core/management/commands/deepl_translate.py index 43216d6f..29f87405 100644 --- a/core/management/commands/deepl_translate.py +++ b/core/management/commands/deepl_translate.py @@ -114,7 +114,7 @@ class Command(BaseCommand): action="append", required=True, metavar="APP", - help="App label for translation, e.g. core, geo." + help="App label for translation, e.g. core, payments." ) def handle(self, *args, **options) -> None: diff --git a/core/management/commands/purify_translated.py b/core/management/commands/purify_translated.py index f86ab3eb..566937b3 100644 --- a/core/management/commands/purify_translated.py +++ b/core/management/commands/purify_translated.py @@ -76,7 +76,7 @@ class Command(BaseCommand): action='append', required=True, metavar='APP', - help='App label(s) to scan, e.g. core, geo' + help='App label(s) to scan, e.g. core, payments' ) parser.add_argument( '-p', '--path', diff --git a/core/managers.py b/core/managers.py index e69de29b..6ee2a940 100644 --- a/core/managers.py +++ b/core/managers.py @@ -0,0 +1,61 @@ +import requests +from constance import config +from django.contrib.gis.geos import Point +from django.db import models + + +class AddressManager(models.Manager): + def create(self, raw_data: str, **kwargs): + """ + Create an Address instance by geocoding the provided raw address string. + + Args: + raw_data (str): The raw address input from the user (e.g., '36 Mornington Rd Loughton England'). + **kwargs: Additional fields to pass to the Address model (e.g., user). + """ + if not raw_data: + raise ValueError("'raw_data' (address string) must be provided.") + + # Query Nominatim + params = { + 'format': 'json', + 'addressdetails': 1, + 'q': raw_data, + } + resp = requests.get(config.NOMINATIM_URL, params=params) + resp.raise_for_status() + results = resp.json() + if not results: + raise ValueError(f"No geocoding result for address: {raw_data}") + data = results[0] + + # Parse address components + addr = data.get('address', {}) + street = addr.get('road') or addr.get('pedestrian') or '' + district = addr.get('city_district') or addr.get('suburb') or '' + city = addr.get('city') or addr.get('town') or addr.get('village') or '' + region = addr.get('state') or addr.get('region') or '' + postal_code = addr.get('postcode') or '' + country = addr.get('country') or '' + + # Parse location + try: + lat = float(data.get('lat')) + lon = float(data.get('lon')) + location = Point(lon, lat, srid=4326) + except (TypeError, ValueError): + location = None + + # Create the model instance, storing both the input string and full API response + return super().create( + raw_data=raw_data, + street=street, + district=district, + city=city, + region=region, + postal_code=postal_code, + country=country, + location=location, + api_response=data, + **kwargs + ) diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py index 017d2409..657d41f1 100644 --- a/core/migrations/0001_initial.py +++ b/core/migrations/0001_initial.py @@ -15,10 +15,6 @@ import core.validators class Migration(migrations.Migration): initial = True - dependencies = [ - ('geo', '0001_initial'), - ] - operations = [ migrations.CreateModel( name='Feedback', @@ -991,14 +987,6 @@ class Migration(migrations.Migration): ('buy_time', models.DateTimeField(blank=True, default=None, help_text='the timestamp when the order was finalized', null=True, verbose_name='buy time')), - ('billing_address', - models.ForeignKey(blank=True, help_text='the billing address used for this order', null=True, - on_delete=django.db.models.deletion.CASCADE, related_name='billing_address_order', - to='geo.address', verbose_name='billing address')), - ('shipping_address', - models.ForeignKey(blank=True, help_text='the shipping address used for this order', null=True, - on_delete=django.db.models.deletion.CASCADE, related_name='shipping_address_order', - to='geo.address', verbose_name='shipping address')), ], options={ 'verbose_name': 'order', diff --git a/geo/migrations/0001_initial.py b/core/migrations/0019_address.py similarity index 86% rename from geo/migrations/0001_initial.py rename to core/migrations/0019_address.py index 3d92bea5..229c86c6 100644 --- a/geo/migrations/0001_initial.py +++ b/core/migrations/0019_address.py @@ -1,4 +1,4 @@ -# Generated by Django 5.2 on 2025-05-19 11:38 +# Generated by Django 5.2 on 2025-05-20 04:57 import uuid @@ -10,9 +10,8 @@ from django.db import migrations, models class Migration(migrations.Migration): - initial = True - dependencies = [ + ('core', '0018_alter_order_human_readable_id'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] @@ -38,20 +37,20 @@ class Migration(migrations.Migration): ('region', models.CharField(max_length=100, null=True, verbose_name='region')), ('postal_code', models.CharField(max_length=20, null=True, verbose_name='postal code')), ('country', models.CharField(max_length=40, null=True, verbose_name='country')), - ('location', django.contrib.gis.db.models.PointField(blank=True, geography=True, - help_text='Geolocation point: (longitude, latitude)', - null=True, srid=4326)), - ('raw_data', models.JSONField(blank=True, help_text='Full JSON response from geocoder for this address', + ('location', django.contrib.gis.db.models.fields.PointField(blank=True, geography=True, + help_text='geolocation point: (longitude, latitude)', + null=True, srid=4326)), + ('raw_data', models.JSONField(blank=True, help_text='full JSON response from geocoder for this address', null=True)), ('api_response', - models.JSONField(blank=True, help_text='Stored JSON response from the geocoding service', null=True)), + models.JSONField(blank=True, help_text='stored JSON response from the geocoding service', null=True)), ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ 'verbose_name': 'address', 'verbose_name_plural': 'addresses', - 'indexes': [models.Index(fields=['location'], name='geo_address_locatio_83b064_idx')], + 'indexes': [models.Index(fields=['location'], name='core_addres_locatio_eb6b39_idx')], }, ), ] diff --git a/core/migrations/0020_order_billing_address_order_shipping_address.py b/core/migrations/0020_order_billing_address_order_shipping_address.py new file mode 100644 index 00000000..f7930089 --- /dev/null +++ b/core/migrations/0020_order_billing_address_order_shipping_address.py @@ -0,0 +1,27 @@ +# Generated by Django 5.2 on 2025-05-20 04:59 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('core', '0019_address'), + ] + + operations = [ + migrations.AddField( + model_name='order', + name='billing_address', + field=models.ForeignKey(blank=True, help_text='the billing address used for this order', null=True, + on_delete=django.db.models.deletion.CASCADE, related_name='billing_address_order', + to='core.address', verbose_name='billing address'), + ), + migrations.AddField( + model_name='order', + name='shipping_address', + field=models.ForeignKey(blank=True, help_text='the shipping address used for this order', null=True, + on_delete=django.db.models.deletion.CASCADE, related_name='shipping_address_order', + to='core.address', verbose_name='shipping address'), + ), + ] diff --git a/core/models.py b/core/models.py index 29c04a96..d1e1d1ad 100644 --- a/core/models.py +++ b/core/models.py @@ -4,6 +4,7 @@ import logging from typing import Self from constance import config +from django.contrib.gis.db.models import PointField from django.contrib.postgres.indexes import GinIndex from django.core.cache import cache from django.core.exceptions import BadRequest, ValidationError @@ -28,6 +29,7 @@ from django.db.models import ( PositiveIntegerField, TextField, ) +from django.db.models.indexes import Index from django.http import Http404 from django.utils import timezone from django.utils.encoding import force_bytes @@ -40,11 +42,11 @@ from mptt.models import MPTTModel from core.abstract import NiceModel from core.choices import ORDER_PRODUCT_STATUS_CHOICES, ORDER_STATUS_CHOICES from core.errors import DisabledCommerceError, NotEnoughMoneyError +from core.managers import AddressManager from core.utils import generate_human_readable_id, get_product_uuid_as_path, get_random_code from core.utils.lists import FAILED_STATUSES from core.validators import validate_category_image_dimensions from evibes.settings import CURRENCY_CODE -from geo.models import Address from payments.models import Transaction logger = logging.getLogger(__name__) @@ -433,7 +435,7 @@ class Order(NiceModel): is_publicly_visible = False billing_address = ForeignKey( - "geo.Address", + "core.Address", on_delete=CASCADE, blank=True, null=True, @@ -450,7 +452,7 @@ class Order(NiceModel): verbose_name=_("applied promo code"), ) shipping_address = ForeignKey( - "geo.Address", + "core.Address", on_delete=CASCADE, blank=True, null=True, @@ -1225,3 +1227,52 @@ class Documentary(NiceModel): @property def file_type(self): return self.document.name.split(".")[-1] or _("unresolved") + + +class Address(NiceModel): + street = CharField(_("street"), max_length=255, null=True) # noqa: DJ001 + district = CharField(_("district"), max_length=255, null=True) # noqa: DJ001 + city = CharField(_("city"), max_length=100, null=True) # noqa: DJ001 + region = CharField(_("region"), max_length=100, null=True) # noqa: DJ001 + postal_code = CharField(_("postal code"), max_length=20, null=True) # noqa: DJ001 + country = CharField(_("country"), max_length=40, null=True) # noqa: DJ001 + + location = PointField( + geography=True, + srid=4326, + null=True, + blank=True, + help_text=_("geolocation point: (longitude, latitude)") + ) + + raw_data = JSONField( + blank=True, + null=True, + help_text=_("full JSON response from geocoder for this address") + ) + + api_response = JSONField( + blank=True, + null=True, + help_text=_("stored JSON response from the geocoding service") + ) + + user = ForeignKey( + to="vibes_auth.User", + on_delete=CASCADE, + blank=True, + null=True + ) + + objects = AddressManager() + + class Meta: + verbose_name = _("address") + verbose_name_plural = _("addresses") + indexes = [ + Index(fields=["location"]), + ] + + def __str__(self): + base = f"{self.street}, {self.city}, {self.country}" + return f"{base} for {self.user.email}" if self.user else base diff --git a/core/serializers/__init__.py b/core/serializers/__init__.py index ab21b46e..2733dec8 100644 --- a/core/serializers/__init__.py +++ b/core/serializers/__init__.py @@ -1,6 +1,18 @@ -from rest_framework.fields import BooleanField, CharField, Field, IntegerField, JSONField, ListField, UUIDField +from rest_framework.fields import ( + BooleanField, + CharField, + DictField, + Field, + FloatField, + IntegerField, + JSONField, + ListField, + UUIDField, +) from rest_framework.serializers import ListSerializer, Serializer +from core.models import Address + from .detail import * # noqa: F403 from .simple import * # noqa: F403 @@ -91,3 +103,65 @@ class BuyAsBusinessOrderSerializer(Serializer): billing_business_address_uuid = CharField(required=False) shipping_business_address_uuid = CharField(required=False) payment_method = CharField(required=True) + + +class AddressAutocompleteInputSerializer(Serializer): + q = CharField( + required=True + ) + limit = IntegerField( + required=False, + min_value=1, + max_value=10, + default=5 + ) + + +class AddressSuggestionSerializer(Serializer): + display_name = CharField() + lat = FloatField() + lon = FloatField() + address = DictField(child=CharField()) + + +class AddressSerializer(ModelSerializer): # noqa: F405 + latitude = FloatField(source="location.y", read_only=True) + longitude = FloatField(source="location.x", read_only=True) + + class Meta: + model = Address + fields = [ + "uuid", + "street", + "district", + "city", + "region", + "postal_code", + "country", + "latitude", + "longitude", + "raw_data", + "api_response", + "user", + ] + read_only_fields = [ + "latitude", + "longitude", + "raw_data", + "api_response", + ] + + +class AddressCreateSerializer(ModelSerializer): # noqa: F405 + raw_data = CharField( + write_only=True, + max_length=512, + ) + + class Meta: + model = Address + fields = ["raw_data", "user"] + + def create(self, validated_data): + raw = validated_data.pop("raw_data") + return Address.objects.create(raw_data=raw, **validated_data) diff --git a/geo/static/flags/ar-AR.png b/core/static/flags/ar-AR.png similarity index 100% rename from geo/static/flags/ar-AR.png rename to core/static/flags/ar-AR.png diff --git a/geo/static/flags/cs-CZ.png b/core/static/flags/cs-CZ.png similarity index 100% rename from geo/static/flags/cs-CZ.png rename to core/static/flags/cs-CZ.png diff --git a/geo/static/flags/da-DK.png b/core/static/flags/da-DK.png similarity index 100% rename from geo/static/flags/da-DK.png rename to core/static/flags/da-DK.png diff --git a/geo/static/flags/de-DE.png b/core/static/flags/de-DE.png similarity index 100% rename from geo/static/flags/de-DE.png rename to core/static/flags/de-DE.png diff --git a/geo/static/flags/en-GB.png b/core/static/flags/en-GB.png similarity index 100% rename from geo/static/flags/en-GB.png rename to core/static/flags/en-GB.png diff --git a/geo/static/flags/en-US.png b/core/static/flags/en-US.png similarity index 100% rename from geo/static/flags/en-US.png rename to core/static/flags/en-US.png diff --git a/geo/static/flags/es-ES.png b/core/static/flags/es-ES.png similarity index 100% rename from geo/static/flags/es-ES.png rename to core/static/flags/es-ES.png diff --git a/geo/static/flags/fr-FR.png b/core/static/flags/fr-FR.png similarity index 100% rename from geo/static/flags/fr-FR.png rename to core/static/flags/fr-FR.png diff --git a/geo/static/flags/hi-IN.png b/core/static/flags/hi-IN.png similarity index 100% rename from geo/static/flags/hi-IN.png rename to core/static/flags/hi-IN.png diff --git a/geo/static/flags/it-IT.png b/core/static/flags/it-IT.png similarity index 100% rename from geo/static/flags/it-IT.png rename to core/static/flags/it-IT.png diff --git a/geo/static/flags/ja-JP.png b/core/static/flags/ja-JP.png similarity index 100% rename from geo/static/flags/ja-JP.png rename to core/static/flags/ja-JP.png diff --git a/geo/static/flags/kk-KZ.png b/core/static/flags/kk-KZ.png similarity index 100% rename from geo/static/flags/kk-KZ.png rename to core/static/flags/kk-KZ.png diff --git a/geo/static/flags/nl-NL.png b/core/static/flags/nl-NL.png similarity index 100% rename from geo/static/flags/nl-NL.png rename to core/static/flags/nl-NL.png diff --git a/geo/static/flags/pl-PL.png b/core/static/flags/pl-PL.png similarity index 100% rename from geo/static/flags/pl-PL.png rename to core/static/flags/pl-PL.png diff --git a/geo/static/flags/pt-BR.png b/core/static/flags/pt-BR.png similarity index 100% rename from geo/static/flags/pt-BR.png rename to core/static/flags/pt-BR.png diff --git a/geo/static/flags/ro-RO.png b/core/static/flags/ro-RO.png similarity index 100% rename from geo/static/flags/ro-RO.png rename to core/static/flags/ro-RO.png diff --git a/geo/static/flags/ru-RU.png b/core/static/flags/ru-RU.png similarity index 100% rename from geo/static/flags/ru-RU.png rename to core/static/flags/ru-RU.png diff --git a/geo/static/flags/zh-hans.png b/core/static/flags/zh-hans.png similarity index 100% rename from geo/static/flags/zh-hans.png rename to core/static/flags/zh-hans.png diff --git a/geo/utils/nominatim.py b/core/utils/nominatim.py similarity index 100% rename from geo/utils/nominatim.py rename to core/utils/nominatim.py diff --git a/core/viewsets.py b/core/viewsets.py index 2cbae3af..46e8e0f8 100644 --- a/core/viewsets.py +++ b/core/viewsets.py @@ -16,6 +16,7 @@ from rest_framework_xml.renderers import XMLRenderer from rest_framework_yaml.renderers import YAMLRenderer from core.docs.drf.viewsets import ( + ADDRESS_SCHEMA, ATTRIBUTE_GROUP_SCHEMA, ATTRIBUTE_SCHEMA, ATTRIBUTE_VALUE_SCHEMA, @@ -26,6 +27,7 @@ from core.docs.drf.viewsets import ( ) from core.filters import BrandFilter, CategoryFilter, OrderFilter, ProductFilter from core.models import ( + Address, Attribute, AttributeGroup, AttributeValue, @@ -46,6 +48,9 @@ from core.models import ( from core.permissions import EvibesPermission from core.serializers import ( AddOrderProductSerializer, + AddressAutocompleteInputSerializer, + AddressCreateSerializer, + AddressSerializer, AddWishlistProductSerializer, AttributeDetailSerializer, AttributeGroupDetailSerializer, @@ -80,6 +85,7 @@ from core.serializers import ( ) from core.utils import format_attributes from core.utils.messages import permission_denied_message +from core.utils.nominatim import fetch_address_suggestions from payments.serializers import TransactionProcessSerializer @@ -461,3 +467,34 @@ class WishlistViewSet(EvibesViewSet): return Response(status=status.HTTP_200_OK, data=WishlistDetailSerializer(wishlist).data) except Order.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) + + +@extend_schema_view(**ADDRESS_SCHEMA) +class AddressViewSet(EvibesViewSet): + queryset = Address.objects.all() + serializer_class = AddressSerializer + + def get_serializer_class(self): + if self.action == 'create': + return AddressCreateSerializer + if self.action == 'autocomplete': + return AddressAutocompleteInputSerializer + return AddressSerializer + + @action(detail=False, methods=["get"], url_path="autocomplete") + def autocomplete(self, request): + serializer = AddressAutocompleteInputSerializer(data=request.query_params) + serializer.is_valid(raise_exception=True) + + q = serializer.validated_data["q"] + limit = serializer.validated_data["limit"] + + try: + suggestions = fetch_address_suggestions(query=q, limit=limit) + except Exception as e: + return Response( + {"detail": _(f"Geocoding error: {e}")}, + status=status.HTTP_502_BAD_GATEWAY, + ) + + return Response(suggestions, status=status.HTTP_200_OK) diff --git a/evibes/api_urls.py b/evibes/api_urls.py index 3b0c21cf..154ed5a3 100644 --- a/evibes/api_urls.py +++ b/evibes/api_urls.py @@ -11,23 +11,24 @@ from core.views import CustomGraphQLView, CustomRedocView, CustomSwaggerView, fa from evibes.settings import SPECTACULAR_PLATFORM_SETTINGS urlpatterns = [ - path(r"graphql/", csrf_exempt(CustomGraphQLView.as_view(graphiql=True, schema=schema))), - path( - r"docs/", - SpectacularAPIView.as_view(urlconf="evibes.api_urls", custom_settings=SPECTACULAR_PLATFORM_SETTINGS), - name="schema-platform", - ), - path(r"docs/swagger/", CustomSwaggerView.as_view(url_name="schema-platform"), name="swagger-ui-platform"), - path(r"docs/redoc/", CustomRedocView.as_view(url_name="schema-platform"), name="redoc-ui-platform"), - path(r"i18n/", include("django.conf.urls.i18n")), - path(r"favicon.ico", favicon_view), - path(r"", index), - path(r"", include("core.api_urls")), - path(r"auth/", include("vibes_auth.urls")), - path(r"geo/", include("geo.urls")), - path(r"payments/", include("payments.urls")), - path(r"blog/", include("blog.urls")), -] + i18n_patterns(path("admin/", admin.site.urls)) + path(r"graphql/", csrf_exempt(CustomGraphQLView.as_view(graphiql=True, schema=schema))), + path( + r"docs/", + SpectacularAPIView.as_view(urlconf="evibes.api_urls", + custom_settings=SPECTACULAR_PLATFORM_SETTINGS), + name="schema-platform", + ), + path(r"docs/swagger/", CustomSwaggerView.as_view(url_name="schema-platform"), + name="swagger-ui-platform"), + path(r"docs/redoc/", CustomRedocView.as_view(url_name="schema-platform"), name="redoc-ui-platform"), + path(r"i18n/", include("django.conf.urls.i18n")), + path(r"favicon.ico", favicon_view), + path(r"", index), + path(r"", include("core.api_urls")), + path(r"auth/", include("vibes_auth.urls")), + path(r"payments/", include("payments.urls")), + path(r"blog/", include("blog.urls")), + ] + i18n_patterns(path("admin/", admin.site.urls)) if settings.DEBUG: urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/evibes/settings/base.py b/evibes/settings/base.py index a99ccf34..09316240 100644 --- a/evibes/settings/base.py +++ b/evibes/settings/base.py @@ -91,7 +91,6 @@ INSTALLED_APPS = [ "django_mailbox", "graphene_django", "core", - "geo", "payments", "vibes_auth", "blog", @@ -120,7 +119,6 @@ TEMPLATES = [ "DIRS": [ BASE_DIR / "vibes_auth/templates", BASE_DIR / "core/templates", - BASE_DIR / "geo/templates", BASE_DIR / "payments/templates", ], "APP_DIRS": True, @@ -249,39 +247,32 @@ DAISY_SETTINGS = { "priority": 1, "apps": "", }, - "geo": { - "icon": "fa fa-solid fa-globe", - "hide": False, - "app": "geo", - "priority": 2, - "apps": "", - }, "payments": { "icon": "fa fa-solid fa-wallet", "hide": False, "app": "payments", - "priority": 3, + "priority": 2, "apps": "", }, "blog": { "icon": "fa fa-solid fa-book", "hide": False, "app": "blog", - "priority": 4, + "priority": 3, "apps": "", }, "core": { "icon": "fa fa-solid fa-house", "hide": False, "app": "core", - "priority": 5, + "priority": 4, "apps": "", }, "vibes_auth": { "icon": "fa fa-solid fa-user", "hide": False, "app": "vibes_auth", - "priority": 6, + "priority": 5, "apps": "", }, }, diff --git a/evibes/settings/caches.py b/evibes/settings/caches.py index 3bd38cb0..81b25f40 100644 --- a/evibes/settings/caches.py +++ b/evibes/settings/caches.py @@ -32,5 +32,4 @@ else: "vibes_auth.*": {"ops": {"fetch", "get"}, "timeout": 60 * 60}, "auth.permission": {"ops": "all", "timeout": 60 * 60}, "core.*": {"ops": "all", "timeout": 60 * 60}, - "geo.*": {"ops": "all", "timeout": 60 * 60}, } diff --git a/geo/__init__.py b/geo/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/geo/admin.py b/geo/admin.py deleted file mode 100644 index da0072e1..00000000 --- a/geo/admin.py +++ /dev/null @@ -1,19 +0,0 @@ -from django.contrib import admin -from django.contrib.gis.admin import GISModelAdmin - -from .models import Address - - -@admin.register(Address) -class AddressAdmin(GISModelAdmin): - list_display = ("street", "city", "region", "country", "user") - list_filter = ("country", "region") - search_fields = ("raw_data", "street", "city", "postal_code", "user__email") - - gis_widget_kwargs = { - "attrs": { - "default_lon": 37.61556, - "default_lat": 55.75222, - "default_zoom": 6, - } - } diff --git a/geo/apps.py b/geo/apps.py deleted file mode 100644 index 5ca8d734..00000000 --- a/geo/apps.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.apps import AppConfig -from django.utils.translation import gettext_lazy as _ - - -class GeoConfig(AppConfig): - default_auto_field = "django.db.models.BigAutoField" - name = "geo" - verbose_name = _("geodata") diff --git a/geo/docs/__init__.py b/geo/docs/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/geo/docs/drf/__init__.py b/geo/docs/drf/__init__.py deleted file mode 100644 index 43d0045a..00000000 --- a/geo/docs/drf/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -from drf_spectacular.utils import inline_serializer -from rest_framework import status -from rest_framework.fields import CharField - -error = inline_serializer("error", fields={"detail": CharField()}) - -BASE_ERRORS = { - status.HTTP_400_BAD_REQUEST: error, - status.HTTP_401_UNAUTHORIZED: error, - status.HTTP_403_FORBIDDEN: error, - status.HTTP_404_NOT_FOUND: error, - status.HTTP_405_METHOD_NOT_ALLOWED: error, - status.HTTP_500_INTERNAL_SERVER_ERROR: error, -} diff --git a/geo/docs/drf/views.py b/geo/docs/drf/views.py deleted file mode 100644 index e69de29b..00000000 diff --git a/geo/docs/drf/viewsets.py b/geo/docs/drf/viewsets.py deleted file mode 100644 index 62a7c343..00000000 --- a/geo/docs/drf/viewsets.py +++ /dev/null @@ -1,62 +0,0 @@ -from django.utils.translation import gettext_lazy as _ -from drf_spectacular.utils import extend_schema -from rest_framework import status - -from core.docs.drf import BASE_ERRORS -from geo.serializers import AddressAutocompleteInputSerializer, AddressSerializer, AddressSuggestionSerializer - -ADDRESS_SCHEMA = { - "list": extend_schema( - summary=_("list all addresses"), - responses={ - status.HTTP_200_OK: AddressSerializer(many=True), - **BASE_ERRORS, - }, - ), - "retrieve": extend_schema( - summary=_("retrieve a single address"), - responses={ - status.HTTP_200_OK: AddressSerializer, - **BASE_ERRORS, - }, - ), - "create": extend_schema( - summary=_("create a new address"), - request=AddressSerializer, - responses={ - status.HTTP_201_CREATED: AddressSerializer, - **BASE_ERRORS, - }, - ), - "destroy": extend_schema( - summary=_("delete an address"), - responses={ - status.HTTP_204_NO_CONTENT: {}, - **BASE_ERRORS, - }, - ), - "update": extend_schema( - summary=_("update an entire address"), - request=AddressSerializer, - responses={ - status.HTTP_200_OK: AddressSerializer, - **BASE_ERRORS, - }, - ), - "partial_update": extend_schema( - summary=_("partially update an address"), - request=AddressSerializer, - responses={ - status.HTTP_200_OK: AddressSerializer, - **BASE_ERRORS, - }, - ), - "autocomplete": extend_schema( - summary=_("autocomplete address suggestions"), - request=AddressAutocompleteInputSerializer, - responses={ - status.HTTP_200_OK: AddressSuggestionSerializer(many=True), - **BASE_ERRORS, - }, - ), -} diff --git a/geo/filters.py b/geo/filters.py deleted file mode 100644 index e69de29b..00000000 diff --git a/geo/graphene/__init__.py b/geo/graphene/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/geo/graphene/mutations.py b/geo/graphene/mutations.py deleted file mode 100644 index 0f154561..00000000 --- a/geo/graphene/mutations.py +++ /dev/null @@ -1,76 +0,0 @@ -import graphene -from django.core.exceptions import BadRequest -from django.http import Http404 -from django.utils.translation import gettext_lazy as _ -from graphene.types.generic import GenericScalar -from rest_framework.exceptions import PermissionDenied - -from core.graphene import BaseMutation -from core.utils.messages import permission_denied_message -from geo.graphene.object_types import AddressType -from geo.models import Address -from geo.utils.nominatim import fetch_address_suggestions - - -class CreateAddress(graphene.Mutation): - class Arguments: - raw_data = graphene.String( - required=True, - description=_("original address string provided by the user") - ) - - address = graphene.Field(AddressType) - - @staticmethod - def mutate(_parent, info, raw_data): - user = info.context.user if info.context.user.is_authenticated else None - - address = Address.objects.create( - raw_data=raw_data, - user=user - ) - return CreateAddress(address=address) - - -class DeleteAddress(BaseMutation): - class Arguments: - uuid = graphene.UUID(required=True) - - success = graphene.Boolean() - - @staticmethod - def mutate(_parent, info, uuid): - try: - address = Address.objects.get(uuid=uuid) - if ( - info.context.user.is_superuser - or info.context.user.has_perm("geo.delete_address") - or info.context.user == address.user - ): - address.delete() - return DeleteAddress(success=True) - - raise PermissionDenied(permission_denied_message) - - except Address.DoesNotExist: - name = "Address" - raise Http404(_(f"{name} does not exist: {uuid}")) - - -class AutocompleteAddress(BaseMutation): - class Arguments: - q = graphene.String() - limit = graphene.Int() - - suggestions = GenericScalar() - - @staticmethod - def mutate(_parent, info, q, limit): - if 1 > limit > 10: - raise BadRequest(_("limit must be between 1 and 10")) - try: - suggestions = fetch_address_suggestions(query=q, limit=limit) - except Exception as e: - raise BadRequest(f"geocoding error: {e!s}") from e - - return AutocompleteAddress(suggestions=suggestions) diff --git a/geo/graphene/object_types.py b/geo/graphene/object_types.py deleted file mode 100644 index d710e3cf..00000000 --- a/geo/graphene/object_types.py +++ /dev/null @@ -1,55 +0,0 @@ -import graphene -from django.utils.translation import gettext_lazy as _ -from graphene import Float, ObjectType, String -from graphene.types.generic import GenericScalar -from graphene_django import DjangoObjectType - -from geo.models import Address - - -class AddressAutocompleteInput(graphene.InputObjectType): - q = graphene.String( - required=True, - description=_("partial or full address string to search for") - ) - limit = graphene.Int( - required=False, - description=_("maximum number of suggestions to return (1–10)"), - default_value=5 - ) - - -class AddressSuggestionType(ObjectType): - display_name = String() - lat = Float() - lon = Float() - address = GenericScalar( - description=_("the address breakdown as key/value pairs") - ) - - -class AddressType(DjangoObjectType): - latitude = graphene.Float(description=_("Latitude (Y coordinate)")) - longitude = graphene.Float(description=_("Longitude (X coordinate)")) - - class Meta: - model = Address - fields = ( - "uuid", - "street", - "district", - "city", - "region", - "postal_code", - "country", - "raw_data", - "api_response", - "user", - ) - read_only_fields = ("api_response",) - - def resolve_latitude(self, info): - return self.location.y if self.location else None - - def resolve_longitude(self, info): - return self.location.x if self.location else None diff --git a/geo/locale/ar_AR/LC_MESSAGES/django.mo b/geo/locale/ar_AR/LC_MESSAGES/django.mo deleted file mode 100644 index 95aef6cd..00000000 Binary files a/geo/locale/ar_AR/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/ar_AR/LC_MESSAGES/django.po b/geo/locale/ar_AR/LC_MESSAGES/django.po deleted file mode 100644 index 2d10a3af..00000000 --- a/geo/locale/ar_AR/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: ARABIC \n" -"Language: ARABIC\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "البيانات الجغرافية" - -#: geo/conf.py:407 -msgid "Name" -msgstr "الاسم" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "الاختصار" - -#: geo/conf.py:409 -msgid "Link" -msgstr "رابط إلى" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "رمز (مطار) IATA (المطار)" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "رمز (مطار) منظمة الطيران المدني الدولي (ICAO)" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "الرمز (المطار) FAAC (المطار)" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} غير موجود: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} غير موجود: {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} غير موجود: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "المعرف الفريد" - -#: geo/models.py:48 -msgid "active" -msgstr "نشط" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "يجب أن تنفذ الفئات الفرعية ل 'المكان' طريقة سلوغفايفي" - -#: geo/models.py:123 -msgid "continent" -msgstr "القارة" - -#: geo/models.py:124 -msgid "continents" -msgstr "القارات" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "البلد" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "الدول" - -#: geo/models.py:182 -msgid "region" -msgstr "المنطقة" - -#: geo/models.py:183 -msgid "regions" -msgstr "المناطق" - -#: geo/models.py:205 -msgid "subregion" -msgstr "المنطقة الفرعية" - -#: geo/models.py:206 -msgid "subregions" -msgstr "المناطق الفرعية" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "المدينة" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "المدن" - -#: geo/models.py:270 -msgid "district" -msgstr "المنطقة" - -#: geo/models.py:271 -msgid "districts" -msgstr "المقاطعات" - -#: geo/models.py:344 -msgid "postal code" -msgstr "الرمز البريدي" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "الرموز البريدية" - -#: geo/models.py:391 -msgid "address" -msgstr "العنوان" - -#: geo/models.py:392 -msgid "addresses" -msgstr "العناوين" diff --git a/geo/locale/cs_CZ/LC_MESSAGES/django.mo b/geo/locale/cs_CZ/LC_MESSAGES/django.mo deleted file mode 100644 index ab377194..00000000 Binary files a/geo/locale/cs_CZ/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/cs_CZ/LC_MESSAGES/django.po b/geo/locale/cs_CZ/LC_MESSAGES/django.po deleted file mode 100644 index bec4dd57..00000000 --- a/geo/locale/cs_CZ/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: CZECH \n" -"Language: CZECH\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Geodata" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Název" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Zkratka" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Odkaz na" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "Kód IATA (letiště)" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "Kód ICAO (letiště)" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "FAAC (letiště) Kód" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} neexistuje: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} neexistuje: {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} neexistuje: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "Jedinečné ID" - -#: geo/models.py:48 -msgid "active" -msgstr "Aktivní" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Podtřídy třídy `Místo` musí implementovat metodu slugify" - -#: geo/models.py:123 -msgid "continent" -msgstr "Kontinent" - -#: geo/models.py:124 -msgid "continents" -msgstr "Kontinenty" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "Země" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Země" - -#: geo/models.py:182 -msgid "region" -msgstr "Region" - -#: geo/models.py:183 -msgid "regions" -msgstr "Regiony" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Subregion" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Subregiony" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "Město" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Města" - -#: geo/models.py:270 -msgid "district" -msgstr "Okres" - -#: geo/models.py:271 -msgid "districts" -msgstr "Okresy" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Poštovní směrovací číslo" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Poštovní směrovací čísla" - -#: geo/models.py:391 -msgid "address" -msgstr "Adresa" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Adresy" diff --git a/geo/locale/da_DK/LC_MESSAGES/django.mo b/geo/locale/da_DK/LC_MESSAGES/django.mo deleted file mode 100644 index ed47d46b..00000000 Binary files a/geo/locale/da_DK/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/da_DK/LC_MESSAGES/django.po b/geo/locale/da_DK/LC_MESSAGES/django.po deleted file mode 100644 index 868859f5..00000000 --- a/geo/locale/da_DK/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: DANISH \n" -"Language: DANISH\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Geodata" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Navn" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Forkortelse" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Link til" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "IATA-kode (lufthavn)" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "ICAO-kode (lufthavn)" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "FAAC (lufthavn) Kode" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} findes ikke: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} findes ikke: {postal_code_uuid}." - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} findes ikke: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "Unikt ID" - -#: geo/models.py:48 -msgid "active" -msgstr "Aktiv" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Underklasser af `Place` skal implementere slugify-metoden" - -#: geo/models.py:123 -msgid "continent" -msgstr "Kontinent" - -#: geo/models.py:124 -msgid "continents" -msgstr "Kontinenter" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "Land" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Lande" - -#: geo/models.py:182 -msgid "region" -msgstr "Region" - -#: geo/models.py:183 -msgid "regions" -msgstr "Regioner" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Underregion" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Underregioner" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "By" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Byer" - -#: geo/models.py:270 -msgid "district" -msgstr "Distrikt" - -#: geo/models.py:271 -msgid "districts" -msgstr "Distrikter" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Postnummer" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Postnumre" - -#: geo/models.py:391 -msgid "address" -msgstr "Adresse" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Adresser" diff --git a/geo/locale/de_DE/LC_MESSAGES/django.mo b/geo/locale/de_DE/LC_MESSAGES/django.mo deleted file mode 100644 index 1d08c2da..00000000 Binary files a/geo/locale/de_DE/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/de_DE/LC_MESSAGES/django.po b/geo/locale/de_DE/LC_MESSAGES/django.po deleted file mode 100644 index f45edc71..00000000 --- a/geo/locale/de_DE/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: BRITISH ENGLISH \n" -"Language: BRITISH ENGLISH\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Geodaten" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Name" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Abkürzung" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Link zu" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "IATA (Flughafen) Code" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "ICAO (Flughafen) Code" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "FAAC (Flughafen) Code" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} existiert nicht: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} existiert nicht: {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} existiert nicht: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "Eindeutige ID" - -#: geo/models.py:48 -msgid "active" -msgstr "Aktiv" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Unterklassen von `Place` müssen die slugify-Methode implementieren" - -#: geo/models.py:123 -msgid "continent" -msgstr "Kontinent" - -#: geo/models.py:124 -msgid "continents" -msgstr "Kontinente" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "Land" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Länder" - -#: geo/models.py:182 -msgid "region" -msgstr "Region" - -#: geo/models.py:183 -msgid "regions" -msgstr "Regionen" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Unterregion" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Teilregionen" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "Stadt" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Städte" - -#: geo/models.py:270 -msgid "district" -msgstr "Bezirk" - -#: geo/models.py:271 -msgid "districts" -msgstr "Bezirke" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Postleitzahl" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Postleitzahlen" - -#: geo/models.py:391 -msgid "address" -msgstr "Adresse" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Adressen" diff --git a/geo/locale/en_GB/LC_MESSAGES/django.mo b/geo/locale/en_GB/LC_MESSAGES/django.mo deleted file mode 100644 index 3c4772fb..00000000 Binary files a/geo/locale/en_GB/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/en_GB/LC_MESSAGES/django.po b/geo/locale/en_GB/LC_MESSAGES/django.po deleted file mode 100644 index 320e8607..00000000 --- a/geo/locale/en_GB/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -# ,fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: BRITISH ENGLISH \n" -"Language: BRITISH ENGLISH\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Geodata" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Name" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Abbreviation" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Link" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "IATA (Airport) Code" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "ICAO (Airport) Code" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "FAAC (Airport) Code" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} does not exist: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} does not exist: {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} does not exist: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "Unique ID" - -#: geo/models.py:48 -msgid "active" -msgstr "Active" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Subclasses of `Place` must implement slugify method" - -#: geo/models.py:123 -msgid "continent" -msgstr "Continent" - -#: geo/models.py:124 -msgid "continents" -msgstr "Continents" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "Country" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Countries" - -#: geo/models.py:182 -msgid "region" -msgstr "Region" - -#: geo/models.py:183 -msgid "regions" -msgstr "Regions" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Subregion" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Subregions" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "City" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Cities" - -#: geo/models.py:270 -msgid "district" -msgstr "District" - -#: geo/models.py:271 -msgid "districts" -msgstr "Districts" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Postal code" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Postal codes" - -#: geo/models.py:391 -msgid "address" -msgstr "Address" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Addresses" diff --git a/geo/locale/en_US/LC_MESSAGES/django.mo b/geo/locale/en_US/LC_MESSAGES/django.mo deleted file mode 100644 index 85f16fb6..00000000 Binary files a/geo/locale/en_US/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/en_US/LC_MESSAGES/django.po b/geo/locale/en_US/LC_MESSAGES/django.po deleted file mode 100644 index 99f8fa8f..00000000 --- a/geo/locale/en_US/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: BRITISH ENGLISH \n" -"Language: BRITISH ENGLISH\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Geodata" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Name" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Abbreviation" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Link to" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "IATA (Airport) Code" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "ICAO (Airport) Code" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "FAAC (Airport) Code" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} does not exist: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} does not exist: {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} does not exist: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "Unique ID" - -#: geo/models.py:48 -msgid "active" -msgstr "Active" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Subclasses of `Place` must implement slugify method" - -#: geo/models.py:123 -msgid "continent" -msgstr "Continent" - -#: geo/models.py:124 -msgid "continents" -msgstr "Continents" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "Country" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Countries" - -#: geo/models.py:182 -msgid "region" -msgstr "Region" - -#: geo/models.py:183 -msgid "regions" -msgstr "Regions" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Subregion" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Subregions" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "City" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Cities" - -#: geo/models.py:270 -msgid "district" -msgstr "District" - -#: geo/models.py:271 -msgid "districts" -msgstr "Districts" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Postal code" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Postal codes" - -#: geo/models.py:391 -msgid "address" -msgstr "Address" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Addresses" diff --git a/geo/locale/es_ES/LC_MESSAGES/django.mo b/geo/locale/es_ES/LC_MESSAGES/django.mo deleted file mode 100644 index 0d1798a7..00000000 Binary files a/geo/locale/es_ES/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/es_ES/LC_MESSAGES/django.po b/geo/locale/es_ES/LC_MESSAGES/django.po deleted file mode 100644 index 65757e53..00000000 --- a/geo/locale/es_ES/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: SPANISH \n" -"Language: SPANISH\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Geodatos" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Nombre" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Abreviatura" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Enlace" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "Código IATA (aeropuerto)" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "Código OACI (Aeropuerto)" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "FAAC (Aeropuerto) Código" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} no existe: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} no existe: {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} no existe: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "Identificación única" - -#: geo/models.py:48 -msgid "active" -msgstr "Activo" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Las subclases de `Place` deben implementar el método slugify" - -#: geo/models.py:123 -msgid "continent" -msgstr "Continente" - -#: geo/models.py:124 -msgid "continents" -msgstr "Continentes" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "País" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Países" - -#: geo/models.py:182 -msgid "region" -msgstr "Región" - -#: geo/models.py:183 -msgid "regions" -msgstr "Regiones" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Subregion" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Subregiones" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "Ciudad" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Ciudades" - -#: geo/models.py:270 -msgid "district" -msgstr "Distrito" - -#: geo/models.py:271 -msgid "districts" -msgstr "Distritos" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Código postal" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Códigos postales" - -#: geo/models.py:391 -msgid "address" -msgstr "Dirección" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Direcciones" diff --git a/geo/locale/fr_FR/LC_MESSAGES/django.mo b/geo/locale/fr_FR/LC_MESSAGES/django.mo deleted file mode 100644 index 3901032d..00000000 Binary files a/geo/locale/fr_FR/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/fr_FR/LC_MESSAGES/django.po b/geo/locale/fr_FR/LC_MESSAGES/django.po deleted file mode 100644 index a1f6b421..00000000 --- a/geo/locale/fr_FR/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: BRITISH ENGLISH \n" -"Language: BRITISH ENGLISH\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Géodonnées" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Nom" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Abréviation" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Lien vers" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "Code IATA (aéroport)" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "Code OACI (aéroport)" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "Code FAAC (Aéroport)" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} n'existe pas : {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} n'existe pas : {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} n'existe pas : {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "Unique ID" - -#: geo/models.py:48 -msgid "active" -msgstr "Actif" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Les sous-classes de `Place` doivent implémenter la méthode slugify" - -#: geo/models.py:123 -msgid "continent" -msgstr "Continent" - -#: geo/models.py:124 -msgid "continents" -msgstr "Continents" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "Pays" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Pays" - -#: geo/models.py:182 -msgid "region" -msgstr "Région" - -#: geo/models.py:183 -msgid "regions" -msgstr "Régions" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Sous-région" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Sous-régions" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "Ville" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Villes" - -#: geo/models.py:270 -msgid "district" -msgstr "District" - -#: geo/models.py:271 -msgid "districts" -msgstr "Districts" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Code postal" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Codes postaux" - -#: geo/models.py:391 -msgid "address" -msgstr "Adresse" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Adresses" diff --git a/geo/locale/hi_IN/LC_MESSAGES/django.mo b/geo/locale/hi_IN/LC_MESSAGES/django.mo deleted file mode 100644 index 6c5906d1..00000000 Binary files a/geo/locale/hi_IN/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/hi_IN/LC_MESSAGES/django.po b/geo/locale/hi_IN/LC_MESSAGES/django.po deleted file mode 100644 index a5c05e36..00000000 --- a/geo/locale/hi_IN/LC_MESSAGES/django.po +++ /dev/null @@ -1,137 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "" - -#: geo/conf.py:407 -msgid "Name" -msgstr "" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "" - -#: geo/conf.py:409 -msgid "Link" -msgstr "" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "" - -#: geo/models.py:47 -msgid "UUID" -msgstr "" - -#: geo/models.py:48 -msgid "active" -msgstr "" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "" - -#: geo/models.py:123 -msgid "continent" -msgstr "" - -#: geo/models.py:124 -msgid "continents" -msgstr "" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "" - -#: geo/models.py:182 -msgid "region" -msgstr "" - -#: geo/models.py:183 -msgid "regions" -msgstr "" - -#: geo/models.py:205 -msgid "subregion" -msgstr "" - -#: geo/models.py:206 -msgid "subregions" -msgstr "" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "" - -#: geo/models.py:270 -msgid "district" -msgstr "" - -#: geo/models.py:271 -msgid "districts" -msgstr "" - -#: geo/models.py:344 -msgid "postal code" -msgstr "" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "" - -#: geo/models.py:391 -msgid "address" -msgstr "" - -#: geo/models.py:392 -msgid "addresses" -msgstr "" diff --git a/geo/locale/it_IT/LC_MESSAGES/django.mo b/geo/locale/it_IT/LC_MESSAGES/django.mo deleted file mode 100644 index a1ede1da..00000000 Binary files a/geo/locale/it_IT/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/it_IT/LC_MESSAGES/django.po b/geo/locale/it_IT/LC_MESSAGES/django.po deleted file mode 100644 index ab891edb..00000000 --- a/geo/locale/it_IT/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: ITALIAN \n" -"Language: ITALIAN\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Geodati" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Nome" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Abbreviazione" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Collegamento a" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "IATA (Airport) Code" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "ICAO (Airport) Code" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "Codice FAAC (Aeroporto)" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} non esiste: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} non esiste: {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} non esiste: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "ID univoco" - -#: geo/models.py:48 -msgid "active" -msgstr "Attivo" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Le sottoclassi di `Place` devono implementare il metodo slugify" - -#: geo/models.py:123 -msgid "continent" -msgstr "Continente" - -#: geo/models.py:124 -msgid "continents" -msgstr "Continenti" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "Paese" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Paesi" - -#: geo/models.py:182 -msgid "region" -msgstr "Regione" - -#: geo/models.py:183 -msgid "regions" -msgstr "Regioni" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Sottoregione" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Sottoregioni" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "Città" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Città" - -#: geo/models.py:270 -msgid "district" -msgstr "Distretto" - -#: geo/models.py:271 -msgid "districts" -msgstr "Distretti" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Codice postale" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Codici postali" - -#: geo/models.py:391 -msgid "address" -msgstr "Indirizzo" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Indirizzi" diff --git a/geo/locale/ja_JP/LC_MESSAGES/django.mo b/geo/locale/ja_JP/LC_MESSAGES/django.mo deleted file mode 100644 index c7b1d9a7..00000000 Binary files a/geo/locale/ja_JP/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/ja_JP/LC_MESSAGES/django.po b/geo/locale/ja_JP/LC_MESSAGES/django.po deleted file mode 100644 index 6e86ad64..00000000 --- a/geo/locale/ja_JP/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: BRITISH ENGLISH \n" -"Language: BRITISH ENGLISH\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "ジオデータ" - -#: geo/conf.py:407 -msgid "Name" -msgstr "名称" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "略語" - -#: geo/conf.py:409 -msgid "Link" -msgstr "リンク" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "IATA(空港)コード" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "ICAO(空港)コード" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "FAAC (空港) コード" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name}が存在しません:{city_uuid}が存在しません。" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name}が存在しません:{postal_code_uuid}が存在しません。" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name}が存在しません:{uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "ユニークID" - -#: geo/models.py:48 -msgid "active" -msgstr "アクティブ" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Place` のサブクラスは slugify メソッドを実装しなければならない。" - -#: geo/models.py:123 -msgid "continent" -msgstr "大陸" - -#: geo/models.py:124 -msgid "continents" -msgstr "大陸" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "国名" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "国名" - -#: geo/models.py:182 -msgid "region" -msgstr "地域" - -#: geo/models.py:183 -msgid "regions" -msgstr "地域" - -#: geo/models.py:205 -msgid "subregion" -msgstr "サブリージョン" - -#: geo/models.py:206 -msgid "subregions" -msgstr "サブリージョン" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "都市" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "都市" - -#: geo/models.py:270 -msgid "district" -msgstr "地区" - -#: geo/models.py:271 -msgid "districts" -msgstr "地区" - -#: geo/models.py:344 -msgid "postal code" -msgstr "郵便番号" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "郵便番号" - -#: geo/models.py:391 -msgid "address" -msgstr "住所" - -#: geo/models.py:392 -msgid "addresses" -msgstr "住所" diff --git a/geo/locale/kk_KZ/LC_MESSAGES/django.mo b/geo/locale/kk_KZ/LC_MESSAGES/django.mo deleted file mode 100644 index 6c5906d1..00000000 Binary files a/geo/locale/kk_KZ/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/kk_KZ/LC_MESSAGES/django.po b/geo/locale/kk_KZ/LC_MESSAGES/django.po deleted file mode 100644 index a5c05e36..00000000 --- a/geo/locale/kk_KZ/LC_MESSAGES/django.po +++ /dev/null @@ -1,137 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "" - -#: geo/conf.py:407 -msgid "Name" -msgstr "" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "" - -#: geo/conf.py:409 -msgid "Link" -msgstr "" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "" - -#: geo/models.py:47 -msgid "UUID" -msgstr "" - -#: geo/models.py:48 -msgid "active" -msgstr "" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "" - -#: geo/models.py:123 -msgid "continent" -msgstr "" - -#: geo/models.py:124 -msgid "continents" -msgstr "" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "" - -#: geo/models.py:182 -msgid "region" -msgstr "" - -#: geo/models.py:183 -msgid "regions" -msgstr "" - -#: geo/models.py:205 -msgid "subregion" -msgstr "" - -#: geo/models.py:206 -msgid "subregions" -msgstr "" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "" - -#: geo/models.py:270 -msgid "district" -msgstr "" - -#: geo/models.py:271 -msgid "districts" -msgstr "" - -#: geo/models.py:344 -msgid "postal code" -msgstr "" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "" - -#: geo/models.py:391 -msgid "address" -msgstr "" - -#: geo/models.py:392 -msgid "addresses" -msgstr "" diff --git a/geo/locale/nl_NL/LC_MESSAGES/django.mo b/geo/locale/nl_NL/LC_MESSAGES/django.mo deleted file mode 100644 index c49e7944..00000000 Binary files a/geo/locale/nl_NL/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/nl_NL/LC_MESSAGES/django.po b/geo/locale/nl_NL/LC_MESSAGES/django.po deleted file mode 100644 index 56044337..00000000 --- a/geo/locale/nl_NL/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: DUTCH \n" -"Language: DUTCH\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Geodata" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Naam" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Afkorting" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Koppeling naar" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "IATA (Luchthaven) Code" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "ICAO (Luchthaven) Code" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "FAAC (Luchthaven) Code" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} bestaat niet: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} bestaat niet: {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} bestaat niet: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "Uniek ID" - -#: geo/models.py:48 -msgid "active" -msgstr "Actief" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Subklassen van `Place` moeten de methode slugify implementeren" - -#: geo/models.py:123 -msgid "continent" -msgstr "Continent" - -#: geo/models.py:124 -msgid "continents" -msgstr "Continenten" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "Land" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Landen" - -#: geo/models.py:182 -msgid "region" -msgstr "Regio" - -#: geo/models.py:183 -msgid "regions" -msgstr "Regio's" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Subregio" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Subregio's" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "Stad" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Steden" - -#: geo/models.py:270 -msgid "district" -msgstr "District" - -#: geo/models.py:271 -msgid "districts" -msgstr "Wijken" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Postcode" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Postcodes" - -#: geo/models.py:391 -msgid "address" -msgstr "Adres" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Adressen" diff --git a/geo/locale/pl_PL/LC_MESSAGES/django.mo b/geo/locale/pl_PL/LC_MESSAGES/django.mo deleted file mode 100644 index 9a5aeb24..00000000 Binary files a/geo/locale/pl_PL/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/pl_PL/LC_MESSAGES/django.po b/geo/locale/pl_PL/LC_MESSAGES/django.po deleted file mode 100644 index b73c055d..00000000 --- a/geo/locale/pl_PL/LC_MESSAGES/django.po +++ /dev/null @@ -1,133 +0,0 @@ -# -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: BRITISH ENGLISH \n" -"Language: pl-PL\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Geodane" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Nazwa" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Skrót" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Link do" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "Kod IATA (lotniska)" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "Kod ICAO (lotniska)" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "Kod FAAC (lotnisko)" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} nie istnieje: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} nie istnieje: {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} nie istnieje: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "Unikalny identyfikator" - -#: geo/models.py:48 -msgid "active" -msgstr "Aktywny" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Podklasy `Place` muszą implementować metodę slugify" - -#: geo/models.py:123 -msgid "continent" -msgstr "Kontynent" - -#: geo/models.py:124 -msgid "continents" -msgstr "Kontynenty" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "Kraj" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Kraje" - -#: geo/models.py:182 -msgid "region" -msgstr "Region" - -#: geo/models.py:183 -msgid "regions" -msgstr "Regiony" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Podregion" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Podregiony" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "Miasto" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Miasta" - -#: geo/models.py:270 -msgid "district" -msgstr "Okręg" - -#: geo/models.py:271 -msgid "districts" -msgstr "Okręgi" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Kod pocztowy" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Kody pocztowe" - -#: geo/models.py:391 -msgid "address" -msgstr "Adres" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Adresy" diff --git a/geo/locale/pt_BR/LC_MESSAGES/django.mo b/geo/locale/pt_BR/LC_MESSAGES/django.mo deleted file mode 100644 index 3082bcc4..00000000 Binary files a/geo/locale/pt_BR/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/pt_BR/LC_MESSAGES/django.po b/geo/locale/pt_BR/LC_MESSAGES/django.po deleted file mode 100644 index b58b7344..00000000 --- a/geo/locale/pt_BR/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: BRITISH ENGLISH \n" -"Language: BRITISH ENGLISH\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Geodados" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Nome" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Abreviação" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Link para" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "Código IATA (aeroporto)" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "Código ICAO (aeroporto)" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "Código FAAC (Aeroporto)" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} não existe: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} não existe: {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} não existe: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "ID exclusivo" - -#: geo/models.py:48 -msgid "active" -msgstr "Ativo" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "As subclasses de `Place` devem implementar o método slugify" - -#: geo/models.py:123 -msgid "continent" -msgstr "Continente" - -#: geo/models.py:124 -msgid "continents" -msgstr "Continentes" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "País" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Países" - -#: geo/models.py:182 -msgid "region" -msgstr "Região" - -#: geo/models.py:183 -msgid "regions" -msgstr "Regiões" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Sub-região" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Sub-regiões" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "Cidade" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Cidades" - -#: geo/models.py:270 -msgid "district" -msgstr "Distrito" - -#: geo/models.py:271 -msgid "districts" -msgstr "Distritos" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Código postal" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Códigos postais" - -#: geo/models.py:391 -msgid "address" -msgstr "Endereço" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Endereços" diff --git a/geo/locale/ro_RO/LC_MESSAGES/django.mo b/geo/locale/ro_RO/LC_MESSAGES/django.mo deleted file mode 100644 index 2cbf6ca4..00000000 Binary files a/geo/locale/ro_RO/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/ro_RO/LC_MESSAGES/django.po b/geo/locale/ro_RO/LC_MESSAGES/django.po deleted file mode 100644 index ed8f756a..00000000 --- a/geo/locale/ro_RO/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: BRITISH ENGLISH \n" -"Language: BRITISH ENGLISH\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Geodata" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Nume și prenume" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Abreviere" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Link către" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "Cod IATA (Aeroport)" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "Cod OACI (Aeroport)" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "FAAC (Aeroport) Cod" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} nu există: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} nu există: {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} nu există: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "ID unic" - -#: geo/models.py:48 -msgid "active" -msgstr "Activ" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Subclasele lui `Place` trebuie să implementeze metoda slugify" - -#: geo/models.py:123 -msgid "continent" -msgstr "Continent" - -#: geo/models.py:124 -msgid "continents" -msgstr "Continente" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "Țara" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Țări" - -#: geo/models.py:182 -msgid "region" -msgstr "Regiunea" - -#: geo/models.py:183 -msgid "regions" -msgstr "Regiuni" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Subregiune" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Subregiuni" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "Oraș" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Orașe" - -#: geo/models.py:270 -msgid "district" -msgstr "Districtul" - -#: geo/models.py:271 -msgid "districts" -msgstr "Districte" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Cod poștal" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Coduri poștale" - -#: geo/models.py:391 -msgid "address" -msgstr "Adresă" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Adrese" diff --git a/geo/locale/ru_RU/LC_MESSAGES/django.mo b/geo/locale/ru_RU/LC_MESSAGES/django.mo deleted file mode 100644 index 5649eeda..00000000 Binary files a/geo/locale/ru_RU/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/ru_RU/LC_MESSAGES/django.po b/geo/locale/ru_RU/LC_MESSAGES/django.po deleted file mode 100644 index f5f62380..00000000 --- a/geo/locale/ru_RU/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: BRITISH ENGLISH \n" -"Language: BRITISH ENGLISH\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "Геоданные" - -#: geo/conf.py:407 -msgid "Name" -msgstr "Имя" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "Аббревиатура" - -#: geo/conf.py:409 -msgid "Link" -msgstr "Ссылка на" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "Код IATA (аэропорта)" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "Код ИКАО (аэропорта)" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "Код FAAC (аэропорт)" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} не существует: {city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} не существует: {postal_code_uuid}" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} не существует: {uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "Уникальный идентификатор" - -#: geo/models.py:48 -msgid "active" -msgstr "Активный" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Подклассы `Place` должны реализовывать метод slugify" - -#: geo/models.py:123 -msgid "continent" -msgstr "Континент" - -#: geo/models.py:124 -msgid "continents" -msgstr "Континенты" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "Страна" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "Страны" - -#: geo/models.py:182 -msgid "region" -msgstr "Регион" - -#: geo/models.py:183 -msgid "regions" -msgstr "Регионы" - -#: geo/models.py:205 -msgid "subregion" -msgstr "Субрегион" - -#: geo/models.py:206 -msgid "subregions" -msgstr "Субрегионы" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "Город" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "Города" - -#: geo/models.py:270 -msgid "district" -msgstr "Округ" - -#: geo/models.py:271 -msgid "districts" -msgstr "Районы" - -#: geo/models.py:344 -msgid "postal code" -msgstr "Почтовый индекс" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "Почтовые индексы" - -#: geo/models.py:391 -msgid "address" -msgstr "Адрес" - -#: geo/models.py:392 -msgid "addresses" -msgstr "Адреса" diff --git a/geo/locale/zh_Hans/LC_MESSAGES/django.mo b/geo/locale/zh_Hans/LC_MESSAGES/django.mo deleted file mode 100644 index a30d37ce..00000000 Binary files a/geo/locale/zh_Hans/LC_MESSAGES/django.mo and /dev/null differ diff --git a/geo/locale/zh_Hans/LC_MESSAGES/django.po b/geo/locale/zh_Hans/LC_MESSAGES/django.po deleted file mode 100644 index 8fc4f58f..00000000 --- a/geo/locale/zh_Hans/LC_MESSAGES/django.po +++ /dev/null @@ -1,138 +0,0 @@ -# eVibes Translations. -# Copyright (C) 2025 Egor "fureunoir" Gorbunov -# This file is distributed under the same license as the eVibes package. -# EGOR GORBUNOV , 2025. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: 1\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-04-28 16:26+0100\n" -"PO-Revision-Date: 2025-01-30 03:27+0000\n" -"Last-Translator: EGOR GORBUNOV \n" -"Language-Team: CHINESE SIMPLIFIED \n" -"Language: CHINESE SIMPLIFIED\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: geo/apps.py:8 -msgid "geodata" -msgstr "地理数据" - -#: geo/conf.py:407 -msgid "Name" -msgstr "名称" - -#: geo/conf.py:408 -msgid "Abbreviation" -msgstr "缩写" - -#: geo/conf.py:409 -msgid "Link" -msgstr "链接到" - -#: geo/conf.py:413 -msgid "IATA (Airport) Code" -msgstr "空运协会(机场)代码" - -#: geo/conf.py:414 -msgid "ICAO (Airport) Code" -msgstr "国际民航组织(机场)代码" - -#: geo/conf.py:415 -msgid "FAAC (Airport) Code" -msgstr "FAAC (机场)代码" - -#: geo/graphene/mutations.py:30 -#, python-brace-format -msgid "{name} does not exist: {city_uuid}" -msgstr "{name} 不存在:{city_uuid}" - -#: geo/graphene/mutations.py:33 -#, python-brace-format -msgid "{name} does not exist: {postal_code_uuid}" -msgstr "{name} 不存在:{postal_code_uuid}不存在" - -#: geo/graphene/mutations.py:92 geo/graphene/mutations.py:117 -#, python-brace-format -msgid "{name} does not exist: {uuid}" -msgstr "{name} 不存在:{uuid}" - -#: geo/models.py:47 -msgid "UUID" -msgstr "唯一 ID" - -#: geo/models.py:48 -msgid "active" -msgstr "活跃" - -#: geo/models.py:54 -msgid "subclasses_of_place_must_implement_slugify" -msgstr "Place \"的子类必须实现 slugify 方法" - -#: geo/models.py:123 -msgid "continent" -msgstr "大陆" - -#: geo/models.py:124 -msgid "continents" -msgstr "各大洲" - -#: geo/models.py:149 geo/models.py:169 -msgid "country" -msgstr "国家" - -#: geo/models.py:150 geo/models.py:170 -msgid "countries" -msgstr "国家" - -#: geo/models.py:182 -msgid "region" -msgstr "地区" - -#: geo/models.py:183 -msgid "regions" -msgstr "地区" - -#: geo/models.py:205 -msgid "subregion" -msgstr "次区域" - -#: geo/models.py:206 -msgid "subregions" -msgstr "次区域" - -#: geo/models.py:237 geo/models.py:253 -msgid "city" -msgstr "城市" - -#: geo/models.py:238 geo/models.py:254 -msgid "cities" -msgstr "城市" - -#: geo/models.py:270 -msgid "district" -msgstr "地区" - -#: geo/models.py:271 -msgid "districts" -msgstr "地区" - -#: geo/models.py:344 -msgid "postal code" -msgstr "邮政编码" - -#: geo/models.py:345 -msgid "postal codes" -msgstr "邮政编码" - -#: geo/models.py:391 -msgid "address" -msgstr "地址" - -#: geo/models.py:392 -msgid "addresses" -msgstr "地址" diff --git a/geo/managers.py b/geo/managers.py deleted file mode 100644 index 6ee2a940..00000000 --- a/geo/managers.py +++ /dev/null @@ -1,61 +0,0 @@ -import requests -from constance import config -from django.contrib.gis.geos import Point -from django.db import models - - -class AddressManager(models.Manager): - def create(self, raw_data: str, **kwargs): - """ - Create an Address instance by geocoding the provided raw address string. - - Args: - raw_data (str): The raw address input from the user (e.g., '36 Mornington Rd Loughton England'). - **kwargs: Additional fields to pass to the Address model (e.g., user). - """ - if not raw_data: - raise ValueError("'raw_data' (address string) must be provided.") - - # Query Nominatim - params = { - 'format': 'json', - 'addressdetails': 1, - 'q': raw_data, - } - resp = requests.get(config.NOMINATIM_URL, params=params) - resp.raise_for_status() - results = resp.json() - if not results: - raise ValueError(f"No geocoding result for address: {raw_data}") - data = results[0] - - # Parse address components - addr = data.get('address', {}) - street = addr.get('road') or addr.get('pedestrian') or '' - district = addr.get('city_district') or addr.get('suburb') or '' - city = addr.get('city') or addr.get('town') or addr.get('village') or '' - region = addr.get('state') or addr.get('region') or '' - postal_code = addr.get('postcode') or '' - country = addr.get('country') or '' - - # Parse location - try: - lat = float(data.get('lat')) - lon = float(data.get('lon')) - location = Point(lon, lat, srid=4326) - except (TypeError, ValueError): - location = None - - # Create the model instance, storing both the input string and full API response - return super().create( - raw_data=raw_data, - street=street, - district=district, - city=city, - region=region, - postal_code=postal_code, - country=country, - location=location, - api_response=data, - **kwargs - ) diff --git a/geo/migrations/0002_alter_address_api_response_alter_address_location_and_more.py b/geo/migrations/0002_alter_address_api_response_alter_address_location_and_more.py deleted file mode 100644 index 70eca6fe..00000000 --- a/geo/migrations/0002_alter_address_api_response_alter_address_location_and_more.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 5.2 on 2025-05-19 11:40 - -import django.contrib.gis.db.models.fields -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('geo', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='address', - name='api_response', - field=models.JSONField(blank=True, help_text='stored JSON response from the geocoding service', null=True), - ), - migrations.AlterField( - model_name='address', - name='location', - field=django.contrib.gis.db.models.fields.PointField(blank=True, geography=True, - help_text='geolocation point: (longitude, latitude)', - null=True, srid=4326), - ), - migrations.AlterField( - model_name='address', - name='raw_data', - field=models.JSONField(blank=True, help_text='full JSON response from geocoder for this address', - null=True), - ), - ] diff --git a/geo/migrations/__init__.py b/geo/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/geo/models.py b/geo/models.py deleted file mode 100644 index c8a89a8f..00000000 --- a/geo/models.py +++ /dev/null @@ -1,56 +0,0 @@ -from django.contrib.gis.db import models as gis_models -from django.db import models -from django.db.models import Index -from django.utils.translation import gettext_lazy as _ - -from core.abstract import NiceModel -from geo.managers import AddressManager - - -class Address(NiceModel): - street = models.CharField(_("street"), max_length=255, null=True) # noqa: DJ001 - district = models.CharField(_("district"), max_length=255, null=True) # noqa: DJ001 - city = models.CharField(_("city"), max_length=100, null=True) # noqa: DJ001 - region = models.CharField(_("region"), max_length=100, null=True) # noqa: DJ001 - postal_code = models.CharField(_("postal code"), max_length=20, null=True) # noqa: DJ001 - country = models.CharField(_("country"), max_length=40, null=True) # noqa: DJ001 - - location = gis_models.PointField( - geography=True, - srid=4326, - null=True, - blank=True, - help_text=_("geolocation point: (longitude, latitude)") - ) - - raw_data = models.JSONField( - blank=True, - null=True, - help_text=_("full JSON response from geocoder for this address") - ) - - api_response = models.JSONField( - blank=True, - null=True, - help_text=_("stored JSON response from the geocoding service") - ) - - user = models.ForeignKey( - to="vibes_auth.User", - on_delete=models.CASCADE, - blank=True, - null=True - ) - - objects = AddressManager() - - class Meta: - verbose_name = _("address") - verbose_name_plural = _("addresses") - indexes = [ - Index(fields=["location"]), - ] - - def __str__(self): - base = f"{self.street}, {self.city}, {self.country}" - return f"{base} for {self.user.email}" if self.user else base diff --git a/geo/serializers.py b/geo/serializers.py deleted file mode 100644 index 1e1ff6c7..00000000 --- a/geo/serializers.py +++ /dev/null @@ -1,65 +0,0 @@ -from rest_framework import serializers - -from geo.models import Address - - -class AddressAutocompleteInputSerializer(serializers.Serializer): - q = serializers.CharField( - required=True - ) - limit = serializers.IntegerField( - required=False, - min_value=1, - max_value=10, - default=5 - ) - - -class AddressSuggestionSerializer(serializers.Serializer): - display_name = serializers.CharField() - lat = serializers.FloatField() - lon = serializers.FloatField() - address = serializers.DictField(child=serializers.CharField()) - - -class AddressSerializer(serializers.ModelSerializer): - latitude = serializers.FloatField(source="location.y", read_only=True) - longitude = serializers.FloatField(source="location.x", read_only=True) - - class Meta: - model = Address - fields = [ - "uuid", - "street", - "district", - "city", - "region", - "postal_code", - "country", - "latitude", - "longitude", - "raw_data", - "api_response", - "user", - ] - read_only_fields = [ - "latitude", - "longitude", - "raw_data", - "api_response", - ] - - -class AddressCreateSerializer(serializers.ModelSerializer): - raw_data = serializers.CharField( - write_only=True, - max_length=512, - ) - - class Meta: - model = Address - fields = ["raw_data", "user"] - - def create(self, validated_data): - raw = validated_data.pop("raw_data") - return Address.objects.create(raw_data=raw, **validated_data) diff --git a/geo/templates/__init__.py b/geo/templates/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/geo/tests.py b/geo/tests.py deleted file mode 100644 index e55d6890..00000000 --- a/geo/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase # noqa: F401 - -# Create your tests here. diff --git a/geo/urls.py b/geo/urls.py deleted file mode 100644 index 55325b74..00000000 --- a/geo/urls.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.urls import include, path -from rest_framework.routers import DefaultRouter - -from geo.viewsets import AddressViewSet - -geo_router = DefaultRouter() -geo_router.register(r"addresses", AddressViewSet, basename="addresses") - -urlpatterns = [ - path(r"", include(geo_router.urls)), -] diff --git a/geo/utils/__init__.py b/geo/utils/__init__.py deleted file mode 100644 index e9371806..00000000 --- a/geo/utils/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ -from django.contrib.gis.db.models import PointField -from django.contrib.gis.geos import Point -from graphene.types.scalars import Scalar -from graphene_django.converter import convert_django_field -from graphql.language import ast - - -class PointScalar(Scalar): - """Custom scalar for GeoDjango PointField""" - - @staticmethod - def serialize(point): - if not isinstance(point, Point): - raise Exception("Expected a Point instance") - return {"x": point.x, "y": point.y} - - @staticmethod - def parse_literal(node): - if isinstance(node, ast.ObjectValue): - return Point(x=node.value["x"], y=node.value["y"]) - return None - - @staticmethod - def parse_value(value): - if isinstance(value, dict): - return Point(x=value["x"], y=value["y"]) - return None - - -@convert_django_field.register(PointField) -def convert_point_field_to_custom_type(field, registry=None): - return PointScalar(description=field.help_text, required=not field.null) diff --git a/geo/views.py b/geo/views.py deleted file mode 100644 index e69de29b..00000000 diff --git a/geo/viewsets.py b/geo/viewsets.py deleted file mode 100644 index 60c8c04f..00000000 --- a/geo/viewsets.py +++ /dev/null @@ -1,44 +0,0 @@ -from django.utils.translation import gettext_lazy as _ -from drf_spectacular.utils import extend_schema_view -from rest_framework import status, viewsets -from rest_framework.decorators import action -from rest_framework.permissions import IsAdminUser -from rest_framework.response import Response - -from core.permissions import IsOwner -from geo.docs.drf.viewsets import ADDRESS_SCHEMA -from geo.models import Address -from geo.serializers import AddressAutocompleteInputSerializer, AddressCreateSerializer, AddressSerializer -from geo.utils.nominatim import fetch_address_suggestions - - -@extend_schema_view(**ADDRESS_SCHEMA) -class AddressViewSet(viewsets.ModelViewSet): - queryset = Address.objects.all() - serializer_class = AddressSerializer - permission_classes = [IsOwner, IsAdminUser] - - def get_serializer_class(self): - if self.action == 'create': - return AddressCreateSerializer - if self.action == 'autocomplete': - return AddressAutocompleteInputSerializer - return AddressSerializer - - @action(detail=False, methods=["get"], url_path="autocomplete") - def autocomplete(self, request): - serializer = AddressAutocompleteInputSerializer(data=request.query_params) - serializer.is_valid(raise_exception=True) - - q = serializer.validated_data["q"] - limit = serializer.validated_data["limit"] - - try: - suggestions = fetch_address_suggestions(query=q, limit=limit) - except Exception as e: - return Response( - {"detail": _(f"Geocoding error: {e}")}, - status=status.HTTP_502_BAD_GATEWAY, - ) - - return Response(suggestions, status=status.HTTP_200_OK) diff --git a/payments/models.py b/payments/models.py index 31708baa..de32abb8 100644 --- a/payments/models.py +++ b/payments/models.py @@ -9,7 +9,7 @@ from core.abstract import NiceModel class Balance(NiceModel): amount = FloatField(null=False, blank=False, default=0) user = OneToOneField( - to="vibes_auth.User", on_delete=CASCADE, blank=False, null=False, related_name="payments_balance" + to="vibes_auth.User", on_delete=CASCADE, blank=True, null=True, related_name="payments_balance" ) def __str__(self): @@ -45,8 +45,8 @@ class Transaction(NiceModel): def save(self, **kwargs): if self.amount != 0.0 and ( - (config.PAYMENT_GATEWAY_MINIMUM <= self.amount <= config.PAYMENT_GATEWAY_MAXIMUM) - or (config.PAYMENT_GATEWAY_MINIMUM == 0 and config.PAYMENT_GATEWAY_MAXIMUM == 0) + (config.PAYMENT_GATEWAY_MINIMUM <= self.amount <= config.PAYMENT_GATEWAY_MAXIMUM) + or (config.PAYMENT_GATEWAY_MINIMUM == 0 and config.PAYMENT_GATEWAY_MAXIMUM == 0) ): if len(str(self.amount).split(".")[1]) > 2: self.amount = round(self.amount, 2)