diff --git a/core/apps/accounts/migrations/0002_alter_user_role.py b/core/apps/accounts/migrations/0002_alter_user_role.py new file mode 100644 index 0000000..15c5b8c --- /dev/null +++ b/core/apps/accounts/migrations/0002_alter_user_role.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2.7 on 2026-02-12 10:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('accounts', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='user', + name='role', + field=models.CharField(choices=[('superuser', 'Superuser'), ('admin', 'Admin'), ('user', 'User'), ('evaluator', 'Evaluator'), ('dealer', 'Dealer'), ('client', 'Client')], default='user', max_length=255), + ), + ] diff --git a/core/apps/evaluation/admin/__init__.py b/core/apps/evaluation/admin/__init__.py index e69de29..f22e1ba 100644 --- a/core/apps/evaluation/admin/__init__.py +++ b/core/apps/evaluation/admin/__init__.py @@ -0,0 +1 @@ +from .customer import * # noqa diff --git a/core/apps/evaluation/admin/customer.py b/core/apps/evaluation/admin/customer.py new file mode 100644 index 0000000..07f55b1 --- /dev/null +++ b/core/apps/evaluation/admin/customer.py @@ -0,0 +1,21 @@ +from django.contrib import admin +from unfold.admin import ModelAdmin + +from core.apps.evaluation.models import CustomerModel, PropertyOwnerModel + + +@admin.register(CustomerModel) +class CustomerAdmin(ModelAdmin): + list_display = ( + "id", + "__str__", + ) + + +@admin.register(PropertyOwnerModel) +class PropertyOwnerAdmin(ModelAdmin): + list_display = ( + "id", + "__str__", + ) + diff --git a/core/apps/evaluation/filters/__init__.py b/core/apps/evaluation/filters/__init__.py new file mode 100644 index 0000000..f22e1ba --- /dev/null +++ b/core/apps/evaluation/filters/__init__.py @@ -0,0 +1 @@ +from .customer import * # noqa diff --git a/core/apps/evaluation/filters/customer.py b/core/apps/evaluation/filters/customer.py new file mode 100644 index 0000000..98a89e3 --- /dev/null +++ b/core/apps/evaluation/filters/customer.py @@ -0,0 +1,18 @@ +from django_filters import rest_framework as filters + +from core.apps.evaluation.models import CustomerModel, PropertyOwnerModel + + +class CustomerFilter(filters.FilterSet): + + class Meta: + model = CustomerModel + fields = [] + + +class PropertyOwnerFilter(filters.FilterSet): + + class Meta: + model = PropertyOwnerModel + fields = [] + diff --git a/core/apps/evaluation/forms/__init__.py b/core/apps/evaluation/forms/__init__.py new file mode 100644 index 0000000..f22e1ba --- /dev/null +++ b/core/apps/evaluation/forms/__init__.py @@ -0,0 +1 @@ +from .customer import * # noqa diff --git a/core/apps/evaluation/forms/customer.py b/core/apps/evaluation/forms/customer.py new file mode 100644 index 0000000..6701b54 --- /dev/null +++ b/core/apps/evaluation/forms/customer.py @@ -0,0 +1,18 @@ +from django import forms + +from core.apps.evaluation.models import CustomerModel, PropertyOwnerModel + + +class CustomerForm(forms.ModelForm): + + class Meta: + model = CustomerModel + fields = "__all__" + + +class PropertyOwnerForm(forms.ModelForm): + + class Meta: + model = PropertyOwnerModel + fields = "__all__" + diff --git a/core/apps/evaluation/migrations/0001_initial.py b/core/apps/evaluation/migrations/0001_initial.py new file mode 100644 index 0000000..549234a --- /dev/null +++ b/core/apps/evaluation/migrations/0001_initial.py @@ -0,0 +1,42 @@ +# Generated by Django 5.2.7 on 2026-02-12 10:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='CustomerModel', + 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)), + ('name', models.CharField(max_length=255, verbose_name='name')), + ], + options={ + 'verbose_name': 'CustomerModel', + 'verbose_name_plural': 'CustomerModels', + 'db_table': 'Customer', + }, + ), + migrations.CreateModel( + name='PropertyownerModel', + 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)), + ('name', models.CharField(max_length=255, verbose_name='name')), + ], + options={ + 'verbose_name': 'PropertyownerModel', + 'verbose_name_plural': 'PropertyownerModels', + 'db_table': 'PropertyOwner', + }, + ), + ] diff --git a/core/apps/evaluation/migrations/0002_alter_customermodel_options_and_more.py b/core/apps/evaluation/migrations/0002_alter_customermodel_options_and_more.py new file mode 100644 index 0000000..91b0b7d --- /dev/null +++ b/core/apps/evaluation/migrations/0002_alter_customermodel_options_and_more.py @@ -0,0 +1,209 @@ +# Generated by Django 5.2.7 on 2026-02-12 10:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('evaluation', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='customermodel', + options={'verbose_name': 'Customer', 'verbose_name_plural': 'Customers'}, + ), + migrations.AlterModelOptions( + name='propertyownermodel', + options={'verbose_name': 'Property Owner', 'verbose_name_plural': 'Property Owners'}, + ), + migrations.RemoveField( + model_name='customermodel', + name='name', + ), + migrations.RemoveField( + model_name='propertyownermodel', + name='name', + ), + migrations.AddField( + model_name='customermodel', + name='address', + field=models.TextField(blank=True, default='', verbose_name='address'), + ), + migrations.AddField( + model_name='customermodel', + name='bank_account', + field=models.CharField(blank=True, default='', max_length=30, verbose_name='bank account (HISOB raqam)'), + ), + migrations.AddField( + model_name='customermodel', + name='certificate_file', + field=models.FileField(blank=True, null=True, upload_to='customers/certificates/', verbose_name='certificate file (guvohnoma)'), + ), + migrations.AddField( + model_name='customermodel', + name='customer_type', + field=models.CharField(choices=[('legal', 'Yuridik shaxs'), ('individual', 'Jismoniy shaxs')], default=1, max_length=20, verbose_name='customer type'), + preserve_default=False, + ), + migrations.AddField( + model_name='customermodel', + name='director_name', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='director full name'), + ), + migrations.AddField( + model_name='customermodel', + name='first_name', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='first name'), + ), + migrations.AddField( + model_name='customermodel', + name='inn', + field=models.CharField(blank=True, default='', max_length=20, verbose_name='INN'), + ), + migrations.AddField( + model_name='customermodel', + name='jshshir', + field=models.CharField(blank=True, default='', max_length=14, verbose_name='JSHSHIR'), + ), + migrations.AddField( + model_name='customermodel', + name='last_name', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='last name'), + ), + migrations.AddField( + model_name='customermodel', + name='mfo', + field=models.CharField(blank=True, default='', max_length=10, verbose_name='MFO'), + ), + migrations.AddField( + model_name='customermodel', + name='middle_name', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='middle name'), + ), + migrations.AddField( + model_name='customermodel', + name='org_address', + field=models.TextField(blank=True, default='', verbose_name='organization address'), + ), + migrations.AddField( + model_name='customermodel', + name='org_name', + field=models.CharField(blank=True, default='', max_length=500, verbose_name='organization name'), + ), + migrations.AddField( + model_name='customermodel', + name='passport_issued_by', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='passport issued by'), + ), + migrations.AddField( + model_name='customermodel', + name='passport_issued_date', + field=models.DateField(blank=True, null=True, verbose_name='passport issued date'), + ), + migrations.AddField( + model_name='customermodel', + name='passport_number', + field=models.CharField(blank=True, default='', max_length=20, verbose_name='passport number'), + ), + migrations.AddField( + model_name='customermodel', + name='passport_series', + field=models.CharField(blank=True, default='', max_length=10, verbose_name='passport series'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='address', + field=models.TextField(blank=True, default='', verbose_name='address'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='bank_account', + field=models.CharField(blank=True, default='', max_length=30, verbose_name='bank account (HISOB raqam)'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='certificate_file', + field=models.FileField(blank=True, null=True, upload_to='property_owners/certificates/', verbose_name='certificate file (guvohnoma)'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='director_name', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='director full name'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='first_name', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='first name'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='inn', + field=models.CharField(blank=True, default='', max_length=20, verbose_name='INN'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='jshshir', + field=models.CharField(blank=True, default='', max_length=14, verbose_name='JSHSHIR'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='last_name', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='last name'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='mfo', + field=models.CharField(blank=True, default='', max_length=10, verbose_name='MFO'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='middle_name', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='middle name'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='org_address', + field=models.TextField(blank=True, default='', verbose_name='organization address'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='org_name', + field=models.CharField(blank=True, default='', max_length=500, verbose_name='organization name'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='owner_type', + field=models.CharField(choices=[('legal', 'Yuridik shaxs'), ('individual', 'Jismoniy shaxs')], default=1, max_length=20, verbose_name='owner type'), + preserve_default=False, + ), + migrations.AddField( + model_name='propertyownermodel', + name='passport_issued_by', + field=models.CharField(blank=True, default='', max_length=255, verbose_name='passport issued by'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='passport_issued_date', + field=models.DateField(blank=True, null=True, verbose_name='passport issued date'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='passport_number', + field=models.CharField(blank=True, default='', max_length=20, verbose_name='passport number'), + ), + migrations.AddField( + model_name='propertyownermodel', + name='passport_series', + field=models.CharField(blank=True, default='', max_length=10, verbose_name='passport series'), + ), + migrations.AlterModelTable( + name='customermodel', + table='customer', + ), + migrations.AlterModelTable( + name='propertyownermodel', + table='property_owner', + ), + ] diff --git a/core/apps/evaluation/models/__init__.py b/core/apps/evaluation/models/__init__.py index e69de29..f22e1ba 100644 --- a/core/apps/evaluation/models/__init__.py +++ b/core/apps/evaluation/models/__init__.py @@ -0,0 +1 @@ +from .customer import * # noqa diff --git a/core/apps/evaluation/models/customer.py b/core/apps/evaluation/models/customer.py new file mode 100644 index 0000000..bbab869 --- /dev/null +++ b/core/apps/evaluation/models/customer.py @@ -0,0 +1,167 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ +from django_core.models import AbstractBaseModel +from model_bakery import baker + + +class CustomerTypeChoice(models.TextChoices): + LEGAL = "legal", _("Yuridik shaxs") + INDIVIDUAL = "individual", _("Jismoniy shaxs") + + +class CustomerModel(AbstractBaseModel): + """Buyurtmachi — baholashga buyurtma beruvchi (yuridik yoki jismoniy shaxs)""" + + customer_type = models.CharField( + verbose_name=_("customer type"), + max_length=20, + choices=CustomerTypeChoice, + ) + + # --- Jismoniy shaxs ma'lumotlari --- + jshshir = models.CharField( + verbose_name=_("JSHSHIR"), max_length=14, blank=True, default="" + ) # Kiritiladi + passport_series = models.CharField( + verbose_name=_("passport series"), max_length=10, blank=True, default="" + ) # Kiritiladi + passport_number = models.CharField( + verbose_name=_("passport number"), max_length=20, blank=True, default="" + ) # Kiritiladi + first_name = models.CharField( + verbose_name=_("first name"), max_length=255, blank=True, default="" + ) # 🌐 API: JSHSHIR orqali to'ladi + last_name = models.CharField( + verbose_name=_("last name"), max_length=255, blank=True, default="" + ) # 🌐 API: JSHSHIR orqali to'ladi + middle_name = models.CharField( + verbose_name=_("middle name"), max_length=255, blank=True, default="" + ) # 🌐 API: JSHSHIR orqali to'ladi + address = models.TextField( + verbose_name=_("address"), blank=True, default="" + ) # 🌐 API: JSHSHIR orqali to'ladi + passport_issued_date = models.DateField( + verbose_name=_("passport issued date"), null=True, blank=True + ) # 🌐 API + passport_issued_by = models.CharField( + verbose_name=_("passport issued by"), max_length=255, blank=True, default="" + ) # 🌐 API + + # --- Yuridik shaxs ma'lumotlari --- + inn = models.CharField( + verbose_name=_("INN"), max_length=20, blank=True, default="" + ) # Kiritiladi + org_name = models.CharField( + verbose_name=_("organization name"), max_length=500, blank=True, default="" + ) # 🌐 API: INN orqali to'ladi + org_address = models.TextField( + verbose_name=_("organization address"), blank=True, default="" + ) # 🌐 API: INN orqali to'ladi + director_name = models.CharField( + verbose_name=_("director full name"), max_length=255, blank=True, default="" + ) # 🌐 API: INN orqali to'ladi + mfo = models.CharField( + verbose_name=_("MFO"), max_length=10, blank=True, default="" + ) # 🌐 API: INN orqali to'ladi + bank_account = models.CharField( + verbose_name=_("bank account (HISOB raqam)"), max_length=30, blank=True, default="" + ) # 🌐 API: INN orqali to'ladi + certificate_file = models.FileField( + verbose_name=_("certificate file (guvohnoma)"), + upload_to="customers/certificates/", + null=True, + blank=True, + ) # Yuridik shaxs guvohnomasi + + def __str__(self): + if self.customer_type == CustomerTypeChoice.LEGAL: + return self.org_name or str(self.pk) + return f"{self.last_name} {self.first_name}" or str(self.pk) + + @classmethod + def _baker(cls): + return baker.make(cls, customer_type=CustomerTypeChoice.INDIVIDUAL) + + class Meta: + db_table = "customer" + verbose_name = _("Customer") + verbose_name_plural = _("Customers") + + +class PropertyOwnerModel(AbstractBaseModel): + """Mulk egasi — agar buyurtmachi va mulk egasi boshqa-boshqa bo'lsa""" + + owner_type = models.CharField( + verbose_name=_("owner type"), + max_length=20, + choices=CustomerTypeChoice, + ) + + # --- Jismoniy shaxs ma'lumotlari --- + jshshir = models.CharField( + verbose_name=_("JSHSHIR"), max_length=14, blank=True, default="" + ) + passport_series = models.CharField( + verbose_name=_("passport series"), max_length=10, blank=True, default="" + ) + passport_number = models.CharField( + verbose_name=_("passport number"), max_length=20, blank=True, default="" + ) + first_name = models.CharField( + verbose_name=_("first name"), max_length=255, blank=True, default="" + ) # 🌐 API + last_name = models.CharField( + verbose_name=_("last name"), max_length=255, blank=True, default="" + ) # 🌐 API + middle_name = models.CharField( + verbose_name=_("middle name"), max_length=255, blank=True, default="" + ) # 🌐 API + address = models.TextField( + verbose_name=_("address"), blank=True, default="" + ) # 🌐 API + passport_issued_date = models.DateField( + verbose_name=_("passport issued date"), null=True, blank=True + ) # 🌐 API + passport_issued_by = models.CharField( + verbose_name=_("passport issued by"), max_length=255, blank=True, default="" + ) # 🌐 API + + # --- Yuridik shaxs ma'lumotlari --- + inn = models.CharField( + verbose_name=_("INN"), max_length=20, blank=True, default="" + ) + org_name = models.CharField( + verbose_name=_("organization name"), max_length=500, blank=True, default="" + ) # 🌐 API + org_address = models.TextField( + verbose_name=_("organization address"), blank=True, default="" + ) # 🌐 API + director_name = models.CharField( + verbose_name=_("director full name"), max_length=255, blank=True, default="" + ) # 🌐 API + mfo = models.CharField( + verbose_name=_("MFO"), max_length=10, blank=True, default="" + ) # 🌐 API + bank_account = models.CharField( + verbose_name=_("bank account (HISOB raqam)"), max_length=30, blank=True, default="" + ) # 🌐 API + certificate_file = models.FileField( + verbose_name=_("certificate file (guvohnoma)"), + upload_to="property_owners/certificates/", + null=True, + blank=True, + ) + + def __str__(self): + if self.owner_type == CustomerTypeChoice.LEGAL: + return self.org_name or str(self.pk) + return f"{self.last_name} {self.first_name}" or str(self.pk) + + @classmethod + def _baker(cls): + return baker.make(cls, owner_type=CustomerTypeChoice.INDIVIDUAL) + + class Meta: + db_table = "property_owner" + verbose_name = _("Property Owner") + verbose_name_plural = _("Property Owners") diff --git a/core/apps/evaluation/permissions/__init__.py b/core/apps/evaluation/permissions/__init__.py new file mode 100644 index 0000000..f22e1ba --- /dev/null +++ b/core/apps/evaluation/permissions/__init__.py @@ -0,0 +1 @@ +from .customer import * # noqa diff --git a/core/apps/evaluation/permissions/customer.py b/core/apps/evaluation/permissions/customer.py new file mode 100644 index 0000000..32739eb --- /dev/null +++ b/core/apps/evaluation/permissions/customer.py @@ -0,0 +1,23 @@ +from rest_framework import permissions + + +class CustomerPermission(permissions.BasePermission): + + def __init__(self) -> None: ... + + def __call__(self, *args, **kwargs): + return self + + def has_permission(self, request, view): + return True + + +class PropertyownerPermission(permissions.BasePermission): + + def __init__(self) -> None: ... + + def __call__(self, *args, **kwargs): + return self + + def has_permission(self, request, view): + return True diff --git a/core/apps/evaluation/serializers/__init__.py b/core/apps/evaluation/serializers/__init__.py index e69de29..f22e1ba 100644 --- a/core/apps/evaluation/serializers/__init__.py +++ b/core/apps/evaluation/serializers/__init__.py @@ -0,0 +1 @@ +from .customer import * # noqa diff --git a/core/apps/evaluation/serializers/customer/Customer.py b/core/apps/evaluation/serializers/customer/Customer.py new file mode 100644 index 0000000..6c0b379 --- /dev/null +++ b/core/apps/evaluation/serializers/customer/Customer.py @@ -0,0 +1,27 @@ +from rest_framework import serializers + +from core.apps.evaluation.models import CustomerModel + + +class BaseCustomerSerializer(serializers.ModelSerializer): + class Meta: + model = CustomerModel + fields = [ + "id", + ] + + +class ListCustomerSerializer(BaseCustomerSerializer): + class Meta(BaseCustomerSerializer.Meta): ... + + +class RetrieveCustomerSerializer(BaseCustomerSerializer): + class Meta(BaseCustomerSerializer.Meta): ... + + +class CreateCustomerSerializer(BaseCustomerSerializer): + class Meta(BaseCustomerSerializer.Meta): + fields = [ + "id", + ] + diff --git a/core/apps/evaluation/serializers/customer/PropertyOwner.py b/core/apps/evaluation/serializers/customer/PropertyOwner.py new file mode 100644 index 0000000..ee912c3 --- /dev/null +++ b/core/apps/evaluation/serializers/customer/PropertyOwner.py @@ -0,0 +1,27 @@ +from rest_framework import serializers + +from core.apps.evaluation.models import PropertyOwnerModel + + +class BasePropertyOwnerSerializer(serializers.ModelSerializer): + class Meta: + model = PropertyOwnerModel + fields = [ + "id", + ] + + +class ListPropertyOwnerSerializer(BasePropertyOwnerSerializer): + class Meta(BasePropertyOwnerSerializer.Meta): ... + + +class RetrievePropertyOwnerSerializer(BasePropertyOwnerSerializer): + class Meta(BasePropertyOwnerSerializer.Meta): ... + + +class CreatePropertyOwnerSerializer(BasePropertyOwnerSerializer): + class Meta(BasePropertyOwnerSerializer.Meta): + fields = [ + "id", + ] + diff --git a/core/apps/evaluation/serializers/customer/__init__.py b/core/apps/evaluation/serializers/customer/__init__.py new file mode 100644 index 0000000..6183ce9 --- /dev/null +++ b/core/apps/evaluation/serializers/customer/__init__.py @@ -0,0 +1,2 @@ +from .Customer import * # noqa +from .PropertyOwner import * # noqa diff --git a/core/apps/evaluation/signals/__init__.py b/core/apps/evaluation/signals/__init__.py new file mode 100644 index 0000000..f22e1ba --- /dev/null +++ b/core/apps/evaluation/signals/__init__.py @@ -0,0 +1 @@ +from .customer import * # noqa diff --git a/core/apps/evaluation/signals/customer.py b/core/apps/evaluation/signals/customer.py new file mode 100644 index 0000000..9fc2385 --- /dev/null +++ b/core/apps/evaluation/signals/customer.py @@ -0,0 +1,13 @@ +from django.db.models.signals import post_save +from django.dispatch import receiver + +from core.apps.evaluation.models import CustomerModel, PropertyOwnerModel + + +@receiver(post_save, sender=CustomerModel) +def CustomerSignal(sender, instance, created, **kwargs): ... + + +@receiver(post_save, sender=PropertyOwnerModel) +def PropertyOwnerSignal(sender, instance, created, **kwargs): ... + diff --git a/core/apps/evaluation/tests/__init__.py b/core/apps/evaluation/tests/__init__.py index e69de29..f22e1ba 100644 --- a/core/apps/evaluation/tests/__init__.py +++ b/core/apps/evaluation/tests/__init__.py @@ -0,0 +1 @@ +from .customer import * # noqa diff --git a/core/apps/evaluation/tests/customer/__init__.py b/core/apps/evaluation/tests/customer/__init__.py new file mode 100644 index 0000000..54d7e6f --- /dev/null +++ b/core/apps/evaluation/tests/customer/__init__.py @@ -0,0 +1,2 @@ +from .test_Customer import * # noqa +from .test_PropertyOwner import * # noqa diff --git a/core/apps/evaluation/tests/customer/test_Customer.py b/core/apps/evaluation/tests/customer/test_Customer.py new file mode 100644 index 0000000..41c54e5 --- /dev/null +++ b/core/apps/evaluation/tests/customer/test_Customer.py @@ -0,0 +1,101 @@ +import pytest +from django.urls import reverse +from rest_framework.test import APIClient + +from core.apps.evaluation.models import CustomerModel + + +@pytest.fixture +def instance(db): + return CustomerModel._baker() + + +@pytest.fixture +def api_client(instance): + client = APIClient() + ##client.force_authenticate(user=instance.user) + return client, instance + + +@pytest.fixture +def data(api_client): + client, instance = api_client + return ( + { + "list": reverse("customer-list"), + "retrieve": reverse("customer-detail", kwargs={"pk": instance.pk}), + "retrieve-not-found": reverse("customer-detail", kwargs={"pk": 1000}), + }, + client, + instance, + ) + + +@pytest.mark.django_db +def test_list(data): + urls, client, _ = data + response = client.get(urls["list"]) + data_resp = response.json() + assert response.status_code == 200 + assert data_resp["status"] is True + + +@pytest.mark.django_db +def test_retrieve(data): + urls, client, _ = data + response = client.get(urls["retrieve"]) + data_resp = response.json() + assert response.status_code == 200 + assert data_resp["status"] is True + + +@pytest.mark.django_db +def test_retrieve_not_found(data): + urls, client, _ = data + response = client.get(urls["retrieve-not-found"]) + data_resp = response.json() + assert response.status_code == 404 + assert data_resp["status"] is False + + +# @pytest.mark.django_db +# def test_create(data): +# urls, client, _ = data +# response = client.post(urls["list"], data={"name": "test"}) +# assert response.json()["status"] is True +# assert response.status_code == 201 + + +# @pytest.mark.django_db +# def test_update(data): +# urls, client, _ = data +# response = client.patch(urls["retrieve"], data={"name": "updated"}) +# assert response.json()["status"] is True +# assert response.status_code == 200 +# +# # verify updated value +# response = client.get(urls["retrieve"]) +# assert response.json()["status"] is True +# assert response.status_code == 200 +# assert response.json()["data"]["name"] == "updated" + + +# @pytest.mark.django_db +# def test_partial_update(): +# urls, client, _ = data +# response = client.patch(urls["retrieve"], data={"name": "updated"}) +# assert response.json()["status"] is True +# assert response.status_code == 200 +# +# # verify updated value +# response = client.get(urls["retrieve"]) +# assert response.json()["status"] is True +# assert response.status_code == 200 +# assert response.json()["data"]["name"] == "updated" + + +# @pytest.mark.django_db +# def test_destroy(data): +# urls, client, _ = data +# response = client.delete(urls["retrieve"]) +# assert response.status_code == 204 diff --git a/core/apps/evaluation/tests/customer/test_PropertyOwner.py b/core/apps/evaluation/tests/customer/test_PropertyOwner.py new file mode 100644 index 0000000..cf79962 --- /dev/null +++ b/core/apps/evaluation/tests/customer/test_PropertyOwner.py @@ -0,0 +1,101 @@ +import pytest +from django.urls import reverse +from rest_framework.test import APIClient + +from core.apps.evaluation.models import PropertyOwnerModel + + +@pytest.fixture +def instance(db): + return PropertyOwnerModel._baker() + + +@pytest.fixture +def api_client(instance): + client = APIClient() + ##client.force_authenticate(user=instance.user) + return client, instance + + +@pytest.fixture +def data(api_client): + client, instance = api_client + return ( + { + "list": reverse("property-owner-list"), + "retrieve": reverse("property-owner-detail", kwargs={"pk": instance.pk}), + "retrieve-not-found": reverse("property-owner-detail", kwargs={"pk": 1000}), + }, + client, + instance, + ) + + +@pytest.mark.django_db +def test_list(data): + urls, client, _ = data + response = client.get(urls["list"]) + data_resp = response.json() + assert response.status_code == 200 + assert data_resp["status"] is True + + +@pytest.mark.django_db +def test_retrieve(data): + urls, client, _ = data + response = client.get(urls["retrieve"]) + data_resp = response.json() + assert response.status_code == 200 + assert data_resp["status"] is True + + +@pytest.mark.django_db +def test_retrieve_not_found(data): + urls, client, _ = data + response = client.get(urls["retrieve-not-found"]) + data_resp = response.json() + assert response.status_code == 404 + assert data_resp["status"] is False + + +# @pytest.mark.django_db +# def test_create(data): +# urls, client, _ = data +# response = client.post(urls["list"], data={"name": "test"}) +# assert response.json()["status"] is True +# assert response.status_code == 201 + + +# @pytest.mark.django_db +# def test_update(data): +# urls, client, _ = data +# response = client.patch(urls["retrieve"], data={"name": "updated"}) +# assert response.json()["status"] is True +# assert response.status_code == 200 +# +# # verify updated value +# response = client.get(urls["retrieve"]) +# assert response.json()["status"] is True +# assert response.status_code == 200 +# assert response.json()["data"]["name"] == "updated" + + +# @pytest.mark.django_db +# def test_partial_update(): +# urls, client, _ = data +# response = client.patch(urls["retrieve"], data={"name": "updated"}) +# assert response.json()["status"] is True +# assert response.status_code == 200 +# +# # verify updated value +# response = client.get(urls["retrieve"]) +# assert response.json()["status"] is True +# assert response.status_code == 200 +# assert response.json()["data"]["name"] == "updated" + + +# @pytest.mark.django_db +# def test_destroy(data): +# urls, client, _ = data +# response = client.delete(urls["retrieve"]) +# assert response.status_code == 204 diff --git a/core/apps/evaluation/translation/__init__.py b/core/apps/evaluation/translation/__init__.py new file mode 100644 index 0000000..f22e1ba --- /dev/null +++ b/core/apps/evaluation/translation/__init__.py @@ -0,0 +1 @@ +from .customer import * # noqa diff --git a/core/apps/evaluation/translation/customer.py b/core/apps/evaluation/translation/customer.py new file mode 100644 index 0000000..11ad440 --- /dev/null +++ b/core/apps/evaluation/translation/customer.py @@ -0,0 +1,14 @@ +from modeltranslation.translator import TranslationOptions, register + +from core.apps.evaluation.models import CustomerModel, PropertyOwnerModel + + +@register(CustomerModel) +class CustomerTranslation(TranslationOptions): + fields = [] + + +@register(PropertyOwnerModel) +class PropertyOwnerTranslation(TranslationOptions): + fields = [] + diff --git a/core/apps/evaluation/urls.py b/core/apps/evaluation/urls.py index 5fa41be..6842719 100644 --- a/core/apps/evaluation/urls.py +++ b/core/apps/evaluation/urls.py @@ -1,9 +1,9 @@ -from django.urls import path, include +from django.urls import include, path from rest_framework.routers import DefaultRouter +from .views import CustomerView, PropertyOwnerView + router = DefaultRouter() - - -urlpatterns = [ - path("", include(router.urls)), -] +router.register("property-owner", PropertyOwnerView, basename="property-owner") +router.register("customer", CustomerView, basename="customer") +urlpatterns = [path("", include(router.urls))] diff --git a/core/apps/evaluation/validators/__init__.py b/core/apps/evaluation/validators/__init__.py new file mode 100644 index 0000000..f22e1ba --- /dev/null +++ b/core/apps/evaluation/validators/__init__.py @@ -0,0 +1 @@ +from .customer import * # noqa diff --git a/core/apps/evaluation/validators/customer.py b/core/apps/evaluation/validators/customer.py new file mode 100644 index 0000000..2ab0464 --- /dev/null +++ b/core/apps/evaluation/validators/customer.py @@ -0,0 +1,15 @@ +# from django.core.exceptions import ValidationError + + +class CustomerValidator: + def __init__(self): ... + + def __call__(self): + return True + + +class PropertyownerValidator: + def __init__(self): ... + + def __call__(self): + return True diff --git a/core/apps/evaluation/views/__init__.py b/core/apps/evaluation/views/__init__.py index e69de29..f22e1ba 100644 --- a/core/apps/evaluation/views/__init__.py +++ b/core/apps/evaluation/views/__init__.py @@ -0,0 +1 @@ +from .customer import * # noqa diff --git a/core/apps/evaluation/views/customer.py b/core/apps/evaluation/views/customer.py new file mode 100644 index 0000000..510f309 --- /dev/null +++ b/core/apps/evaluation/views/customer.py @@ -0,0 +1,43 @@ +from django_core.mixins import BaseViewSetMixin +from drf_spectacular.utils import extend_schema +from rest_framework.permissions import AllowAny +from rest_framework.viewsets import ReadOnlyModelViewSet + +from core.apps.evaluation.models import CustomerModel, PropertyOwnerModel +from core.apps.evaluation.serializers.customer import ( + CreateCustomerSerializer, + CreatePropertyOwnerSerializer, + ListCustomerSerializer, + ListPropertyOwnerSerializer, + RetrieveCustomerSerializer, + RetrievePropertyOwnerSerializer, +) + + +@extend_schema(tags=["Customer"]) +class CustomerView(BaseViewSetMixin, ReadOnlyModelViewSet): + queryset = CustomerModel.objects.all() + serializer_class = ListCustomerSerializer + permission_classes = [AllowAny] + + action_permission_classes = {} + action_serializer_class = { + "list": ListCustomerSerializer, + "retrieve": RetrieveCustomerSerializer, + "create": CreateCustomerSerializer, + } + + +@extend_schema(tags=["PropertyOwner"]) +class PropertyOwnerView(BaseViewSetMixin, ReadOnlyModelViewSet): + queryset = PropertyOwnerModel.objects.all() + serializer_class = ListPropertyOwnerSerializer + permission_classes = [AllowAny] + + action_permission_classes = {} + action_serializer_class = { + "list": ListPropertyOwnerSerializer, + "retrieve": RetrievePropertyOwnerSerializer, + "create": CreatePropertyOwnerSerializer, + } +