Razmig Sarkissian 2 months ago
commit 40705b061c
  1. 2
      api/urls.py
  2. 8
      api/views.py
  3. 22
      biz/admin.py
  4. 2
      biz/templates/admin/biz/prospect/change_list.html
  5. 4
      tournaments/admin.py
  6. 28
      tournaments/migrations/0138_remove_customuser_agents_customuser_supervisors_and_more.py
  7. 19
      tournaments/migrations/0139_customuser_organizers.py
  8. 5
      tournaments/models/custom_user.py

@ -8,7 +8,7 @@ from authentication.views import CustomAuthToken, Logout, ChangePasswordView
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'user-agents', views.ShortUserViewSet)
router.register(r'user-supervisors', views.SupervisorViewSet)
router.register(r'clubs', views.ClubViewSet)
router.register(r'tournaments', views.TournamentViewSet)
router.register(r'tournament-summaries', views.TournamentSummaryViewSet)

@ -342,13 +342,13 @@ class UnregisteredPlayerViewSet(SoftDeleteViewSet):
return self.queryset.filter(unregistered_team__tournament__event__creator=self.request.user)
return []
class ShortUserViewSet(viewsets.ModelViewSet):
class SupervisorViewSet(viewsets.ModelViewSet):
queryset = CustomUser.objects.all()
serializer_class = ShortUserSerializer
permission_classes = [] # Users are public whereas the other requests are only for logged users
def get_queryset(self):
return self.request.user.agents
return self.request.user.supervisors
class ImageViewSet(viewsets.ModelViewSet):
"""
@ -617,8 +617,8 @@ def validate_stripe_account(request):
@permission_classes([IsAuthenticated])
def is_granted_unlimited_access(request):
can_create = False
if request.user and request.user.is_anonymous == False and request.user.owners:
for owner in request.user.owners.all():
if request.user and request.user.is_anonymous == False and request.user.organising_for:
for owner in request.user.organising_for.all():
purchases = Purchase.objects.filter(user=owner,product_id='app.padelclub.tournament.subscription.unlimited')
for purchase in purchases:
if purchase.is_active():

@ -119,7 +119,7 @@ class ProspectAdmin(SyncedObjectAdmin):
list_display = ('first_name', 'last_name', 'entity_names', 'last_update_date', 'current_status', 'current_text', 'contact_again')
list_filter = (ContactAgainFilter, ProspectStatusFilter, ProspectDeclineReasonFilter, ProspectGroupFilter, PhoneFilter, 'creation_date', StaffUserFilter, 'source', ProspectProfileFilter)
search_fields = ('first_name', 'last_name', 'email', 'entities__name')
search_fields = ('first_name', 'last_name', 'email')
date_hierarchy = 'creation_date'
change_list_template = "admin/biz/prospect/change_list.html"
ordering = ['-last_update']
@ -361,9 +361,12 @@ class ProspectAdmin(SyncedObjectAdmin):
if form.is_valid():
email_template = form.cleaned_data['email_template']
self.process_selected_items_with_template(request, queryset, email_template)
sent_count, failed_count = self.process_selected_items_with_template(request, queryset, email_template)
self.message_user(request, f"Email sent to {queryset.count()} prospects using the '{email_template.name}' template.", messages.SUCCESS)
if failed_count > 0:
self.message_user(request, f"Email sent to {sent_count} prospects, {failed_count} failed using the '{email_template.name}' template.", messages.WARNING)
else:
self.message_user(request, f"Email sent to {sent_count} prospects using the '{email_template.name}' template.", messages.SUCCESS)
return HttpResponseRedirect(request.get_full_path())
else:
form = EmailTemplateSelectionForm()
@ -396,11 +399,24 @@ class ProspectAdmin(SyncedObjectAdmin):
fail_silently=False,
)
sent_count += 1
activity = Activity.objects.create(
type=ActivityType.MAIL,
status=Status.CONTACTED,
description=f"Email sent: {email_template.subject}"
)
activity.prospects.add(prospect)
except Exception as e:
error_emails.append(prospect.email)
logger.error(f'Failed to send email to {prospect.email}: {str(e)}')
time.sleep(1)
if error_emails:
logger.error(f'Failed to send emails to: {error_emails}')
return sent_count, len(error_emails)
@admin.register(ProspectGroup)
class ProspectGroupAdmin(SyncedObjectAdmin):
list_display = ('name', 'user_count')

@ -5,6 +5,6 @@
<li>
<a href="{% url 'admin:import_file' %}" class="addlink" style="margin-right: 5px;">Import</a>
<a href="{% url 'admin:import_app_users' %}" class="addlink" style="margin-right: 5px;">Import App Users</a>
<a href="{% url 'admin:cleanup' %}" class="deletelink" style="margin-right: 5px;">Reset</a>
<!--<a href="{% url 'admin:cleanup' %}" class="deletelink" style="margin-right: 5px;">Reset</a>-->
</li>
{% endblock %}

@ -32,7 +32,7 @@ class CustomUserAdmin(UserAdmin):
list_display = ['email', 'first_name', 'last_name', 'username', 'date_joined', 'latest_event_club_name', 'is_active', 'event_count', 'origin', 'registration_payment_mode', 'licence_id']
list_filter = ['is_active', 'origin', UserWithEventsFilter, UserWithPurchasesFilter, UserWithProspectFilter]
ordering = ['-date_joined']
raw_id_fields = ['agents']
raw_id_fields = ['supervisors', 'organizers']
fieldsets = [
(None, {'fields': ['id', 'username', 'email', 'password', 'first_name', 'last_name', 'is_active']}),
('Permissions', {'fields': ['is_staff', 'is_superuser', 'groups', 'user_permissions']}),
@ -41,7 +41,7 @@ class CustomUserAdmin(UserAdmin):
'summons_message_body', 'summons_message_signature', 'summons_available_payment_methods',
'summons_display_format', 'summons_display_entry_fee', 'summons_use_full_custom_message',
'match_formats_default_duration', 'bracket_match_format_preference', 'group_stage_match_format_preference',
'loser_bracket_match_format_preference', 'device_id', 'loser_bracket_mode', 'origin', 'agents', 'should_synchronize', 'can_synchronize'
'loser_bracket_match_format_preference', 'device_id', 'loser_bracket_mode', 'origin', 'supervisors', 'organizers', 'should_synchronize', 'can_synchronize'
]}),
]

@ -0,0 +1,28 @@
# Generated by Django 5.1 on 2025-09-24 14:19
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0137_playerregistration_is_anonymous_and_more'),
]
operations = [
migrations.RemoveField(
model_name='customuser',
name='agents',
),
migrations.AddField(
model_name='customuser',
name='supervisors',
field=models.ManyToManyField(blank=True, related_name='supervising_for', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='tournament',
name='animation_type',
field=models.IntegerField(choices=[(0, 'Tournoi'), (1, 'Mêlée'), (2, 'Classement'), (3, 'Consolation'), (4, 'Custom')], default=0),
),
]

@ -0,0 +1,19 @@
# Generated by Django 5.1 on 2025-09-24 14:20
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0138_remove_customuser_agents_customuser_supervisors_and_more'),
]
operations = [
migrations.AddField(
model_name='customuser',
name='organizers',
field=models.ManyToManyField(blank=True, related_name='organising_for', to=settings.AUTH_USER_MODEL),
),
]

@ -36,7 +36,8 @@ class CustomUser(AbstractUser):
loser_bracket_match_format_preference = models.IntegerField(default=enums.FederalMatchCategory.NINE_GAMES, choices=enums.FederalMatchCategory.choices, null=True, blank=True)
device_id = models.CharField(max_length=50, null=True, blank=True)
agents = models.ManyToManyField('CustomUser', blank=True, related_name='owners')
supervisors = models.ManyToManyField('CustomUser', blank=True, related_name='supervising_for')
organizers = models.ManyToManyField('CustomUser', blank=True, related_name='organising_for')
loser_bracket_mode = models.IntegerField(default=0)
origin = models.IntegerField(default=enums.UserOrigin.ADMIN, choices=enums.UserOrigin.choices, null=True, blank=True)
@ -64,7 +65,7 @@ class CustomUser(AbstractUser):
'summons_display_format', 'summons_display_entry_fee',
'summons_use_full_custom_message', 'match_formats_default_duration', 'bracket_match_format_preference',
'group_stage_match_format_preference', 'loser_bracket_match_format_preference', 'device_id', 'loser_bracket_mode',
'origin', 'agents', 'should_synchronize', 'user_role', 'registration_payment_mode',
'origin', 'supervisors', 'organizers', 'should_synchronize', 'user_role', 'registration_payment_mode',
'umpire_custom_mail', 'umpire_custom_contact', 'umpire_custom_phone', 'hide_umpire_mail', 'hide_umpire_phone',
'disable_ranking_federal_ruling']

Loading…
Cancel
Save