Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

регистрация компании #62

Merged
merged 40 commits into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
06ddf43
Add SoftDeleteMixin, CustomManager, migration
ByJIaT Aug 14, 2023
74fc1dd
Add djoser, pytest. pytest settings
ByJIaT Aug 14, 2023
c619e50
Add users urls
ByJIaT Aug 14, 2023
3a0ebf9
Add users tests
ByJIaT Aug 14, 2023
e0bac06
Add djoser settings
ByJIaT Aug 14, 2023
087b028
Add CustomUserViewSet, companies endpoints
ByJIaT Aug 14, 2023
0bf300f
Add CompanyCreateSerializer, BaseSerializer, CompanySerializer, Addre…
ByJIaT Aug 14, 2023
2e6ea2b
Fix resolves
ByJIaT Aug 14, 2023
a50c09c
Add field AddressSerializer
ByJIaT Aug 14, 2023
d35139a
Add docstring PhoneNumberSerializer
ByJIaT Aug 14, 2023
17b1f1d
Add docstring PhoneNumberSerializer
ByJIaT Aug 14, 2023
ba5f094
Add get_serializer_class get_serializer_class
ByJIaT Aug 14, 2023
d2a367a
Changed directory
ByJIaT Aug 14, 2023
374e496
Changed directory
ByJIaT Aug 14, 2023
1df8a11
removed unused fields
ByJIaT Aug 14, 2023
b9fde9f
add email login field djoser settings
ByJIaT Aug 14, 2023
b580248
add docstrings BaseSerializer
ByJIaT Aug 14, 2023
37d30eb
add docstrings companies serializers
ByJIaT Aug 14, 2023
63d205d
add user delete test
ByJIaT Aug 14, 2023
49e2c14
add user deleting
ByJIaT Aug 14, 2023
07bcd2d
refactor url patterns
ByJIaT Aug 14, 2023
523e499
poetry.lock
ByJIaT Aug 14, 2023
664793f
Merge branch develop
ByJIaT Aug 14, 2023
8d177a2
Change UserCompanyReadSerializer name
ByJIaT Aug 15, 2023
aa59e15
Change UserCompanyWriteSerializer name
ByJIaT Aug 15, 2023
22e8856
Add DynamicRouter
ByJIaT Aug 15, 2023
532e84c
Change router in users
ByJIaT Aug 15, 2023
61c03a6
Reduced the number of queries get_companies to the database
ByJIaT Aug 15, 2023
9be6e22
Add schema pagination result
ByJIaT Aug 15, 2023
bc6533d
Del "company_account" from CompanyReadSerializer
ByJIaT Aug 15, 2023
9bc8747
Add null=True ogrn, company_account fields Company model
ByJIaT Aug 16, 2023
c30a448
changed python version 3.9 -> 3.11
ByJIaT Aug 16, 2023
5f8debd
Merge develop branch
ByJIaT Aug 16, 2023
f8bdc3c
changed python version
ByJIaT Aug 16, 2023
bd00839
changed python version
ByJIaT Aug 16, 2023
b3baab6
merge migrations 0002_alter_address_options_alter_address_address_and…
ByJIaT Aug 16, 2023
88c82bb
add blank=true company_account Company
ByJIaT Aug 16, 2023
7fb33e1
add blank=true ogrn Company
ByJIaT Aug 16, 2023
eca2a23
add blank=true ogrn Company
ByJIaT Aug 16, 2023
cc44289
fix users tests utils
ByJIaT Aug 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/users/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class CustomUserAdmin(UserAdmin):
"username",
"email",
"is_company",
"is_active",
)
list_filter = ("is_company",)
empty_value_display = "-empty-"
Expand Down
20 changes: 20 additions & 0 deletions apps/users/migrations/0002_alter_customuser_managers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 4.1 on 2023-08-14 16:43

from django.db import migrations

import apps.users.models


class Migration(migrations.Migration):
dependencies = [
("users", "0001_initial"),
]

operations = [
migrations.AlterModelManagers(
name="customuser",
managers=[
("objects", apps.users.models.CustomUserManager()),
],
),
]
19 changes: 18 additions & 1 deletion apps/users/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import re

from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import AbstractUser, UserManager
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models import Q
from django.utils.translation import gettext_lazy as _


Expand Down Expand Up @@ -128,6 +129,11 @@ def __str__(self):
return f"{self.first_name} {self.last_name}"


class CustomUserManager(UserManager):
def get_companies(self):
return self.filter(Q(is_company=True) & Q(is_active=True))


class CustomUser(AbstractUser):
email = models.EmailField(unique=True, blank=False, max_length=254, verbose_name="Email")
username = models.CharField(
Expand All @@ -154,13 +160,16 @@ class CustomUser(AbstractUser):
on_delete=models.SET_NULL,
)

objects = CustomUserManager()

class Meta:
swappable = "AUTH_USER_MODEL"
ordering = ("username",)
verbose_name = _("User")
verbose_name_plural = _("Users")

def clean(self):
super().clean()
if self.is_company and not self.company:
raise ValidationError(_("Company field is required for companies!"))
if not (self.is_superuser or self.is_staff) and not (self.is_company or self.personal):
Expand All @@ -178,3 +187,11 @@ def save(self, *args, **kwargs):

def __str__(self):
return self.username

