Add optional task categories resequencing and requirement aware documents

This commit is contained in:
A R R R Associates
2026-08-12 14:57:20 +05:30
parent eb18a5695f
commit 74586d60ed
5 changed files with 128 additions and 4 deletions
+31 -1
View File
@@ -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>