[UPDT] PAYROLL: Comment section updation in reimbursement,leave and bonus encashment request and updation with multiple file uploading comment both card and list view
This commit is contained in:
@@ -3,17 +3,20 @@ forms.py
|
||||
"""
|
||||
|
||||
from datetime import date
|
||||
from typing import Any
|
||||
from django import forms
|
||||
from django.forms import widgets
|
||||
from django.utils.translation import gettext_lazy as trans
|
||||
from django.template.loader import render_to_string
|
||||
from base import thread_local_middleware
|
||||
from base.forms import Form
|
||||
from employee.forms import MultipleFileField
|
||||
from employee.models import Employee
|
||||
from payroll.context_processors import get_active_employees
|
||||
from payroll.models.models import (
|
||||
EncashmentGeneralSettings,
|
||||
PayrollGeneralSetting,
|
||||
ReimbursementFile,
|
||||
ReimbursementrequestComment,
|
||||
WorkRecord,
|
||||
)
|
||||
@@ -176,7 +179,48 @@ class ReimbursementRequestCommentForm(ModelForm):
|
||||
|
||||
model = ReimbursementrequestComment
|
||||
fields = ("comment",)
|
||||
exclude = ["is_active"]
|
||||
|
||||
|
||||
class reimbursementCommentForm(ModelForm):
|
||||
"""
|
||||
Reimbursement request comment model form
|
||||
"""
|
||||
|
||||
verbose_name = "Add Comment"
|
||||
|
||||
class Meta:
|
||||
model = ReimbursementrequestComment
|
||||
fields = "__all__"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields["files"] = MultipleFileField(label="files")
|
||||
self.fields["files"].required = False
|
||||
|
||||
def as_p(self):
|
||||
"""
|
||||
Render the form fields as HTML table rows with Bootstrap styling.
|
||||
"""
|
||||
context = {"form": self}
|
||||
table_html = render_to_string("common_form.html", context)
|
||||
return table_html
|
||||
|
||||
def save(self, commit: bool = ...) -> Any:
|
||||
multiple_files_ids = []
|
||||
files = None
|
||||
if self.files.getlist("files"):
|
||||
files = self.files.getlist("files")
|
||||
self.instance.attachemnt = files[0]
|
||||
multiple_files_ids = []
|
||||
for attachemnt in files:
|
||||
file_instance = ReimbursementFile()
|
||||
file_instance.file = attachemnt
|
||||
file_instance.save()
|
||||
multiple_files_ids.append(file_instance.pk)
|
||||
instance = super().save(commit)
|
||||
if commit:
|
||||
instance.files.add(*multiple_files_ids)
|
||||
return instance, files
|
||||
|
||||
|
||||
class EncashmentGeneralSettingsForm(ModelForm):
|
||||
|
||||
@@ -1757,6 +1757,11 @@ except:
|
||||
pass
|
||||
|
||||
|
||||
class ReimbursementFile(models.Model):
|
||||
file = models.FileField(upload_to="payroll/request_files")
|
||||
objects = models.Manager()
|
||||
|
||||
|
||||
class ReimbursementrequestComment(HorillaModel):
|
||||
"""
|
||||
ReimbursementRequestComment Model
|
||||
@@ -1765,6 +1770,12 @@ class ReimbursementrequestComment(HorillaModel):
|
||||
request_id = models.ForeignKey(Reimbursement, on_delete=models.CASCADE)
|
||||
employee_id = models.ForeignKey(Employee, on_delete=models.CASCADE)
|
||||
comment = models.TextField(null=True, verbose_name=_("Comment"), max_length=255)
|
||||
files = models.ManyToManyField(ReimbursementFile, blank=True)
|
||||
created_at = models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
verbose_name=_("Created At"),
|
||||
null=True,
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.comment}"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% load i18n %}
|
||||
<div class="oh-main__titlebar-button-container">
|
||||
<div class="oh-dropdown" x-data="{open: false}">
|
||||
<button class="oh-btn ml-2" @click="open = !open">
|
||||
<button class="oh-btn ml-2" @click="open = !open" onclick="event.preventDefault()">
|
||||
<ion-icon name="filter" class="mr-1"></ion-icon>{% trans "Filter" %}
|
||||
</button>
|
||||
<div
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
{% load i18n static %}
|
||||
<style>
|
||||
#enlargeImageContainer {
|
||||
position: absolute;
|
||||
left: -300px;
|
||||
top: 100px;
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
}
|
||||
</style>
|
||||
|
||||
{% if messages %}
|
||||
<div class="oh-alert-container">
|
||||
{% for message in messages %}
|
||||
<div class="oh-alert oh-alert--animated {{message.tags}}">{{ message }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<script>
|
||||
setTimeout(() => {
|
||||
$(".oh-modal__close").click();
|
||||
}, 1000);
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
<div class="oh-activity-sidebar__header">
|
||||
<a
|
||||
style="cursor: pointer;"
|
||||
onclick="$('.oh-activity-sidebar--show').removeClass('oh-activity-sidebar--show');">
|
||||
<ion-icon
|
||||
name="chevron-forward-outline"
|
||||
class="oh-activity-sidebar__header-icon me-2 oh-activity-sidebar__close"
|
||||
data-target="#activitySidebar"
|
||||
></ion-icon>
|
||||
</a>
|
||||
<span class="oh-activity-sidebar__title"> {% trans "Comments" %} </span>
|
||||
</div>
|
||||
|
||||
<form method="post"
|
||||
hx-target="#commentContainer"
|
||||
hx-post="{% url 'payroll-request-add-comment' request_id %}" id="commentForm">
|
||||
{% csrf_token %}
|
||||
|
||||
<div>
|
||||
<input type="text" name="comment" id="commentInput" class="oh-input w-100" placeholder="Comment here">
|
||||
<button type="submit" id="commentButton" class="oh-btn oh-btn--secondary mt-2 mr-0 oh-btn--w-100-resp" style="display: none;">
|
||||
{% trans "Comment" %}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="oh-inner-sidebar-content__footer"></div>
|
||||
</form>
|
||||
|
||||
|
||||
{% if comments %}
|
||||
<ol class="oh-activity-sidebar__qa-list" role="list">
|
||||
{% for comment in comments %}
|
||||
<li class="oh-activity-sidebar__qa-item">
|
||||
<span class="oh-activity-sidebar__q">{{ comment.comment }}
|
||||
<span class="float-end" title="Delete" hx-get='{% url "payroll-request-delete-comment" comment.id %}' data-target="#activitySidebar" hx-swap="innerHTML" hx-target="#commentContainer">
|
||||
<ion-icon name="close-outline" style="font-size: 24px" role="img" class="md hydrated" aria-label="close outline"></ion-icon></span>
|
||||
</span>
|
||||
|
||||
<div class="d-flex mt-2 mb-2">
|
||||
{% for file in comment.files.all %}
|
||||
<a
|
||||
href="{{ file.file.url }}"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
><span
|
||||
class="oh-file-icon oh-file-icon--pdf"
|
||||
onmouseover="enlargeImage('{{ file.file.url }}',$(this))"
|
||||
style="width: 40px; height: 40px"
|
||||
><img
|
||||
src="{% static 'images/ui/minus-icon.png' %}"
|
||||
style="display: block; width: 50%; height: 50%"
|
||||
hx-get="{% url 'delete-reimbursement-comment-file' %}?ids={{ file.id }}&payroll_id={{ request_id }}"
|
||||
hx-target="#commentContainer"
|
||||
onclick="event.stopPropagation();event.preventDefault()" /></span
|
||||
></a>
|
||||
{% endfor %}
|
||||
|
||||
<form
|
||||
hx-post="{% url 'payroll-request-view-comment' comment.request_id.id %}?comment_id={{ comment.id }}"
|
||||
class="add-files-form"
|
||||
hx-encoding="multipart/form-data"
|
||||
data-target="#activitySidebar" hx-swap="innerHTML" hx-target="#commentContainer"
|
||||
|
||||
>
|
||||
{% csrf_token %}
|
||||
<label for="addFile_{{comment.id}}" title="Add Files"
|
||||
><ion-icon
|
||||
name="add-outline"
|
||||
style="font-size: 24px"
|
||||
role="img"
|
||||
class="md hydrated"
|
||||
aria-label="add outline"
|
||||
></ion-icon
|
||||
></label>
|
||||
<input
|
||||
type="file"
|
||||
name="files"
|
||||
class="d-none"
|
||||
multiple="true"
|
||||
id="addFile_{{comment.id}}"
|
||||
onchange="submitForm(this)"
|
||||
/>
|
||||
<input
|
||||
type="submit"
|
||||
class="d-none add_more_submit"
|
||||
value="save"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
<span class="oh-activity-sidebar__a">
|
||||
{% trans 'by' %}
|
||||
<img
|
||||
src="{{ note.note_by.get_avatar }}"
|
||||
style="width: 1.5em; border-radius: 100%"
|
||||
/>
|
||||
{{ comment.employee_id.get_full_name }} @ {{comment.request_id.employee_id.get_full_name }}
|
||||
{% trans "'s reimbursement request" %}
|
||||
</span>
|
||||
<div style="width: 50%">
|
||||
<div id="enlargeImageContainer" class="enlargeImageContainer"></div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
{% endfor %}
|
||||
</ol>
|
||||
{% else %}
|
||||
<div class="oh-timeoff-modal__profile-content">
|
||||
<div class="oh-404">
|
||||
<div class="">
|
||||
<span class="oh-timeoff-title fw-bold" style="display: block"
|
||||
>{% trans "There are no comments to show." %}</span
|
||||
>
|
||||
<img
|
||||
style="display: block; width: 100px; margin: 20px auto"
|
||||
src="/static/images/ui/comment.png"
|
||||
class=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- start of comment modal -->
|
||||
<div
|
||||
class="oh-modal"
|
||||
id="shiftcommentModal"
|
||||
role="dialog"
|
||||
aria-labelledby="emptagModal"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="oh-modal__dialog" id="shiftRequestCommentForm">
|
||||
</div>
|
||||
</div>
|
||||
<!-- end of comment modal -->
|
||||
|
||||
|
||||
<script>
|
||||
// Get references to the input field and comment button
|
||||
const commentInput = document.getElementById('commentInput');
|
||||
const commentButton = document.getElementById('commentButton');
|
||||
|
||||
// Add event listener to the input field
|
||||
commentInput.addEventListener('input', function() {
|
||||
// Show the comment button if the input field is not empty, hide it otherwise
|
||||
if (commentInput.value.trim() !== '') {
|
||||
commentButton.style.display = 'inline';
|
||||
} else {
|
||||
commentButton.style.display = 'none';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -110,6 +110,7 @@
|
||||
>
|
||||
{% trans "Description" %}
|
||||
</div>
|
||||
<div class="oh-sticky-table__th" style="width:115px;">{% trans "Comment" %}</div>
|
||||
<div class="oh-sticky-table__th"> {% trans "Actions" %} </div>
|
||||
<div class="oh-sticky-table__th oh-sticky-table__right">{% trans "Confirmation" %}</div>
|
||||
</div>
|
||||
@@ -159,6 +160,12 @@
|
||||
</div>
|
||||
<div data-cell-index="5" class="oh-sticky-table__td">
|
||||
{{req.description}}
|
||||
</div>
|
||||
<div class="oh-sticky-table__td" onclick="event.stopPropagation();">
|
||||
<button type="button" hx-get="{% url 'payroll-request-view-comment' req.id %}" hx-target="#commentContainer"
|
||||
data-target = '#activitySidebar' title="View Comment" class="oh-btn oh-btn--light oh-activity-sidebar__open w-100" style="flex: 1 0 auto; width:20px;height: 40.68px; padding: 0;" onclick="event.stopPropagation()">
|
||||
<ion-icon name="newspaper-outline" role="img" class="md hydrated" aria-label="newspaper outline"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oh-sticky-table__td">
|
||||
<div class="oh-btn-group">
|
||||
@@ -394,6 +401,7 @@
|
||||
>
|
||||
{% trans "Description" %}
|
||||
</div>
|
||||
<div class="oh-sticky-table__th" style="width:115px;">{% trans "Comment" %}</div>
|
||||
<div class="oh-sticky-table__th"> {% trans "Actions" %} </div>
|
||||
<div class="oh-sticky-table__th oh-sticky-table__right" style="width:180px">{% trans "Confirmation" %}</div>
|
||||
</div>
|
||||
@@ -438,7 +446,7 @@
|
||||
<div data-cell-index="13" class="oh-sticky-table__td">
|
||||
<input type="number" required
|
||||
default="0" min="0" placeholder="Amount"
|
||||
name="amount" class="w-50"{% if req.status == "approved" %}disabled{% endif %} {% if req.amount %}
|
||||
name="amount" class="w-75"{% if req.status == "approved" %}disabled{% endif %} {% if req.amount %}
|
||||
value="{{req.amount}}"{% endif %} />
|
||||
</div>
|
||||
<div data-cell-index="14" class="oh-sticky-table__td">
|
||||
@@ -455,7 +463,14 @@
|
||||
</div>
|
||||
<div data-cell-index="18" class="oh-sticky-table__td">
|
||||
{{req.description}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__td" onclick="event.stopPropagation();">
|
||||
<button type="button" hx-get="{% url 'payroll-request-view-comment' req.id %}" hx-target="#commentContainer"
|
||||
data-target = '#activitySidebar' title="View Comment" class="oh-btn oh-btn--light oh-activity-sidebar__open w-100" style="flex: 1 0 auto; width:20px;height: 40.68px; padding: 0;" onclick="event.stopPropagation()">
|
||||
<ion-icon name="newspaper-outline" role="img" class="md hydrated" aria-label="newspaper outline"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="oh-sticky-table__td">
|
||||
<div class="oh-btn-group">
|
||||
{% if perms.payroll.change_reimbursement or request.user %}
|
||||
@@ -684,6 +699,7 @@
|
||||
>
|
||||
{% trans "Description" %}
|
||||
</div>
|
||||
<div class="oh-sticky-table__th" style="width:115px;">{% trans "Comment" %}</div>
|
||||
<div class="oh-sticky-table__th"> {% trans "Actions" %} </div>
|
||||
<div class="oh-sticky-table__th oh-sticky-table__right" style="width:180px"> {% trans "Confirmation" %} </div>
|
||||
</div>
|
||||
@@ -728,7 +744,7 @@
|
||||
<div data-cell-index="23" class="oh-sticky-table__td">
|
||||
<input type="number" required
|
||||
default="0" min="0" placeholder="Amount"
|
||||
name="amount" class="w-50"{% if req.status == "approved" %}disabled{% endif %} {% if req.amount %}
|
||||
name="amount" class="w-75"{% if req.status == "approved" %}disabled{% endif %} {% if req.amount %}
|
||||
value="{{req.amount}}"{% endif %} />
|
||||
</div>
|
||||
<div data-cell-index="24" class="oh-sticky-table__td">
|
||||
@@ -739,7 +755,13 @@
|
||||
</div>
|
||||
<div data-cell-index="26" class="oh-sticky-table__td">
|
||||
{{req.description}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="oh-sticky-table__td" onclick="event.stopPropagation();">
|
||||
<button type="button" hx-get="{% url 'payroll-request-view-comment' req.id %}" hx-target="#commentContainer"
|
||||
data-target = '#activitySidebar' title="View Comment" class="oh-btn oh-btn--light oh-activity-sidebar__open w-100" style="flex: 1 0 auto; width:20px;height: 40.68px; padding: 0;" onclick="event.stopPropagation()">
|
||||
<ion-icon name="newspaper-outline" role="img" class="md hydrated" aria-label="newspaper outline"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oh-sticky-table__td">
|
||||
<div class="oh-btn-group">
|
||||
{% if perms.payroll.change_reimbursement or request.user %}
|
||||
@@ -908,55 +930,16 @@
|
||||
</div>
|
||||
<!-- end of tabs -->
|
||||
|
||||
<!-- Activty side bar for comment section-->
|
||||
|
||||
<!-- start of comment modal -->
|
||||
<div
|
||||
class="oh-modal"
|
||||
id="shiftcommentModal"
|
||||
role="dialog"
|
||||
aria-labelledby="emptagModal"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="oh-modal__dialog">
|
||||
<div class="oh-modal__dialog-header">
|
||||
<h2 class="oh-modal__dialog-title" id="createModalTitle">
|
||||
{% trans "Add Comment" %}
|
||||
</h2>
|
||||
<button class="oh-modal__close" aria-label="Close">
|
||||
<ion-icon name="close-outline"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="oh-modal__dialog-body"
|
||||
id="shiftRequestCommentForm"
|
||||
></div>
|
||||
<div class="oh-activity-sidebar" id="activitySidebar" style="z-index:1000;">
|
||||
|
||||
<div class="oh-activity-sidebar__body" id="commentContainer">
|
||||
</div>
|
||||
</div>
|
||||
<!-- end of comment modal -->
|
||||
|
||||
<div
|
||||
class="oh-modal"
|
||||
style="z-index: 60"
|
||||
id="shiftRequestDetailModal"
|
||||
role="dialog"
|
||||
aria-labelledby="shiftRequestDetailModal"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="oh-modal__dialog">
|
||||
<div class="oh-modal__dialog-header">
|
||||
<h2 class="oh-modal__dialog-title" id="">
|
||||
{% trans "Details" %}
|
||||
</h2>
|
||||
<button class="oh-modal__close" aria-label="Close">
|
||||
<ion-icon name="close-outline"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="oh-modal__dialog-body oh-modal__dialog-relative"
|
||||
id="shiftRequestDetailTarget"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End of Activty side bar for comment section-->
|
||||
|
||||
|
||||
<script>
|
||||
function reimbursementConfirm(params, target, approve = false) {
|
||||
|
||||
@@ -75,6 +75,8 @@
|
||||
hx-get="{% url 'create-reimbursement' %}?instance_id={{ req.id }}"
|
||||
hx-target="#objectCreateModalTarget"
|
||||
class="mr-2"
|
||||
style="cursor:pointer;"
|
||||
title='{% trans "Update" %}'
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#objectCreateModal"
|
||||
><ion-icon
|
||||
@@ -87,6 +89,7 @@
|
||||
{% endif %}
|
||||
{% if perms.payroll.delete_reimbursement %}
|
||||
<a href="{% url "delete-reimbursement" %}?ids={{req.id}}" onclick="return confirm('Do you want to delete this record?')"
|
||||
title='{% trans "Delete" %}'
|
||||
><ion-icon
|
||||
class="text-danger md hydrated"
|
||||
name="trash-outline"
|
||||
@@ -129,25 +132,12 @@
|
||||
<div class="mb-2">
|
||||
<i
|
||||
><a
|
||||
hx-target="#shiftRequestCommentForm"
|
||||
hx-get="{% url 'payroll-request-add-comment' req.id %}"
|
||||
class="text-primary"
|
||||
hx-swap="innerHTML"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#shiftcommentModal"
|
||||
style="cursor: pointer"
|
||||
>{% trans 'Add Comments' %}</a
|
||||
>
|
||||
 ,
|
||||
|
||||
<a
|
||||
hx-target="#shiftRequestDetailTarget"
|
||||
hx-get="{% url 'payroll-request-view-comment' req.id %}"
|
||||
class="text-primary"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#shiftRequestDetailModal"
|
||||
hx-target="#commentContainer"
|
||||
data-target = '#activitySidebar'
|
||||
class="text-primary fw-bold oh-activity-sidebar__open w-100"
|
||||
style="cursor: pointer"
|
||||
>{% trans 'View Comments' %}</a
|
||||
>{% trans 'Comments' %}</a
|
||||
></i
|
||||
>
|
||||
</div>
|
||||
@@ -371,6 +361,8 @@
|
||||
hx-get="{% url 'create-reimbursement' %}?instance_id={{ req.id }}"
|
||||
hx-target="#objectCreateModalTarget"
|
||||
class="mr-2"
|
||||
style="cursor:pointer;"
|
||||
title='{% trans "Update" %}'
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#objectCreateModal"
|
||||
><ion-icon
|
||||
@@ -383,6 +375,7 @@
|
||||
{% endif %}
|
||||
{% if perms.payroll.delete_reimbursement %}
|
||||
<a href="{% url "delete-reimbursement" %}?ids={{req.id}}" onclick="return confirm('Do you want to delete this record?')"
|
||||
title='{% trans "Delete" %}'
|
||||
><ion-icon
|
||||
class="text-danger md hydrated"
|
||||
name="trash-outline"
|
||||
@@ -424,25 +417,12 @@
|
||||
<div class="mb-2">
|
||||
<i
|
||||
><a
|
||||
hx-target="#shiftRequestCommentForm"
|
||||
hx-get="{% url 'payroll-request-add-comment' req.id %}"
|
||||
class="text-primary"
|
||||
hx-swap="innerHTML"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#shiftcommentModal"
|
||||
style="cursor: pointer"
|
||||
>{% trans 'Add Comments' %}</a
|
||||
>
|
||||
 ,
|
||||
|
||||
<a
|
||||
hx-target="#shiftRequestDetailTarget"
|
||||
hx-target="#commentContainer"
|
||||
hx-get="{% url 'payroll-request-view-comment' req.id %}"
|
||||
class="text-primary"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#shiftRequestDetailModal"
|
||||
class="text-primary fw-bold oh-activity-sidebar__open w-100"
|
||||
data-target = '#activitySidebar'
|
||||
style="cursor: pointer"
|
||||
>{% trans 'View Comments' %}</a
|
||||
>{% trans 'Comments' %}</a
|
||||
></i
|
||||
>
|
||||
</div>
|
||||
@@ -664,6 +644,8 @@
|
||||
hx-get="{% url 'create-reimbursement' %}?instance_id={{ req.id }}"
|
||||
hx-target="#objectCreateModalTarget"
|
||||
class="mr-2"
|
||||
style="cursor:pointer;"
|
||||
title='{% trans "Update" %}'
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#objectCreateModal"
|
||||
><ion-icon
|
||||
@@ -676,7 +658,7 @@
|
||||
{% endif %}
|
||||
{% if perms.payroll.delete_reimbursement %}
|
||||
<a href="{% url "delete-reimbursement" %}?ids={{req.id}}" onclick="return confirm('Do you want to delete this record?')"
|
||||
><ion-icon
|
||||
title='{% trans "Delete" %}'><ion-icon
|
||||
class="text-danger md hydrated"
|
||||
name="trash-outline"
|
||||
role="img"
|
||||
@@ -717,25 +699,12 @@
|
||||
<div class="mb-2">
|
||||
<i
|
||||
><a
|
||||
hx-target="#shiftRequestCommentForm"
|
||||
hx-get="{% url 'payroll-request-add-comment' req.id %}"
|
||||
class="text-primary"
|
||||
hx-swap="innerHTML"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#shiftcommentModal"
|
||||
style="cursor: pointer"
|
||||
>{% trans 'Add Comments' %}</a
|
||||
>
|
||||
 ,
|
||||
|
||||
<a
|
||||
hx-target="#shiftRequestDetailTarget"
|
||||
hx-target="#commentContainer"
|
||||
hx-get="{% url 'payroll-request-view-comment' req.id %}"
|
||||
class="text-primary"
|
||||
data-toggle="oh-modal-toggle"
|
||||
data-target="#shiftRequestDetailModal"
|
||||
class="text-primary fw-bold oh-activity-sidebar__open w-100"
|
||||
data-target = '#activitySidebar'
|
||||
style="cursor: pointer"
|
||||
>{% trans 'View Comments' %}</a
|
||||
>{% trans 'Comments' %}</a
|
||||
></i
|
||||
>
|
||||
</div>
|
||||
@@ -936,55 +905,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- start of comment modal -->
|
||||
<div
|
||||
class="oh-modal"
|
||||
id="shiftcommentModal"
|
||||
role="dialog"
|
||||
aria-labelledby="emptagModal"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="oh-modal__dialog">
|
||||
<div class="oh-modal__dialog-header">
|
||||
<h2 class="oh-modal__dialog-title" id="createModalTitle">
|
||||
{% trans "Add Comment" %}
|
||||
</h2>
|
||||
<button class="oh-modal__close" aria-label="Close">
|
||||
<ion-icon name="close-outline"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="oh-modal__dialog-body"
|
||||
id="shiftRequestCommentForm"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end of comment modal -->
|
||||
<!-- Activty side bar for comment section-->
|
||||
|
||||
<div
|
||||
class="oh-modal"
|
||||
style="z-index: 60"
|
||||
id="shiftRequestDetailModal"
|
||||
role="dialog"
|
||||
aria-labelledby="shiftRequestDetailModal"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="oh-modal__dialog">
|
||||
<div class="oh-modal__dialog-header">
|
||||
<h2 class="oh-modal__dialog-title" id="">
|
||||
{% trans "Details" %}
|
||||
</h2>
|
||||
<button class="oh-modal__close" aria-label="Close">
|
||||
<ion-icon name="close-outline"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="oh-modal__dialog-body oh-modal__dialog-relative"
|
||||
id="shiftRequestDetailTarget"
|
||||
></div>
|
||||
<div class="oh-activity-sidebar" id="activitySidebar" style="z-index:1000;">
|
||||
|
||||
<div class="oh-activity-sidebar__body" id="commentContainer">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- End of Activty side bar for comment section-->
|
||||
|
||||
|
||||
<script>
|
||||
function reimbursementConfirm(params, target, approve = false) {
|
||||
Swal.fire({
|
||||
|
||||
@@ -54,6 +54,14 @@
|
||||
<div class="oh-modal__dialog-body" id="reimbursementAttachementModalBody"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="oh-activity-sidebar" id="activitySidebar" style="z-index:1000;">
|
||||
|
||||
<div class="oh-activity-sidebar__body" id="commentContainer">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function reimbursementConfirm(params, target, approve = false) {
|
||||
Swal.fire({
|
||||
@@ -79,5 +87,42 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
// This lines is used to set default selected stage for exits lines
|
||||
|
||||
function enlargeImage(src,$element) {
|
||||
$(".enlargeImageContainer").empty()
|
||||
var enlargeImageContainer = $element.parents().closest("li").find(".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()
|
||||
}
|
||||
})
|
||||
function submitForm(elem) {
|
||||
$(elem).siblings(".add_more_submit").click();
|
||||
}
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -157,6 +157,11 @@ urlpatterns = [
|
||||
views.delete_payrollrequest_comment,
|
||||
name="payroll-request-delete-comment",
|
||||
),
|
||||
path(
|
||||
"delete-reimbursement-comment-file/",
|
||||
views.delete_reimbursement_comment_file,
|
||||
name="delete-reimbursement-comment-file",
|
||||
),
|
||||
path(
|
||||
"initial-notice-period",
|
||||
views.initial_notice_period,
|
||||
|
||||
@@ -29,6 +29,7 @@ from payroll.models.models import (
|
||||
PayrollGeneralSetting,
|
||||
Payslip,
|
||||
Reimbursement,
|
||||
ReimbursementFile,
|
||||
ReimbursementrequestComment,
|
||||
WorkRecord,
|
||||
Contract,
|
||||
@@ -1487,30 +1488,70 @@ def create_payrollrequest_comment(request, payroll_id):
|
||||
form.instance.employee_id = emp
|
||||
form.instance.request_id = payroll
|
||||
form.save()
|
||||
comments = ReimbursementrequestComment.objects.filter(
|
||||
request_id=payroll_id
|
||||
).order_by("-created_at")
|
||||
no_comments = False
|
||||
if not comments.exists():
|
||||
no_comments = True
|
||||
form = ReimbursementRequestCommentForm(
|
||||
initial={"employee_id": emp.id, "request_id": payroll_id}
|
||||
)
|
||||
messages.success(request, _("Comment added successfully!"))
|
||||
|
||||
if request.user.employee_get.id == payroll.employee_id.id:
|
||||
rec = (
|
||||
payroll.employee_id.employee_work_info.reporting_manager_id.employee_user_id
|
||||
)
|
||||
notify.send(
|
||||
request.user.employee_get,
|
||||
recipient=rec,
|
||||
verb=f"{payroll.employee_id}'s reimbursement request has received a comment.",
|
||||
verb_ar=f"تلقى طلب استرداد نفقات {payroll.employee_id} تعليقًا.",
|
||||
verb_de=f"{payroll.employee_id}s Rückerstattungsantrag hat einen Kommentar erhalten.",
|
||||
verb_es=f"La solicitud de reembolso de gastos de {payroll.employee_id} ha recibido un comentario.",
|
||||
verb_fr=f"La demande de remboursement de frais de {payroll.employee_id} a reçu un commentaire.",
|
||||
redirect="/payroll/view-reimbursement",
|
||||
icon="chatbox-ellipses",
|
||||
)
|
||||
elif (
|
||||
request.user.employee_get.id
|
||||
== payroll.employee_id.employee_work_info.reporting_manager_id.id
|
||||
if (
|
||||
payroll.employee_id.employee_work_info.reporting_manager_id
|
||||
is not None
|
||||
):
|
||||
|
||||
if request.user.employee_get.id == payroll.employee_id.id:
|
||||
rec = (
|
||||
payroll.employee_id.employee_work_info.reporting_manager_id.employee_user_id
|
||||
)
|
||||
notify.send(
|
||||
request.user.employee_get,
|
||||
recipient=rec,
|
||||
verb=f"{payroll.employee_id}'s reimbursement request has received a comment.",
|
||||
verb_ar=f"تلقى طلب استرداد نفقات {payroll.employee_id} تعليقًا.",
|
||||
verb_de=f"{payroll.employee_id}s Rückerstattungsantrag hat einen Kommentar erhalten.",
|
||||
verb_es=f"La solicitud de reembolso de gastos de {payroll.employee_id} ha recibido un comentario.",
|
||||
verb_fr=f"La demande de remboursement de frais de {payroll.employee_id} a reçu un commentaire.",
|
||||
redirect="/payroll/view-reimbursement",
|
||||
icon="chatbox-ellipses",
|
||||
)
|
||||
elif (
|
||||
request.user.employee_get.id
|
||||
== payroll.employee_id.employee_work_info.reporting_manager_id.id
|
||||
):
|
||||
rec = payroll.employee_id.employee_user_id
|
||||
notify.send(
|
||||
request.user.employee_get,
|
||||
recipient=rec,
|
||||
verb="Your reimbursement request has received a comment.",
|
||||
verb_ar="تلقى طلب استرداد نفقاتك تعليقًا.",
|
||||
verb_de="Ihr Rückerstattungsantrag hat einen Kommentar erhalten.",
|
||||
verb_es="Tu solicitud de reembolso ha recibido un comentario.",
|
||||
verb_fr="Votre demande de remboursement a reçu un commentaire.",
|
||||
redirect="/payroll/view-reimbursement",
|
||||
icon="chatbox-ellipses",
|
||||
)
|
||||
else:
|
||||
rec = [
|
||||
payroll.employee_id.employee_user_id,
|
||||
payroll.employee_id.employee_work_info.reporting_manager_id.employee_user_id,
|
||||
]
|
||||
notify.send(
|
||||
request.user.employee_get,
|
||||
recipient=rec,
|
||||
verb=f"{payroll.employee_id}'s reimbursement request has received a comment.",
|
||||
verb_ar=f"تلقى طلب استرداد نفقات {payroll.employee_id} تعليقًا.",
|
||||
verb_de=f"{payroll.employee_id}s Rückerstattungsantrag hat einen Kommentar erhalten.",
|
||||
verb_es=f"La solicitud de reembolso de gastos de {payroll.employee_id} ha recibido un comentario.",
|
||||
verb_fr=f"La demande de remboursement de frais de {payroll.employee_id} a reçu un commentaire.",
|
||||
redirect="/payroll/view-reimbursement",
|
||||
icon="chatbox-ellipses",
|
||||
)
|
||||
else:
|
||||
rec = payroll.employee_id.employee_user_id
|
||||
notify.send(
|
||||
request.user.employee_get,
|
||||
@@ -1523,27 +1564,15 @@ def create_payrollrequest_comment(request, payroll_id):
|
||||
redirect="/payroll/view-reimbursement",
|
||||
icon="chatbox-ellipses",
|
||||
)
|
||||
else:
|
||||
rec = [
|
||||
payroll.employee_id.employee_user_id,
|
||||
payroll.employee_id.employee_work_info.reporting_manager_id.employee_user_id,
|
||||
]
|
||||
notify.send(
|
||||
request.user.employee_get,
|
||||
recipient=rec,
|
||||
verb=f"{payroll.employee_id}'s reimbursement request has received a comment.",
|
||||
verb_ar=f"تلقى طلب استرداد نفقات {payroll.employee_id} تعليقًا.",
|
||||
verb_de=f"{payroll.employee_id}s Rückerstattungsantrag hat einen Kommentar erhalten.",
|
||||
verb_es=f"La solicitud de reembolso de gastos de {payroll.employee_id} ha recibido un comentario.",
|
||||
verb_fr=f"La demande de remboursement de frais de {payroll.employee_id} a reçu un commentaire.",
|
||||
redirect="/payroll/view-reimbursement",
|
||||
icon="chatbox-ellipses",
|
||||
)
|
||||
|
||||
return HttpResponse("<script>window.location.reload()</script>")
|
||||
return render(
|
||||
request,
|
||||
"payroll/reimbursement/reimbursement_comment.html",
|
||||
{"comments": comments, "no_comments": no_comments, "request_id": payroll_id,},
|
||||
)
|
||||
return render(
|
||||
request,
|
||||
"payroll/reimbursement/reimbursement_request_comment_form.html",
|
||||
"payroll/reimbursement/reimbursement_comment.html",
|
||||
{"form": form, "request_id": payroll_id},
|
||||
)
|
||||
|
||||
@@ -1556,14 +1585,26 @@ def view_payrollrequest_comment(request, payroll_id):
|
||||
comments = ReimbursementrequestComment.objects.filter(
|
||||
request_id=payroll_id
|
||||
).order_by("-created_at")
|
||||
|
||||
no_comments = False
|
||||
if not comments.exists():
|
||||
no_comments = True
|
||||
|
||||
if request.FILES:
|
||||
files = request.FILES.getlist("files")
|
||||
comment_id = request.GET["comment_id"]
|
||||
comment = ReimbursementrequestComment.objects.get(id=comment_id)
|
||||
attachments = []
|
||||
for file in files:
|
||||
file_instance = ReimbursementFile()
|
||||
file_instance.file = file
|
||||
file_instance.save()
|
||||
attachments.append(file_instance)
|
||||
comment.files.add(*attachments)
|
||||
return render(
|
||||
request,
|
||||
"payroll/reimbursement/comment_view.html",
|
||||
{"comments": comments, "no_comments": no_comments},
|
||||
"payroll/reimbursement/reimbursement_comment.html",
|
||||
{"comments": comments, "no_comments": no_comments, "request_id": payroll_id,},
|
||||
)
|
||||
|
||||
|
||||
@@ -1572,12 +1613,34 @@ def delete_payrollrequest_comment(request, comment_id):
|
||||
"""
|
||||
This method is used to delete Reimbursement request comments
|
||||
"""
|
||||
ReimbursementrequestComment.objects.get(id=comment_id).delete()
|
||||
comment=ReimbursementrequestComment.objects.get(id=comment_id)
|
||||
reimbursementrequest = comment.request_id.id
|
||||
comment.delete()
|
||||
|
||||
messages.success(request, _("Comment deleted successfully!"))
|
||||
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
||||
return redirect('payroll-request-view-comment', payroll_id = reimbursementrequest)
|
||||
|
||||
|
||||
@login_required
|
||||
def delete_reimbursement_comment_file(request):
|
||||
"""
|
||||
Used to delete attachment
|
||||
"""
|
||||
ids = request.GET.getlist("ids")
|
||||
ReimbursementFile.objects.filter(id__in=ids).delete()
|
||||
payroll_id = request.GET["payroll_id"]
|
||||
comments = ReimbursementrequestComment.objects.filter(request_id=payroll_id).order_by(
|
||||
"-created_at"
|
||||
)
|
||||
return render(
|
||||
request,
|
||||
"payroll/reimbursement/reimbursement_comment.html",
|
||||
{
|
||||
"comments": comments,
|
||||
"request_id": payroll_id,
|
||||
},
|
||||
)
|
||||
|
||||
@login_required
|
||||
@permission_required("payroll.add_payrollgeneralsetting")
|
||||
def initial_notice_period(request):
|
||||
|
||||
Reference in New Issue
Block a user