Skip to content

Commit

Permalink
Organization registration (#119)
Browse files Browse the repository at this point in the history
* messages display for mobile and desktop fixed

* removed pre-commit

* bulk export bug fixed

* Organization Registration form completed

---------

Co-authored-by: Shahryar Tayeb <[email protected]>
  • Loading branch information
Esmat-Farjad and shtayeb authored Dec 18, 2023
1 parent e524eb7 commit c073731
Show file tree
Hide file tree
Showing 17 changed files with 188 additions and 26 deletions.
27 changes: 27 additions & 0 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ django-debug-toolbar = "^4.2.0"
django-import-export = "^3.3.4"
factory-boy = "^3.3.0"
sentry-sdk = {extras = ["django"], version = "^1.39.1"}
ruff = "^0.1.8"


[tool.poetry.group.dev.dependencies]
Expand Down
3 changes: 2 additions & 1 deletion src/core/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@
]

# Can use MailTrap SMTP Setup for now (dev and staging only).
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"


EMAIL_HOST = env("EMAIL_HOST",default="smtp.mailtrap.io")
EMAIL_PORT = env("EMAIL_PORT",default=587) # 2525
Expand Down
35 changes: 35 additions & 0 deletions src/rh/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,3 +327,38 @@ def __init__(self, *args, project, **kwargs):
)
self.fields["donor"].queryset = self.fields["donor"].queryset.filter(pk__in=donor_ids)
self.fields["budget_currency"].queryset = self.fields["budget_currency"].queryset.filter(pk=budget_currency.pk)


class OrganizationRegisterForm(forms.ModelForm):
"""Organization Registeration Form"""

class Meta:
model = Organization
fields = "__all__"
exclude = ("old_id",)
labels = {"clusters": "Clusters / Sectors", "name": "Organization Name"}

widgets = {
"clusters": forms.SelectMultiple(attrs={"class": "js_multiselect"}),
"countries": forms.SelectMultiple(attrs={"class": "js_multiselect"}),
}

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["countries"].queryset = self.fields["countries"].queryset.filter(type="Country")

def clean_name(self):
"""check if organization name already exits"""
name = self.cleaned_data.get("name")
org_name = Organization.objects.filter(name__iexact=name)
if org_name.exists():
raise forms.ValidationError(f"{name} already exists...!")
return name

def clean_code(self):
"""check if organization code exists"""
code = self.cleaned_data.get("code")
org_code = Organization.objects.filter(code__iexact=code)
if org_code.exists():
raise forms.ValidationError(f"{code} aleady exists...!")
return code
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,18 @@


class Migration(migrations.Migration):

dependencies = [
('rh', '0004_rename_gran_type_indicator_grant_type'),
("rh", "0004_rename_gran_type_indicator_grant_type"),
]

operations = [
migrations.RemoveField(
model_name='beneficiarytype',
name='is_regular_beneficiary',
model_name="beneficiarytype",
name="is_regular_beneficiary",
),
migrations.AlterField(
model_name='beneficiarytype',
name='is_hrp_beneficiary',
model_name="beneficiarytype",
name="is_hrp_beneficiary",
field=models.BooleanField(default=False, null=True),
),
]
27 changes: 27 additions & 0 deletions src/rh/migrations/0006_alter_organization_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 4.0.6 on 2023-12-18 07:28

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("rh", "0005_remove_beneficiarytype_is_regular_beneficiary_and_more"),
]

operations = [
migrations.AlterField(
model_name="organization",
name="type",
field=models.CharField(
blank=True,
choices=[
("National NGO", "National NGO"),
("International NGO", "International NGO"),
("Government", "Government"),
("Business", "Business"),
],
max_length=200,
null=True,
),
),
]
10 changes: 8 additions & 2 deletions src/rh/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class BeneficiaryType(models.Model):
on_delete=models.SET_NULL,
)
clusters = models.ManyToManyField(Cluster)
is_hrp_beneficiary = models.BooleanField(default=False,null=True)
is_hrp_beneficiary = models.BooleanField(default=False, null=True)
start_date = models.DateTimeField(blank=True, null=True)
end_date = models.DateTimeField(blank=True, null=True)
description = models.CharField(max_length=DESCRIPTION_MAX_LENGTH, blank=True, null=True)
Expand All @@ -88,12 +88,18 @@ class Meta:
class Organization(models.Model):
"""Organizations Model"""

