Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 62 additions & 2 deletions backend/donations/admin/ngos.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import codecs
import csv
import logging

from django import forms
from django.conf import settings
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.core.exceptions import PermissionDenied, ValidationError
from django.db import transaction
from django.db.models import QuerySet
from django.http import HttpRequest
from django.http import HttpRequest, HttpResponse
from django.shortcuts import redirect, render
from django.urls import reverse, reverse_lazy
from django.urls import path, reverse, reverse_lazy
from django.utils import timezone
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
from unfold.admin import ModelAdmin, StackedInline, TabularInline
Expand Down Expand Up @@ -274,6 +278,62 @@ class NgoAdmin(ModelAdmin):
),
)

def get_urls(self):
return [
path(
"export/",
self.admin_site.admin_view(self.export_ngos),
name="export-cult-registry-ngos",
),
*super().get_urls(),
]

def export_ngos(self, request: HttpRequest):
if not request.user.has_perm("users.view_ngo"):
raise PermissionDenied

raw_registered = request.GET.get("registered")
if raw_registered is None:
registered = None
else:
registered = bool(int(raw_registered))

try:
ngos = Ngo.export_cult_registry(registered=registered)
except ValidationError as e:
return HttpResponse(e.message)

filename = "ngos_cult_registry_export_{}.csv".format(timezone.now())

response = HttpResponse(
content_type="text/csv; charset=utf-8-sig",
headers={"Content-Disposition": 'attachment; filename="{}"'.format(filename)},
)
response.write(codecs.BOM_UTF8)

writer = csv.writer(response, dialect=csv.excel)
writer.writerow(
(
_("Legal name"),
_("date created"),
_("NGO Hub organization ID"),
_("VAT ID"),
_("registration number"),
_("email"),
_("telephone"),
_("website"),
_("is verified"),
_("is active"),
_("presence in the ANAF Cult Registry"),
_("last completed check in the ANAF Cult Registry"),
)
)

for ngo in ngos:
writer.writerow(ngo)

return response

def get_actions(self, request: HttpRequest):
if request.user.is_superuser:
return super().get_actions(request)
Expand Down
27 changes: 27 additions & 0 deletions backend/donations/models/ngos.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,33 @@ def delete_prefilled_form(ngo_id):
for cause in ngo.causes.all():
cause.delete_prefilled_form()

@staticmethod
def export_cult_registry(*, registered: None | bool):
ngos_query = Ngo.objects
if registered is None:
ngos_query = ngos_query.filter(is_in_cult_registry__isnull=True)
elif not registered:
ngos_query = ngos_query.filter(is_in_cult_registry=False)
else:
ngos_query = ngos_query.filter(is_in_cult_registry=True)

ngos = ngos_query.values_list(
"name",
"date_created",
"ngohub_org_id",
"vat_id",
"registration_number",
"email",
"phone",
"website",
"is_verified",
"is_active",
"is_in_cult_registry",
"cult_registry_check_ended",
)

return ngos


class CauseVisibilityChoices(models.TextChoices):
PUBLIC = "pub", _("public")
Expand Down
58 changes: 31 additions & 27 deletions backend/locale/en/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-23 11:55+0200\n"
"POT-Creation-Date: 2026-03-26 16:28+0200\n"
"PO-Revision-Date: 2025-03-27 14:48+0000\n"
"Last-Translator: Andrei Ioniță <andrei.ionita@commitglobal.org>\n"
"Language-Team: English <https://translate.commitglobal.org/projects/act4good/"
Expand Down Expand Up @@ -317,8 +317,8 @@ msgstr "Has owner"
#: donations/views/dashboard/ngo_dashboard.py:78
#: donations/views/dashboard/stats_helpers/utils.py:12
#: redirectioneaza/context_processors/headers.py:68
#: redirectioneaza/settings/unfold.py:103
#: redirectioneaza/settings/unfold.py:118
#: redirectioneaza/settings/unfold.py:109
#: redirectioneaza/settings/unfold.py:124
msgid "Donations"
msgstr "Donations"

Expand Down Expand Up @@ -987,7 +987,7 @@ msgstr ""

#: donations/models/ngos.py:282 partners/models.py:68
#: redirectioneaza/context_processors/headers.py:63
#: redirectioneaza/settings/unfold.py:106
#: redirectioneaza/settings/unfold.py:112
msgid "NGOs"
msgstr "NGOs"

Expand Down Expand Up @@ -1054,7 +1054,7 @@ msgstr "Cause"

#: donations/models/ngos.py:542 donations/views/ngo_account/causes.py:181
#: donations/views/ngo_account/causes.py:232 partners/admin.py:50
#: partners/models.py:75 redirectioneaza/settings/unfold.py:112
#: partners/models.py:75 redirectioneaza/settings/unfold.py:118
#: templates/v2/ngo-account/causes/main.html:11
msgid "Causes"
msgstr "Causes"
Expand Down Expand Up @@ -1813,7 +1813,7 @@ msgstr "Order"
msgid "Section"
msgstr "Section"

#: frequent_questions/models.py:16 redirectioneaza/settings/unfold.py:153
#: frequent_questions/models.py:16 redirectioneaza/settings/unfold.py:159
msgid "Sections"
msgstr "Sections"

