diff --git a/base/announcement.py b/base/announcement.py index 6df76eeed..7600fe9b0 100644 --- a/base/announcement.py +++ b/base/announcement.py @@ -82,63 +82,82 @@ def announcement_list(request): @hx_request_required def create_announcement(request): """ - This method renders form and template to update Announcement + Create a new announcement and notify relevant users. """ - form = AnnouncementForm() if request.method == "POST": form = AnnouncementForm(request.POST, request.FILES) if form.is_valid(): - anou, attachment_ids = form.save(commit=False) - anou.save() - anou.attachments.set(attachment_ids) + announcement, attachment_ids = form.save(commit=False) + announcement.save() + announcement.attachments.set(attachment_ids) + employees = form.cleaned_data["employees"] departments = form.cleaned_data["department"] job_positions = form.cleaned_data["job_position"] company = form.cleaned_data["company_id"] - anou.department.set(departments) - anou.job_position.set(job_positions) - anou.company_id.set(company) + + announcement.department.set(departments) + announcement.job_position.set(job_positions) + announcement.company_id.set(company) + + dept_ids = departments.values_list("id", flat=True) + job_ids = job_positions.values_list("id", flat=True) + + employees_from_dept = Employee.objects.filter( + employee_work_info__department_id__in=dept_ids + ) + employees_from_job = Employee.objects.filter( + employee_work_info__job_position_id__in=job_ids + ) + + all_employees = ( + employees | employees_from_dept | employees_from_job + ).distinct() + announcement.employees.add(*all_employees) + + all_emps = employees_from_dept | employees_from_job | employees + user_map = User.objects.filter(employee_get__in=all_emps).distinct() + + dept_emp_ids = set(employees_from_dept.values_list("id", flat=True)) + job_emp_ids = set(employees_from_job.values_list("id", flat=True)) + direct_emp_ids = set(employees.values_list("id", flat=True)) + + notified_ids = dept_emp_ids.union(job_emp_ids) + direct_only_ids = direct_emp_ids - notified_ids + + sender = request.user.employee_get + + def send_notification(users, verb): + if users.exists(): + notify.send( + sender, + recipient=users, + verb=verb, + verb_ar="لقد تم ذكرك في إعلان.", + verb_de="Sie wurden in einer Ankündigung erwähnt.", + verb_es="Has sido mencionado en un anuncio.", + verb_fr="Vous avez été mentionné dans une annonce.", + redirect="/", + icon="chatbox-ellipses", + ) + + send_notification( + user_map.filter(employee_get__id__in=dept_emp_ids), + _("Your department was mentioned in an announcement."), + ) + send_notification( + user_map.filter(employee_get__id__in=job_emp_ids), + _("Your job position was mentioned in an announcement."), + ) + send_notification( + user_map.filter(employee_get__id__in=direct_only_ids), + _("You have been mentioned in an announcement."), + ) + messages.success(request, _("Announcement created successfully.")) + form = AnnouncementForm() # Reset the form - emp_dep = User.objects.filter( - employee_get__employee_work_info__department_id__in=departments - ) - emp_jobs = User.objects.filter( - employee_get__employee_work_info__job_position_id__in=job_positions - ) - employees = employees | Employee.objects.filter( - employee_work_info__department_id__in=departments - ) - employees = employees | Employee.objects.filter( - employee_work_info__job_position_id__in=job_positions - ) - anou.employees.add(*employees) - - notify.send( - request.user.employee_get, - recipient=emp_dep, - verb="Your department was mentioned in a post.", - verb_ar="تم ذكر قسمك في منشور.", - verb_de="Ihr Abteilung wurde in einem Beitrag erwähnt.", - verb_es="Tu departamento fue mencionado en una publicación.", - verb_fr="Votre département a été mentionné dans un post.", - redirect="/", - icon="chatbox-ellipses", - ) - - notify.send( - request.user.employee_get, - recipient=emp_jobs, - verb="Your job position was mentioned in a post.", - verb_ar="تم ذكر وظيفتك في منشور.", - verb_de="Ihre Arbeitsposition wurde in einem Beitrag erwähnt.", - verb_es="Tu puesto de trabajo fue mencionado en una publicación.", - verb_fr="Votre poste de travail a été mentionné dans un post.", - redirect="/", - icon="chatbox-ellipses", - ) - form = AnnouncementForm() return render(request, "announcement/announcement_form.html", {"form": form}) diff --git a/base/forms.py b/base/forms.py index d10a67fc9..b1ac19880 100644 --- a/base/forms.py +++ b/base/forms.py @@ -2361,7 +2361,6 @@ class AnnouncementForm(ModelForm): filter_class=EmployeeFilter, filter_instance_contex_name="f", filter_template_path="employee_filters.html", - required=True, ), label="Employees", ) @@ -2421,14 +2420,32 @@ class AnnouncementForm(ModelForm): def clean(self): cleaned_data = super().clean() + + # Remove 'employees' field error if it's handled manually if isinstance(self.fields["employees"], HorillaMultiSelectField): self.errors.pop("employees", None) - employee_data = self.fields["employees"].queryset.filter( id__in=self.data.getlist("employees") ) cleaned_data["employees"] = employee_data + # Get submitted M2M values + employees_selected = cleaned_data.get("employees") + departments_selected = self.cleaned_data.get("department") + job_positions_selected = self.cleaned_data.get("job_position") + + # Check if none of the three are selected + if ( + not employees_selected + and not departments_selected + and not job_positions_selected + ): + raise forms.ValidationError( + _( + "You must select at least one of: Employees, Department, or Job Position." + ) + ) + return cleaned_data