diff --git a/core/admin.py b/core/admin.py index b7c13db..c64df21 100644 --- a/core/admin.py +++ b/core/admin.py @@ -8,6 +8,8 @@ from core.models.video import Video from core.models.glb import Glb from core.models.pdf import Pdf from core.models.TeamMember import TeamMember +from core.models.AssetBundleRoom import AssetBundleRoom +from core.models.AssignRoomUser import AssignRoomUser # from .model import user from core.models.AssignedRule import AssignedRule @@ -21,3 +23,5 @@ admin.site.register(AssignedRule) admin.site.register(Customer) admin.site.register(Subscription) admin.site.register(TeamMember) +admin.site.register(AssetBundleRoom) +admin.site.register(AssignRoomUser) diff --git a/core/migrations/0003_subscription_adminuser_alter_subscription_user.py b/core/migrations/0003_subscription_adminuser_alter_subscription_user.py new file mode 100644 index 0000000..2f217a2 --- /dev/null +++ b/core/migrations/0003_subscription_adminuser_alter_subscription_user.py @@ -0,0 +1,26 @@ +# Generated by Django 5.0 on 2025-05-24 10:36 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0002_teammember'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AddField( + model_name='subscription', + name='adminUser', + field=models.ForeignKey(blank=True, default=None, on_delete=django.db.models.deletion.CASCADE, related_name='admin_subscriptions', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='subscription', + name='user', + field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='subscriptions', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/core/migrations/0004_remove_subscription_adminuser.py b/core/migrations/0004_remove_subscription_adminuser.py new file mode 100644 index 0000000..f305a2a --- /dev/null +++ b/core/migrations/0004_remove_subscription_adminuser.py @@ -0,0 +1,17 @@ +# Generated by Django 5.0 on 2025-05-24 10:51 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0003_subscription_adminuser_alter_subscription_user'), + ] + + operations = [ + migrations.RemoveField( + model_name='subscription', + name='adminUser', + ), + ] diff --git a/core/migrations/0005_assetbundleroom.py b/core/migrations/0005_assetbundleroom.py new file mode 100644 index 0000000..b8c9dfd --- /dev/null +++ b/core/migrations/0005_assetbundleroom.py @@ -0,0 +1,24 @@ +# Generated by Django 5.0 on 2025-05-24 12:12 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0004_remove_subscription_adminuser'), + ] + + operations = [ + migrations.CreateModel( + name='AssetBundleRoom', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('url', models.TextField()), + ('name', models.CharField(max_length=255)), + ('description', models.TextField(blank=True)), + ('maxPerson', models.PositiveIntegerField()), + ('img', models.TextField()), + ], + ), + ] diff --git a/core/migrations/0006_alter_assetbundleroom_img_alter_assetbundleroom_url.py b/core/migrations/0006_alter_assetbundleroom_img_alter_assetbundleroom_url.py new file mode 100644 index 0000000..6c5c9a0 --- /dev/null +++ b/core/migrations/0006_alter_assetbundleroom_img_alter_assetbundleroom_url.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0 on 2025-05-24 12:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0005_assetbundleroom'), + ] + + operations = [ + migrations.AlterField( + model_name='assetbundleroom', + name='img', + field=models.FileField(blank=True, null=True, upload_to='user_imgs/'), + ), + migrations.AlterField( + model_name='assetbundleroom', + name='url', + field=models.FileField(blank=True, null=True, upload_to='user_files/'), + ), + ] diff --git a/core/migrations/0007_assetbundleroom_private.py b/core/migrations/0007_assetbundleroom_private.py new file mode 100644 index 0000000..cd397a3 --- /dev/null +++ b/core/migrations/0007_assetbundleroom_private.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0 on 2025-05-24 13:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0006_alter_assetbundleroom_img_alter_assetbundleroom_url'), + ] + + operations = [ + migrations.AddField( + model_name='assetbundleroom', + name='Private', + field=models.BooleanField(default=True), + ), + ] diff --git a/core/migrations/0008_assignroomuser.py b/core/migrations/0008_assignroomuser.py new file mode 100644 index 0000000..d147242 --- /dev/null +++ b/core/migrations/0008_assignroomuser.py @@ -0,0 +1,27 @@ +# Generated by Django 5.0 on 2025-05-24 13:26 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0007_assetbundleroom_private'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='AssignRoomUser', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('assetbundle_room', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.assetbundleroom')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'unique_together': {('user', 'assetbundle_room')}, + }, + ), + ] diff --git a/core/models/AssetBundleRoom.py b/core/models/AssetBundleRoom.py new file mode 100644 index 0000000..ea0e76c --- /dev/null +++ b/core/models/AssetBundleRoom.py @@ -0,0 +1,13 @@ +from django.db import models + +class AssetBundleRoom(models.Model): + url = models.FileField(upload_to='user_files/', blank=True, null=True) + name = models.CharField(max_length=255) + description = models.TextField(blank=True) + maxPerson = models.PositiveIntegerField() + img = models.FileField(upload_to='user_imgs/', blank=True, null=True) + + Private = models.BooleanField(default=True) # New boolean field + + def __str__(self): + return f"{self.name} (Max: {self.maxPerson})" diff --git a/core/models/AssignRoomUser.py b/core/models/AssignRoomUser.py new file mode 100644 index 0000000..f7ad9df --- /dev/null +++ b/core/models/AssignRoomUser.py @@ -0,0 +1,13 @@ +from django.db import models +from django.conf import settings +from core.models.AssetBundleRoom import AssetBundleRoom # Adjust import path if needed + +class AssignRoomUser(models.Model): + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + assetbundle_room = models.ForeignKey(AssetBundleRoom, on_delete=models.CASCADE) + + class Meta: + unique_together = ('user', 'assetbundle_room') # Prevent duplicate assignments + + def __str__(self): + return f"{self.user.username} assigned to {self.assetbundle_room.name}" diff --git a/core/models/Subscription.py b/core/models/Subscription.py index 2a485d8..b408ad7 100644 --- a/core/models/Subscription.py +++ b/core/models/Subscription.py @@ -4,21 +4,20 @@ from django.conf import settings class Subscription(models.Model): - # uid = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) - user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, on_delete=models.CASCADE) + user = models.ForeignKey( + settings.AUTH_USER_MODEL, + blank=True, + on_delete=models.CASCADE, + related_name='subscriptions' # For user subscriptions + ) + + license_number = models.CharField(max_length=100) - user_count = models.PositiveIntegerField(default = 0,blank=True) # changed from license_number CharField - + user_count = models.PositiveIntegerField(default=0, blank=True) startTime = models.DateTimeField() endTime = models.DateTimeField() price = models.DecimalField(max_digits=30, decimal_places=2) def __str__(self): return f"Subscription {self.user_count} - License: {self.license_number}" - - - - - - \ No newline at end of file diff --git a/core/urls.py b/core/urls.py index 1d62dd5..5029eab 100644 --- a/core/urls.py +++ b/core/urls.py @@ -47,6 +47,7 @@ urlpatterns = [ re_path('add_subscription', userView.addSubscription), re_path('add_teamMember', userView.addTeamMember), + re_path('get_team_member_info', userView.get_team_member_info), diff --git a/core/views/userView.py b/core/views/userView.py index 6a85300..01f1956 100644 --- a/core/views/userView.py +++ b/core/views/userView.py @@ -30,6 +30,7 @@ from core.models.video import Video from core.models.pdf import Pdf from core.models.glb import Glb from core.models.Subscription import Subscription +from core.models.TeamMember import TeamMember from django.core.mail import EmailMultiAlternatives from django.template.loader import render_to_string @@ -330,6 +331,12 @@ def getInfo(request): subscription_serializer = SubscriptionSerializer(user_subscriptions, many=True) + first_subscription = subscription_serializer.data[0] if subscription_serializer.data else None + + user_subscription_data = first_subscription.get('user_count') if first_subscription else None + + + user_data = { 'id': user.id, 'first_name': user.first_name, @@ -345,7 +352,7 @@ def getInfo(request): 'pdfs': pdf_serializer.data, 'videos': video_serializer.data, 'glbs': glb_serializer.data, - 'subscription': subscription_serializer.data, + 'subscription': user_subscription_data, }, 'message': 'موفق' }, status=status.HTTP_200_OK) @@ -496,12 +503,7 @@ def submitSmsVerification(request): @authentication_classes([SessionAuthentication, TokenAuthentication]) @permission_classes([IsAuthenticated]) def test_token(request): - if not user_has_role(request.user, 'admin'): - return Response({ - "status": 403, - "data": {}, - "message": "دسترسی غیرمجاز" - }, status=status.HTTP_403_FORBIDDEN) + return Response({ "status": 200, @@ -1120,3 +1122,28 @@ def addTeamMember(request): +@api_view(['GET']) +@authentication_classes([SessionAuthentication, TokenAuthentication]) +@permission_classes([IsAuthenticated]) +def get_team_member_info(request): + user = request.user + + # Count team members where this user is the admin + team_member_count = TeamMember.objects.filter(adminUser=user).count() + + # Get subscriptions where this user is the actual subscriber + user_subscriptions = Subscription.objects.filter(user=user) + subscription_serializer = SubscriptionSerializer(user_subscriptions, many=True) + + # Extract user_count from the first subscription + first_subscription = subscription_serializer.data[0] if subscription_serializer.data else None + user_subscription_data = first_subscription.get('user_count') if first_subscription else None + + return Response({ + 'status': 200, + 'data': { + 'team_member_capacity': team_member_count, + 'subscriptionCount': user_subscription_data, + }, + 'message': 'موفق' + }, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/media/user_files/newbundle_RjuXfe2 b/media/user_files/newbundle_RjuXfe2 new file mode 100644 index 0000000..909994c Binary files /dev/null and b/media/user_files/newbundle_RjuXfe2 differ diff --git a/media/user_imgs/image-1745664489613.png b/media/user_imgs/image-1745664489613.png new file mode 100644 index 0000000..c498030 Binary files /dev/null and b/media/user_imgs/image-1745664489613.png differ diff --git a/test.rest b/test.rest index 4959240..da1dcb4 100644 --- a/test.rest +++ b/test.rest @@ -10,7 +10,7 @@ Content-Type: application/json POST http://127.0.0.1:8000/login Content-Type: application/json -{ "mobile_number":"09140086509", "password": "123456728" } +{ "mobile_number":"09140086509", "password": "13245678" } ### @@ -37,7 +37,7 @@ Authorization: token d3f1b03996140c8f7561d67221953ff704b482cb GET http://127.0.0.1:8000/test_token Content-Type: application/json -Authorization: token 224648840820ad0948ddee5b00d53ae67c040c49 +Authorization: token 8dcae0063521ca707a9d0ab6ce3d4794a90064ca # Authorization: token 53e2b003a92e22aca85c95088a438ece8d9a5dfb @@ -45,7 +45,7 @@ Authorization: token 224648840820ad0948ddee5b00d53ae67c040c49 GET http://127.0.0.1:8000/getInfo Content-Type: application/json -Authorization: token 224648840820ad0948ddee5b00d53ae67c040c49 +Authorization: token 8dcae0063521ca707a9d0ab6ce3d4794a90064ca # Authorization: token 53e2b003a92e22aca85c95088a438ece8d9a5dfb @@ -94,3 +94,14 @@ Content-Type: application/json Authorization: token 8dcae0063521ca707a9d0ab6ce3d4794a90064ca { "mobile_number": "09140086608", "first_name":"mahdi", "last_name":"arabi", "semat":"modir", "password": "12345678", "isAdmin":"true" } + + +### + + + +GET http://127.0.0.1:8000/get_team_member_info +Content-Type: application/json +Authorization: token 8dcae0063521ca707a9d0ab6ce3d4794a90064ca +# Authorization: token 53e2b003a92e22aca85c95088a438ece8d9a5dfb +