Add controlled client subscription team reassignment
This commit is contained in:
@@ -20,6 +20,12 @@
|
||||
class="rounded-xl border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50">
|
||||
Back
|
||||
</a>
|
||||
{% if can_edit_subscription %}
|
||||
<a href="/services/subscriptions/{{ plan.id }}/edit"
|
||||
class="rounded-xl border border-brand-300 px-4 py-2 text-sm font-medium text-brand-700 hover:bg-brand-50">
|
||||
Edit Subscription
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="/services/engagements/new?client_id={{ plan.client_id }}"
|
||||
class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-medium text-white hover:bg-brand-700">
|
||||
Create Engagement
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
{% extends "ui/templates/base/layout.html" %}
|
||||
{% block content %}
|
||||
<div class="space-y-6">
|
||||
{% set _uiux_partner_role_text = (current_user_roles or [])|join('|')|lower %}
|
||||
{% if 'partner' in _uiux_partner_role_text %}
|
||||
{% include "ui/templates/components/partner_navigation_v2.html" %}
|
||||
{% endif %}
|
||||
|
||||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||||
<div>
|
||||
<h2 class="text-xl font-semibold text-slate-900">Edit Client Service Subscription</h2>
|
||||
<p class="text-sm text-slate-500">
|
||||
{{ plan.client.client_name }} — {{ plan.catalogue.service_name }}
|
||||
</p>
|
||||
</div>
|
||||
<a href="/services/subscriptions/{{ plan.id }}"
|
||||
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>
|
||||
|
||||
{% if saved %}
|
||||
<div class="rounded-xl border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm text-emerald-800">
|
||||
Subscription defaults saved. {{ updated_engagements }} open engagement(s) and {{ updated_tasks }} unfinished Staff task(s) were updated.
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if error %}
|
||||
<div class="rounded-xl border border-rose-200 bg-rose-50 px-4 py-3 text-sm text-rose-800">
|
||||
The subscription could not be saved. Please verify the selected team, dates, status and propagation option.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/services/subscriptions/{{ plan.id }}/edit" class="space-y-6">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
|
||||
<section class="rounded-2xl bg-white p-5 shadow-soft">
|
||||
<h3 class="text-base font-semibold text-slate-900">Default Assignment Team</h3>
|
||||
<p class="mt-1 text-sm text-slate-500">These defaults will be used for newly generated engagements.</p>
|
||||
<div class="mt-5 grid gap-5 md:grid-cols-2">
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-slate-700">Engagement Partner</label>
|
||||
<select name="default_partner_user_id" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
|
||||
<option value="">No default Partner</option>
|
||||
{% for row in partners %}<option value="{{ row.id }}" {% if plan.default_partner_user_id == row.id %}selected{% endif %}>{{ row.full_name or row.email }}</option>{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-slate-700">Performing Partner</label>
|
||||
<select name="default_performing_partner_user_id" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
|
||||
<option value="">Same as Engagement Partner</option>
|
||||
{% for row in partners %}<option value="{{ row.id }}" {% if plan.default_performing_partner_user_id == row.id %}selected{% endif %}>{{ row.full_name or row.email }}</option>{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-slate-700">Manager</label>
|
||||
<select name="default_manager_user_id" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
|
||||
<option value="">No default Manager</option>
|
||||
{% for row in managers %}<option value="{{ row.id }}" {% if plan.default_manager_user_id == row.id %}selected{% endif %}>{{ row.full_name or row.email }}</option>{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-slate-700">Staff</label>
|
||||
<select name="default_staff_user_id" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
|
||||
<option value="">No default Staff</option>
|
||||
{% for row in staff_users %}<option value="{{ row.id }}" {% if plan.default_staff_user_id == row.id %}selected{% endif %}>{{ row.full_name or row.email }}</option>{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-slate-700">Review Partner</label>
|
||||
<select name="default_review_partner_user_id" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
|
||||
<option value="">Not required / no default</option>
|
||||
{% for row in review_partners %}<option value="{{ row.id }}" {% if plan.default_review_partner_user_id == row.id %}selected{% endif %}>{{ row.full_name or row.email }}</option>{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="rounded-2xl bg-white p-5 shadow-soft">
|
||||
<h3 class="text-base font-semibold text-slate-900">Subscription Settings</h3>
|
||||
<div class="mt-5 grid gap-5 md:grid-cols-2">
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-slate-700">Effective From</label>
|
||||
<input type="date" name="effective_from" value="{{ plan.effective_from or '' }}" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-slate-700">Effective To</label>
|
||||
<input type="date" name="effective_to" value="{{ plan.effective_to or '' }}" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-slate-700">Status</label>
|
||||
<select name="status" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
|
||||
{% for value, label in subscription_statuses %}<option value="{{ value }}" {% if plan.status == value %}selected{% endif %}>{{ label }}</option>{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<label class="mt-7 inline-flex items-center gap-2 text-sm text-slate-700">
|
||||
<input type="checkbox" name="auto_generate_periods" value="1" {% if plan.auto_generate_periods %}checked{% endif %} class="rounded border-slate-300">
|
||||
Automatically generate recurring periods when the scheduler is enabled
|
||||
</label>
|
||||
<div class="md:col-span-2">
|
||||
<label class="mb-1 block text-sm font-medium text-slate-700">Remarks</label>
|
||||
<textarea name="remarks" rows="3" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">{{ plan.remarks or '' }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="rounded-2xl border border-amber-200 bg-amber-50 p-5">
|
||||
<h3 class="text-base font-semibold text-slate-900">Apply Team Change</h3>
|
||||
<p class="mt-1 text-sm text-slate-600">Completed and locked engagements, completed tasks, evidence and review history are never changed.</p>
|
||||
<div class="mt-4 space-y-3">
|
||||
<label class="flex items-start gap-3 rounded-xl border border-amber-200 bg-white p-4">
|
||||
<input type="radio" name="propagation_mode" value="future_only" checked class="mt-1">
|
||||
<span><strong class="block text-sm text-slate-900">Future engagements only</strong><span class="text-sm text-slate-500">Save new defaults without changing any existing engagement.</span></span>
|
||||
</label>
|
||||
<label class="flex items-start gap-3 rounded-xl border border-amber-200 bg-white p-4">
|
||||
<input type="radio" name="propagation_mode" value="open_engagements" class="mt-1">
|
||||
<span><strong class="block text-sm text-slate-900">Future engagements and currently open engagements</strong><span class="text-sm text-slate-500">Update unlocked, non-completed engagement assignments and unfinished Staff tasks.</span></span>
|
||||
</label>
|
||||
<div class="grid gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-slate-700">Open engagements effective from</label>
|
||||
<input type="date" name="reassignment_effective_from" class="w-full rounded-xl border border-amber-300 bg-white px-3 py-2 text-sm">
|
||||
<p class="mt-1 text-xs text-slate-500">Leave blank to update all open engagements under this subscription.</p>
|
||||
</div>
|
||||
<div>
|
||||
<label class="mb-1 block text-sm font-medium text-slate-700">Reason for reassignment</label>
|
||||
<input type="text" name="reassignment_reason" maxlength="500" placeholder="Optional operational reason" class="w-full rounded-xl border border-amber-300 bg-white px-3 py-2 text-sm">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="flex justify-end gap-3">
|
||||
<a href="/services/subscriptions/{{ plan.id }}" class="rounded-xl border border-slate-300 px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50">Cancel</a>
|
||||
<button type="submit" class="rounded-xl bg-brand-600 px-5 py-2 text-sm font-medium text-white hover:bg-brand-700">Save Subscription</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user