Add optional task categories resequencing and requirement aware documents
This commit is contained in:
@@ -23,7 +23,7 @@ from app.modules.core.tenancy.settings_models import BranchSettings
|
||||
from app.modules.employees.models import Employee, EmployeeAttendance, EmployeeRegistrationRequest, EmployeeLeaveType, EmployeeLeaveBalance, EmployeeLeaveRequest, EmployeeDocumentType, EmployeeDocument, EmployeeOnboardingChecklistItem, EmployeeOnboardingTask, EmployeeOffboardingRequest, EmployeeOffboardingTask, EmployeeSalaryStructure, EmployeePayrollRun, EmployeePayslip
|
||||
from app.modules.clients.models import Client, ClientBusinessUnit, ClientBranch
|
||||
from app.modules.documents.models import EngagementDocument
|
||||
from app.modules.services.models import ClientServiceTaskInstance, ClientServiceSubscription, ServiceCatalogue, ServiceTaskComment
|
||||
from app.modules.services.models import ClientServiceTaskInstance, ClientServiceSubscription, ServiceCatalogue, ServiceTaskComment, FirmTaskDocumentRequirement
|
||||
from app.modules.registrations.models import ClientRegistration, RegistrationType
|
||||
from app.modules.services.execution import (
|
||||
CLOSED_TASK_STATUSES,
|
||||
@@ -3890,6 +3890,10 @@ def get_employee_engagement_work_board(
|
||||
if int(row.id) in assigned_ids
|
||||
or (getattr(row, "default_role_name", None) or "").strip().lower() in reviewer_roles
|
||||
]
|
||||
use_task_categories = any(
|
||||
bool((getattr(row, "task_category", None) or "").strip())
|
||||
for row in tasks
|
||||
)
|
||||
|
||||
summary = {
|
||||
"total": len(tasks),
|
||||
@@ -3984,6 +3988,27 @@ def get_employee_engagement_work_board(
|
||||
engagement_documents = list_employee_engagement_documents(
|
||||
db, scope, engagement_id, financial_year=financial_year
|
||||
)
|
||||
|
||||
firm_template_ids = {
|
||||
int(row.firm_task_template_id)
|
||||
for row in tasks
|
||||
if getattr(row, "firm_task_template_id", None) is not None
|
||||
}
|
||||
mandatory_requirement_template_ids: set[int] = set()
|
||||
if firm_template_ids:
|
||||
mandatory_requirement_template_ids = {
|
||||
int(template_id)
|
||||
for (template_id,) in db.execute(
|
||||
select(FirmTaskDocumentRequirement.firm_task_template_id).where(
|
||||
FirmTaskDocumentRequirement.tenant_id == scope.tenant_id,
|
||||
FirmTaskDocumentRequirement.firm_task_template_id.in_(firm_template_ids),
|
||||
FirmTaskDocumentRequirement.is_active.is_(True),
|
||||
FirmTaskDocumentRequirement.is_mandatory.is_(True),
|
||||
)
|
||||
).all()
|
||||
if template_id is not None
|
||||
}
|
||||
|
||||
task_document_counts: dict[int, int] = {}
|
||||
for document in engagement_documents:
|
||||
task_instance_id = getattr(document, "task_instance_id", None)
|
||||
@@ -4004,6 +4029,10 @@ def get_employee_engagement_work_board(
|
||||
read_only=int(task.id) not in assigned_ids,
|
||||
)
|
||||
task.i1_documents = task_documents.get(int(task.id), [])
|
||||
task.i1_has_mandatory_document_requirement = bool(
|
||||
getattr(task, "firm_task_template_id", None) is not None
|
||||
and int(task.firm_task_template_id) in mandatory_requirement_template_ids
|
||||
)
|
||||
|
||||
scope_display = _employee_work_scope_display_map(
|
||||
db,
|
||||
@@ -4027,6 +4056,7 @@ def get_employee_engagement_work_board(
|
||||
"sla": _engagement_sla(subscription, tasks),
|
||||
"escalation_levels": WORKFLOW_ESCALATION_LEVELS,
|
||||
"categories": categories,
|
||||
"use_task_categories": use_task_categories,
|
||||
"active_task": selected_task,
|
||||
"active_category": selected_category,
|
||||
"next_task": next_task,
|
||||
|
||||
@@ -108,9 +108,11 @@
|
||||
|
||||
<div class="divide-y divide-slate-100">
|
||||
{% for category in board.categories %}
|
||||
{% if board.use_task_categories %}
|
||||
<div class="bg-slate-50 px-5 py-2 text-xs font-semibold uppercase tracking-wide text-slate-500">
|
||||
{{ category.name }} · {{ category.completed }}/{{ category.total }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% for task in category.tasks %}
|
||||
{% set status = task.i1_status or (task.status or 'pending') %}
|
||||
@@ -207,12 +209,14 @@
|
||||
<span class="rounded-xl bg-slate-100 px-3 py-2 text-sm font-semibold text-slate-500">🔒 Locked</span>
|
||||
{% endif %}
|
||||
|
||||
{% if task.i1_has_mandatory_document_requirement %}
|
||||
<button type="button"
|
||||
data-i1-panel-trigger="documents"
|
||||
data-i1-task-id="{{ task.id }}"
|
||||
class="rounded-xl border border-violet-200 bg-violet-50 text-violet-700 hover:bg-violet-100 px-3 py-2 text-sm font-semibold">
|
||||
Documents{% if task.i1_documents %} · {{ task.i1_documents|length }}{% endif %}
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
<button type="button"
|
||||
data-i1-panel-trigger="messages"
|
||||
@@ -231,6 +235,7 @@
|
||||
</div>
|
||||
|
||||
<div class="mt-3 space-y-3" data-i1-panels-for-task="{{ task.id }}">
|
||||
{% if task.i1_has_mandatory_document_requirement %}
|
||||
<div data-i1-panel="documents" class="hidden w-full rounded-2xl border border-violet-200 bg-violet-50/40 p-4">
|
||||
<div class="flex flex-wrap items-start justify-between gap-3">
|
||||
<div>
|
||||
@@ -268,6 +273,7 @@
|
||||
<button type="submit" class="rounded-lg bg-violet-600 px-4 py-2 text-sm font-semibold text-white hover:bg-violet-700">Upload</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div data-i1-panel="messages" class="hidden w-full rounded-2xl border border-sky-200 bg-sky-50/40 p-4">
|
||||
<div class="flex flex-wrap items-start justify-between gap-3">
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user