Separate client service subscriptions from engagement instances

This commit is contained in:
A R R R Associates
2026-08-05 13:42:11 +05:30
parent 3bba0c1e32
commit 0e9eb2bef2
11 changed files with 273 additions and 2 deletions
+78 -1
View File
@@ -9,7 +9,7 @@ from app.modules.clients.models import Client
from app.modules.core.iam.models import User
from app.modules.core.rbac.models import Role, UserRole
from app.modules.core.tenancy.models import Tenant
from app.modules.services.models import ClientServiceSubscription, FirmServiceSelection, ServiceCatalogue
from app.modules.services.models import ClientServicePlan, ClientServiceSubscription, FirmServiceSelection, ServiceCatalogue
SUBSCRIPTION_STATUSES = [
("draft", "Draft"),
@@ -640,3 +640,80 @@ def enforce_quality_gate_on_subscription(subscription: ClientServiceSubscription
subscription.is_active = False
if not subscription.quality_block_reason:
subscription.quality_block_reason = "AQMM acceptance workflow pending for assurance engagement."
def get_or_create_client_service_plan(
db: Session,
*,
tenant_id: int,
client: Client,
catalogue: ServiceCatalogue,
firm_selection: FirmServiceSelection | None,
branch_id: int | None,
partner_user_id: int | None,
performing_partner_user_id: int | None,
manager_user_id: int | None,
staff_user_id: int | None,
review_partner_user_id: int | None,
actor_user_id: int | None,
remarks: str | None = None,
) -> ClientServicePlan:
plan = db.execute(
select(ClientServicePlan).where(
ClientServicePlan.tenant_id == tenant_id,
ClientServicePlan.client_id == client.id,
ClientServicePlan.service_catalogue_id == catalogue.id,
)
).scalar_one_or_none()
if plan is None:
plan = ClientServicePlan(
tenant_id=tenant_id,
client_id=client.id,
service_catalogue_id=catalogue.id,
created_by_user_id=actor_user_id,
)
db.add(plan)
plan.branch_id = branch_id or getattr(client, "branch_id", None)
plan.firm_service_selection_id = getattr(firm_selection, "id", None)
plan.default_partner_user_id = partner_user_id or getattr(client, "partner_id", None)
plan.default_performing_partner_user_id = performing_partner_user_id or getattr(client, "default_performing_partner_user_id", None) or plan.default_partner_user_id
plan.default_manager_user_id = manager_user_id
plan.default_staff_user_id = staff_user_id
plan.default_review_partner_user_id = review_partner_user_id or getattr(client, "default_review_partner_user_id", None)
plan.recurrence_type = normalized_recurrence_type(getattr(catalogue, "recurrence_type", None)) or "one_time"
plan.auto_generate_periods = recurrence_requires_period(plan.recurrence_type)
plan.status = "active"
plan.is_active = True
if remarks and not plan.remarks:
plan.remarks = remarks
plan.updated_by_user_id = actor_user_id
db.flush()
return plan
def attach_engagement_to_plan(
db: Session,
*,
engagement: ClientServiceSubscription,
client: Client,
catalogue: ServiceCatalogue,
firm_selection: FirmServiceSelection | None,
actor_user_id: int | None,
) -> ClientServicePlan:
plan = get_or_create_client_service_plan(
db,
tenant_id=engagement.tenant_id,
client=client,
catalogue=catalogue,
firm_selection=firm_selection,
branch_id=engagement.branch_id,
partner_user_id=engagement.assigned_partner_user_id,
performing_partner_user_id=getattr(engagement, "performing_partner_user_id", None),
manager_user_id=engagement.assigned_manager_user_id,
staff_user_id=engagement.assigned_staff_user_id,
review_partner_user_id=engagement.review_partner_user_id,
actor_user_id=actor_user_id,
remarks=engagement.remarks,
)
engagement.service_plan_id = plan.id
return plan