diff --git a/core/apps/accounts/serializers/auth.py b/core/apps/accounts/serializers/auth.py index 6fe3edb..bb29ac9 100644 --- a/core/apps/accounts/serializers/auth.py +++ b/core/apps/accounts/serializers/auth.py @@ -66,7 +66,7 @@ class ChoiseRoleSerializer(serializers.Serializer): def validate(self, data): try: - user = User.objects.get(phone=data.get("phone"), is_active=False) + user = User.objects.get(phone=data.get("phone"), is_active=True) except User.DoesNotExist: raise serializers.ValidationError({"detail": "user not found"}) data['user'] = user diff --git a/core/apps/contracts/admins/contract.py b/core/apps/contracts/admins/contract.py index c14c16e..e2ce0cb 100644 --- a/core/apps/contracts/admins/contract.py +++ b/core/apps/contracts/admins/contract.py @@ -1,6 +1,6 @@ from django.contrib import admin -from core.apps.contracts.models.contract import Contract, ContractFile, ContractNotification,ContractSide, ContractSignature +from core.apps.contracts.models.contract import Contract, ContractSide, ContractSignature @admin.register(Contract) @@ -11,13 +11,6 @@ class ContractAdmin(admin.ModelAdmin): class ContractSideAdmin(admin.ModelAdmin): list_display = ['id', 'full_name'] -@admin.register(ContractFile) -class ContractFileAdmin(admin.ModelAdmin): - list_display = ['id', 'name'] - -@admin.register(ContractNotification) -class ContractNotificationAdmin(admin.ModelAdmin): - list_display = ['id', 'message', 'contract'] @admin.register(ContractSignature) class ContractSignatureAdmin(admin.ModelAdmin): diff --git a/core/apps/contracts/migrations/0001_initial.py b/core/apps/contracts/migrations/0001_initial.py index f953f58..d2d6b68 100644 --- a/core/apps/contracts/migrations/0001_initial.py +++ b/core/apps/contracts/migrations/0001_initial.py @@ -1,6 +1,5 @@ -# Generated by Django 5.2 on 2025-07-16 14:45 +# Generated by Django 5.2 on 2025-07-16 17:14 -import django.contrib.postgres.fields import django.db.models.deletion import uuid from django.conf import settings @@ -31,6 +30,7 @@ class Migration(migrations.Migration): ('attach_file', models.BooleanField(default=False)), ('add_folder', models.BooleanField(default=False)), ('add_notification', models.BooleanField(default=False)), + ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='c', to=settings.AUTH_USER_MODEL)), ], options={ 'verbose_name': 'contract', @@ -38,43 +38,6 @@ class Migration(migrations.Migration): 'db_table': 'contracts', }, ), - migrations.CreateModel( - name='ContractFile', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('name', models.CharField(max_length=150)), - ('file_type', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(choices=[('all_files', 'all files'), ('PDF', 'pdf'), ('word_files', 'word files'), ('image', 'image')], max_length=10), blank=True, default=list, size=None)), - ('user_permission', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(choices=[('all', 'all'), ('add', 'add'), ('delete', 'delete')], max_length=10), blank=True, default=list, size=None)), - ('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contract_files', to='contracts.contract')), - ], - options={ - 'verbose_name': 'contract file', - 'verbose_name_plural': 'contract files', - 'db_table': 'contract_files', - }, - ), - migrations.CreateModel( - name='ContractNotification', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('notification_event', models.CharField(choices=[('exact_date', 'exact date'), ('counterparty_signing', 'counterparty signing'), ('signature_all_parties', 'Signature of all parties')], max_length=24)), - ('type_notification', models.CharField(choices=[('sms', 'sms'), ('whatsup', 'whatsup')], max_length=8)), - ('type_message', models.CharField(blank=True, choices=[('krill', 'krill'), ('latin', 'latin')], max_length=8, null=True)), - ('message', models.CharField(max_length=160)), - ('time', models.TimeField(blank=True, null=True)), - ('date', models.DateField(blank=True, null=True)), - ('contract', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contract_notifications', to='contracts.contract')), - ], - options={ - 'verbose_name': 'contract notification', - 'verbose_name_plural': 'contract notifications', - 'db_table': 'contract_notifications', - }, - ), migrations.CreateModel( name='ContractSide', fields=[ diff --git a/core/apps/contracts/models/contract.py b/core/apps/contracts/models/contract.py index e47ea44..90620d4 100644 --- a/core/apps/contracts/models/contract.py +++ b/core/apps/contracts/models/contract.py @@ -5,10 +5,7 @@ from django.contrib.postgres.fields import ArrayField from core.apps.shared.models.base import BaseModel from core.apps.contracts.enums.contract import SIDES, STATUS from core.apps.contracts.enums.contract_side import ROLE -from core.apps.contracts.enums.contract_file import FILE_TYPE, USER_PERMISSION from core.apps.contracts.enums.contract_signature import SIGNATURE_TYPE, SIGNATURE_STATUS -from core.apps.contracts.enums.contract_notification import NOTIFICATION_EVENT, TYPE_MESSAGE, TYPE_NOTIFICATION -from core.apps.accounts.validators.user import phone_regex class Contract(BaseModel): @@ -24,6 +21,8 @@ class Contract(BaseModel): add_folder = models.BooleanField(default=False) add_notification = models.BooleanField(default=False) + company = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='c') + def __str__(self): return f'{self.name}' @@ -55,49 +54,6 @@ class ContractSide(BaseModel): unique_together = ['contract', 'user'] -class ContractFile(BaseModel): - name = models.CharField(max_length=150) - file_type = ArrayField( - models.CharField(max_length=10, choices=FILE_TYPE), - default=list, - blank=True - ) - user_permission = ArrayField( - models.CharField(max_length=10, choices=USER_PERMISSION), - default=list, - blank=True - ) - contract = models.ForeignKey(Contract, on_delete=models.CASCADE, related_name='contract_files') - - def __str__(self): - return f'{self.name} - {self.contract}' - - class Meta: - verbose_name = 'contract file' - verbose_name_plural = 'contract files' - db_table = 'contract_files' - - -class ContractNotification(BaseModel): - notification_event = models.CharField(choices=NOTIFICATION_EVENT, max_length=24) - type_notification = models.CharField(choices=TYPE_NOTIFICATION, max_length=8) - type_message = models.CharField(null=True, blank=True, choices=TYPE_MESSAGE, max_length=8) - - message = models.CharField(max_length=160) - time = models.TimeField(null=True, blank=True) - date = models.DateField(null=True, blank=True) - - contract = models.ForeignKey(Contract, on_delete=models.CASCADE, related_name="contract_notifications") - - def __str__(self): - return f'{self.type_notification} - {self.contract}' - - class Meta: - verbose_name = 'contract notification' - verbose_name_plural = 'contract notifications' - db_table = 'contract_notifications' - - class ContractSignature(BaseModel): contract = models.ForeignKey(Contract, on_delete=models.CASCADE, related_name='contract_signatures') user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='contract_users') diff --git a/core/apps/contracts/serializers/contract.py b/core/apps/contracts/serializers/contract.py index 500f966..de99a01 100644 --- a/core/apps/contracts/serializers/contract.py +++ b/core/apps/contracts/serializers/contract.py @@ -3,7 +3,7 @@ from django.db import transaction from rest_framework import serializers from core.apps.contracts.models.contract import Contract -from core.apps.contracts.serializers.contract_side import ContractSideCreateSerializer +from core.apps.contracts.serializers.contract_side import ContractSideCreateSerializer, ContractSideListSerializer class ContractCreateSerializer(serializers.Serializer): @@ -18,6 +18,7 @@ class ContractCreateSerializer(serializers.Serializer): def create(self, validated_data): with transaction.atomic(): + user = self.context.get('user') contract = Contract.objects.create( file=validated_data.pop('file'), contract_number=validated_data.pop('contract_number'), @@ -27,6 +28,7 @@ class ContractCreateSerializer(serializers.Serializer): attach_file=validated_data.pop('attach_file'), add_folder=validated_data.pop('add_folder'), add_notification=validated_data.pop('add_notification'), + company=user ) return contract.id @@ -36,4 +38,14 @@ class ContractListSerializer(serializers.ModelSerializer): model = Contract fields = [ 'id', 'name', 'file', 'contract_number', 'sides', 'face_id', 'add_folder', 'attach_file', 'add_notification', 'created_at' + ] + + +class ContractDetailSerializer(serializers.ModelSerializer): + contract_sides = ContractSideListSerializer(many=True) + + class Meta: + model = Contract + fields = [ + 'id', 'name', 'file', 'contract_number', 'contract_sides', ] \ No newline at end of file diff --git a/core/apps/contracts/serializers/contract_side.py b/core/apps/contracts/serializers/contract_side.py index e339b94..2aba5b2 100644 --- a/core/apps/contracts/serializers/contract_side.py +++ b/core/apps/contracts/serializers/contract_side.py @@ -22,4 +22,11 @@ class ContractSideCreateSerializer(serializers.Serializer): if not Contract.objects.filter(id=data.get('contract_id')).exists(): raise serializers.ValidationError({'detail': 'Contract not found!'}) return data - \ No newline at end of file + + +class ContractSideListSerializer(serializers.ModelSerializer): + class Meta: + model = ContractSide + fields = [ + 'id', 'full_name', 'user' + ] \ No newline at end of file diff --git a/core/apps/contracts/urls.py b/core/apps/contracts/urls.py index 6207ac2..1c3e4ad 100644 --- a/core/apps/contracts/urls.py +++ b/core/apps/contracts/urls.py @@ -9,6 +9,7 @@ urlpatterns = [ [ path('create/', contract_views.ContractCreateApiView.as_view(), name='create-contract'), path('list/', contract_views.ContractListApiView.as_view(), name='list-contract'), + path('/', contract_views.ContractDetailApiView.as_view(), name='detail-contract'), ] )), path('contract_side/', include([ diff --git a/core/apps/contracts/views/contract.py b/core/apps/contracts/views/contract.py index 500dbd1..c7db079 100644 --- a/core/apps/contracts/views/contract.py +++ b/core/apps/contracts/views/contract.py @@ -32,3 +32,12 @@ class ContractListApiView(generics.ListAPIView): def get_queryset(self): return Contract.objects.filter(contract_sides__user=self.request.user) + + +class ContractDetailApiView(views.APIView): + def get(self, request, id): + contract = Contract.objects.filter(id=id, contract_sides__user=request.user).prefetch_related('contract_sides').first() + if not contract: + return Response({'success': False, "message": 'contract not found'}, status=404) + serializer = contract_serializer.ContractDetailSerializer(contract) + return Response(serializer.data, status=200) \ No newline at end of file