[ADD] EMPLOYEE: Initial configuration for company policies
This commit is contained in:
@@ -4,7 +4,15 @@ admin.py
|
||||
This page is used to register the model with admins site.
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from employee.models import Employee, EmployeeWorkInformation, EmployeeBankDetails, EmployeeNote, EmployeeTag
|
||||
from employee.models import (
|
||||
Employee,
|
||||
EmployeeWorkInformation,
|
||||
EmployeeBankDetails,
|
||||
EmployeeNote,
|
||||
EmployeeTag,
|
||||
PolicyMultipleFile,
|
||||
Policy,
|
||||
)
|
||||
from simple_history.admin import SimpleHistoryAdmin
|
||||
|
||||
|
||||
@@ -13,4 +21,4 @@ from simple_history.admin import SimpleHistoryAdmin
|
||||
admin.site.register(Employee)
|
||||
admin.site.register(EmployeeBankDetails)
|
||||
admin.site.register(EmployeeWorkInformation, SimpleHistoryAdmin)
|
||||
admin.site.register([EmployeeNote, EmployeeTag])
|
||||
admin.site.register([EmployeeNote, EmployeeTag, PolicyMultipleFile, Policy])
|
||||
|
||||
@@ -4,6 +4,7 @@ filters.py
|
||||
This page is used to register filter for employee models
|
||||
|
||||
"""
|
||||
from employee.models import Policy
|
||||
import uuid
|
||||
from django import forms
|
||||
import django_filters
|
||||
@@ -84,7 +85,7 @@ class EmployeeFilter(FilterSet):
|
||||
"employee_work_info__reporting_manager_id",
|
||||
"employee_work_info__company_id",
|
||||
"employee_work_info__shift_id",
|
||||
"employee_work_info__tags"
|
||||
"employee_work_info__tags",
|
||||
]
|
||||
|
||||
def not_in_yet_func(self, queryset, _, value):
|
||||
@@ -196,3 +197,15 @@ class EmployeeReGroup:
|
||||
("employee_work_info.reporting_manager_id", "Reporting Manager"),
|
||||
("employee_work_info.company_id", "Company"),
|
||||
]
|
||||
|
||||
|
||||
class PolicyFilter(FilterSet):
|
||||
"""
|
||||
PolicyFilter filterset class
|
||||
"""
|
||||
|
||||
search = django_filters.CharFilter(field_name="title", lookup_expr="icontains")
|
||||
|
||||
class Meta:
|
||||
model = Policy
|
||||
fields = "__all__"
|
||||
|
||||
@@ -27,7 +27,14 @@ from django.contrib.auth.models import User
|
||||
from django.forms import DateInput, TextInput
|
||||
from django.utils.translation import gettext as _
|
||||
from django.utils.translation import gettext_lazy as trans
|
||||
from employee.models import Employee, EmployeeWorkInformation, EmployeeBankDetails, EmployeeNote
|
||||
from employee.models import (
|
||||
Employee,
|
||||
EmployeeWorkInformation,
|
||||
EmployeeBankDetails,
|
||||
EmployeeNote,
|
||||
Policy,
|
||||
PolicyMultipleFile,
|
||||
)
|
||||
from base.methods import reload_queryset
|
||||
|
||||
|
||||
@@ -405,12 +412,69 @@ class EmployeeNoteForm(ModelForm):
|
||||
"""
|
||||
|
||||
model = EmployeeNote
|
||||
exclude = (
|
||||
"updated_by",
|
||||
)
|
||||
exclude = ("updated_by",)
|
||||
fields = "__all__"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
field = self.fields["employee_id"]
|
||||
field.widget = field.hidden_widget()
|
||||
field.widget = field.hidden_widget()
|
||||
|
||||
|
||||
class MultipleFileInput(forms.ClearableFileInput):
|
||||
allow_multiple_selected = True
|
||||
|
||||
|
||||
class MultipleFileField(forms.FileField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault("widget", MultipleFileInput())
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def clean(self, data, initial=None):
|
||||
single_file_clean = super().clean
|
||||
if isinstance(data, (list, tuple)):
|
||||
result = [single_file_clean(d, initial) for d in data]
|
||||
else:
|
||||
result = [single_file_clean(data, initial)]
|
||||
if len(result) == 0:
|
||||
result = [[]]
|
||||
return result[0]
|
||||
|
||||
|
||||
class PolicyForm(ModelForm):
|
||||
"""
|
||||
PolicyForm
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Policy
|
||||
fields = "__all__"
|
||||
exclude = ["attachments"]
|
||||
widgets = {
|
||||
"body": forms.Textarea(
|
||||
attrs={"data-summernote": "", "style": "display:none;"}
|
||||
),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["attachment"] = MultipleFileField(
|
||||
label="Attachements", required=False
|
||||
)
|
||||
|
||||
def save(self, *args, commit=True, **kwargs):
|
||||
attachemnt = []
|
||||
multiple_attachment_ids = []
|
||||
attachemnts = None
|
||||
if self.files.getlist("attachment"):
|
||||
attachemnts = self.files.getlist("attachment")
|
||||
multiple_attachment_ids = []
|
||||
for attachemnt in attachemnts:
|
||||
file_instance = PolicyMultipleFile()
|
||||
file_instance.attachment = attachemnt
|
||||
file_instance.save()
|
||||
multiple_attachment_ids.append(file_instance.pk)
|
||||
instance = super().save(commit)
|
||||
if commit:
|
||||
instance.attachments.add(*multiple_attachment_ids)
|
||||
return instance, attachemnts
|
||||
|
||||
@@ -7,6 +7,7 @@ This module is used to register models for employee app
|
||||
import datetime as dtime
|
||||
from datetime import date, datetime
|
||||
import json
|
||||
from typing import Any
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User, Permission
|
||||
@@ -211,7 +212,7 @@ class Employee(models.Model):
|
||||
"""
|
||||
today = datetime.today()
|
||||
attendance = self.employee_attendances.filter(attendance_date=today).first()
|
||||
minimum_hour_seconds = strtime_seconds(getattr(attendance,"minimum_hour","0"))
|
||||
minimum_hour_seconds = strtime_seconds(getattr(attendance, "minimum_hour", "0"))
|
||||
at_work = 0
|
||||
forecasted_pending_hours = 0
|
||||
if attendance:
|
||||
@@ -546,3 +547,30 @@ class EmployeeNote(models.Model):
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.description}"
|
||||
|
||||
|
||||
class PolicyMultipleFile(models.Model):
|
||||
"""
|
||||
PoliciesMultipleFile model
|
||||
"""
|
||||
|
||||
attachment = models.FileField(upload_to="employee/policies")
|
||||
|
||||
|
||||
class Policy(models.Model):
|
||||
"""
|
||||
Policies model
|
||||
"""
|
||||
|
||||
title = models.CharField(max_length=50)
|
||||
body = models.TextField()
|
||||
is_visible_to_all = models.BooleanField(default=True)
|
||||
specific_employees = models.ManyToManyField(Employee, blank=True,editable=False)
|
||||
attachments = models.ManyToManyField(PolicyMultipleFile, blank=True)
|
||||
company_id = models.ManyToManyField(Company, blank=True)
|
||||
|
||||
objects = HorillaCompanyManager()
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
super().delete(*args, **kwargs)
|
||||
self.attachments.all().delete()
|
||||
|
||||
127
employee/policies.py
Normal file
127
employee/policies.py
Normal file
@@ -0,0 +1,127 @@
|
||||
"""
|
||||
policies.py
|
||||
|
||||
This module is used to write operation related to policies
|
||||
"""
|
||||
|
||||
|
||||
from django.contrib import messages
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import render
|
||||
from base.views import paginator_qry
|
||||
from employee.filters import PolicyFilter
|
||||
from employee.forms import PolicyForm
|
||||
from employee.models import Policy, PolicyMultipleFile
|
||||
from horilla.decorators import permission_required, login_required
|
||||
|
||||
|
||||
@login_required
|
||||
def view_policies(request):
|
||||
"""
|
||||
Method is used render template to view all the policy records
|
||||
"""
|
||||
policies = Policy.objects.all()
|
||||
if not request.user.has_perm("employee.view_policy"):
|
||||
policies = policies.filter(is_visible_to_all=True)
|
||||
return render(
|
||||
request,
|
||||
"policies/view_policies.html",
|
||||
{"policies": paginator_qry(policies, request.GET.get("page"))},
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required("employee.add_policy")
|
||||
def create_policy(request):
|
||||
"""
|
||||
Method is used to create/update new policy
|
||||
"""
|
||||
instance_id = request.GET.get("instance_id")
|
||||
instance = None
|
||||
if isinstance(eval(str(instance_id)), int):
|
||||
instance = Policy.objects.filter(id=instance_id).first()
|
||||
form = PolicyForm(instance=instance)
|
||||
if request.method == "POST":
|
||||
form = PolicyForm(request.POST, request.FILES, instance=instance)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(request, "Policy saved")
|
||||
return HttpResponse("<script>window.location.reload()</script>")
|
||||
return render(request, "policies/form.html", {"form": form})
|
||||
|
||||
|
||||
@login_required
|
||||
def search_policies(request):
|
||||
"""
|
||||
This method is used to search in policies
|
||||
"""
|
||||
policies = PolicyFilter(request.GET).qs
|
||||
if not request.user.has_perm("employee.view_policy"):
|
||||
policies = policies.filter(is_visible_to_all=True)
|
||||
return render(
|
||||
request,
|
||||
"policies/records.html",
|
||||
{
|
||||
"policies": paginator_qry(policies, request.GET.get("page")),
|
||||
"pd": request.GET.urlencode(),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
def view_policy(request):
|
||||
"""
|
||||
This method is used to view the policy
|
||||
"""
|
||||
instance_id = request.GET["instance_id"]
|
||||
policy = Policy.objects.filter(id=instance_id).first()
|
||||
return render(
|
||||
request,
|
||||
"policies/view_policy.html",
|
||||
{
|
||||
"policy": policy,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required("employee.change_policy")
|
||||
def add_attachment(request):
|
||||
"""
|
||||
This method is used to add attachment to policy
|
||||
"""
|
||||
files = request.FILES.getlist("files")
|
||||
policy_id = request.GET["policy_id"]
|
||||
attachments = []
|
||||
for file in files:
|
||||
attachment = PolicyMultipleFile()
|
||||
attachment.attachment = file
|
||||
attachment.save()
|
||||
attachments.append(attachment)
|
||||
policy = Policy.objects.get(id=policy_id)
|
||||
policy.attachments.add(*attachments)
|
||||
messages.success(request, "Attachments added")
|
||||
return render(request, "policies/attachments.html", {"policy": policy})
|
||||
|
||||
|
||||
@login_required
|
||||
@permission_required("employee.delete_policy")
|
||||
def remove_attachment(request):
|
||||
"""
|
||||
This method is used to remove the attachments
|
||||
"""
|
||||
ids = request.GET.getlist("ids")
|
||||
policy_id = request.GET["policy_id"]
|
||||
policy = Policy.objects.get(id=policy_id)
|
||||
PolicyMultipleFile.objects.filter(id__in=ids).delete()
|
||||
return render(request, "policies/attachments.html", {"policy": policy})
|
||||
|
||||
|
||||
@login_required
|
||||
def get_attachments(request):
|
||||
"""
|
||||
This method is used to view all the attachments inside the policy
|
||||
"""
|
||||
policy = request.GET["policy_id"]
|
||||
policy = Policy.objects.get(id=policy)
|
||||
return render(request, "policies/attachments.html", {"policy": policy})
|
||||
26
employee/templates/policies/attachments.html
Normal file
26
employee/templates/policies/attachments.html
Normal file
@@ -0,0 +1,26 @@
|
||||
{% load static %}
|
||||
<form hx-post="{% url 'add-attachment-policy' %}?policy_id={{policy.id}}" hx-target="#attachmentContainer" class="add-files-form d-flex" method="post"
|
||||
hx-encoding="multipart/form-data">
|
||||
{% for attachment in policy.attachments.all %}
|
||||
<a href="{{ attachment.attachment.url }}" rel="noopener noreferrer" target="_blank"><span
|
||||
class="oh-file-icon oh-file-icon--pdf" onmouseover="enlargeImage('{{ attachment.attachment.url }}')"
|
||||
style="width:40px;height:40px"><img src="{% static '/images/ui/minus-icon.png' %}"
|
||||
style="display:block;width:50%;height:50%"
|
||||
hx-get="{% url 'remove-attachment-policy' %}?ids={{ attachment.id }}&policy_id={{ policy.id }}"
|
||||
hx-target="#attachmentContainer"
|
||||
onclick="event.stopPropagation();event.preventDefault()" />
|
||||
</span>
|
||||
</a>
|
||||
|
||||
{% endfor %}
|
||||
{% if perms.employee.add_policy %}
|
||||
<input type="hidden" name="csrfmiddlewaretoken"/>
|
||||
<input type="file" name="files" class="d-none" multiple="true" id="addFile_18" onchange="submitForm(this)" />
|
||||
<input type="submit" class="d-none add_more_submit" value="save" />
|
||||
<label for="addFile_18" title="Add Files" onclick="console.log($(this).closest('[type=file]'));"
|
||||
style="cursor: pointer;">
|
||||
<ion-icon name="add-outline" style="font-size: 24px" role="img" class="md hydrated"
|
||||
aria-label="add outline"></ion-icon>
|
||||
</label>
|
||||
{% endif %}
|
||||
</form>
|
||||
0
employee/templates/policies/filter.html
Normal file
0
employee/templates/policies/filter.html
Normal file
7
employee/templates/policies/form.html
Normal file
7
employee/templates/policies/form.html
Normal file
@@ -0,0 +1,7 @@
|
||||
{% load i18n %}
|
||||
<form hx-post="{% url 'create-policy' %}?instance_id={{form.instance.id}}" hx-encoding="multipart/form-data">
|
||||
{{ form.as_p }}
|
||||
<div class="d-flex flex-row-reverse">
|
||||
<button type="submit" class="oh-btn oh-btn--secondary">{% trans 'Save' %}</button>
|
||||
</div>
|
||||
</form>
|
||||
34
employee/templates/policies/nav.html
Normal file
34
employee/templates/policies/nav.html
Normal file
@@ -0,0 +1,34 @@
|
||||
{% load i18n %}
|
||||
<section class="oh-wrapper oh-main__topbar" style="padding-bottom: 1rem;">
|
||||
<div class="oh-main__titlebar oh-main__titlebar--left oh-d-flex-column--resp oh-mb-3--small">
|
||||
<h1 class="oh-main__titlebar-title fw-bold">{% trans 'Policies' %}</h1>
|
||||
</div>
|
||||
|
||||
<div class="oh-main__titlebar oh-main__titlebar--right oh-d-flex-column--resp oh-mb-3--small">
|
||||
<div class="oh-input-group oh-input__search-group mr-4">
|
||||
<ion-icon name="search-outline" class="oh-input-group__icon oh-input-group__icon--left md hydrated" role="img" aria-label="search outline"></ion-icon>
|
||||
<input hx-get="{% url 'search-policies' %}" name="search" hx-trigger="keyup changed delay:.2s" hx-target="#policyContainer" type="text" placeholder="Search" style="margin-right:10px" class="oh-input oh-input__icon mr-3" autocomplete="false" aria-label="Search Input" />
|
||||
</div>
|
||||
{% include 'policies/filter.html' %}
|
||||
{% if perms.payroll.add_policyaccount %}
|
||||
<div class="oh-main__titlebar-button-container">
|
||||
<div class="oh-main__titlebar-button-container">
|
||||
<a hx-get="{% url 'create-policy' %}" hx-target="#policyModalBody" data-toggle="oh-modal-toggle" data-target="#policyModal" class="oh-btn oh-btn--secondary">
|
||||
<ion-icon name="add-outline"></ion-icon>
|
||||
{% trans 'Create' %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="oh-modal" id="policyModal" role="dialog" aria-hidden="true">
|
||||
<div class="oh-modal__dialog" style="max-width: 550px">
|
||||
<div class="oh-modal__dialog-header">
|
||||
<button type="button" class="oh-modal__close" aria-label="Close"><ion-icon name="close-outline"></ion-icon></button>
|
||||
</div>
|
||||
|
||||
<div class="oh-modal__dialog-body" id="policyModalBody"></div>
|
||||
</div>
|
||||
</div>
|
||||
98
employee/templates/policies/records.html
Normal file
98
employee/templates/policies/records.html
Normal file
@@ -0,0 +1,98 @@
|
||||
{% load i18n %}
|
||||
<div class="oh-faq-cards">
|
||||
{% for policy in policies %}
|
||||
<div class="oh-faq-card">
|
||||
<h3 class="oh-faq-card__title d-flex justify-content-between">
|
||||
<span>
|
||||
{% if policy.is_visible_to_all %}
|
||||
<span class="oh-dot oh-dot--small me-1" style="background-color:yellowgreen"></span>
|
||||
{% else %}
|
||||
<span class="oh-dot oh-dot--small me-1" style="background-color:gray"></span>
|
||||
{% endif %}
|
||||
{{ policy.title }}</span>
|
||||
<div>
|
||||
{% if perms.employee.change_policiy %}
|
||||
<a hx-get="{% url 'create-policy' %}?instance_id={{ policy.id }}" hx-target="#policyModalBody" data-toggle="oh-modal-toggle" data-target="#policyModal" title="Edit" style="cursor: pointer;"><ion-icon name="create-outline" role="img" class="md hydrated" aria-label="copy outline"></ion-icon></a>
|
||||
{% endif %}
|
||||
{% if perms.employee.delete_policy %}
|
||||
<a href="/recruitment/delete-mail-template/?ids=1" class="text-danger" style="cursor: pointer;" onclick="return confirm('Do you want to delete this policy?')" title="Delete"><ion-icon name="trash-outline" role="img" class="md hydrated" aria-label="trash outline"></ion-icon></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</h3>
|
||||
<p class="oh-card__footer--border-top">
|
||||
<div style="max-height: 350px;overflow: hidden;" class="truncated-text">{{ policy.body|safe }}</div>
|
||||
</p>
|
||||
{% if perms.recruitment.change_recruitmentmailtemplate %}
|
||||
<a hx-get="{% url 'view-policy' %}?instance_id={{ policy.id }}" hx-target="#policyModalBody" data-toggle="oh-modal-toggle" data-target="#policyModal" class="oh-btn oh-btn--secondary oh-btn--block">{% trans 'View policy' %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="oh-wrapper w-100">
|
||||
<div class="oh-pagination">
|
||||
<span class="oh-pagination__page" data-toggle="modal" data-target="#policyContainer">{% trans 'Page' %} {{ policies.number }} {% trans 'of' %} {{ policies.paginator.num_pages }}.</span>
|
||||
|
||||
<nav class="oh-pagination__nav">
|
||||
<div class="oh-pagination__input-container me-3">
|
||||
<span class="oh-pagination__label me-1">{% trans 'Page' %}</span>
|
||||
|
||||
<input type="number" name="page" class="oh-pagination__input" value="{{ policies.number }}" hx-get="{% url 'search-policies' %}?{{ pd }}" hx-target="#policyContainer" min="1" />
|
||||
<span class="oh-pagination__label">{% trans 'of' %} {{ policies.paginator.num_pages }}</span>
|
||||
</div>
|
||||
|
||||
<ul class="oh-pagination__items">
|
||||
{% if policies.has_previous %}
|
||||
<li class="oh-pagination__item oh-pagination__item--wide">
|
||||
<a hx-target="#policyContainer" hx-get="{% url 'search-policies' %}?{{ pd }}&page=1" class="oh-pagination__link">{% trans 'First' %}</a>
|
||||
</li>
|
||||
<li class="oh-pagination__item oh-pagination__item--wide">
|
||||
<a hx-target="#policyContainer" hx-get="{% url 'search-policies' %}?{{ pd }}&page={{ policies.previous_page_number }}" class="oh-pagination__link">{% trans 'Previous' %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if policies.has_next %}
|
||||
<li class="oh-pagination__item oh-pagination__item--wide">
|
||||
<a hx-target="#policyContainer" hx-get="{% url 'search-policies' %}?{{ pd }}&page={{ policies.next_page_number }}" class="oh-pagination__link">{% trans 'Next' %}</a>
|
||||
</li>
|
||||
<li class="oh-pagination__item oh-pagination__item--wide">
|
||||
<a hx-target="#policyContainer" hx-get="{% url 'search-policies' %}?{{ pd }}&page={{ policies.paginator.num_pages }}" class="oh-pagination__link">{% trans 'Last' %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function submitForm(elem) {
|
||||
$(elem).siblings('.add_more_submit').click()
|
||||
}
|
||||
|
||||
function enlargeImage(src) {
|
||||
var enlargeImageContainer = $('#enlargeImageContainer')
|
||||
enlargeImageContainer.empty()
|
||||
style = 'width:100%; height:90%; box-shadow: 0 10px 10px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.2); background:white'
|
||||
var enlargedImage = $('<iframe>').attr({ src: src, style: style })
|
||||
var name = $('<span>').text(src.split('/').pop().replace(/_/g, ' '))
|
||||
enlargeImageContainer.append(enlargedImage)
|
||||
enlargeImageContainer.append(name)
|
||||
setTimeout(function () {
|
||||
enlargeImageContainer.show()
|
||||
|
||||
const iframe = document.querySelector('iframe').contentWindow
|
||||
var iframe_document = iframe.document
|
||||
iframe_image = iframe_document.getElementsByTagName('img')[0]
|
||||
$(iframe_image).attr('style', 'width:100%; height:100%;')
|
||||
}, 100)
|
||||
}
|
||||
|
||||
function hideEnlargeImage() {
|
||||
var enlargeImageContainer = $('#enlargeImageContainer')
|
||||
enlargeImageContainer.empty()
|
||||
}
|
||||
|
||||
$(document).on('click', function (event) {
|
||||
if (!$(event.target).closest('#enlargeImageContainer').length) {
|
||||
hideEnlargeImage()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
7
employee/templates/policies/view_policies.html
Normal file
7
employee/templates/policies/view_policies.html
Normal file
@@ -0,0 +1,7 @@
|
||||
{% extends 'index.html' %}
|
||||
{% block content %}
|
||||
{% include 'policies/nav.html' %}
|
||||
<div class="oh-wrapper" id="policyContainer">
|
||||
{% include 'policies/records.html' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
15
employee/templates/policies/view_policy.html
Normal file
15
employee/templates/policies/view_policy.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<style>
|
||||
#enlargeImageContainer {
|
||||
position: absolute;
|
||||
left: -300px;
|
||||
top: 100px;
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
}
|
||||
</style>
|
||||
<h2>{{ policy.title }}</h2>
|
||||
<p class="oh-card__footer--border-top"></p>
|
||||
{{ policy.body|safe }}
|
||||
<div id="attachmentContainer" class="d-flex" hx-get="{% url 'get-attachments-policy' %}?policy_id={{ policy.id }}" hx-trigger="load"></div>
|
||||
|
||||
<div id="enlargeImageContainer"></div>
|
||||
@@ -4,7 +4,7 @@ urls.py
|
||||
This module is used to map url path with view methods.
|
||||
"""
|
||||
from django.urls import path
|
||||
from employee import not_in_out_dashboard, views
|
||||
from employee import not_in_out_dashboard, policies, views
|
||||
from employee.models import Employee
|
||||
|
||||
urlpatterns = [
|
||||
@@ -188,10 +188,22 @@ urlpatterns = [
|
||||
path("note-tab/<int:emp_id>", views.note_tab, name="note-tab"),
|
||||
path("add-employee-note/<int:emp_id>/", views.add_note, name="add-employee-note"),
|
||||
path("add-employee-note-post", views.add_note, name="add-employee-note-post"),
|
||||
path("employee-note-update/<int:note_id>/", views.employee_note_update, name="employee-note-update"),
|
||||
path("employee-note-delete/<int:note_id>/", views.employee_note_delete, name="employee-note-delete"),
|
||||
path(
|
||||
"employee-note-update/<int:note_id>/",
|
||||
views.employee_note_update,
|
||||
name="employee-note-update",
|
||||
),
|
||||
path(
|
||||
"employee-note-delete/<int:note_id>/",
|
||||
views.employee_note_delete,
|
||||
name="employee-note-delete",
|
||||
),
|
||||
path("attendance-tab/<int:emp_id>", views.attendance_tab, name="attendance-tab"),
|
||||
path("allowances-deductions-tab/<int:emp_id>", views.allowances_deductions_tab, name="allowances-deductions-tab"),
|
||||
path(
|
||||
"allowances-deductions-tab/<int:emp_id>",
|
||||
views.allowances_deductions_tab,
|
||||
name="allowances-deductions-tab",
|
||||
),
|
||||
path("shift-tab/<int:emp_id>", views.shift_tab, name="shift-tab"),
|
||||
path(
|
||||
"contract-tab/<int:obj_id>",
|
||||
@@ -207,7 +219,26 @@ urlpatterns = [
|
||||
),
|
||||
path("not-in-yet/", not_in_out_dashboard.not_in_yet, name="not-in-yet"),
|
||||
path("not-out-yet/", not_in_out_dashboard.not_out_yet, name="not-out-yet"),
|
||||
path("send-mail/<int:emp_id>/", not_in_out_dashboard.send_mail, name="send-mail-employee"),
|
||||
path("send-mail", not_in_out_dashboard.send_mail_to_employee, name="send-mail-to-employee"),
|
||||
path("get-template/<int:emp_id>/", not_in_out_dashboard.get_template, name="get-template-employee"),
|
||||
path(
|
||||
"send-mail/<int:emp_id>/",
|
||||
not_in_out_dashboard.send_mail,
|
||||
name="send-mail-employee",
|
||||
),
|
||||
path(
|
||||
"send-mail",
|
||||
not_in_out_dashboard.send_mail_to_employee,
|
||||
name="send-mail-to-employee",
|
||||
),
|
||||
path(
|
||||
"get-template/<int:emp_id>/",
|
||||
not_in_out_dashboard.get_template,
|
||||
name="get-template-employee",
|
||||
),
|
||||
path("view-policies", policies.view_policies, name="view-policies"),
|
||||
path("search-policies", policies.search_policies, name="search-policies"),
|
||||
path("create-policy", policies.create_policy, name="create-policy"),
|
||||
path("view-policy", policies.view_policy, name="view-policy"),
|
||||
path("add-attachment-policy", policies.add_attachment, name="add-attachment-policy"),
|
||||
path("remove-attachment-policy", policies.remove_attachment, name="remove-attachment-policy"),
|
||||
path("get-attachments-policy", policies.get_attachments, name="get-attachments-policy"),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user