Add full sync retirement for missing system default tasks

This commit is contained in:
A R R R Associates
2026-09-19 14:13:16 +05:30
parent 2d6043962b
commit 7bd7f52278
6 changed files with 195 additions and 33 deletions
@@ -66,12 +66,13 @@
<section class="rounded-2xl bg-white p-5 shadow-soft">
<h3 class="text-sm font-semibold text-slate-900">Import system default tasks</h3>
<p class="mt-1 text-sm text-slate-500">System Admin only. Creates/updates default task templates by service code and sequence no.</p>
<p class="mt-1 text-sm text-slate-500">System Admin only. Creates/updates centrally maintained default tasks. Exported workbooks use stable system_task_id; Full Synchronization can retire old tasks omitted from the workbook.</p>
<a href="/services/bulk-imports/templates/system-default-tasks.xlsx" class="mt-4 inline-flex rounded-xl border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50">Download Template</a>
<form method="post" action="/services/bulk-imports/system-default-tasks" enctype="multipart/form-data" class="mt-4 space-y-3">
<form method="post" action="/services/bulk-imports/system-default-tasks" enctype="multipart/form-data" class="mt-4 space-y-3" onsubmit="if (this.full_sync.checked) return confirm('Full Synchronization will retire existing system-default tasks that are missing from the workbook for each service represented in this file. Historical work will be preserved. Continue?');">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="file" name="file" accept=".xlsx" required class="block w-full rounded-xl border border-slate-300 px-4 py-2 text-sm">
<label class="inline-flex items-center gap-2 text-sm text-slate-700"><input type="checkbox" name="update_existing" checked> Update existing sequence rows</label>
<label class="inline-flex items-center gap-2 text-sm text-slate-700"><input type="checkbox" name="update_existing" checked> Update existing tasks</label>
<label class="inline-flex items-start gap-2 rounded-xl border border-amber-200 bg-amber-50 p-3 text-sm text-amber-900"><input type="checkbox" name="full_sync" class="mt-1"><span><strong>Full Synchronization</strong> — for each service present in this workbook, retire existing system-default tasks that are missing from the workbook. Use this when replacing a complete checklist, such as reducing Tax Audit from 120 to 78 tasks.</span></label>
<div><button class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-medium text-white hover:bg-brand-700">Upload Default Tasks</button></div>
</form>
</section>
@@ -9,9 +9,10 @@
<a href="{{ back_url }}" class="rounded-xl border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50">Back</a>
</div>
<div class="grid gap-4 md:grid-cols-4">
<div class="grid gap-4 md:grid-cols-5">
<div class="rounded-2xl bg-white p-5 shadow-soft"><div class="text-xs text-slate-500">Created</div><div class="mt-1 text-2xl font-semibold text-slate-900">{{ result.created }}</div></div>
<div class="rounded-2xl bg-white p-5 shadow-soft"><div class="text-xs text-slate-500">Updated</div><div class="mt-1 text-2xl font-semibold text-slate-900">{{ result.updated }}</div></div>
<div class="rounded-2xl bg-white p-5 shadow-soft"><div class="text-xs text-slate-500">Retired</div><div class="mt-1 text-2xl font-semibold text-amber-700">{{ result.retired|default(0) }}</div></div>
<div class="rounded-2xl bg-white p-5 shadow-soft"><div class="text-xs text-slate-500">Skipped</div><div class="mt-1 text-2xl font-semibold text-slate-900">{{ result.skipped }}</div></div>
<div class="rounded-2xl bg-white p-5 shadow-soft"><div class="text-xs text-slate-500">Errors</div><div class="mt-1 text-2xl font-semibold {% if result.errors %}text-rose-700{% else %}text-emerald-700{% endif %}">{{ result.errors|length }}</div></div>
</div>
@@ -31,7 +32,8 @@
</div>
</section>
{% else %}
<div class="rounded-2xl border border-emerald-200 bg-emerald-50 p-5 text-sm text-emerald-800">Import completed successfully.</div>
<div class="rounded-2xl border border-emerald-200 bg-emerald-50 p-5 text-sm text-emerald-800">Import completed successfully.{% if result.full_sync %} Full Synchronization was applied; omitted existing system tasks were retired rather than hard-deleted.{% endif %}</div>
{% if result.full_sync %}<div class="rounded-2xl border border-amber-200 bg-amber-50 p-5 text-sm text-amber-900"><strong>History-safe synchronization:</strong> retired system tasks remain in the database for audit/history. Inherited firm tasks are synchronized automatically; customized firm tasks use the existing Firm Admin decision flow; safe pending/unstarted open-engagement tasks are updated/deactivated while started/completed/reviewed history is preserved.</div>{% endif %}
{% endif %}
</div>
{% endblock %}
@@ -9,11 +9,11 @@
<div class="flex flex-wrap gap-2"><a href="/services/catalogue/{{ service.id }}/defaults/export" class="rounded-xl border border-emerald-300 bg-emerald-50 px-4 py-2 text-sm font-medium text-emerald-800 hover:bg-emerald-100">Export Tasks</a><a href="/services/catalogue/{{ service.id }}/defaults/duplicates" class="rounded-xl border border-amber-300 bg-amber-50 px-4 py-2 text-sm font-medium text-amber-800 hover:bg-amber-100">Duplicate Review</a><a href="/services/catalogue/{{ service.id }}/task-categories" class="rounded-xl border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50">Task Categories</a><a href="/services/defaults" class="rounded-xl border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50">Back</a><a href="/services/catalogue/{{ service.id }}" class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-medium text-white hover:bg-brand-700">Catalogue Detail</a></div>
</div>
{% if request.query_params.get('imported') %}<div class="rounded-xl border border-emerald-200 bg-emerald-50 p-4 text-sm text-emerald-800">Excel import completed: {{ request.query_params.get('created','0') }} created, {{ request.query_params.get('updated','0') }} updated.</div>{% endif %}
{% if request.query_params.get('imported') %}<div class="rounded-xl border border-emerald-200 bg-emerald-50 p-4 text-sm text-emerald-800">Excel import completed: {{ request.query_params.get('created','0') }} created, {{ request.query_params.get('updated','0') }} updated, {{ request.query_params.get('retired','0') }} retired.{% if request.query_params.get('full_sync') == '1' %} Full Synchronization was applied.{% endif %}</div>{% endif %}
{% if request.query_params.get('import_error') %}<div class="rounded-xl border border-red-200 bg-red-50 p-4 text-sm text-red-800">Excel import failed validation. No partial update was committed. Review the workbook and try again.</div>{% endif %}
<section class="rounded-2xl border border-emerald-200 bg-emerald-50 p-4">
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between"><div><h3 class="text-sm font-semibold text-emerald-950">Export · Edit · Re-import This Service</h3><p class="mt-1 text-xs text-emerald-800">Export this service's current tasks, edit the Import Ready sheet, then re-import. Matching remains service code + sequence number.</p></div>
<form method="post" action="/services/catalogue/{{ service.id }}/defaults/import" enctype="multipart/form-data" class="flex flex-wrap items-center gap-2"><input type="hidden" name="csrf_token" value="{{ csrf_token }}"><input type="file" name="file" accept=".xlsx" required class="max-w-xs rounded-xl border border-emerald-200 bg-white px-3 py-2 text-xs"><button class="rounded-xl bg-emerald-700 px-4 py-2 text-sm font-semibold text-white hover:bg-emerald-800">Import Updated Excel</button></form></div>
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between"><div><h3 class="text-sm font-semibold text-emerald-950">Export · Edit · Re-import This Service</h3><p class="mt-1 text-xs text-emerald-800">Export this service's current tasks, edit the Import Ready sheet, then re-import. Existing exports now carry a stable system_task_id so renaming and resequencing update the correct task.</p></div>
<form method="post" action="/services/catalogue/{{ service.id }}/defaults/import" enctype="multipart/form-data" class="flex flex-wrap items-center gap-2" onsubmit="if (this.full_sync.checked) return confirm('Full Synchronization will retire existing system-default tasks for this service that are missing from the workbook. Historical work will be preserved. Continue?');"><input type="hidden" name="csrf_token" value="{{ csrf_token }}"><input type="file" name="file" accept=".xlsx" required class="max-w-xs rounded-xl border border-emerald-200 bg-white px-3 py-2 text-xs"><label class="inline-flex items-center gap-2 rounded-xl border border-amber-200 bg-amber-50 px-3 py-2 text-xs font-medium text-amber-900"><input type="checkbox" name="full_sync"> Full Synchronization (retire missing tasks)</label><button class="rounded-xl bg-emerald-700 px-4 py-2 text-sm font-semibold text-white hover:bg-emerald-800">Import Updated Excel</button></form></div>
</section>
<section class="rounded-2xl bg-white p-5 shadow-soft">
<div class="space-y-3">