def delete(self):
"""Предотвращает удаление модели.

Вместо непосредственного удаления, помечает запись удалённой (is_active=True).
"""
self.is_active = False
self.save()
Empty file.
11 changes: 11 additions & 0 deletions apps/users/serializers/addresses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from rest_framework import serializers

from apps.users.models import Address


class AddressSerializer(serializers.ModelSerializer):
"""Сериализатор для получения данных оо адресе."""

class Meta:
model = Address
fields = ("id", "address")
58 changes: 58 additions & 0 deletions apps/users/serializers/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from django.contrib.auth import get_user_model
from django.db import transaction
from djoser.conf import settings
from rest_framework import serializers

from apps.users.models import Address, PhoneNumber

User = get_user_model()


class BaseSerializer(serializers.ModelSerializer):
"""Абстрактный сериализатор для создания нового пользователя."""

password = serializers.CharField(style={"input_type": "password"}, write_only=True)

def perform_create(self, validated_data, **fields):
"""Создает пользователя."""
with transaction.atomic():
user = User.objects.create_user(**validated_data, **fields)
if settings.SEND_ACTIVATION_EMAIL:
user.is_active = False
user.save(update_fields=["is_active"])
return user

def _address_phone_attach(self, obj):
"""Создает объекты адреса и номера телефона."""
address = obj.pop("address", None)
phone_number = obj.pop("phone_number", None)

address_obj = Address.objects.create(**address)
phone_number_obj = PhoneNumber.objects.create(**phone_number)

return {"address": address_obj, "phone_number": phone_number_obj}

def _extract_relations(self, validated_data):
"""Извлекает один уровень вложенных отношений."""
reverse_relations = {}
for field_name, field in self.fields.items():
if isinstance(field, serializers.ModelSerializer | serializers.ListSerializer):
ByJIaT marked this conversation as resolved.
Show resolved Hide resolved
if field.source not in validated_data:
continue

reverse_relations[field_name] = (
self.fields[field_name].Meta.model,
validated_data.pop(field_name),
)
return reverse_relations

def update_or_create(self, validated_data):
"""Создает объекты компании или физ. лица."""
reverse_relations = {}
relations = self._extract_relations(validated_data)

for field_name, (model, data) in relations.items():
with transaction.atomic():
address_phone = self._address_phone_attach(data)
reverse_relations[field_name] = model.objects.create(**data, **address_phone)
return reverse_relations
95 changes: 95 additions & 0 deletions apps/users/serializers/companies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
from django.contrib.auth import get_user_model
from django.db import transaction
from rest_framework import serializers

from apps.users.models import Company
from apps.users.serializers.addresses import AddressSerializer
from apps.users.serializers.base import BaseSerializer
from apps.users.serializers.phonenumbers import PhoneNumberSerializer

User = get_user_model()


class CompanyReadSerializer(serializers.ModelSerializer):
"""Сериализатор для получения и отображения данных о компании.

Используется в безопасных http-методах.
"""

class Meta:
model = Company
depth = 1
fields = (
"id",
"role",
"name",
"company_account",
ByJIaT marked this conversation as resolved.
Show resolved Hide resolved
"inn",
"ogrn",
"phone_number",
"address",
)


class CompanyWriteSerializer(serializers.ModelSerializer):
"""Сериализатор для создания компании."""

address = AddressSerializer()
phone_number = PhoneNumberSerializer()

class Meta:
model = Company
fields = (
"role",
"name",
"inn",
"phone_number",
"address",
)

def to_representation(self, instance):
serializer = CompanyReadSerializer(instance)
return serializer.data


class UserReadSerializer(serializers.ModelSerializer):
"""Сериализатор для получения и отображения данных о пользователях.

Используется в безопасных http-методах.
"""

company = CompanyReadSerializer()

class Meta:
model = User
fields = (
"id",
"email",
"username",
"is_company",
"company",
)


class CompanySerializer(BaseSerializer):
"""Сериализатор для создания пользователя-компании."""

company = CompanyWriteSerializer()

class Meta:
model = User
fields = (
"email",
"username",
"password",
"company",
)

@transaction.atomic
def create(self, validated_data):
relations = self.update_or_create(validated_data)
return self.perform_create(validated_data, **relations, is_company=True)

def to_representation(self, instance):
serializer = UserReadSerializer(instance)
return serializer.data
11 changes: 11 additions & 0 deletions apps/users/serializers/phonenumbers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from rest_framework import serializers

from apps.users.models import PhoneNumber


class PhoneNumberSerializer(serializers.ModelSerializer):
"""Сериализатор для получения данных о номере телефона."""

class Meta:
model = PhoneNumber
fields = ("id", "phone_number")
Empty file added apps/users/tests/__init__.py
Empty file.
38 changes: 38 additions & 0 deletions apps/users/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import pytest
from rest_framework.test import APIClient

from apps.users.models import Address, Company, PhoneNumber


@pytest.fixture
def apiclient():
return APIClient()


@pytest.fixture
def company(django_user_model):
phone_number = PhoneNumber.objects.create(phone_number="1234567")
address = Address.objects.create(address="earth")
company_obj = Company.objects.create(
role="supplier",
name="best_company",
company_account="12345678901234567890",
inn="1234567890",
ogrn="1234567890123",
phone_number=phone_number,
address=address,
)
return django_user_model.objects.create_user(
email="[email protected]",
username="companyuser",
password="12345678",
is_company=True,
company=company_obj,
)


@pytest.fixture
def company_client(company):
client = APIClient()
client.force_authenticate(user=company)
return client
Loading