diff --git a/meetings/admin.py b/meetings/admin.py index d4bff9e..668135e 100644 --- a/meetings/admin.py +++ b/meetings/admin.py @@ -54,7 +54,7 @@ class AdminWeeklyAvailabilityAdmin(admin.ModelAdmin): @admin.register(AppointmentRequest) class AppointmentRequestAdmin(admin.ModelAdmin): - list_display = ['full_name', 'email', 'status', 'formatted_created_at', 'formatted_scheduled_datetime'] + list_display = ['id','full_name', 'email', 'status', 'formatted_created_at', 'formatted_scheduled_datetime'] list_filter = ['status', 'created_at', 'scheduled_datetime'] search_fields = ['first_name', 'last_name', 'email'] readonly_fields = ['id', 'created_at', 'updated_at', 'formatted_created_at', 'formatted_scheduled_datetime'] diff --git a/meetings/migrations/0001_initial.py b/meetings/migrations/0001_initial.py new file mode 100644 index 0000000..23dbc8b --- /dev/null +++ b/meetings/migrations/0001_initial.py @@ -0,0 +1,56 @@ +# Generated by Django 5.2.8 on 2025-11-27 14:43 + +import meetings.models +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='AdminWeeklyAvailability', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('availability_schedule', models.JSONField(default=dict, help_text='Dictionary with days as keys and lists of time slots as values')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + options={ + 'verbose_name': 'Admin Weekly Availability', + 'verbose_name_plural': 'Admin Weekly Availability', + }, + ), + migrations.CreateModel( + name='AppointmentRequest', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('first_name', meetings.models.EncryptedCharField(max_length=255)), + ('last_name', meetings.models.EncryptedCharField(max_length=255)), + ('email', meetings.models.EncryptedEmailField(max_length=254)), + ('phone', meetings.models.EncryptedCharField(blank=True, max_length=255)), + ('reason', meetings.models.EncryptedTextField(blank=True)), + ('preferred_dates', models.JSONField(help_text='List of preferred dates (YYYY-MM-DD format)')), + ('preferred_time_slots', models.JSONField(help_text='List of preferred time slots (morning/afternoon/evening)')), + ('status', models.CharField(choices=[('pending_review', 'Pending Review'), ('scheduled', 'Scheduled'), ('rejected', 'Rejected'), ('completed', 'Completed'), ('cancelled', 'Cancelled')], default='pending_review', max_length=20)), + ('scheduled_datetime', models.DateTimeField(blank=True, null=True)), + ('scheduled_duration', models.PositiveIntegerField(default=60, help_text='Duration in minutes')), + ('rejection_reason', meetings.models.EncryptedTextField(blank=True)), + ('jitsi_meet_url', models.URLField(blank=True, help_text='Jitsi Meet URL for the video session')), + ('jitsi_room_id', models.CharField(blank=True, help_text='Jitsi room ID', max_length=100, unique=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + options={ + 'verbose_name': 'Appointment Request', + 'verbose_name_plural': 'Appointment Requests', + 'ordering': ['-created_at'], + 'indexes': [models.Index(fields=['status', 'scheduled_datetime'], name='meetings_ap_status_4e4e26_idx'), models.Index(fields=['email', 'created_at'], name='meetings_ap_email_b8ed9d_idx')], + }, + ), + ] diff --git a/meetings/models.py b/meetings/models.py index 4b8c260..bb5950c 100644 --- a/meetings/models.py +++ b/meetings/models.py @@ -177,10 +177,10 @@ class AppointmentRequest(models.Model): ] id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) - first_name = EncryptedCharField(max_length=100) - last_name = EncryptedCharField(max_length=100) + first_name = EncryptedCharField(max_length=255) + last_name = EncryptedCharField(max_length=255) email = EncryptedEmailField() - phone = EncryptedCharField(max_length=20, blank=True) + phone = EncryptedCharField(max_length=255, blank=True) reason = EncryptedTextField(blank=True) preferred_dates = models.JSONField( diff --git a/meetings/serializers.py b/meetings/serializers.py index c31cf64..c12c1a0 100644 --- a/meetings/serializers.py +++ b/meetings/serializers.py @@ -287,7 +287,6 @@ class AppointmentScheduleSerializer(serializers.Serializer): return data def _convert_to_datetime(self, date_obj, time_slot): - """Convert date and time slot to actual datetime""" time_mapping = { 'morning': (9, 0), 'afternoon': (13, 0), diff --git a/users/migrations/0001_initial.py b/users/migrations/0001_initial.py new file mode 100644 index 0000000..535ea17 --- /dev/null +++ b/users/migrations/0001_initial.py @@ -0,0 +1,54 @@ +# Generated by Django 5.2.8 on 2025-11-27 14:43 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='CustomUser', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('email', models.EmailField(max_length=254, unique=True)), + ('first_name', models.CharField(max_length=50)), + ('last_name', models.CharField(max_length=50)), + ('is_staff', models.BooleanField(default=False)), + ('is_superuser', models.BooleanField(default=False)), + ('is_active', models.BooleanField(default=True)), + ('isVerified', models.BooleanField(default=False)), + ('verify_otp', models.CharField(blank=True, max_length=6, null=True)), + ('verify_otp_expiry', models.DateTimeField(blank=True, null=True)), + ('forgot_password_otp', models.CharField(blank=True, max_length=6, null=True)), + ('forgot_password_otp_expiry', models.DateTimeField(blank=True, null=True)), + ('phone_number', models.CharField(blank=True, max_length=20)), + ('last_login', models.DateTimeField(auto_now=True)), + ('date_joined', models.DateTimeField(auto_now_add=True)), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='UserProfile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('bio', models.TextField(blank=True, max_length=500)), + ('timezone', models.CharField(default='UTC', max_length=50)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)), + ], + ), + ]