diff --git a/asset/filters.py b/asset/filters.py
index ace7f1ce1..e0da7cb05 100644
--- a/asset/filters.py
+++ b/asset/filters.py
@@ -7,6 +7,7 @@ import django_filters
from django import forms
from django_filters import FilterSet
from .models import Asset, AssetAssignment, AssetCategory, AssetRequest
+from base.methods import reload_queryset
class CustomFilterSet(FilterSet):
@@ -23,42 +24,40 @@ class CustomFilterSet(FilterSet):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
-
- for field_name, field in self.filters.items():
+ reload_queryset(self.form.fields)
+ for field_name, field in self.form.fields.items():
filter_widget = self.filters[field_name]
widget = filter_widget.field.widget
if isinstance(
- widget, (forms.NumberInput, forms.EmailInput, forms.TextInput)
+ widget, (forms.NumberInput, forms.EmailInput, forms.TextInput)
):
- filter_widget.field.widget.attrs.update({"class": "oh-input w-100"})
+ field.widget.attrs.update({"class": "oh-input w-100"})
elif isinstance(widget, (forms.Select,)):
- filter_widget.field.widget.attrs.update(
+ field.widget.attrs.update(
{
"class": "oh-select oh-select-2",
}
)
elif isinstance(widget, (forms.Textarea)):
- filter_widget.field.widget.attrs.update({"class": "oh-input w-100"})
+ field.widget.attrs.update({"class": "oh-input w-100"})
elif isinstance(
- widget,
- (
- forms.CheckboxInput,
- forms.CheckboxSelectMultiple,
- ),
+ widget,
+ (
+ forms.CheckboxInput,
+ forms.CheckboxSelectMultiple,
+ ),
):
filter_widget.field.widget.attrs.update(
{"class": "oh-switch__checkbox"}
)
elif isinstance(widget, (forms.ModelChoiceField)):
- filter_widget.field.widget.attrs.update(
+ field.widget.attrs.update(
{
"class": "oh-select oh-select-2 ",
}
)
elif isinstance(widget, (forms.DateField)):
- filter_widget.field.widget.attrs.update(
- {"type": "date", "class": "oh-input w-100"}
- )
+ field.widget.attrs.update({"type": "date", "class": "oh-input w-100"})
if isinstance(field, django_filters.CharFilter):
field.lookup_expr = "icontains"
@@ -217,8 +216,9 @@ class AssetRequestReGroup:
("asset_category_id", "Asset Category"),
("asset_request_date", "Request Date"),
("asset_request_status", "Status"),
- ]
-
+ ]
+
+
class AssetAllocationReGroup:
"""
Class to keep the field name for group by option
@@ -229,4 +229,4 @@ class AssetAllocationReGroup:
("assigned_to_employee_id", "Employee"),
("assigned_date", "Assigned Date"),
("return_date", "Return Date"),
- ]
+ ]
diff --git a/asset/forms.py b/asset/forms.py
index cf1467222..ea211c214 100644
--- a/asset/forms.py
+++ b/asset/forms.py
@@ -1,4 +1,5 @@
"""
+forms.py
Asset Management Forms
This module contains Django ModelForms for handling various aspects of asset management,
@@ -7,11 +8,12 @@ including asset creation, allocation, return, category assignment, and batch han
from datetime import date
import uuid
from django import forms
-from django.forms import ModelForm
+from base.forms import ModelForm
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from employee.models import Employee
-from .models import Asset, AssetRequest, AssetAssignment, AssetCategory, AssetLot
+from asset.models import Asset, AssetRequest, AssetAssignment, AssetCategory, AssetLot
+from base.methods import reload_queryset
def set_date_field_initial(instance):
@@ -84,7 +86,7 @@ class AssetForm(ModelForm):
if instance:
kwargs["initial"] = set_date_field_initial(instance)
super(AssetForm, self).__init__(*args, **kwargs)
-
+ reload_queryset(self.fields)
self.fields["asset_category_id"].widget.attrs.update({"id": str(uuid.uuid4())})
self.fields["asset_lot_number_id"].widget.attrs.update(
{"id": str(uuid.uuid4())}
@@ -95,13 +97,13 @@ class AssetForm(ModelForm):
instance = self.instance
if instance.pk:
if asset_in_use := instance.assetassignment_set.filter(
- return_status__isnull=True
+ return_status__isnull=True
):
raise ValidationError('Asset in use you can"t change the status')
if (
- Asset.objects.filter(asset_tracking_id=self.data["asset_tracking_id"])
- .exclude(id=instance.pk)
- .exists()
+ Asset.objects.filter(asset_tracking_id=self.data["asset_tracking_id"])
+ .exclude(id=instance.pk)
+ .exists()
):
raise ValidationError(
{"asset_tracking_id": "Already asset with this tracking id exists."}
@@ -191,6 +193,7 @@ class AssetRequestForm(ModelForm):
*args,
**kwargs,
)
+ reload_queryset(self.fields)
if user is not None and user.has_perm("asset.add_assetrequest"):
self.fields["requested_employee_id"].queryset = Employee.objects.all()
self.fields["requested_employee_id"].initial = Employee.objects.filter(
@@ -212,8 +215,10 @@ class AssetAllocationForm(ModelForm):
def __init__(self, *args, **kwargs):
super(AssetAllocationForm, self).__init__(*args, **kwargs)
- self.fields['asset_id'].queryset = Asset.objects.filter(asset_status="Available")
-
+ reload_queryset(self.fields)
+ self.fields["asset_id"].queryset = Asset.objects.filter(
+ asset_status="Available"
+ )
class Meta:
"""
@@ -278,6 +283,7 @@ class AssetReturnForm(ModelForm):
attrs={"class": "oh-select oh-select-2", "required": "true"},
),
}
+
def clean_return_date(self):
return_date = self.cleaned_data.get("return_date")
@@ -292,6 +298,10 @@ class AssetBatchForm(ModelForm):
A Django ModelForm for creating or updating AssetLot instances.
"""
+ def __init__(self, *args, **kwargs) -> None:
+ super().__init__(*args, **kwargs)
+ reload_queryset(self.fields)
+
class Meta:
"""
Specifies the model and fields to be used for the AssetBatchForm.
diff --git a/asset/models.py b/asset/models.py
index 3c3dcbf76..0a035df0c 100644
--- a/asset/models.py
+++ b/asset/models.py
@@ -8,6 +8,7 @@ from django.db import models
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from base.models import Company
+from base.horilla_company_manager import HorillaCompanyManager
from employee.models import Employee
@@ -19,7 +20,7 @@ class AssetCategory(models.Model):
asset_category_name = models.CharField(max_length=255, unique=True)
asset_category_description = models.TextField()
objects = models.Manager()
- company_id = models.ForeignKey(Company,null=True, editable=False, on_delete=models.PROTECT)
+ company_id = models.ManyToManyField(Company,blank=True, verbose_name=_("Company"))
def __str__(self):
return f"{self.asset_category_name}"
@@ -32,8 +33,8 @@ class AssetLot(models.Model):
lot_number = models.CharField(max_length=30, null=False, blank=False, unique=True)
lot_description = models.TextField(null=True, blank=True)
- company_id = models.ForeignKey(Company,null=True, editable=False, on_delete=models.PROTECT)
- objects = models.Manager()
+ company_id = models.ManyToManyField(Company,blank=True, verbose_name=_("Company"))
+ objects = HorillaCompanyManager()
def __str__(self):
return f"{self.lot_number}"
@@ -61,7 +62,7 @@ class Asset(models.Model):
asset_lot_number_id = models.ForeignKey(
AssetLot, on_delete=models.PROTECT, null=True, blank=True
)
- objects = models.Manager()
+ objects = HorillaCompanyManager("asset_category_id__company_id")
def __str__(self):
return f"{self.asset_name}-{self.asset_tracking_id}"
@@ -108,7 +109,7 @@ class AssetAssignment(models.Model):
return_status = models.CharField(
choices=STATUS, max_length=30, null=True, blank=True
)
- objects = models.Manager()
+ objects = HorillaCompanyManager("asset_id__asset_lot_number_id__company_id")
class AssetRequest(models.Model):
@@ -134,4 +135,4 @@ class AssetRequest(models.Model):
asset_request_status = models.CharField(
max_length=30, choices=STATUS, default="Requested", null=True, blank=True
)
- objects = models.Manager()
+ objects = HorillaCompanyManager("requested_employee_id__employee_work_info__company_id")
diff --git a/asset/templates/category/asset_category_creation.html b/asset/templates/category/asset_category_creation.html
index afc62fd67..e887ac027 100644
--- a/asset/templates/category/asset_category_creation.html
+++ b/asset/templates/category/asset_category_creation.html
@@ -26,6 +26,11 @@
{% trans "Description" %}
{{asset_category_form.asset_category_description}}
+
+ {% trans "Company" %}
+ {{asset_category_form.company_id}}
+ {{asset_category_form.errors}}
+
-
-{% endblock settings %}
\ No newline at end of file
+
+
+
+
+
+{% endblock settings %}
diff --git a/base/templates/base/company/company_form.html b/base/templates/base/company/company_form.html
new file mode 100644
index 000000000..df1f26050
--- /dev/null
+++ b/base/templates/base/company/company_form.html
@@ -0,0 +1,68 @@
+{% load i18n %}
+
+
+
diff --git a/base/templates/base/company/company_view.html b/base/templates/base/company/company_view.html
index b88f6c446..944ae707d 100644
--- a/base/templates/base/company/company_view.html
+++ b/base/templates/base/company/company_view.html
@@ -1,64 +1,70 @@
{% load i18n %}
-
-
-
-
{% trans "Company" %}
-
{% trans "Is Hq" %}
-
{% trans "Address" %}
-
{% trans "Country" %}
-
{% trans "State" %}
-
{% trans "City" %}
-
{% trans "Zip" %}
-
-
-
-
- {% for company in companies %}
-
-
-
-
-
-
{{company.company}}
-
-
-
-
- {{company.hq}}
-
-
- {{company.address}}
-
-
- {{company.country}}
-
-
- {{company.state}}
-
-
- {{company.city}}
-
-
- {{company.zip}}
-
+
+
+
+
{% trans "Company" %}
+
{% trans "Is Hq" %}
+
{% trans "Address" %}
+
{% trans "Country" %}
+
{% trans "State" %}
+
{% trans "City" %}
+
{% trans "Zip" %}
+
+
+
+
+ {% for company in companies %}
+
+
+
+
{{company.company}}
+
+
+
{{company.hq}}
+
{{company.address}}
+
{{company.country}}
+
{{company.state}}
+
{{company.city}}
+
{{company.zip}}
-
-
-
- {% if perms.base.change_company %}
-
- {% endif %}
- {% if perms.base.delete_company %}
-
- {% endif %}
-
-
-
- {% endfor %}
-
-
-
+
+
+ {% if perms.base.change_company %}
+
+
+
+ {% endif %} {% if perms.base.delete_company %}
+
+ {% endif %}
+
+
+
+ {% endfor %}
+
+
+
diff --git a/base/templates/base/department/department.html b/base/templates/base/department/department.html
index 9692dbb33..fa5bed1c9 100644
--- a/base/templates/base/department/department.html
+++ b/base/templates/base/department/department.html
@@ -3,29 +3,64 @@
{% block settings %}
+
+
+
+
+
+
{% endblock settings %}
\ No newline at end of file
diff --git a/base/templates/base/department/department_form.html b/base/templates/base/department/department_form.html
new file mode 100644
index 000000000..8d321750a
--- /dev/null
+++ b/base/templates/base/department/department_form.html
@@ -0,0 +1,36 @@
+{% load i18n %}
+
diff --git a/base/templates/base/department/department_view.html b/base/templates/base/department/department_view.html
index b5020a6c6..753032888 100644
--- a/base/templates/base/department/department_view.html
+++ b/base/templates/base/department/department_view.html
@@ -1,35 +1,50 @@
{% load i18n %}
-
-
-
-
-
{% trans "Department" %}
-
-
-
-
- {% for dep in departments %}
-
-
-
- {{dep}}
-
-
-
-
- {% if perms.base.change_department %}
-
- {% endif %}
- {% if perms.base.delete_deaprtment %}
-
- {% endif %}
-
-
-
- {% endfor %}
-
-
-
\ No newline at end of file
+
+
+
+
+
{% trans "Department" %}
+
+
+
+
+ {% for dep in departments %}
+
+
{{dep}}
+
+
+ {% if perms.base.change_department %}
+
+
+ {% endif %}
+ {% if perms.base.delete_deaprtment %}
+
+ {% endif %}
+
+
+
+ {% endfor %}
+
+
+
diff --git a/base/templates/base/job_position/job_position.html b/base/templates/base/job_position/job_position.html
index 29044b43f..05d6c468f 100644
--- a/base/templates/base/job_position/job_position.html
+++ b/base/templates/base/job_position/job_position.html
@@ -1,38 +1,39 @@
-{% extends 'settings.html' %}
-{% load i18n %}
-{% block settings %}
+{% extends 'settings.html' %} {% load i18n %} {% block settings %}
-
- {% endif %}
-
- {% include 'base/job_position/job_position_view.html' %}
+ {% if perms.base.add_jobposition %}
+
+ {% include 'base/job_position/job_position_view.html' %} {% endif %}
-{% endblock settings %}
\ No newline at end of file
+
+
+{% endblock settings %}
diff --git a/base/templates/base/job_position/job_position_form.html b/base/templates/base/job_position/job_position_form.html
new file mode 100644
index 000000000..c665d9e2f
--- /dev/null
+++ b/base/templates/base/job_position/job_position_form.html
@@ -0,0 +1,34 @@
+{% load i18n %}
+
+
diff --git a/base/templates/base/job_position/job_position_view.html b/base/templates/base/job_position/job_position_view.html
index dcb2c035c..1e54e5356 100644
--- a/base/templates/base/job_position/job_position_view.html
+++ b/base/templates/base/job_position/job_position_view.html
@@ -1,107 +1,121 @@
{% load i18n %}
-
-
-
-
-
-
-
-
{% trans "Department" %}
-
{% trans "Job Position" %}
-
-
+
+
+
+
+
+
+
+
{% trans "Department" %}
+
+ {% trans "Job Position" %}
+
+
+
-
- {% for department in departments %}
-
-
-
-
-
-
-
- {{department}}
-
-
-
- {% for job in department.job_position.all %}
-
-
-
-
-
-
{{job|capfirst}}
-
-
-
- {% if perms.base.change_jobposition %}
-
- {% endif %} {% if perms.base.delete_jobposition %}
-
-
-
- {% endif %}
-
-
-
- {% endfor %}
-
-
- {% endfor %}
-
-
-
-
-
-
+
+ {% for department in departments %}
+
+
+
+
+
+
+
+ {{department}}
+
+
+
+
+ {{department.job_position.all|length}}
+ {% trans "Job positions" %}
+
+ {% for job in department.job_position.all %}
+
+
+
+
+
+
{{job|capfirst}}
+
+
+
+ {% if perms.base.change_jobposition %}
+
+ {% endif %}
+ {% if perms.base.delete_jobposition %}
+
+
+
+ {% endif %}
+
+
+
+ {% endfor %}
+
+
+ {% endfor %}
+
+
+
+
+
+
diff --git a/base/templates/base/job_role/job_role.html b/base/templates/base/job_role/job_role.html
index 8cfa1368b..105fb8cd9 100644
--- a/base/templates/base/job_role/job_role.html
+++ b/base/templates/base/job_role/job_role.html
@@ -1,38 +1,42 @@
-{% extends 'settings.html' %}
-{% load i18n %}
-{% block settings %}
+{% extends 'settings.html' %} {% load i18n %} {% block settings %}
-
+ {% if perms.base.add_jobrole %}
+
+ {% include 'base/job_role/job_role_view.html' %}
{% endif %}
- {% include 'base/job_role/job_role_view.html' %}
-{% endblock settings %}
\ No newline at end of file
+
+
+
+{% endblock settings %}
diff --git a/base/templates/base/job_role/job_role_form.html b/base/templates/base/job_role/job_role_form.html
new file mode 100644
index 000000000..8def1e7e9
--- /dev/null
+++ b/base/templates/base/job_role/job_role_form.html
@@ -0,0 +1,33 @@
+{% load i18n %}
+
+
diff --git a/base/templates/base/job_role/job_role_view.html b/base/templates/base/job_role/job_role_view.html
index 08628ccf7..9f07fe58e 100644
--- a/base/templates/base/job_role/job_role_view.html
+++ b/base/templates/base/job_role/job_role_view.html
@@ -1,83 +1,115 @@
{% load i18n %}
-
-
-
-
-
-
-
-
-
{% trans "Job Position" %}
-
{% trans "Job Role" %}
-
-
-
-
-
- {% for job in job_positions %}
-
-
-
- {% for role in job.jobrole_set.all %}
-
-
-
-
-
-
{{role|capfirst}}
-
-
-
+
+
+
+
+
+
+
+
+
+ {% trans "Job Position" %}
+
+
{% trans "Job Role" %}
+
+
- {% if perms.base.view_jobrole %}
-
- {% endif %}
- {% if perms.base.delete_jobrole %}
-
-
-
- {% endif %}
-
-
-
- {% endfor %}
-
-
- {% endfor %}
-
-
-
-
-
-
\ No newline at end of file
+
+ {% for job in job_positions %}
+
+
+
+
+ {{job.jobrole_set.all|length}}
+ {% trans "Job positions" %}
+
+ {% for role in job.jobrole_set.all %}
+
+
+
+
+
+
{{role|capfirst}}
+
+
+
+ {% if perms.base.view_jobrole %}
+
+ {% endif %} {% if perms.base.delete_jobrole %}
+
+
+
+ {% endif %}
+
+
+
+ {% endfor %}
+
+
+ {% endfor %}
+
+
+
+
+
+
+
diff --git a/base/templates/base/shift/shift.html b/base/templates/base/shift/shift.html
index 5ed9f8e27..199d0db5b 100644
--- a/base/templates/base/shift/shift.html
+++ b/base/templates/base/shift/shift.html
@@ -30,6 +30,13 @@
{{form.full_time.errors}}
{{form.full_time}}
+
+
+ {% trans "Company" %}
+
+ {{form.company_id.errors}}
+ {{form.company_id}}
+
{% trans "Save Changes" %}
diff --git a/base/templates/base/work_type/work_type.html b/base/templates/base/work_type/work_type.html
index 32c286f7c..53a050587 100644
--- a/base/templates/base/work_type/work_type.html
+++ b/base/templates/base/work_type/work_type.html
@@ -3,29 +3,45 @@
{% block settings %}
+
+
+
+
{% endblock settings %}
\ No newline at end of file
diff --git a/base/templates/base/work_type/work_type_form.html b/base/templates/base/work_type/work_type_form.html
new file mode 100644
index 000000000..08f2b4cae
--- /dev/null
+++ b/base/templates/base/work_type/work_type_form.html
@@ -0,0 +1,33 @@
+{% load i18n %}
+
diff --git a/base/templates/base/work_type/work_type_view.html b/base/templates/base/work_type/work_type_view.html
index 82376b906..987eaaff5 100644
--- a/base/templates/base/work_type/work_type_view.html
+++ b/base/templates/base/work_type/work_type_view.html
@@ -1,36 +1,49 @@
{% load i18n %}
-
-
-
-
{% trans "Work Type" %}
-
-
-
-
- {% for type in work_types %}
-
-
{{type}}
-
-
-
- {% if perms.base.change_worktype %}
-
-
- {% endif %}
- {% if perms.base.delete_worktype %}
-
- {% endif %}
-
-
-
- {% endfor %}
-
-
+
+
+
+
{% trans "Work Type" %}
+
+
+
+
+ {% for type in work_types %}
+
+
{{type}}
+
+
+ {% if perms.base.change_worktype %}
+
+
+ {% endif %}
+ {% if perms.base.delete_worktype %}
+
+ {% endif %}
+
+
+
+ {% endfor %}
+
+
-
\ No newline at end of file
diff --git a/base/thread_local_middleware.py b/base/thread_local_middleware.py
new file mode 100644
index 000000000..b81e910b8
--- /dev/null
+++ b/base/thread_local_middleware.py
@@ -0,0 +1,17 @@
+import threading
+
+_thread_locals = threading.local()
+
+
+class ThreadLocalMiddleware:
+ """
+ ThreadLocalMiddleWare
+ """
+
+ def __init__(self, get_response):
+ self.get_response = get_response
+
+ def __call__(self, request):
+ _thread_locals.request = request
+ response = self.get_response(request)
+ return response
diff --git a/base/urls.py b/base/urls.py
index 883c028fa..dd2c78a99 100644
--- a/base/urls.py
+++ b/base/urls.py
@@ -68,7 +68,7 @@ urlpatterns = [
name="remove-permission",
),
path("settings/company-create/", views.company_create, name="company-create"),
- # path('company-view', views.company_view,name='company-view'),
+ path('company-view', views.company_view,name='company-view'),
path(
"settings/company-update//",
views.company_update,
@@ -79,9 +79,10 @@ urlpatterns = [
"company-delete//",
views.object_delete,
name="company-delete",
- kwargs={"model": Company, "redirect": "/settings/company-create"},
+ kwargs={"model": Company, "redirect": "/company-view"},
),
- path("settings/department-creation/", views.department, name="department-creation"),
+ path("settings/department-view/", views.department_view, name="department-view"),
+ path("settings/department-creation/", views.department_create, name="department-creation"),
path(
"settings/department-update//",
views.department_update,
@@ -92,13 +93,18 @@ urlpatterns = [
"department-delete//",
views.object_delete,
name="department-delete",
- kwargs={"model": Department, "redirect": "/settings/department-creation"},
+ kwargs={"model": Department, "redirect": "/settings/department-view"},
),
path(
"settings/job-position-creation/",
- views.job_position,
+ views.job_position_creation,
name="job-position-creation",
),
+ path(
+ "settings/job-position-view/",
+ views.job_position,
+ name="job-position-view",
+ ),
path(
"settings/job-position-update//",
views.job_position_update,
@@ -109,9 +115,10 @@ urlpatterns = [
"job-position-delete//",
views.object_delete,
name="job-position-delete",
- kwargs={"model": JobPosition, "redirect": "/settings/job-position-creation"},
+ kwargs={"model": JobPosition, "redirect": "/settings/job-position-view"},
),
path("settings/job-role-create/", views.job_role_create, name="job-role-create"),
+ path("settings/job-role-view/", views.job_role_view, name="job-role-view"),
path(
"settings/job-role-update//",
views.job_role_update,
@@ -122,8 +129,9 @@ urlpatterns = [
"job-role-delete//",
views.object_delete,
name="job-role-delete",
- kwargs={"model": JobRole, "redirect": "/settings/job-role-create"},
+ kwargs={"model": JobRole, "redirect": "/settings/job-role-view"},
),
+ path("settings/work-type-view/", views.work_type_view, name="work-type-view"),
path("settings/work-type-create/", views.work_type_create, name="work-type-create"),
path(
"settings/work-type-update//",
@@ -135,7 +143,7 @@ urlpatterns = [
"work-type-delete//",
views.object_delete,
name="work-type-delete",
- kwargs={"model": WorkType, "redirect": "/settings/work-type-create"},
+ kwargs={"model": WorkType, "redirect": "/settings/work-type-view"},
),
path(
"settings/rotating-work-type-create/",
diff --git a/base/views.py b/base/views.py
index 128b174c7..b04758c44 100644
--- a/base/views.py
+++ b/base/views.py
@@ -516,15 +516,27 @@ def company_create(request):
companies = Company.objects.all()
if request.method == "POST":
form = CompanyForm(request.POST, request.FILES)
+
if form.is_valid():
form.save()
- form = CompanyForm()
messages.success(request, _("Company has been created successfully!"))
- return redirect(company_create)
+ return HttpResponse("")
return render(
- request, "base/company/company.html", {"form": form, "companies": companies}
+ request, "base/company/company_form.html", {"form": form, "companies": companies}
+ )
+
+@login_required
+@permission_required("base.add_company")
+def company_view(request):
+ """
+ This method used to view created companies
+ """
+
+ companies = Company.objects.all()
+ return render(
+ request, "base/company/company.html", {"companies": companies}
)
@@ -537,7 +549,6 @@ def company_update(request, id, **kwargs):
id : company instance id
"""
- companies = Company.objects.all()
company = Company.objects.get(id=id)
form = CompanyForm(instance=company)
if request.method == "POST":
@@ -545,34 +556,47 @@ def company_update(request, id, **kwargs):
if form.is_valid():
form.save()
messages.success(request, _("Company updated"))
- return redirect(company_create)
+ return HttpResponse("")
return render(
- request, "base/company/company.html", {"form": form, "companies": companies}
+ request, "base/company/company_form.html", {"form": form, "company": company}
)
@login_required
@permission_required("base.add_department")
-def department(request):
+def department_create(request):
"""
- This method render renders form and template to create department
+ This method renders form and template to create department
"""
form = DepartmentForm()
- departments = Department.objects.all()
if request.method == "POST":
form = DepartmentForm(request.POST)
if form.is_valid():
form.save()
form = DepartmentForm()
messages.success(request, _("Department has been created successfully!"))
+ return HttpResponse("")
+ return render(
+ request,
+ "base/department/department_form.html",
+ {"form": form,},
+ )
+
+
+@login_required
+@permission_required("base.add_department")
+def department_view(request):
+ """
+ This method view department
+ """
+ departments = Department.objects.all()
return render(
request,
"base/department/department.html",
- {"form": form, "departments": departments},
+ {"departments": departments,},
)
-
@login_required
@permission_required("base.change_department")
def department_update(request, id, **kwargs):
@@ -582,18 +606,17 @@ def department_update(request, id, **kwargs):
id : department instance id
"""
department = Department.objects.get(id=id)
- departments = Department.objects.all()
form = DepartmentForm(instance=department)
if request.method == "POST":
form = DepartmentForm(request.POST, instance=department)
if form.is_valid():
form.save()
messages.success(request, _("Department updated."))
- return redirect("/settings/department-creation")
+ return HttpResponse("")
return render(
request,
- "base/department/department.html",
- {"form": form, "departments": departments},
+ "base/department/department_form.html",
+ {"form": form, "department": department},
)
@@ -601,7 +624,7 @@ def department_update(request, id, **kwargs):
@permission_required("base.add_jobposition")
def job_position(request):
"""
- This method is used to create job position
+ This method is used to view job position
"""
departments = Department.objects.all()
@@ -617,6 +640,25 @@ def job_position(request):
{"form": form, "departments": departments},
)
+@login_required
+@permission_required("base.add_jobposition")
+def job_position_creation(request):
+ """
+ This method is used to create job position
+ """
+
+ form = JobPositionForm()
+ if request.method == "POST":
+ form = JobPositionForm(request.POST)
+ if form.is_valid():
+ form.save()
+ messages.success(request, _("Job Position has been created successfully!"))
+ return HttpResponse("")
+ return render(
+ request,
+ "base/job_position/job_position_form.html",
+ {"form": form,},
+ )
@login_required
@permission_required("base.change_jobposition")
@@ -628,18 +670,17 @@ def job_position_update(request, id, **kwargs):
"""
job_position = JobPosition.objects.get(id=id)
- departments = Department.objects.all()
form = JobPositionForm(instance=job_position)
if request.method == "POST":
form = JobPositionForm(request.POST, instance=job_position)
if form.is_valid():
form.save()
messages.success(request, _("Job position updated."))
- return redirect("/settings/job-position-creation")
+ return HttpResponse("")
return render(
request,
- "base/job_position/job_position.html",
- {"form": form, "departments": departments},
+ "base/job_position/job_position_form.html",
+ {"form": form, "job_position": job_position},
)
@@ -651,7 +692,6 @@ def job_role_create(request):
"""
form = JobRoleForm()
- jobs = JobPosition.objects.all()
if request.method == "POST":
form = JobRoleForm(request.POST)
if form.is_valid():
@@ -659,8 +699,24 @@ def job_role_create(request):
form = JobRoleForm()
messages.success(request, _("Job role has been created successfully!"))
+ return HttpResponse("")
+
return render(
- request, "base/job_role/job_role.html", {"form": form, "job_positions": jobs}
+ request, "base/job_role/job_role_form.html", {"form": form,}
+ )
+
+
+@login_required
+@permission_required("base.add_jobrole")
+def job_role_view(request):
+ """
+ This method is used to view job role.
+ """
+
+ jobs = JobPosition.objects.all()
+
+ return render(
+ request, "base/job_role/job_role.html", { "job_positions": jobs}
)
@@ -675,7 +731,6 @@ def job_role_update(request, id, **kwargs):
"""
job_role = JobRole.objects.get(id=id)
- jobs = JobPosition.objects.all()
form = JobRoleForm(instance=job_role)
if request.method == "POST":
@@ -683,8 +738,10 @@ def job_role_update(request, id, **kwargs):
if form.is_valid():
form.save()
messages.success(request, _("Job role updated."))
+ return HttpResponse("")
+
return render(
- request, "base/job_role/job_role.html", {"form": form, "job_positions": jobs}
+ request, "base/job_role/job_role_form.html", {"form": form, "job_role": job_role,}
)
@@ -704,10 +761,27 @@ def work_type_create(request):
form = WorkTypeForm()
messages.success(request, _("Work Type has been created successfully!"))
+ return HttpResponse("")
+
+ return render(
+ request,
+ "base/work_type/work_type_form.html",
+ {"form": form, "work_types": work_types},
+ )
+
+
+@login_required
+@permission_required("base.add_worktype")
+def work_type_view(request):
+ """
+ This method is used to view work type
+ """
+
+ work_types = WorkType.objects.all()
return render(
request,
"base/work_type/work_type.html",
- {"form": form, "work_types": work_types},
+ {"work_types": work_types},
)
@@ -722,18 +796,17 @@ def work_type_update(request, id, **kwargs):
"""
work_type = WorkType.objects.get(id=id)
- work_types = WorkType.objects.all()
form = WorkTypeForm(instance=work_type)
if request.method == "POST":
form = WorkTypeForm(request.POST, instance=work_type)
if form.is_valid():
form.save()
messages.success(request, _("Work type updated."))
- return redirect(work_type_create)
+ return HttpResponse("")
return render(
request,
- "base/work_type/work_type.html",
- {"form": form, "work_types": work_types},
+ "base/work_type/work_type_form.html",
+ {"form": form, "work_type": work_type},
)
diff --git a/employee/forms.py b/employee/forms.py
index 54b3107cb..2e246d3e6 100644
--- a/employee/forms.py
+++ b/employee/forms.py
@@ -27,6 +27,7 @@ from django.contrib.auth.models import User
from django.forms import DateInput, TextInput
from django.utils.translation import gettext_lazy as trans
from employee.models import Employee, EmployeeWorkInformation, EmployeeBankDetails
+from base.methods import reload_queryset
class ModelForm(forms.ModelForm):
@@ -36,6 +37,7 @@ class ModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
+ reload_queryset(self.fields)
for _, field in self.fields.items():
widget = field.widget
if isinstance(
diff --git a/employee/models.py b/employee/models.py
index fc593532f..ba163e5de 100644
--- a/employee/models.py
+++ b/employee/models.py
@@ -20,6 +20,7 @@ from base.models import (
Department,
EmployeeShift,
)
+from base.horilla_company_manager import HorillaCompanyManager
from horilla_audit.models import HorillaAuditLog, HorillaAuditInfo
from horilla_audit.methods import get_diff
from django.core.files.storage import default_storage
@@ -89,7 +90,9 @@ class Employee(models.Model):
emergency_contact_relation = models.CharField(max_length=20, null=True, blank=True)
is_active = models.BooleanField(default=True)
additional_info = models.JSONField(null=True, blank=True)
- objects = models.Manager()
+ objects = HorillaCompanyManager(
+ related_company_field="employee_work_info__company_id"
+ )
def get_image(self):
"""
@@ -119,7 +122,7 @@ class Employee(models.Model):
)
if self.employee_profile:
full_filename = settings.MEDIA_ROOT + self.employee_profile.name
-
+
if default_storage.exists(full_filename):
url = self.employee_profile.url
return url
@@ -266,7 +269,7 @@ class EmployeeWorkInformation(models.Model):
HorillaAuditInfo,
],
)
- objects = models.Manager()
+ objects = HorillaCompanyManager()
def __str__(self) -> str:
return f"{self.employee_id} - {self.job_position_id}"
@@ -333,7 +336,9 @@ class EmployeeBankDetails(models.Model):
max_length=50, null=True, blank=True, verbose_name="Bank Code #2"
)
additional_info = models.JSONField(null=True, blank=True)
- objects = models.Manager()
+ objects = HorillaCompanyManager(
+ related_company_field="employee_id__employee_work_info__company_id"
+ )
def __str__(self) -> str:
return f"{self.employee_id}-{self.bank_name}"
diff --git a/employee/views.py b/employee/views.py
index ca2b72303..f1cf3d1eb 100755
--- a/employee/views.py
+++ b/employee/views.py
@@ -152,7 +152,7 @@ def employee_view_individual(request, obj_id, **kwargs):
employee = Employee.objects.get(id=obj_id)
employee_leaves = employee.available_leave.all()
user = Employee.objects.filter(employee_user_id=request.user).first()
- if user.reporting_manager.filter(
+ if user and user.reporting_manager.filter(
employee_id=employee
).exists() or request.user.has_perm("employee.change_employee"):
return render(
@@ -468,7 +468,7 @@ def employee_view_update(request, obj_id, **kwargs):
"""
user = Employee.objects.filter(employee_user_id=request.user).first()
employee = Employee.objects.filter(id=obj_id).first()
- if user.reporting_manager.filter(
+ if user and user.reporting_manager.filter(
employee_id=employee
).exists() or request.user.has_perm("employee.change_employee"):
form = EmployeeForm(instance=employee)
diff --git a/horilla/__init__.py b/horilla/__init__.py
index 0b187b3cd..1a8421826 100755
--- a/horilla/__init__.py
+++ b/horilla/__init__.py
@@ -2,3 +2,5 @@
init.py
"""
from horilla import horilla_apps
+from horilla import horilla_middlewares
+from horilla import horilla_context_processors
diff --git a/horilla/filters.py b/horilla/filters.py
index f7a8e6e5f..840a9dded 100755
--- a/horilla/filters.py
+++ b/horilla/filters.py
@@ -1,7 +1,10 @@
-import django_filters
-from django_filters import CharFilter
-from django import forms
+"""
+filters.py
+"""
import uuid
+import django_filters
+from django import forms
+from base.methods import reload_queryset
def filter_by_name(queryset, name, value):
"""
@@ -25,16 +28,17 @@ def filter_by_name(queryset, name, value):
class FilterSet(django_filters.FilterSet):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- for field_name, field in self.filters.items():
+ reload_queryset(self.form.fields)
+ for field_name, field in self.form.fields.items():
filter_widget = self.filters[field_name]
widget = filter_widget.field.widget
if isinstance(widget, (forms.NumberInput, forms.EmailInput,forms.TextInput)):
- filter_widget.field.widget.attrs.update({'class': 'oh-input w-100'})
+ field.widget.attrs.update({'class': 'oh-input w-100'})
elif isinstance(widget,(forms.Select,)):
- filter_widget.field.widget.attrs.update({'class': 'oh-select oh-select-2 select2-hidden-accessible','id':uuid.uuid4()})
+ field.widget.attrs.update({'class': 'oh-select oh-select-2 select2-hidden-accessible','id':uuid.uuid4()})
elif isinstance(widget,(forms.Textarea)):
- filter_widget.field.widget.attrs.update({'class': 'oh-input w-100'})
+ field.widget.attrs.update({'class': 'oh-input w-100'})
elif isinstance(widget, (forms.CheckboxInput,forms.CheckboxSelectMultiple,)):
- filter_widget.field.widget.attrs.update({'class': 'oh-switch__checkbox'})
+ field.widget.attrs.update({'class': 'oh-switch__checkbox'})
elif isinstance(widget,(forms.ModelChoiceField)):
- filter_widget.field.widget.attrs.update({'class': 'oh-select oh-select-2 select2-hidden-accessible',})
\ No newline at end of file
+ field.widget.attrs.update({'class': 'oh-select oh-select-2 select2-hidden-accessible',})
\ No newline at end of file
diff --git a/horilla/horilla_context_processors.py b/horilla/horilla_context_processors.py
new file mode 100644
index 000000000..2dd13736c
--- /dev/null
+++ b/horilla/horilla_context_processors.py
@@ -0,0 +1,10 @@
+"""
+horilla_context_process.py
+
+This module is used to register context processors without effecting the horilla/settings.py module
+"""
+from horilla.settings import TEMPLATES
+
+TEMPLATES[0]["OPTIONS"]["context_processors"].append(
+ "base.context_processors.get_companies",
+)
diff --git a/horilla/horilla_middlewares.py b/horilla/horilla_middlewares.py
new file mode 100644
index 000000000..2f1d0362f
--- /dev/null
+++ b/horilla/horilla_middlewares.py
@@ -0,0 +1,9 @@
+"""
+horilla_middlewares.py
+
+This module is used to register horilla's middlewares without affecting the horilla/settings.py
+"""
+from horilla.settings import MIDDLEWARE
+
+MIDDLEWARE.append("base.middleware.CompanyMiddleware")
+MIDDLEWARE.append("base.thread_local_middleware.ThreadLocalMiddleware")
diff --git a/horilla/settings.py b/horilla/settings.py
index 77ec660bc..7150f45a5 100755
--- a/horilla/settings.py
+++ b/horilla/settings.py
@@ -57,6 +57,7 @@ INSTALLED_APPS = [
'asset',
'attendance',
'payroll',
+ 'horilla_widgets',
'widget_tweaks',
"django_apscheduler",
diff --git a/horilla/urls.py b/horilla/urls.py
index 9bed4ea20..4934325d0 100755
--- a/horilla/urls.py
+++ b/horilla/urls.py
@@ -22,7 +22,7 @@ import notifications.urls
urlpatterns = [
- # path('admin/',admin.site.urls),
+ path('admin/',admin.site.urls),
path('',include('base.urls')),
path('recruitment/',include('recruitment.urls')),
path('employee/',include('employee.urls')),
diff --git a/horilla_widgets/templates/horilla_widgets/multiselect_components/table.html b/horilla_widgets/templates/horilla_widgets/multiselect_components/table.html
index adc414b60..e5189c737 100644
--- a/horilla_widgets/templates/horilla_widgets/multiselect_components/table.html
+++ b/horilla_widgets/templates/horilla_widgets/multiselect_components/table.html
@@ -200,4 +200,16 @@
});
});
});
+ $("#choose-all-user").click(function (e) {
+ setTimeout(() => {
+ $("#choose-all-user").closest(".oh-sticky-table__th--custom")[0].click()
+ }, 2);
+ });
+ $(".all-choose-user-row").click(function (e) {
+ e.preventDefault();
+ setTimeout(() => {
+ $(this).closest(".oh-sticky-table__tr--custom")[0].click()
+ }, 1);
+
+ });
diff --git a/leave/filters.py b/leave/filters.py
index 3799f84b1..e33320612 100644
--- a/leave/filters.py
+++ b/leave/filters.py
@@ -22,46 +22,10 @@ from .models import (
CompanyLeave,
LeaveAllocationRequest,
)
+from base.filters import FilterSet
-class FilterSet(FilterSet):
- """
- Custom FilterSet class for styling filter widgets.
- """
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- for field_name, field in self.filters.items():
- filter_widget = self.filters[field_name]
- widget = filter_widget.field.widget
- if isinstance(
- widget, (forms.NumberInput, forms.EmailInput, forms.TextInput)
- ):
- filter_widget.field.widget.attrs.update({"class": "oh-input w-100"})
- elif isinstance(widget, (forms.Select,)):
- filter_widget.field.widget.attrs.update(
- {
- "class": "oh-select oh-select-2 select2-hidden-accessible",
- }
- )
- elif isinstance(widget, (forms.Textarea)):
- filter_widget.field.widget.attrs.update({"class": "oh-input w-100"})
- elif isinstance(
- widget,
- (
- forms.CheckboxInput,
- forms.CheckboxSelectMultiple,
- ),
- ):
- filter_widget.field.widget.attrs.update(
- {"class": "oh-switch__checkbox"}
- )
- elif isinstance(widget, (forms.ModelChoiceField)):
- filter_widget.field.widget.attrs.update(
- {
- "class": "oh-select oh-select-2 select2-hidden-accessible",
- }
- )
class LeaveTypeFilter(FilterSet):
diff --git a/leave/forms.py b/leave/forms.py
index 3900a3ca7..c2807f4b1 100644
--- a/leave/forms.py
+++ b/leave/forms.py
@@ -8,6 +8,7 @@ from django.utils.translation import gettext_lazy as _
from django.template.loader import render_to_string
from employee.filters import EmployeeFilter
from employee.models import Employee
+from base.methods import reload_queryset
from horilla_widgets.forms import HorillaForm
from horilla_widgets.widgets.horilla_multi_select_field import HorillaMultiSelectField
from horilla_widgets.widgets.select_widgets import HorillaMultiSelectWidget
@@ -33,6 +34,7 @@ CHOICES = [("yes", _("Yes")), ("no", _("No"))]
class ModelForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
+ reload_queryset(self.fields)
for field_name, field in self.fields.items():
widget = field.widget
@@ -70,6 +72,7 @@ class ModelForm(forms.ModelForm):
class ConditionForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
+ reload_queryset(self.fields)
for field_name, field in self.fields.items():
widget = field.widget
if isinstance(widget, (forms.Select,)):
@@ -723,16 +726,6 @@ class AssignLeaveForm(HorillaForm):
),
label="Employee",
)
- # leave_type_id = HorillaMultiSelectField(
- # queryset=LeaveType.objects.all(),
- # widget=HorillaMultiSelectWidget(
- # filter_route_name="leave-type-widget-filter",
- # filter_class=LeaveTypeFilter,
- # filter_instance_contex_name="form",
- # filter_template_path="leave/leave_type/leave_type_filter.html",
- # ),
- # label="Leave Type",
- # )
def clean(self):
cleaned_data = super().clean()
@@ -755,7 +748,7 @@ class AssignLeaveForm(HorillaForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
-
+ reload_queryset(self.fields)
self.fields["employee_id"].widget.attrs.update(
{"required": True, "id": uuid.uuid4()}
),
diff --git a/leave/models.py b/leave/models.py
index f206883a0..32cf078cf 100644
--- a/leave/models.py
+++ b/leave/models.py
@@ -7,6 +7,7 @@ from django.core.exceptions import ValidationError
from dateutil.relativedelta import relativedelta
from django.utils.translation import gettext_lazy as _
from base.models import Company
+from base.horilla_company_manager import HorillaCompanyManager
from employee.models import Employee
from .methods import calculate_requested_days
from django.core.files.storage import default_storage
@@ -165,8 +166,9 @@ class LeaveType(models.Model):
exclude_company_leave = models.CharField(max_length=30, choices=CHOICES)
exclude_holiday = models.CharField(max_length=30, choices=CHOICES)
company_id = models.ForeignKey(Company,null=True, editable=False, on_delete=models.PROTECT)
- objects = models.Manager()
-
+ objects = HorillaCompanyManager(
+ related_company_field="company_id"
+ )
class Meta:
ordering = ['-id']
@@ -192,8 +194,9 @@ class Holiday(models.Model):
end_date = models.DateField(null=True, blank=True, verbose_name=_("End Date"))
recurring = models.BooleanField(default=False, verbose_name=_("Recurring"))
company_id = models.ForeignKey(Company,null=True, editable=False, on_delete=models.PROTECT)
- objects = models.Manager()
-
+ objects = HorillaCompanyManager(
+ related_company_field="company_id"
+ )
def __str__(self):
return self.name
@@ -205,7 +208,9 @@ class CompanyLeave(models.Model):
based_on_week_day = models.CharField(max_length=100, choices=WEEK_DAYS)
company_id = models.ForeignKey(Company,null=True, editable=False, on_delete=models.PROTECT)
objects = models.Manager()
-
+ objects = HorillaCompanyManager(
+ related_company_field="company_id"
+ )
class Meta:
unique_together = ("based_on_week", "based_on_week_day")
@@ -242,8 +247,9 @@ class AvailableLeave(models.Model):
expired_date = models.DateField(
blank=True, null=True, verbose_name=_("CarryForward Expired Date")
)
- objects = models.Manager()
-
+ objects = HorillaCompanyManager(
+ related_company_field="employee_id__employee_work_info__company_id"
+ )
class Meta:
unique_together = ("leave_type_id", "employee_id")
@@ -410,8 +416,9 @@ class LeaveRequest(models.Model):
approved_carryforward_days = models.FloatField(default=0)
created_at = models.DateTimeField(auto_now="True")
reject_reason = models.TextField(blank=True, verbose_name=_("Reject Reason"))
- objects = models.Manager()
-
+ objects = HorillaCompanyManager(
+ related_company_field="employee_id__employee_work_info__company_id"
+ )
def __str__(self):
return f"{self.employee_id} | {self.leave_type_id} | {self.status}"
@@ -578,8 +585,9 @@ class LeaveAllocationRequest(models.Model):
)
created_at = models.DateTimeField(auto_now="True")
reject_reason = models.TextField(blank=True)
- objects = models.Manager()
-
+ objects = HorillaCompanyManager(
+ related_company_field="employee_id__employee_work_info__company_id"
+ )
def __str__(self):
return f"{self.employee_id}| {self.leave_type_id}| {self.id}"
diff --git a/leave/templates/leave/leave_allocation_request/leave_allocation_request_group_by.html b/leave/templates/leave/leave_allocation_request/leave_allocation_request_group_by.html
index dede9b323..eecc97427 100644
--- a/leave/templates/leave/leave_allocation_request/leave_allocation_request_group_by.html
+++ b/leave/templates/leave/leave_allocation_request/leave_allocation_request_group_by.html
@@ -2,6 +2,7 @@
{% load basefilters %}
{% load static %}
{% load i18n %} {% include 'filter_tags.html' %}
+
{% if my_leave_allocation_requests %}
@@ -361,6 +362,7 @@
{% endif %}
+