Expand All @@ -1825,7 +1825,7 @@ msgstr "Question"
msgid "Answer"
msgstr "Answer"

#: frequent_questions/models.py:41 redirectioneaza/settings/unfold.py:159
#: frequent_questions/models.py:41 redirectioneaza/settings/unfold.py:165
msgid "Questions"
msgstr "Questions"

Expand Down Expand Up @@ -1884,7 +1884,7 @@ msgstr "Invite new manager"

#: partners/apps.py:8 partners/models.py:90
#: redirectioneaza/context_processors/headers.py:73
#: redirectioneaza/settings/unfold.py:142
#: redirectioneaza/settings/unfold.py:148
msgid "Partners"
msgstr "Partners"

Expand Down Expand Up @@ -1998,7 +1998,7 @@ msgstr ""

#: redirectioneaza/context_processors/headers.py:27
#: redirectioneaza/context_processors/headers.py:37
#: redirectioneaza/settings/unfold.py:150
#: redirectioneaza/settings/unfold.py:156
msgid "Frequently asked questions"
msgstr "Frequently asked questions"

Expand Down Expand Up @@ -2041,13 +2041,13 @@ msgid "FAQ Questions"
msgstr "FAQ Questions"

#: redirectioneaza/context_processors/headers.py:83
#: redirectioneaza/settings/unfold.py:167
#: redirectioneaza/settings/unfold.py:170 users/apps.py:8
#: redirectioneaza/settings/unfold.py:173
#: redirectioneaza/settings/unfold.py:176 users/apps.py:8
msgid "Users"
msgstr "Users"

#: redirectioneaza/context_processors/headers.py:88
#: redirectioneaza/settings/unfold.py:86 redirectioneaza/settings/unfold.py:89
#: redirectioneaza/settings/unfold.py:92 redirectioneaza/settings/unfold.py:95
msgid "Dashboard"
msgstr "Dashboard"

Expand Down Expand Up @@ -2109,78 +2109,82 @@ msgid "Background Tasks"
msgstr "Background Tasks"

#: redirectioneaza/settings/unfold.py:15
msgid "NGOs not in Cult Registry"
msgstr ""

#: redirectioneaza/settings/unfold.py:21
#, fuzzy
#| msgid "All causes"
msgid "All users"
msgstr "All causes"

#: redirectioneaza/settings/unfold.py:21
#: redirectioneaza/settings/unfold.py:27
#, fuzzy
#| msgid "Register without NGO Hub"
msgid "Users with NGOs"
msgstr "Register without NGO Hub"

#: redirectioneaza/settings/unfold.py:30
#: redirectioneaza/settings/unfold.py:36
msgid "Audit Logs"
msgstr ""

#: redirectioneaza/settings/unfold.py:36
#: redirectioneaza/settings/unfold.py:42
msgid "TASKS — Failed"
msgstr ""

#: redirectioneaza/settings/unfold.py:42
#: redirectioneaza/settings/unfold.py:48
msgid "TASKS — Queued"
msgstr ""

#: redirectioneaza/settings/unfold.py:48
#: redirectioneaza/settings/unfold.py:54
msgid "TASKS — Scheduled"
msgstr ""

#: redirectioneaza/settings/unfold.py:54
#: redirectioneaza/settings/unfold.py:60
msgid "TASKS — Successful"
msgstr ""

#: redirectioneaza/settings/unfold.py:64
#: redirectioneaza/settings/unfold.py:70
msgid "Clear staging data"
msgstr ""

#: redirectioneaza/settings/unfold.py:75
#: redirectioneaza/settings/unfold.py:81
msgid "Django SES Stats"
msgstr ""

#: redirectioneaza/settings/unfold.py:95
#: redirectioneaza/settings/unfold.py:101
msgid "Home page"
msgstr "Home page"

#: redirectioneaza/settings/unfold.py:124
#: redirectioneaza/settings/unfold.py:130
#, fuzzy
#| msgid "Generate ANAF Archive"
msgid "Internal ANAF Archives"
msgstr "Generate ANAF Archive"

#: redirectioneaza/settings/unfold.py:130
#: redirectioneaza/settings/unfold.py:136
#, fuzzy
#| msgid "Generate ANAF Archive"
msgid "External ANAF Archives"
msgstr "Generate ANAF Archive"

#: redirectioneaza/settings/unfold.py:136
#: redirectioneaza/settings/unfold.py:142
#, fuzzy
#| msgid "Donations"
msgid "Donation downloads"
msgstr "Donations"

#: redirectioneaza/settings/unfold.py:176 users/models.py:211
#: redirectioneaza/settings/unfold.py:182 users/models.py:211
msgid "Groups"
msgstr "Groups"

#: redirectioneaza/settings/unfold.py:184
#: redirectioneaza/settings/unfold.py:190
#, fuzzy
#| msgid "Donation exports"
msgid "Data Export"
msgstr "Donation exports"

#: redirectioneaza/settings/unfold.py:189
#: redirectioneaza/settings/unfold.py:195
msgid "Advanced"
msgstr ""

Expand Down
Loading
Loading