Files
arrr-erp/app/modules/services/templates/services/task_template_detail.html
T
2026-07-07 11:30:59 +05:30

200 lines
15 KiB
HTML

{% extends "ui/templates/base/layout.html" %}
{% block content %}
<div class="space-y-6">
<div class="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
<div>
<h2 class="text-xl font-semibold text-slate-900">Firm Task Templates</h2>
<p class="mt-1 text-sm text-slate-500">
{{ service.service_code }} · {{ service.service_name }}
{% if selection and selection.default_branch_id %} · Default Branch ID {{ selection.default_branch_id }}{% endif %}
</p>
</div>
<div class="flex flex-wrap gap-2">
<a href="/services/templates" class="rounded-xl border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50">Back to Templates</a>
<a href="/services/catalogue/{{ service.id }}" class="rounded-xl border border-brand-300 px-4 py-2 text-sm font-medium text-brand-700 hover:bg-brand-50">View Catalogue</a>
</div>
</div>
{% if request.query_params.get('requirement_added') %}<div class="rounded-2xl border border-emerald-200 bg-emerald-50 p-4 text-sm text-emerald-800">Document requirement added successfully.</div>{% endif %}
{% if request.query_params.get('template_uploaded') %}<div class="rounded-2xl border border-emerald-200 bg-emerald-50 p-4 text-sm text-emerald-800">Template file uploaded successfully.</div>{% endif %}
{% if request.query_params.get('error') %}<div class="rounded-2xl border border-red-200 bg-red-50 p-4 text-sm text-red-800">Action failed. Please check the selected task, file and permissions.</div>{% endif %}
<section class="grid gap-4 md:grid-cols-3">
<div class="rounded-2xl bg-white p-5 shadow-soft">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Firm Status</div>
<div class="mt-2 text-lg font-semibold text-slate-900">{{ 'Enabled' if selection and selection.is_enabled else 'Not Enabled' }}</div>
<p class="mt-1 text-sm text-slate-500">Firm-level service selection controls whether these task templates are used.</p>
</div>
<div class="rounded-2xl bg-white p-5 shadow-soft">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Firm Tasks</div>
<div class="mt-2 text-lg font-semibold text-slate-900">{{ task_templates|length }}</div>
<p class="mt-1 text-sm text-slate-500">Tasks customised for the active firm.</p>
</div>
<div class="rounded-2xl bg-white p-5 shadow-soft">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">System Defaults</div>
<div class="mt-2 text-lg font-semibold text-slate-900">{{ default_tasks|length }}</div>
<p class="mt-1 text-sm text-slate-500">Defaults may be copied and customised for the firm.</p>
</div>
</section>
{% if can_manage_tasks %}
<section class="rounded-2xl bg-white p-5 shadow-soft">
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
<div>
<h3 class="text-sm font-semibold text-slate-900">Add Firm Task</h3>
<p class="text-sm text-slate-500">Create a task template for this firm and service.</p>
</div>
{% if default_tasks|length > 0 %}
<form method="post" action="/services/catalogue/{{ service.id }}/defaults/copy-to-firm">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<button class="rounded-xl border border-brand-300 px-4 py-2 text-sm font-medium text-brand-700 hover:bg-brand-50" type="submit">Copy System Defaults</button>
</form>
{% endif %}
</div>
<form method="post" action="/services/templates/{{ service.id }}/tasks/new" class="mt-5 grid gap-4 lg:grid-cols-12">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<div class="lg:col-span-4">
<label class="mb-1 block text-xs font-semibold uppercase tracking-wide text-slate-500">Task Name</label>
<input name="task_name" required class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm" placeholder="e.g. Verify books with GSTR-2B">
</div>
<div class="lg:col-span-3">
<label class="mb-1 block text-xs font-semibold uppercase tracking-wide text-slate-500">Default Role</label>
<input name="default_role_name" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm" placeholder="Staff / Manager / Partner">
</div>
<div class="lg:col-span-2">
<label class="mb-1 block text-xs font-semibold uppercase tracking-wide text-slate-500">Sequence</label>
<input name="sequence_no" type="number" min="1" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm" placeholder="Auto">
</div>
<div class="lg:col-span-3">
<label class="mb-1 block text-xs font-semibold uppercase tracking-wide text-slate-500">Options</label>
<div class="flex flex-wrap gap-3 rounded-xl border border-slate-200 px-3 py-2 text-xs text-slate-700">
<label class="inline-flex items-center gap-1"><input type="checkbox" name="is_mandatory" checked> Mandatory</label>
<label class="inline-flex items-center gap-1"><input type="checkbox" name="requires_review"> Review</label>
<label class="inline-flex items-center gap-1"><input type="checkbox" name="is_active" checked> Active</label>
</div>
</div>
<div class="lg:col-span-12 rounded-2xl border border-indigo-200 bg-indigo-50 p-4">
<div class="text-sm font-semibold text-indigo-950">AQMM / Quality Control Tagging</div>
<p class="mt-1 text-xs text-indigo-800">Tick only the service checklist tasks that should form part of assurance engagement quality evidence.</p>
<div class="mt-3 grid gap-2 md:grid-cols-4 text-xs text-slate-700">
<label class="inline-flex items-center gap-1"><input type="checkbox" name="is_aqmm_task"> Part of AQMM</label>
<label class="inline-flex items-center gap-1"><input type="checkbox" name="aqmm_mandatory"> Mandatory</label>
<label class="inline-flex items-center gap-1"><input type="checkbox" name="aqmm_evidence_required"> Evidence required</label>
<label class="inline-flex items-center gap-1"><input type="checkbox" name="aqmm_manager_review_required"> Manager review</label>
<label class="inline-flex items-center gap-1"><input type="checkbox" name="aqmm_partner_review_required"> Partner review</label>
<label class="inline-flex items-center gap-1"><input type="checkbox" name="aqmm_review_partner_required"> Review partner review</label>
<label class="inline-flex items-center gap-1"><input type="checkbox" name="aqmm_blocks_final_release"> Blocks final release</label>
<input name="aqmm_reference" placeholder="AQMM reference / clause" class="rounded-lg border border-indigo-200 px-2 py-1 text-xs">
</div>
</div>
<div class="lg:col-span-10">
<label class="mb-1 block text-xs font-semibold uppercase tracking-wide text-slate-500">Description</label>
<textarea name="description" rows="2" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm" placeholder="Optional instructions for staff or reviewer"></textarea>
</div>
<div class="flex items-end lg:col-span-2">
<button class="w-full rounded-xl bg-brand-600 px-4 py-2 text-sm font-medium text-white hover:bg-brand-700" type="submit">Add Task</button>
</div>
</form>
</section>
{% endif %}
<section class="overflow-hidden rounded-2xl bg-white shadow-soft">
<div class="border-b border-slate-100 px-5 py-4">
<h3 class="text-sm font-semibold text-slate-900">Firm Task List</h3>
<p class="text-sm text-slate-500">These tasks will be used when work is generated for this firm.</p>
</div>
<table class="min-w-full divide-y divide-slate-200">
<thead class="bg-slate-50">
<tr>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">Seq</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">Task</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">Role</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">Flags</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">Document Requirements</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">Template Uploads</th>
<th class="px-4 py-3"></th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100">
{% for task in task_templates %}
<tr>
<td class="px-4 py-3 text-sm font-medium text-slate-900">{{ task.sequence_no }}</td>
<td class="px-4 py-3 text-sm text-slate-700">
<div class="font-medium text-slate-900">{{ task.task_name }}</div>
{% if task.description %}<div class="mt-1 text-xs text-slate-500">{{ task.description }}</div>{% endif %}
</td>
<td class="px-4 py-3 text-sm text-slate-700">{{ task.default_role_name or '-' }}</td>
<td class="px-4 py-3 text-xs text-slate-600">
<div class="flex flex-wrap gap-1">
{% if task.is_mandatory %}<span class="rounded-full bg-slate-100 px-2 py-1">Mandatory</span>{% endif %}
{% if task.requires_review %}<span class="rounded-full bg-amber-100 px-2 py-1 text-amber-800">Review</span>{% endif %}
{% if task.is_aqmm_task %}<span class="rounded-full bg-indigo-100 px-2 py-1 text-indigo-800">AQMM</span>{% endif %}
{% if task.aqmm_mandatory %}<span class="rounded-full bg-rose-100 px-2 py-1 text-rose-800">AQMM Mandatory</span>{% endif %}
{% if task.aqmm_evidence_required %}<span class="rounded-full bg-sky-100 px-2 py-1 text-sky-800">Evidence</span>{% endif %}
{% if task.aqmm_blocks_final_release %}<span class="rounded-full bg-purple-100 px-2 py-1 text-purple-800">Final Gate</span>{% endif %}
<span class="rounded-full px-2 py-1 {{ 'bg-emerald-100 text-emerald-800' if task.is_active else 'bg-slate-100 text-slate-500' }}">{{ 'Active' if task.is_active else 'Inactive' }}</span>
</div>
</td>
<td class="px-4 py-3 text-xs text-slate-600 align-top">
{% set reqs = task_requirement_map.get(task.id, []) if task_requirement_map else [] %}
<div class="space-y-2">
{% for req in reqs %}
<div class="rounded-lg border border-slate-200 p-2">
<div class="font-medium text-slate-800">{{ req.document_name }}</div>
<div class="text-[11px] text-slate-500">{{ req.document_type.replace('_',' ').title() }} · {{ 'Mandatory' if req.is_mandatory else 'Optional' }} · {{ 'Active' if req.is_active else 'Inactive' }}</div>
{% if can_manage_tasks %}
<form method="post" action="/services/templates/{{ service.id }}/tasks/{{ task.id }}/document-requirements/{{ req.id }}/toggle" class="mt-1">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<button class="text-[11px] font-semibold text-brand-700">{{ 'Deactivate' if req.is_active else 'Activate' }}</button>
</form>
{% endif %}
</div>
{% else %}<span class="text-slate-400">No requirements</span>{% endfor %}
</div>
{% if can_manage_tasks %}
<form method="post" action="/services/templates/{{ service.id }}/tasks/{{ task.id }}/document-requirements/new" class="mt-3 space-y-2 rounded-xl bg-slate-50 p-3">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input name="document_name" required placeholder="Document name" class="w-full rounded-lg border border-slate-300 px-2 py-1 text-xs">
<div class="grid grid-cols-2 gap-2">
<input name="document_type" value="GENERAL" placeholder="Type" class="rounded-lg border border-slate-300 px-2 py-1 text-xs">
<input name="sort_order" type="number" value="100" class="rounded-lg border border-slate-300 px-2 py-1 text-xs">
</div>
<input name="allowed_file_types" placeholder="Allowed: pdf,docx,xlsx" class="w-full rounded-lg border border-slate-300 px-2 py-1 text-xs">
<textarea name="instructions" rows="2" placeholder="Instructions" class="w-full rounded-lg border border-slate-300 px-2 py-1 text-xs"></textarea>
<label class="inline-flex items-center gap-1 text-[11px]"><input type="checkbox" name="is_mandatory" checked> Mandatory</label>
<button class="block rounded-lg bg-slate-900 px-3 py-1 text-xs font-semibold text-white">Add Requirement</button>
</form>
{% endif %}
</td>
<td class="px-4 py-3 text-xs text-slate-600 align-top">
{% set files = task_template_file_map.get(task.id, []) if task_template_file_map else [] %}
<div class="space-y-1">
{% for tpl in files %}
<div><a href="/services/document-templates/{{ tpl.id }}/download" class="font-medium text-brand-700 hover:underline">{{ tpl.template_name }}</a><div class="text-[11px] text-slate-500">{{ tpl.template_category or 'Template' }} · {{ tpl.original_filename }}</div></div>
{% else %}<span class="text-slate-400">No template files</span>{% endfor %}
</div>
{% if can_manage_tasks %}
<form method="post" action="/services/templates/{{ service.id }}/tasks/{{ task.id }}/document-templates/upload" enctype="multipart/form-data" class="mt-3 space-y-2 rounded-xl bg-slate-50 p-3">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input name="template_name" placeholder="Template name" class="w-full rounded-lg border border-slate-300 px-2 py-1 text-xs">
<input name="template_category" placeholder="NOC / Agreement / Deed" class="w-full rounded-lg border border-slate-300 px-2 py-1 text-xs">
<input type="file" name="file" required class="w-full rounded-lg border border-slate-300 px-2 py-1 text-xs">
<textarea name="description" rows="2" placeholder="Description" class="w-full rounded-lg border border-slate-300 px-2 py-1 text-xs"></textarea>
<button class="block rounded-lg bg-brand-600 px-3 py-1 text-xs font-semibold text-white">Upload Template</button>
</form>
{% endif %}
</td>
<td class="px-4 py-3 text-right align-top">
{% if can_manage_tasks %}<a href="/services/templates/{{ service.id }}/tasks/{{ task.id }}/edit" class="text-sm font-medium text-brand-700 hover:underline">Edit</a>{% endif %}
</td>
</tr>
{% else %}
<tr><td colspan="7" class="px-4 py-8 text-center text-sm text-slate-500">No firm task templates yet. Copy defaults or add tasks manually.</td></tr>
{% endfor %}
</tbody>
</table>
</section>
</div>
{% endblock %}