interview result added and issue resolved #113
6
.env
6
.env
@ -1,3 +1,3 @@
|
||||
DB_NAME=norahuniversity
|
||||
DB_USER=norahuniversity
|
||||
DB_PASSWORD=norahuniversity
|
||||
DB_NAME=haikal_db
|
||||
DB_USER=faheed
|
||||
DB_PASSWORD=Faheed@215
|
||||
@ -208,7 +208,9 @@ ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True
|
||||
ACCOUNT_FORMS = {"signup": "recruitment.forms.StaffSignupForm"}
|
||||
|
||||
|
||||
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
|
||||
MAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
|
||||
EMAIL_HOST = "10.10.1.110"
|
||||
EMAIL_PORT = 2225
|
||||
# EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
|
||||
|
||||
# EMAIL_HOST_PASSWORD = os.getenv("EMAIL_PASSWORD", "mssp.0Q0rSwb.zr6ke4n2k3e4on12.aHwJqnI")
|
||||
@ -217,10 +219,10 @@ EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
|
||||
# EMAIL_HOST_USER = "MS_lhygCJ@test-65qngkd8nx3lwr12.mlsender.net"
|
||||
# EMAIL_HOST_PASSWORD = "mssp.0Q0rSwb.zr6ke4n2k3e4on12.aHwJqnI"
|
||||
# EMAIL_USE_TLS = True
|
||||
EMAIL_HOST = 'sandbox.smtp.mailtrap.io'
|
||||
EMAIL_HOST_USER = '38e5179debe69a'
|
||||
EMAIL_HOST_PASSWORD = 'ffa75647d01ecb'
|
||||
EMAIL_PORT = '2525'
|
||||
# EMAIL_HOST = 'sandbox.smtp.mailtrap.io'
|
||||
# EMAIL_HOST_USER = '38e5179debe69a'
|
||||
# EMAIL_HOST_PASSWORD = 'ffa75647d01ecb'
|
||||
# EMAIL_PORT = '2525'
|
||||
|
||||
|
||||
# Crispy Forms Configuration
|
||||
|
||||
@ -3,6 +3,7 @@ from django.core.mail import send_mail, EmailMessage
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.template.loader import render_to_string
|
||||
from django.conf import settings # To access EMAIL_HOST_USER, etc.
|
||||
from recruitment.models import Message
|
||||
|
||||
UserModel = get_user_model()
|
||||
User = UserModel # Type alias for clarity
|
||||
@ -17,28 +18,37 @@ class EmailService:
|
||||
subject: str,
|
||||
body: str,
|
||||
recipient_list: List[str],
|
||||
context:dict,
|
||||
from_email: str = settings.DEFAULT_FROM_EMAIL,
|
||||
html_content: Union[str, None] = None
|
||||
html_content: Union[str, None] = None,
|
||||
) -> int:
|
||||
"""
|
||||
Internal method to handle the actual sending using Django's email backend.
|
||||
"""
|
||||
|
||||
try:
|
||||
# Using EmailMessage for more control (e.g., HTML content)
|
||||
email = EmailMessage(
|
||||
subject=subject,
|
||||
body=body,
|
||||
from_email=from_email,
|
||||
to=recipient_list,
|
||||
)
|
||||
|
||||
for recipient in recipient_list:
|
||||
email = EmailMessage(
|
||||
subject=subject,
|
||||
body=body,
|
||||
from_email=from_email,
|
||||
to=[recipient],
|
||||
)
|
||||
|
||||
if html_content:
|
||||
email.content_subtype = "html" # Main content is HTML
|
||||
email.body = html_content # Overwrite body with HTML
|
||||
if html_content:
|
||||
email.content_subtype = "html" # Main content is HTML
|
||||
email.body = html_content # Overwrite body with HTML
|
||||
|
||||
# Returns the number of successfully sent emails (usually 1 or the count of recipients)
|
||||
sent_count = email.send(fail_silently=False)
|
||||
return sent_count
|
||||
# Returns the number of successfully sent emails (usually 1 or the count of recipients)
|
||||
result=email.send(fail_silently=False)
|
||||
recipient_user=User.objects.filter(email=recipient).first()
|
||||
if result and recipient_user and not context["message_created"]:
|
||||
Message.objects.create(sender=context['sender_user'],recipient=recipient_user,job=context['job'],subject=subject,content=context['email_message'],message_type='DIRECT',is_read=False)
|
||||
|
||||
|
||||
return len(recipient_list)
|
||||
|
||||
except Exception as e:
|
||||
# Log the error (in a real app, use Django's logger)
|
||||
@ -98,8 +108,10 @@ class EmailService:
|
||||
subject=subject,
|
||||
body="",
|
||||
recipient_list=recipient_emails,
|
||||
context=context,
|
||||
from_email=from_email,
|
||||
html_content=html_content
|
||||
html_content=html_content,
|
||||
|
||||
)
|
||||
|
||||
# Return the count of recipients if successful, or 0 if failure
|
||||
|
||||
@ -3653,10 +3653,8 @@ def message_detail(request, message_id):
|
||||
@login_required
|
||||
def message_create(request):
|
||||
"""Create a new message"""
|
||||
from .email_service import EmailService
|
||||
from .services.email_service import UnifiedEmailService
|
||||
from .dto.email_dto import EmailConfig, BulkEmailConfig, EmailPriority
|
||||
|
||||
from django.conf import settings
|
||||
from django_q.tasks import async_task
|
||||
if request.method == "POST":
|
||||
form = MessageForm(request.user, request.POST)
|
||||
|
||||
@ -3679,22 +3677,25 @@ def message_create(request):
|
||||
# from .services.email_service import UnifiedEmailService
|
||||
# from .dto.email_dto import EmailConfig, EmailPriority
|
||||
|
||||
service = UnifiedEmailService()
|
||||
|
||||
# Create email configuration
|
||||
config = EmailConfig(
|
||||
to_email=message.recipient.email,
|
||||
subject=message.subject,
|
||||
html_content=body,
|
||||
attachments=None,
|
||||
sender=request.user
|
||||
if request and hasattr(request, "user")
|
||||
else None,
|
||||
priority=EmailPriority.NORMAL,
|
||||
|
||||
|
||||
email_addresses = [message.recipient.email]
|
||||
subject=message.subject
|
||||
|
||||
email_result=async_task(
|
||||
"recruitment.tasks.send_bulk_email_task",
|
||||
email_addresses,
|
||||
subject,
|
||||
# message,
|
||||
"emails/email_template.html",
|
||||
{
|
||||
"email_message": body,
|
||||
"logo_url": settings.STATIC_URL + "image/kaauh.png",
|
||||
"message_created":True
|
||||
},
|
||||
)
|
||||
|
||||
# Send email using unified service
|
||||
email_result = service.send_email(config)
|
||||
|
||||
if email_result:
|
||||
messages.success(
|
||||
request, "Message sent successfully via email!"
|
||||
@ -4389,161 +4390,85 @@ def api_application_detail(request, candidate_id):
|
||||
return JsonResponse({"success": False, "error": str(e)})
|
||||
|
||||
|
||||
@login_required
|
||||
@staff_user_required
|
||||
def compose_application_email(request, slug):
|
||||
"""Compose email to participants about a candidate"""
|
||||
from .email_service import send_bulk_email
|
||||
from .services.email_service import EmailService
|
||||
from .dto.email_dto import BulkEmailConfig, EmailPriority
|
||||
# @login_required
|
||||
# @staff_user_required
|
||||
# def compose_application_email(request, slug):
|
||||
# """Compose email to participants about a candidate"""
|
||||
# from django.conf import settings
|
||||
|
||||
job = get_object_or_404(JobPosting, slug=slug)
|
||||
candidate_ids = request.GET.getlist("candidate_ids")
|
||||
candidates = Application.objects.filter(id__in=candidate_ids)
|
||||
# job = get_object_or_404(JobPosting, slug=slug)
|
||||
# candidate_ids = request.GET.getlist("candidate_ids")
|
||||
# candidates = Application.objects.filter(id__in=candidate_ids)
|
||||
|
||||
if request.method == "POST":
|
||||
candidate_ids = request.POST.getlist("candidate_ids")
|
||||
# if request.method == "POST":
|
||||
# candidate_ids = request.POST.getlist("candidate_ids")
|
||||
|
||||
applications = Application.objects.filter(id__in=candidate_ids)
|
||||
form = CandidateEmailForm(job, applications, request.POST)
|
||||
# applications = Application.objects.filter(id__in=candidate_ids)
|
||||
# form = CandidateEmailForm(job, applications, request.POST)
|
||||
|
||||
if form.is_valid():
|
||||
# Get email addresses
|
||||
email_addresses = form.get_email_addresses()
|
||||
# if form.is_valid():
|
||||
# # Get email addresses
|
||||
# email_addresses = form.get_email_addresses()
|
||||
|
||||
if not email_addresses:
|
||||
messages.error(request, "No email selected")
|
||||
referer = request.META.get("HTTP_REFERER")
|
||||
# if not email_addresses:
|
||||
# messages.error(request, "No email selected")
|
||||
# referer = request.META.get("HTTP_REFERER")
|
||||
|
||||
if referer:
|
||||
# Redirect back to the referring page
|
||||
return redirect(referer)
|
||||
else:
|
||||
return redirect("dashboard")
|
||||
# if referer:
|
||||
# # Redirect back to the referring page
|
||||
# return redirect(referer)
|
||||
# else:
|
||||
# return redirect("dashboard")
|
||||
|
||||
subject = form.cleaned_data.get("subject")
|
||||
message = form.get_formatted_message()
|
||||
# subject = form.cleaned_data.get("subject")
|
||||
# message = form.get_formatted_message()
|
||||
|
||||
service = EmailService()
|
||||
|
||||
# async_task(
|
||||
# "recruitment.tasks.send_bulk_email_task",
|
||||
# email_addresses,
|
||||
# subject,
|
||||
# # message,
|
||||
# "emails/email_template.html",
|
||||
# {
|
||||
# "job": job,
|
||||
# "applications": applications,
|
||||
# "email_message": message,
|
||||
# "logo_url": settings.STATIC_URL + "image/kaauh.png",
|
||||
# },
|
||||
# )
|
||||
# return redirect(request.path)
|
||||
|
||||
|
||||
# Prepare recipients data for bulk email
|
||||
# recipients_data = []
|
||||
# for email_addr in email_addresses:
|
||||
# recipients_data.append(
|
||||
# {
|
||||
# "email": email_addr,
|
||||
# "name": email_addr.split("@")[0]
|
||||
# if "@" in email_addr
|
||||
# else email_addr,
|
||||
# }
|
||||
# )
|
||||
from django.conf import settings
|
||||
async_task(
|
||||
"recruitment.tasks.send_bulk_email_task",
|
||||
email_addresses,
|
||||
subject,
|
||||
# message,
|
||||
"emails/email_template.html",
|
||||
{
|
||||
"job": job,
|
||||
"applications": applications,
|
||||
"email_message": message,
|
||||
"logo_url": settings.STATIC_URL + "image/kaauh.png",
|
||||
},
|
||||
)
|
||||
# Create bulk email configuration
|
||||
# bulk_config = BulkEmailConfig(
|
||||
# subject=subject,
|
||||
# recipients_data=recipients_data,
|
||||
# attachments=None,
|
||||
# sender=request.user if request and hasattr(request, "user") else None,
|
||||
# job=job,
|
||||
# priority=EmailPriority.NORMAL,
|
||||
# async_send=True,
|
||||
# )
|
||||
# else:
|
||||
# # Form validation errors
|
||||
# messages.error(request, "Please correct the errors below.")
|
||||
|
||||
# Send bulk emails
|
||||
# if email_result["success"]:
|
||||
# for application in applications:
|
||||
# if hasattr(application, "person") and application.person:
|
||||
# try:
|
||||
# Message.objects.create(
|
||||
# sender=request.user,
|
||||
# recipient=application.person.user,
|
||||
# subject=subject,
|
||||
# content=message,
|
||||
# job=job,
|
||||
# message_type="job_related",
|
||||
# is_email_sent=True,
|
||||
# email_address=application.person.email
|
||||
# if application.person.email
|
||||
# else application.email,
|
||||
# )
|
||||
# # For HTMX requests, return error response
|
||||
# if "HX-Request" in request.headers:
|
||||
# return JsonResponse(
|
||||
# {
|
||||
# "success": False,
|
||||
# "error": "Please correct the form errors and try again.",
|
||||
# }
|
||||
# )
|
||||
|
||||
# except Exception as e:
|
||||
# # Log error but don't fail the entire process
|
||||
# print(f"Error creating message")
|
||||
# return render(
|
||||
# request,
|
||||
# "includes/email_compose_form.html",
|
||||
# {"form": form, "job": job, "candidates": candidates},
|
||||
# )
|
||||
|
||||
# messages.success(
|
||||
# request,
|
||||
# f"Email will be sent shortly to recipient(s)",
|
||||
# )
|
||||
# response = HttpResponse(status=200)
|
||||
# response.headers["HX-Refresh"] = "true"
|
||||
# return response
|
||||
# # return redirect("applications_interview_view", slug=job.slug)
|
||||
# else:
|
||||
# messages.error(
|
||||
# request,
|
||||
# f"Failed to send email: {email_result.get('message', 'Unknown error')}",
|
||||
# )
|
||||
# else:
|
||||
# # GET request - show the form
|
||||
# form = CandidateEmailForm(job, candidates)
|
||||
|
||||
# # For HTMX requests, return error response
|
||||
# if "HX-Request" in request.headers:
|
||||
# return JsonResponse(
|
||||
# {
|
||||
# "success": False,
|
||||
# "error": email_result.get(
|
||||
# "message", "Failed to send email"
|
||||
# ),
|
||||
# }
|
||||
# )
|
||||
|
||||
# return render(
|
||||
# request,
|
||||
# "includes/email_compose_form.html",
|
||||
# {"form": form, "job": job, "candidate": candidates},
|
||||
# )
|
||||
|
||||
else:
|
||||
# Form validation errors
|
||||
messages.error(request, "Please correct the errors below.")
|
||||
|
||||
# For HTMX requests, return error response
|
||||
if "HX-Request" in request.headers:
|
||||
return JsonResponse(
|
||||
{
|
||||
"success": False,
|
||||
"error": "Please correct the form errors and try again.",
|
||||
}
|
||||
)
|
||||
|
||||
return render(
|
||||
request,
|
||||
"includes/email_compose_form.html",
|
||||
{"form": form, "job": job, "candidates": candidates},
|
||||
)
|
||||
|
||||
else:
|
||||
# GET request - show the form
|
||||
form = CandidateEmailForm(job, candidates)
|
||||
|
||||
return render(
|
||||
request,
|
||||
"includes/email_compose_form.html",
|
||||
# {"form": form, "job": job, "candidates": candidates},
|
||||
{"form": form, "job": job},
|
||||
)
|
||||
# return render(
|
||||
# request,
|
||||
# "includes/email_compose_form.html",
|
||||
# # {"form": form, "job": job, "candidates": candidates},
|
||||
# {"form": form, "job": job},
|
||||
# )
|
||||
|
||||
|
||||
# Source CRUD Views
|
||||
@ -6487,55 +6412,196 @@ def sync_history(request, job_slug=None):
|
||||
return render(request, "recruitment/sync_history.html", context)
|
||||
|
||||
|
||||
# def send_interview_email(request, slug):
|
||||
# from django.conf import settings
|
||||
# schedule = get_object_or_404(ScheduledInterview, slug=slug)
|
||||
# application = schedule.application
|
||||
# job = application.job
|
||||
# form = InterviewEmailForm(job, application, schedule)
|
||||
# if request.method == "POST":
|
||||
# form = InterviewEmailForm(job, application, schedule, request.POST)
|
||||
# if form.is_valid():
|
||||
# recipient = form.cleaned_data.get("to").strip()
|
||||
# body_message = form.cleaned_data.get("message")
|
||||
# subject = form.cleaned_data.get("subject")
|
||||
# sender_user = request.user
|
||||
# job = job
|
||||
# try:
|
||||
|
||||
# # Send email using background task
|
||||
# email_result= async_task(
|
||||
# "recruitment.tasks.send_bulk_email_task",
|
||||
# recipient,
|
||||
# subject,
|
||||
# # message,
|
||||
# "emails/email_template.html",
|
||||
# {
|
||||
# "job": job,
|
||||
# "applications": application,
|
||||
# "email_message":body_message,
|
||||
# "logo_url": settings.STATIC_URL + "image/kaauh.png",
|
||||
# },
|
||||
# )
|
||||
|
||||
# if email_result:
|
||||
# messages.success(request, "Message sent successfully via email!")
|
||||
# else:
|
||||
# messages.warning(
|
||||
# request,
|
||||
# f"email failed: {email_result.get('message', 'Unknown error')}",
|
||||
# )
|
||||
|
||||
# except Exception as e:
|
||||
# messages.warning(
|
||||
# request, f"Message saved but email sending failed: {str(e)}"
|
||||
# )
|
||||
# else:
|
||||
# form = InterviewEmailForm(job, application, schedule)
|
||||
# else: # GET request
|
||||
# form = InterviewEmailForm(job, application, schedule)
|
||||
|
||||
# # This is the final return, which handles GET requests and invalid POST requests.
|
||||
# return redirect("interview_detail", slug=schedule.slug)
|
||||
|
||||
|
||||
def send_interview_email(request, slug):
|
||||
from django.conf import settings
|
||||
from django_q.tasks import async_task
|
||||
|
||||
schedule = get_object_or_404(ScheduledInterview, slug=slug)
|
||||
application = schedule.application
|
||||
job = application.job
|
||||
form = InterviewEmailForm(job, application, schedule)
|
||||
|
||||
if request.method == "POST":
|
||||
form = InterviewEmailForm(job, application, schedule, request.POST)
|
||||
if form.is_valid():
|
||||
recipient = form.cleaned_data.get("to").strip()
|
||||
# 1. Ensure recipient is a list (fixes the "@" error)
|
||||
recipient_str = form.cleaned_data.get("to").strip()
|
||||
recipient_list = [recipient_str]
|
||||
|
||||
body_message = form.cleaned_data.get("message")
|
||||
subject = form.cleaned_data.get("subject")
|
||||
sender = request.user
|
||||
job = job
|
||||
|
||||
try:
|
||||
# Use new unified email service for background processing
|
||||
from .services.email_service import UnifiedEmailService
|
||||
from .dto.email_dto import EmailConfig, EmailPriority
|
||||
|
||||
service = UnifiedEmailService()
|
||||
|
||||
# Create email configuration
|
||||
config = EmailConfig(
|
||||
to_email=recipient,
|
||||
subject=subject,
|
||||
html_content=body_message,
|
||||
attachments=None,
|
||||
sender=sender,
|
||||
job=job,
|
||||
priority=EmailPriority.NORMAL,
|
||||
# 2. Match the context expected by your task/service
|
||||
# We pass IDs for the sender/job to avoid serialization issues
|
||||
async_task(
|
||||
"recruitment.tasks.send_bulk_email_task",
|
||||
recipient_list,
|
||||
subject,
|
||||
"emails/email_template.html",
|
||||
{
|
||||
"job": job, # Useful for Message creation
|
||||
"sender_user": request.user,
|
||||
"applications": application,
|
||||
"email_message": body_message,
|
||||
"message_created":False,
|
||||
"logo_url": settings.STATIC_URL + "image/kaauh.png",
|
||||
},
|
||||
)
|
||||
|
||||
# Send email using background task
|
||||
email_result = service.send_email(config)
|
||||
if email_result:
|
||||
messages.success(request, "Message sent successfully via email!")
|
||||
else:
|
||||
messages.warning(
|
||||
request,
|
||||
f"email failed: {email_result.get('message', 'Unknown error')}",
|
||||
)
|
||||
|
||||
messages.success(request, "Interview email enqueued successfully!")
|
||||
return redirect("interview_detail", slug=schedule.slug)
|
||||
|
||||
except Exception as e:
|
||||
messages.warning(
|
||||
request, f"Message saved but email sending failed: {str(e)}"
|
||||
)
|
||||
messages.error(request, f"Task scheduling failed: {str(e)}")
|
||||
else:
|
||||
form = InterviewEmailForm(job, application, schedule)
|
||||
else: # GET request
|
||||
messages.error(request, "Please correct the errors in the form.")
|
||||
else:
|
||||
# GET request
|
||||
form = InterviewEmailForm(job, application, schedule)
|
||||
|
||||
# This is the final return, which handles GET requests and invalid POST requests.
|
||||
return redirect("interview_detail", slug=schedule.slug)
|
||||
# 3. FIX: Instead of always redirecting, render the template
|
||||
# This allows users to see validation errors.
|
||||
return render(
|
||||
request,
|
||||
"recruitment/interview_email_form.html", # Replace with your actual template path
|
||||
{
|
||||
"form": form,
|
||||
"schedule": schedule,
|
||||
"job": job
|
||||
}
|
||||
)
|
||||
|
||||
@login_required
|
||||
@staff_user_required
|
||||
def compose_application_email(request, slug):
|
||||
"""Compose email to participants about a candidate"""
|
||||
from django.conf import settings
|
||||
|
||||
job = get_object_or_404(JobPosting, slug=slug)
|
||||
candidate_ids = request.GET.getlist("candidate_ids")
|
||||
candidates = Application.objects.filter(id__in=candidate_ids)
|
||||
|
||||
if request.method == "POST":
|
||||
candidate_ids = request.POST.getlist("candidate_ids")
|
||||
|
||||
applications = Application.objects.filter(id__in=candidate_ids)
|
||||
form = CandidateEmailForm(job, applications, request.POST)
|
||||
|
||||
if form.is_valid():
|
||||
# Get email addresses
|
||||
email_addresses = form.get_email_addresses()
|
||||
|
||||
if not email_addresses:
|
||||
messages.error(request, "No email selected")
|
||||
referer = request.META.get("HTTP_REFERER")
|
||||
|
||||
if referer:
|
||||
# Redirect back to the referring page
|
||||
return redirect(referer)
|
||||
else:
|
||||
return redirect("dashboard")
|
||||
|
||||
subject = form.cleaned_data.get("subject")
|
||||
message = form.get_formatted_message()
|
||||
|
||||
|
||||
async_task(
|
||||
"recruitment.tasks.send_bulk_email_task",
|
||||
email_addresses,
|
||||
subject,
|
||||
# message,
|
||||
"emails/email_template.html",
|
||||
{
|
||||
"job": job,
|
||||
"sender_user": request.user,
|
||||
"applications": applications,
|
||||
"email_message": message,
|
||||
"message_created":False,
|
||||
"logo_url": settings.STATIC_URL + "image/kaauh.png",
|
||||
|
||||
},
|
||||
)
|
||||
return redirect(request.path)
|
||||
|
||||
|
||||
else:
|
||||
# Form validation errors
|
||||
messages.error(request, "Please correct the errors below.")
|
||||
|
||||
# For HTMX requests, return error response
|
||||
if "HX-Request" in request.headers:
|
||||
return JsonResponse(
|
||||
{
|
||||
"success": False,
|
||||
"error": "Please correct the form errors and try again.",
|
||||
}
|
||||
)
|
||||
|
||||
return render(
|
||||
request,
|
||||
"includes/email_compose_form.html",
|
||||
{"form": form, "job": job, "candidates": candidates},
|
||||
)
|
||||
|
||||
else:
|
||||
# GET request - show the form
|
||||
form = CandidateEmailForm(job, candidates)
|
||||
|
||||
return render(
|
||||
request,
|
||||
"includes/email_compose_form.html",
|
||||
# {"form": form, "job": job, "candidates": candidates},
|
||||
{"form": form, "job": job},
|
||||
)
|
||||
|
||||
@ -92,14 +92,14 @@
|
||||
class="btn btn-sm btn-outline-secondary" title="Edit Setting">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<form method="post" action="{% url 'settings_delete' pk=setting.pk %}"
|
||||
{% comment %} <form method="post" action="{% url 'settings_delete' pk=setting.pk %}"
|
||||
onsubmit="return confirm('Are you sure you want to delete this setting?');"
|
||||
style="display: inline;">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger" title="Delete Setting">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</form> {% endcomment %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user