TYPE_CHOICES = [
("National NGO", "National NGO"),
("International NGO", "International NGO"),
("Government", "Government"),
("Business", "Business"),
]
countries = models.ManyToManyField(Location, blank=True)
clusters = models.ManyToManyField(Cluster, blank=True)

name = models.CharField(max_length=NAME_MAX_LENGTH, blank=True, null=True)
code = models.CharField(max_length=NAME_MAX_LENGTH, blank=True, null=True)
type = models.CharField(max_length=NAME_MAX_LENGTH, blank=True, null=True)
type = models.CharField(max_length=NAME_MAX_LENGTH, choices=TYPE_CHOICES, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
updated_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
old_id = models.CharField("Old ID", max_length=NAME_MAX_LENGTH, blank=True, null=True)
Expand Down
6 changes: 2 additions & 4 deletions src/rh/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from django.contrib.auth.models import User
from import_export.widgets import ManyToManyWidget, ForeignKeyWidget
from .models import (

Cluster,
Currency,
Donor,
Expand Down Expand Up @@ -99,20 +98,19 @@ class Meta:
column_name="clusters", attribute="clusters", widget=ManyToManyWidget(Cluster, field="title", separator=",")
)


# activity planning start
def dehydrate_activity_domain(self, project):
activity_domain = list(project.activityplan_set.all())
return ",".join([child.activity_domain.name for child in activity_domain])

def dehydrate_activity_type(self, project):
activity_types = list(project.activityplan_set.all())
return ",".join([child.activity_type.name for child in activity_types])

def dehydrate_indicators(self, project):
activity_plan = project.activityplan_set.all()
return ",".join([indicator.name for plan in activity_plan for indicator in plan.indicators.all()])

def dehydrate_beneficiary(self, project):
activity_plan = list(project.activityplan_set.all())
return ",".join([child.beneficiary for child in activity_plan if child.beneficiary])
Expand Down
42 changes: 42 additions & 0 deletions src/rh/templates/rh/projects/forms/organization_register_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{% extends "../../../_base.html" %}
{% load static %}
{% load vite %}
{% block content %}
<div class="login-section sign-up base-section">
<div class="decor-holder">
<img src="{% static 'rh/images/login-decor.png' %}"
alt="image description" />
</div>
<div class="container">
<div class="section-heading">
<h1 class="title">Add Organization</h1>
<small id="test"></small>
<div class="description">
<div class="text">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut non magna vel quam aliquet luctus.
Duis imperdiet vel urna eu hendrerit. Suspendisse tristique
odio ac quam porta, at pulvinar enim varius.
</p>
</div>
</div>
</div>
<form method="POST" class="login-form">
{% csrf_token %}
<div class="form-holder">
{% for field in org_form %}
<div class="input-field is-required">
{{ field.label_tag }}
<div class="input-holder">{{ field }}</div>
<div class="sign-up-field-error">{{field.errors}}</div>
</div>
{% endfor %}
<div class="btn-holder">
<button type="submit" class="btn btn-red">Save</button>
</div>

</div>
</form>
</div>
</div>
{% endblock content %}
2 changes: 2 additions & 0 deletions src/rh/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
urlpatterns = [
path("", user_views.index, name="index"),
path("home", user_views.home, name="home"),
# Organization Registration route
path("organization_register/", user_views.organization_register, name="organization_register"),
# Projects CRUD
path("projects/draft/", user_views.draft_projects_view, name="draft_projects"),
path("projects/active/", user_views.active_projects_view, name="active_projects"),
Expand Down
36 changes: 29 additions & 7 deletions src/rh/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@
from rh.resources import ProjectResource

from .filters import ProjectsFilter
from .forms import ActivityPlanFormSet, BudgetProgressForm, DisaggregationFormSet, ProjectForm, TargetLocationFormSet
from .forms import (
ActivityPlanFormSet,
BudgetProgressForm,
DisaggregationFormSet,
OrganizationRegisterForm,
ProjectForm,
TargetLocationFormSet,
)
from .models import (
ActivityDomain,
ActivityPlan,
Expand Down Expand Up @@ -936,9 +943,7 @@ def copy_project_target_location(plan, location):
# Duplicate the original target location
# by retrieving it with the provided primary key.
new_location = get_object_or_404(TargetLocation, pk=location.pk)
new_location.pk = (
None # Generate a new primary key for the duplicated location.
)
new_location.pk = None # Generate a new primary key for the duplicated location.
new_location.save() # Save the duplicated location to the database.

# Associate the duplicated location with the new activity plan.
Expand Down Expand Up @@ -967,9 +972,7 @@ def copy_target_location_disaggregation_locations(location, disaggregation_locat
try:
# Duplicate the original disaggregation location by retrieving it with the provided primary key.
new_disaggregation_location = get_object_or_404(DisaggregationLocation, pk=disaggregation_location.pk)
new_disaggregation_location.pk = (
None # Generate a new primary key for the duplicated location.
)
new_disaggregation_location.pk = None # Generate a new primary key for the duplicated location.
new_disaggregation_location.save() # Save the duplicated location to the database.

# Associate the duplicated disaggregation location with the new target location.
Expand Down Expand Up @@ -1153,6 +1156,25 @@ def delete_budget_progress(request, pk):
return JsonResponse({"success": True})


# Registration Organizations
@login_required
def organization_register(request):
if request.method == "POST":
org_form = OrganizationRegisterForm(request.POST)
if org_form.is_valid():
name = org_form.cleaned_data.get("name")
code = org_form.cleaned_data.get("code")
organization = org_form.save()
if organization:
messages.success(request, f"[{code}] {name} is registered successfully !")
else:
messages.error(request, "Something went wrong ! please try again ")
else:
org_form = OrganizationRegisterForm()
context = {"org_form": org_form}
return render(request, "rh/projects/forms/organization_register_form.html", context)


def ProjectListView(request, flag):
# project_list =json.loads(request.POST.get("projectList"))
project = Project.objects.filter(user=request.user.id)
Expand Down
1 change: 1 addition & 0 deletions src/static/rh/js/all_projects.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ $(function () {
const url = $(this).data('url');
window.location.href = url;
});
$('.js_multiselect').select2()
// toggle between accordion arrow
$("#activityAcc").on("click", function(){
let up =$(".activity-arrow-up");
Expand Down
1 change: 0 additions & 1 deletion src/static/rh/js/project_planning.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,5 +119,4 @@ $(function () {
})

$('.js_multiselect').select2()

});
4 changes: 1 addition & 3 deletions src/stock/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,5 @@
user_views.submit_stock_report_form,
name="submit_stock_report",
),
path("stocks/edit_submitted_stock/",
user_views.edit_submitted_stock,
name="edit_submitted_stock"),
path("stocks/edit_submitted_stock/", user_views.edit_submitted_stock, name="edit_submitted_stock"),
]
3 changes: 2 additions & 1 deletion src/stock/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,6 @@ def submit_stock_report_form(request, pk):
StockReports.objects.filter(id=pk).update(submitted=True, submitted_at=datetime.datetime.now())
return redirect("all_stock_report")


def edit_submitted_stock(request):
return render(request, 'stock/edit_submitted_stock.html')
return render(request, "stock/edit_submitted_stock.html")
3 changes: 3 additions & 0 deletions src/templates/_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@
<li class="inner-nav-item">
<a class="inner-nav-link" href="#">My Cluster/Org</a>
</li>
<li class="inner-nav-item">
<a class="inner-nav-link" href="{% url 'organization_register' %}">Add Organization</a>
</li>
<li class="inner-nav-item">
<a href="{% url 'logout' %}" class="inner-nav-link logout-link">Logout</a>
</li>
Expand Down
2 changes: 1 addition & 1 deletion src/users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def login_view(request):
if request.method == "POST":
email = request.POST["email"]
password = request.POST.get("password")
user = authenticate(request,username=email, email=email, password=password)
user = authenticate(request, username=email, email=email, password=password)

if user is not None:
login(request, user)
Expand Down

0 comments on commit c073731

Please sign in to comment.