Prepare ERP source for Gitea deployment

This commit is contained in:
A R R R Associates
2026-06-20 15:01:44 +05:30
commit 5c75eb6bd9
450 changed files with 67698 additions and 0 deletions
@@ -0,0 +1,154 @@
{% extends "ui/templates/base/layout.html" %}
{% block content %}
{% if role_context == 'client' %}
{% include "modules/clients/templates/clients/_client_tabs.html" ignore missing %}
{% elif role_context == 'consultant' %}
{% include "modules/consultants/templates/consultants/_consultant_tabs.html" ignore missing %}
{% elif role_context == 'partner' %}
{% include "modules/partners/templates/partners/_partner_tabs.html" ignore missing %}
{% elif role_context == 'manager' %}
{% include "modules/managers/templates/managers/_manager_tabs.html" ignore missing %}
{% elif role_context == 'staff' %}
{% include "modules/employees/templates/employees/_my_workspace_tabs.html" ignore missing %}
{% endif %}
{% set client = engagement.client %}
{% set catalogue = engagement.catalogue %}
<div class="space-y-6">
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft">
<div class="flex flex-wrap items-start justify-between gap-4">
<div>
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Unified Work Details</div>
<h2 class="mt-1 text-2xl font-semibold text-slate-900">{{ catalogue.service_name if catalogue else 'Engagement' }}</h2>
<p class="mt-1 text-sm text-slate-500">
{{ client.client_name if client else 'Client' }}{% if client and client.client_code %} • {{ client.client_code }}{% endif %}
{% if engagement.financial_year %} • FY {{ engagement.financial_year }}{% endif %}
{% if engagement.assessment_year %} • AY {{ engagement.assessment_year }}{% endif %}
</p>
</div>
<div class="flex flex-wrap gap-2 text-xs font-semibold">
<span class="rounded-full bg-slate-100 px-3 py-1 text-slate-700">{{ engagement.status.replace('_',' ').title() }}</span>
{% if engagement.current_due_date %}<span class="rounded-full bg-amber-50 px-3 py-1 text-amber-700">Due {{ engagement.current_due_date.strftime('%d-%m-%Y') }}</span>{% endif %}
<a href="{{ access.back_url }}" class="rounded-full border border-slate-300 px-3 py-1 text-slate-700 hover:bg-slate-50">Back</a>
</div>
</div>
<div class="mt-5 grid gap-3 md:grid-cols-4">
<div class="rounded-2xl bg-slate-50 p-4"><div class="text-xs text-slate-500">Open Tasks</div><div class="mt-1 text-2xl font-semibold">{{ open_task_count }}</div></div>
<div class="rounded-2xl bg-slate-50 p-4"><div class="text-xs text-slate-500">Completed</div><div class="mt-1 text-2xl font-semibold">{{ completed_task_count }}</div></div>
<div class="rounded-2xl bg-slate-50 p-4"><div class="text-xs text-slate-500">Engagement Docs</div><div class="mt-1 text-2xl font-semibold">{{ engagement_documents|length }}</div></div>
<div class="rounded-2xl bg-slate-50 p-4"><div class="text-xs text-slate-500">Timeline Notes</div><div class="mt-1 text-2xl font-semibold">{{ timeline|length }}</div></div>
</div>
</div>
<div class="grid gap-6 xl:grid-cols-[minmax(0,1fr)_360px]">
<div class="space-y-4">
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
<div class="border-b border-slate-200 px-5 py-4">
<h3 class="font-semibold text-slate-900">Task Board</h3>
<p class="text-xs text-slate-500">Role-sensitive task view. Clients and consultants see only permitted action/comment options.</p>
</div>
<div class="divide-y divide-slate-100">
{% for task in tasks %}
<div class="p-5">
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<div class="font-semibold text-slate-900">{{ task.sequence_no }}. {{ task.task_name }}</div>
{% if task.description %}<div class="mt-1 text-sm text-slate-500">{{ task.description }}</div>{% endif %}
<div class="mt-2 flex flex-wrap gap-2 text-[11px] font-semibold">
<span class="rounded-full bg-slate-100 px-2 py-1 text-slate-700">{{ task.status_label }}</span>
<span class="rounded-full bg-slate-100 px-2 py-1 text-slate-700">{{ task.priority_label }}</span>
{% if task.internal_target_date %}<span class="rounded-full {% if task.is_overdue_display %}bg-red-50 text-red-700{% else %}bg-slate-100 text-slate-700{% endif %} px-2 py-1">Target {{ task.internal_target_date.strftime('%d-%m-%Y') }}</span>{% endif %}
{% if task.assigned_to %}<span class="rounded-full bg-slate-100 px-2 py-1 text-slate-700">Assigned: {{ task.assigned_to.full_name or task.assigned_to.email }}</span>{% endif %}
</div>
</div>
{% if access.can_update_tasks %}
<form method="post" action="/work/tasks/{{ task.id }}/status" class="flex flex-wrap gap-2">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<select name="status" class="rounded-xl border border-slate-300 px-2 py-1 text-xs">
{% for code, label in task_statuses %}<option value="{{ code }}" {% if task.status == code %}selected{% endif %}>{{ label }}</option>{% endfor %}
</select>
<select name="priority" class="rounded-xl border border-slate-300 px-2 py-1 text-xs">
{% for code, label in task_priorities %}<option value="{{ code }}" {% if task.priority == code %}selected{% endif %}>{{ label }}</option>{% endfor %}
</select>
<button class="rounded-xl bg-brand-600 px-3 py-1 text-xs font-semibold text-white hover:bg-brand-700">Update</button>
</form>
{% endif %}
</div>
{% if access.can_comment %}
<form method="post" action="/work/tasks/{{ task.id }}/comment" class="mt-4 rounded-2xl bg-slate-50 p-3">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<div class="grid gap-2 md:grid-cols-[auto_auto_1fr_auto]">
<select name="comment_type" class="rounded-xl border border-slate-300 px-2 py-2 text-xs">
{% for code, label in access.allowed_comment_types %}<option value="{{ code }}">{{ label }}</option>{% endfor %}
</select>
<select name="visibility" class="rounded-xl border border-slate-300 px-2 py-2 text-xs">
{% for code, label in access.allowed_visibilities %}<option value="{{ code }}">{{ label }}</option>{% endfor %}
</select>
<input name="message" required placeholder="Add note / clarification / submission update" class="rounded-xl border border-slate-300 px-3 py-2 text-sm">
<button class="rounded-xl border border-slate-300 bg-white px-4 py-2 text-xs font-semibold text-slate-700 hover:bg-slate-50">Add</button>
</div>
</form>
{% endif %}
</div>
{% else %}
<div class="p-6 text-sm text-slate-500">No tasks have been generated for this engagement yet.</div>
{% endfor %}
</div>
</div>
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
<div class="border-b border-slate-200 px-5 py-4"><h3 class="font-semibold text-slate-900">Communication Timeline</h3></div>
<div class="divide-y divide-slate-100">
{% for note in timeline %}
<div class="p-5">
<div class="flex flex-wrap items-center gap-2 text-xs text-slate-500">
<span class="font-semibold text-slate-700">{{ note.comment_type.replace('_',' ').title() }}</span>
<span></span><span>{{ note.visibility.replace('_',' ').title() }}</span>
{% if note.created_by %}<span></span><span>{{ note.created_by.full_name or note.created_by.email }}</span>{% endif %}
{% if note.created_at_utc %}<span></span><span>{{ note.created_at_utc.strftime('%d-%m-%Y %H:%M') }}</span>{% endif %}
{% if note.task %}<span></span><span>{{ note.task.task_name }}</span>{% endif %}
</div>
<div class="mt-2 whitespace-pre-wrap text-sm text-slate-700">{{ note.message }}</div>
</div>
{% else %}
<div class="p-6 text-sm text-slate-500">No communication yet.</div>
{% endfor %}
</div>
</div>
</div>
<aside class="space-y-4">
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
<div class="border-b border-slate-200 px-5 py-4"><h3 class="font-semibold text-slate-900">Engagement Documents</h3></div>
<div class="divide-y divide-slate-100">
{% for doc in engagement_documents %}
<div class="p-4">
<div class="font-semibold text-slate-900">{{ doc.title }}</div>
<div class="mt-1 text-xs text-slate-500">{{ doc.document_type }} • v{{ doc.current_version_no }}</div>
{% if doc.versions %}<div class="mt-2 text-xs text-slate-500">Latest: {{ doc.versions[0].original_filename }}</div>{% endif %}
</div>
{% else %}
<div class="p-5 text-sm text-slate-500">No engagement documents uploaded.</div>
{% endfor %}
</div>
</div>
<div class="rounded-3xl border border-slate-200 bg-white shadow-soft">
<div class="border-b border-slate-200 px-5 py-4"><h3 class="font-semibold text-slate-900">Permanent Documents</h3></div>
<div class="divide-y divide-slate-100">
{% for doc in permanent_documents %}
<div class="p-4">
<div class="font-semibold text-slate-900">{{ doc.title }}</div>
<div class="mt-1 text-xs text-slate-500">{{ doc.category }} • v{{ doc.current_version_no }}</div>
</div>
{% else %}
<div class="p-5 text-sm text-slate-500">No permanent documents available.</div>
{% endfor %}
</div>
</div>
</aside>
</div>
</div>
{% endblock %}