diff --git a/core/apps/shared/admin/__init__.py b/core/apps/shared/admin/__init__.py index 310e6d4..478b3c6 100644 --- a/core/apps/shared/admin/__init__.py +++ b/core/apps/shared/admin/__init__.py @@ -6,4 +6,5 @@ from .doctor import * from .plan import * from .tour_plan import * from .location import * -from .factory import * \ No newline at end of file +from .factory import * +from .support import * \ No newline at end of file diff --git a/core/apps/shared/admin/support.py b/core/apps/shared/admin/support.py new file mode 100644 index 0000000..9702738 --- /dev/null +++ b/core/apps/shared/admin/support.py @@ -0,0 +1,12 @@ +# django +from django.contrib import admin + +# shared +from core.apps.shared.models import Support + + +@admin.register(Support) +class SupportAdmin(admin.ModelAdmin): + list_display = ['id', 'problem', 'date', 'user'] + search_fields = ['problem', 'user__first_name', 'user__last_name'] + \ No newline at end of file diff --git a/core/apps/shared/migrations/0014_support.py b/core/apps/shared/migrations/0014_support.py new file mode 100644 index 0000000..ed99fe0 --- /dev/null +++ b/core/apps/shared/migrations/0014_support.py @@ -0,0 +1,31 @@ +# Generated by Django 5.2 on 2025-12-03 10:29 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('shared', '0013_alter_district_name_alter_place_name'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Support', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('problem', models.TextField()), + ('date', models.DateField()), + ('district', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='supports', to='shared.district')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='supports', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/core/apps/shared/migrations/0015_support_type.py b/core/apps/shared/migrations/0015_support_type.py new file mode 100644 index 0000000..1361c4c --- /dev/null +++ b/core/apps/shared/migrations/0015_support_type.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2 on 2025-12-03 10:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('shared', '0014_support'), + ] + + operations = [ + migrations.AddField( + model_name='support', + name='type', + field=models.CharField(choices=[('PROBLEM', 'muammo'), ('HELP', 'yordam')], default='PROBLEM', max_length=8), + ), + ] diff --git a/core/apps/shared/models/__init__.py b/core/apps/shared/models/__init__.py index 99e277b..8e22187 100644 --- a/core/apps/shared/models/__init__.py +++ b/core/apps/shared/models/__init__.py @@ -8,3 +8,4 @@ from .plan import * from .location import * from .tour_plan import * from .factory import * +from .support import * diff --git a/core/apps/shared/models/support.py b/core/apps/shared/models/support.py new file mode 100644 index 0000000..a4792dc --- /dev/null +++ b/core/apps/shared/models/support.py @@ -0,0 +1,24 @@ +# django +from django.db import models + +# shared +from core.apps.shared.models import BaseModel, District +# accounts +from core.apps.accounts.models import User + + +class Support(BaseModel): + TYPE = ( + ('PROBLEM', 'muammo'), + ('HELP', 'yordam'), + ) + + district = models.ForeignKey(District, on_delete=models.CASCADE, related_name='supports') + problem = models.TextField() + date = models.DateField() + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='supports') + type = models.CharField(choices=TYPE, default="PROBLEM", max_length=8) + + def __str__(self): + return f"#{self.id} problem from {self.user.first_name} {self.user.last_name}" + \ No newline at end of file diff --git a/core/apps/shared/serializers/support.py b/core/apps/shared/serializers/support.py new file mode 100644 index 0000000..badb38f --- /dev/null +++ b/core/apps/shared/serializers/support.py @@ -0,0 +1,32 @@ +# django +from django.db import transaction + +# rest framework +from rest_framework import serializers + +# shared +from core.apps.shared.models import Support, District + + +class SupportCreateSerializer(serializers.Serializer): + district_id = serializers.IntegerField() + problem = serializers.CharField() + date = serializers.DateField() + type = serializers.ChoiceField(choices=Support.TYPE) + + def validate(self, data): + district = District.objects.filter(id=data['district_id']).first() + if not district: + raise serializers.ValidationError({'district': "district not found"}) + data['district'] = district + return data + + def create(self, validated_data): + with transaction.atomic(): + return Support.objects.create( + user=self.context.get('user'), + district=validated_data.get('district'), + date=validated_data.get('date'), + type=validated_data.get('type'), + problem=validated_data.get('problem' ) + ) diff --git a/core/apps/shared/urls.py b/core/apps/shared/urls.py index 903ea06..af1f59f 100644 --- a/core/apps/shared/urls.py +++ b/core/apps/shared/urls.py @@ -18,6 +18,8 @@ from core.apps.shared.views import location as location_view from core.apps.shared.views import tour_plan as tp_view # shared factory view from core.apps.shared.views import factory as factory_view +# shared support view +from core.apps.shared.views import support as support_view urlpatterns = [ @@ -83,4 +85,9 @@ urlpatterns = [ path('list/', factory_view.FactoryListApiView.as_view(), name='factory-list-api'), ], )), + path('support/', include( + [ + path('send/', support_view.SupportCreateApiView.as_view(), name='support-create-api'), + ] + )) ] \ No newline at end of file diff --git a/core/apps/shared/views/support.py b/core/apps/shared/views/support.py new file mode 100644 index 0000000..a866e03 --- /dev/null +++ b/core/apps/shared/views/support.py @@ -0,0 +1,37 @@ +# rest framework +from rest_framework import generics, permissions + +# drf yasg +from drf_yasg import openapi +from drf_yasg.utils import swagger_auto_schema + +# shared +from core.apps.shared.models import Support +from core.apps.shared.utils.response_mixin import ResponseMixin +from core.apps.shared.serializers.support import SupportCreateSerializer + + +class SupportCreateApiView(generics.GenericAPIView, ResponseMixin): + serializer_class = SupportCreateSerializer + queryset = Support.objects.all() + permission_classes = [permissions.IsAuthenticated] + + def post(self, request): + try: + serializer = self.serializer_class(data=request.data, context={"user": request.user}) + if serializer.is_valid(): + data = serializer.save() + return self.success_response( + data={}, + message="Xabar yuborildi", + status_code=201 + ) + return self.failure_response( + data=serializer.errors, + message='Xabar yuborilmadi, iltimos malumotlar togri ekanligini tekshirib koring', + ) + except Exception as e: + return self.error_response( + data=str(e), + message='xatolik, backend dastruchiga murojaat qiling iltimos' + ) \ No newline at end of file