489 lines
29 KiB
Python
489 lines
29 KiB
Python
from __future__ import annotations
|
|
from datetime import date
|
|
from fastapi import APIRouter, Form, Request
|
|
from fastapi.responses import HTMLResponse, RedirectResponse
|
|
from sqlalchemy import or_, select
|
|
from sqlalchemy.exc import IntegrityError
|
|
from app.core.db.common import CommonSessionLocal
|
|
from app.core.security.csrf import get_or_create_csrf_token, validate_csrf
|
|
from app.core.security.session_auth import get_current_user
|
|
from app.core.templating import templates
|
|
from app.modules.clients.models import Client, ClientBusinessUnit, ClientBranch
|
|
from app.modules.consultants.models import ConsultantProfile
|
|
from app.modules.core.rbac.deps import get_user_permissions, get_user_roles
|
|
from app.modules.core.rbac.permission_guard import require_permission
|
|
from app.modules.registrations.models import *
|
|
from app.modules.registrations.service import seed_registration_types, run_registration_lifecycle_once, complete_renewal
|
|
|
|
router=APIRouter(prefix="/registrations", tags=["registrations-ui"])
|
|
|
|
def _ctx(request,user,db,**kw):
|
|
base={"request":request,"current_user":user,"current_user_roles":get_user_roles(db,user.id),"current_user_permissions":get_user_permissions(db,user.id),"csrf_token":get_or_create_csrf_token(request)};base.update(kw);return base
|
|
|
|
def _user(request,db):
|
|
user=get_current_user(request,db)
|
|
if not user: return None
|
|
require_permission(db,user,"clients.view");return user
|
|
|
|
def _tenant(request,user): return int(request.session.get("active_tenant_id") or user.tenant_id)
|
|
def _branch(request,user):
|
|
raw=request.session.get("active_branch_id");return int(raw) if raw not in (None,"",0,"0") else None
|
|
|
|
def _can_manage(db,user):
|
|
try: require_permission(db,user,"clients.edit");return True
|
|
except Exception:return False
|
|
|
|
def _d(value): return date.fromisoformat(value) if value else None
|
|
|
|
@router.get("",response_class=HTMLResponse)
|
|
def dashboard(request:Request):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db)
|
|
if not user:return RedirectResponse('/login',303)
|
|
seed_registration_types(db);run_registration_lifecycle_once(db)
|
|
tid=_tenant(request,user); bid=_branch(request,user)
|
|
regq=select(ClientRegistration,Client,RegistrationType).join(Client,Client.id==ClientRegistration.client_id).join(RegistrationType,RegistrationType.id==ClientRegistration.registration_type_id).where(ClientRegistration.tenant_id==tid)
|
|
taskq=select(RegistrationRenewalTask,Client).join(Client,Client.id==RegistrationRenewalTask.client_id).where(RegistrationRenewalTask.tenant_id==tid,RegistrationRenewalTask.status.notin_(["completed","cancelled"]))
|
|
if bid: regq=regq.where(ClientRegistration.branch_id==bid);taskq=taskq.where(RegistrationRenewalTask.branch_id==bid)
|
|
regs=db.execute(regq.order_by(ClientRegistration.valid_until.asc().nullslast(),Client.client_name)).all();tasks=db.execute(taskq.order_by(RegistrationRenewalTask.cycle_due_date)).all()
|
|
counts={"active":0,"due":0,"expired":0,"tasks":len(tasks)}
|
|
for reg,_,_ in regs:
|
|
if reg.status=="expired":counts["expired"]+=1
|
|
elif reg.status in {"renewal_due","update_due"}:counts["due"]+=1
|
|
else:counts["active"]+=1
|
|
return templates.TemplateResponse("modules/registrations/templates/registrations/dashboard.html",_ctx(request,user,db,registrations=regs,tasks=tasks,counts=counts,can_manage=_can_manage(db,user),today=date.today()))
|
|
|
|
@router.get("/masters",response_class=HTMLResponse)
|
|
def masters(request:Request):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db)
|
|
if not user:return RedirectResponse('/login',303)
|
|
seed_registration_types(db);tid=_tenant(request,user)
|
|
return templates.TemplateResponse("modules/registrations/templates/registrations/masters.html",_ctx(request,user,db,types=db.execute(select(RegistrationType).order_by(RegistrationType.sort_order)).scalars().all(),rules=db.execute(select(RegistrationLifecycleRule,RegistrationType).join(RegistrationType).where(or_(RegistrationLifecycleRule.tenant_id.is_(None),RegistrationLifecycleRule.tenant_id==tid))).all(),templates_rows=db.execute(select(RegistrationDocumentTemplate,RegistrationType).join(RegistrationType).where(or_(RegistrationDocumentTemplate.tenant_id.is_(None),RegistrationDocumentTemplate.tenant_id==tid))).all(),can_manage=_can_manage(db,user)))
|
|
|
|
@router.post("/masters/types")
|
|
async def create_type(request:Request,code:str=Form(...),name:str=Form(...),category:str=Form("registration"),issuing_authority:str=Form(""),supports_expiry:bool=Form(False),supports_related_person:bool=Form(False),csrf_token:str=Form(...)):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db);validate_csrf(request,csrf_token);require_permission(db,user,"clients.edit")
|
|
code=code.strip().upper();existing=db.execute(select(RegistrationType).where(RegistrationType.code==code)).scalar_one_or_none()
|
|
if existing: existing.name=name.strip();existing.category=category;existing.issuing_authority=issuing_authority or None;existing.supports_expiry=supports_expiry;existing.supports_related_person=supports_related_person;existing.is_active=True
|
|
else: db.add(RegistrationType(code=code,name=name.strip(),category=category,issuing_authority=issuing_authority or None,supports_expiry=supports_expiry,supports_related_person=supports_related_person,is_system=False))
|
|
db.commit();return RedirectResponse('/registrations/masters',303)
|
|
|
|
@router.post("/masters/rules")
|
|
async def create_rule(request:Request,registration_type_id:int=Form(...),entity_type:str=Form(""),cycle_type:str=Form(...),frequency_months:str=Form(""),renewal_window_days:int=Form(60),reminder_days_csv:str=Form("90,60,30,15,7,0"),grace_period_days:int=Form(0),requires_client_approval:bool=Form(False),requires_partner_review:bool=Form(False),auto_create_task:bool=Form(False),csrf_token:str=Form(...)):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db);validate_csrf(request,csrf_token);require_permission(db,user,"clients.edit")
|
|
db.add(RegistrationLifecycleRule(tenant_id=_tenant(request,user),registration_type_id=registration_type_id,entity_type=entity_type or None,cycle_type=cycle_type,frequency_months=int(frequency_months) if frequency_months else None,renewal_window_days=renewal_window_days,reminder_days_csv=reminder_days_csv,grace_period_days=grace_period_days,requires_client_approval=requires_client_approval,requires_partner_review=requires_partner_review,auto_create_task=auto_create_task,created_by_user_id=user.id));db.commit();return RedirectResponse('/registrations/masters',303)
|
|
|
|
@router.post("/masters/documents")
|
|
async def create_doc_template(request:Request,registration_type_id:int=Form(...),action_type:str=Form(...),document_name:str=Form(...),description:str=Form(""),mandatory:bool=Form(False),csrf_token:str=Form(...)):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db);validate_csrf(request,csrf_token);require_permission(db,user,"clients.edit")
|
|
db.add(RegistrationDocumentTemplate(tenant_id=_tenant(request,user),registration_type_id=registration_type_id,action_type=action_type,document_name=document_name.strip(),description=description or None,mandatory=mandatory));db.commit();return RedirectResponse('/registrations/masters',303)
|
|
|
|
|
|
|
|
@router.get("/bulk", response_class=HTMLResponse)
|
|
def bulk_registration_page(
|
|
request: Request,
|
|
created: int = 0,
|
|
skipped: int = 0,
|
|
invalid: int = 0,
|
|
):
|
|
with CommonSessionLocal() as db:
|
|
user = _user(request, db)
|
|
if not user:
|
|
return RedirectResponse("/login", 303)
|
|
require_permission(db, user, "clients.edit")
|
|
seed_registration_types(db)
|
|
|
|
tenant_id = _tenant(request, user)
|
|
branch_id = _branch(request, user)
|
|
|
|
gstins_by_client = {}
|
|
gstin_rows = db.execute(
|
|
select(
|
|
ClientRegistration.client_id,
|
|
ClientRegistration.registration_number,
|
|
)
|
|
.join(
|
|
RegistrationType,
|
|
RegistrationType.id == ClientRegistration.registration_type_id,
|
|
)
|
|
.where(
|
|
ClientRegistration.tenant_id == tenant_id,
|
|
RegistrationType.code == "GSTIN",
|
|
)
|
|
.order_by(
|
|
ClientRegistration.client_id.asc(),
|
|
ClientRegistration.registration_number.asc(),
|
|
)
|
|
).all()
|
|
for gstin_client_id, gstin_number in gstin_rows:
|
|
number = (gstin_number or "").strip()
|
|
if number:
|
|
gstins_by_client.setdefault(int(gstin_client_id), []).append(number)
|
|
clients_query = select(Client).where(
|
|
Client.tenant_id == tenant_id,
|
|
Client.is_active.is_(True),
|
|
)
|
|
if branch_id:
|
|
clients_query = clients_query.where(Client.branch_id == branch_id)
|
|
|
|
clients = db.execute(
|
|
clients_query.order_by(Client.client_name, Client.client_code)
|
|
).scalars().all()
|
|
client_ids = [row.id for row in clients]
|
|
|
|
business_units = []
|
|
client_branches = []
|
|
if client_ids:
|
|
business_units = db.execute(
|
|
select(ClientBusinessUnit).where(
|
|
ClientBusinessUnit.tenant_id == tenant_id,
|
|
ClientBusinessUnit.client_id.in_(client_ids),
|
|
ClientBusinessUnit.is_active.is_(True),
|
|
).order_by(
|
|
ClientBusinessUnit.client_id,
|
|
ClientBusinessUnit.is_primary.desc(),
|
|
ClientBusinessUnit.business_name,
|
|
)
|
|
).scalars().all()
|
|
client_branches = db.execute(
|
|
select(ClientBranch).where(
|
|
ClientBranch.tenant_id == tenant_id,
|
|
ClientBranch.client_id.in_(client_ids),
|
|
ClientBranch.is_active.is_(True),
|
|
).order_by(
|
|
ClientBranch.client_id,
|
|
ClientBranch.is_primary.desc(),
|
|
ClientBranch.branch_name,
|
|
)
|
|
).scalars().all()
|
|
|
|
businesses_by_client: dict[int, list[ClientBusinessUnit]] = {}
|
|
for row in business_units:
|
|
businesses_by_client.setdefault(row.client_id, []).append(row)
|
|
|
|
branches_by_client: dict[int, list[ClientBranch]] = {}
|
|
for row in client_branches:
|
|
branches_by_client.setdefault(row.client_id, []).append(row)
|
|
|
|
types = db.execute(
|
|
select(RegistrationType).where(
|
|
RegistrationType.is_active.is_(True)
|
|
).order_by(RegistrationType.sort_order, RegistrationType.name)
|
|
).scalars().all()
|
|
|
|
rules = db.execute(
|
|
select(RegistrationLifecycleRule, RegistrationType).join(
|
|
RegistrationType,
|
|
RegistrationType.id == RegistrationLifecycleRule.registration_type_id,
|
|
).where(
|
|
or_(
|
|
RegistrationLifecycleRule.tenant_id.is_(None),
|
|
RegistrationLifecycleRule.tenant_id == tenant_id,
|
|
),
|
|
RegistrationLifecycleRule.is_active.is_(True),
|
|
).order_by(RegistrationType.name, RegistrationLifecycleRule.id)
|
|
).all()
|
|
|
|
consultants = db.execute(
|
|
select(ConsultantProfile).where(
|
|
ConsultantProfile.tenant_id == tenant_id,
|
|
ConsultantProfile.is_active.is_(True),
|
|
)
|
|
).scalars().all()
|
|
|
|
return templates.TemplateResponse(
|
|
"modules/registrations/templates/registrations/bulk.html",
|
|
_ctx(
|
|
request,
|
|
user,
|
|
db,
|
|
title="Bulk Registration Addition",
|
|
clients=clients,
|
|
businesses_by_client=businesses_by_client,
|
|
branches_by_client=branches_by_client,
|
|
types=types,
|
|
rules=rules,
|
|
consultants=consultants,
|
|
gstins_by_client=gstins_by_client,
|
|
created=created,
|
|
skipped=skipped,
|
|
invalid=invalid,
|
|
),
|
|
)
|
|
|
|
|
|
@router.post("/bulk")
|
|
async def bulk_registration_submit(
|
|
request: Request,
|
|
client_ids: list[int] = Form([]),
|
|
registration_type_id: int = Form(...),
|
|
default_scope: str = Form("client"),
|
|
jurisdiction: str = Form(""),
|
|
state_code: str = Form(""),
|
|
issue_date: str = Form(""),
|
|
effective_from: str = Form(""),
|
|
valid_until: str = Form(""),
|
|
next_action_date: str = Form(""),
|
|
lifecycle_rule_id: str = Form(""),
|
|
responsible_party: str = Form("firm"),
|
|
assigned_consultant_id: str = Form(""),
|
|
auto_create_task: bool = Form(False),
|
|
notes: str = Form(""),
|
|
csrf_token: str = Form(...),
|
|
):
|
|
validate_csrf(request, csrf_token)
|
|
|
|
with CommonSessionLocal() as db:
|
|
user = _user(request, db)
|
|
if not user:
|
|
return RedirectResponse("/login", 303)
|
|
require_permission(db, user, "clients.edit")
|
|
|
|
tenant_id = _tenant(request, user)
|
|
branch_id = _branch(request, user)
|
|
|
|
registration_type = db.get(RegistrationType, registration_type_id)
|
|
if not registration_type or not registration_type.is_active:
|
|
return RedirectResponse("/registrations/bulk?invalid=1", 303)
|
|
|
|
selected_ids = list(dict.fromkeys(int(value) for value in client_ids))
|
|
if not selected_ids:
|
|
return RedirectResponse("/registrations/bulk?invalid=1", 303)
|
|
|
|
clients_query = select(Client).where(
|
|
Client.tenant_id == tenant_id,
|
|
Client.id.in_(selected_ids),
|
|
Client.is_active.is_(True),
|
|
)
|
|
if branch_id:
|
|
clients_query = clients_query.where(Client.branch_id == branch_id)
|
|
|
|
permitted_clients = db.execute(clients_query).scalars().all()
|
|
clients_by_id = {row.id: row for row in permitted_clients}
|
|
|
|
form = await request.form()
|
|
created = 0
|
|
skipped = 0
|
|
invalid = 0
|
|
|
|
for client_id in selected_ids:
|
|
client = clients_by_id.get(client_id)
|
|
if not client:
|
|
invalid += 1
|
|
continue
|
|
|
|
registration_number = (
|
|
str(form.get(f"registration_number_{client_id}", ""))
|
|
.strip()
|
|
.upper()
|
|
)
|
|
if not registration_number:
|
|
invalid += 1
|
|
continue
|
|
|
|
business_unit_id = None
|
|
client_branch_id = None
|
|
|
|
raw_business_id = str(
|
|
form.get(f"business_unit_id_{client_id}", "")
|
|
).strip()
|
|
raw_branch_id = str(
|
|
form.get(f"client_branch_id_{client_id}", "")
|
|
).strip()
|
|
|
|
if raw_business_id:
|
|
business = db.get(ClientBusinessUnit, int(raw_business_id))
|
|
if (
|
|
not business
|
|
or business.tenant_id != tenant_id
|
|
or business.client_id != client.id
|
|
or not business.is_active
|
|
):
|
|
invalid += 1
|
|
continue
|
|
business_unit_id = business.id
|
|
|
|
if raw_branch_id:
|
|
client_branch = db.get(ClientBranch, int(raw_branch_id))
|
|
if (
|
|
not client_branch
|
|
or client_branch.tenant_id != tenant_id
|
|
or client_branch.client_id != client.id
|
|
or not client_branch.is_active
|
|
):
|
|
invalid += 1
|
|
continue
|
|
client_branch_id = client_branch.id
|
|
business_unit_id = client_branch.business_unit_id
|
|
|
|
if default_scope == "primary_business" and not business_unit_id:
|
|
business = db.execute(
|
|
select(ClientBusinessUnit).where(
|
|
ClientBusinessUnit.tenant_id == tenant_id,
|
|
ClientBusinessUnit.client_id == client.id,
|
|
ClientBusinessUnit.is_active.is_(True),
|
|
).order_by(
|
|
ClientBusinessUnit.is_primary.desc(),
|
|
ClientBusinessUnit.id,
|
|
)
|
|
).scalars().first()
|
|
if not business:
|
|
invalid += 1
|
|
continue
|
|
business_unit_id = business.id
|
|
|
|
if default_scope == "primary_branch" and not client_branch_id:
|
|
client_branch = db.execute(
|
|
select(ClientBranch).where(
|
|
ClientBranch.tenant_id == tenant_id,
|
|
ClientBranch.client_id == client.id,
|
|
ClientBranch.is_active.is_(True),
|
|
).order_by(
|
|
ClientBranch.is_primary.desc(),
|
|
ClientBranch.id,
|
|
)
|
|
).scalars().first()
|
|
if not client_branch:
|
|
invalid += 1
|
|
continue
|
|
client_branch_id = client_branch.id
|
|
business_unit_id = client_branch.business_unit_id
|
|
|
|
existing = db.execute(
|
|
select(ClientRegistration).where(
|
|
ClientRegistration.tenant_id == tenant_id,
|
|
ClientRegistration.registration_type_id == registration_type.id,
|
|
ClientRegistration.registration_number == registration_number,
|
|
)
|
|
).scalar_one_or_none()
|
|
if existing:
|
|
skipped += 1
|
|
continue
|
|
|
|
legal_name = str(form.get(f"legal_name_{client_id}", "")).strip()
|
|
trade_name = str(form.get(f"trade_name_{client_id}", "")).strip()
|
|
row_state = str(form.get(f"state_{client_id}", "")).strip()
|
|
|
|
db.add(
|
|
ClientRegistration(
|
|
tenant_id=tenant_id,
|
|
branch_id=client.branch_id,
|
|
client_id=client.id,
|
|
business_unit_id=business_unit_id,
|
|
client_branch_id=client_branch_id,
|
|
registration_type_id=registration_type.id,
|
|
registration_number=registration_number,
|
|
legal_name=legal_name or client.client_name,
|
|
trade_name=trade_name or client.trade_name or None,
|
|
state=row_state or client.state or None,
|
|
jurisdiction=jurisdiction.strip() or row_state or client.state or None,
|
|
state_code=state_code.strip().upper() or None,
|
|
issue_date=_d(issue_date),
|
|
effective_from=_d(effective_from),
|
|
valid_until=_d(valid_until),
|
|
next_action_date=_d(next_action_date),
|
|
lifecycle_rule_id=int(lifecycle_rule_id) if lifecycle_rule_id else None,
|
|
responsible_party=responsible_party,
|
|
assigned_user_id=client.partner_id,
|
|
assigned_consultant_id=(
|
|
int(assigned_consultant_id)
|
|
if assigned_consultant_id
|
|
else None
|
|
),
|
|
auto_create_task=auto_create_task,
|
|
status="active",
|
|
notes=notes.strip() or None,
|
|
created_by_user_id=user.id,
|
|
)
|
|
)
|
|
|
|
try:
|
|
db.flush()
|
|
except IntegrityError:
|
|
db.rollback()
|
|
skipped += 1
|
|
continue
|
|
|
|
created += 1
|
|
|
|
db.commit()
|
|
run_registration_lifecycle_once(db)
|
|
|
|
return RedirectResponse(
|
|
f"/registrations/bulk?created={created}&skipped={skipped}&invalid={invalid}",
|
|
status_code=303,
|
|
)
|
|
|
|
@router.get("/clients/{client_id}",response_class=HTMLResponse)
|
|
def client_register(request:Request,client_id:int):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db)
|
|
if not user:return RedirectResponse('/login',303)
|
|
client=db.get(Client,client_id)
|
|
if not client or client.tenant_id!=_tenant(request,user):return RedirectResponse('/registrations',303)
|
|
seed_registration_types(db)
|
|
regs=db.execute(select(ClientRegistration,RegistrationType).join(RegistrationType).where(ClientRegistration.client_id==client_id).order_by(RegistrationType.name)).all()
|
|
people=db.execute(select(ClientRelatedPerson).where(ClientRelatedPerson.client_id==client_id).order_by(ClientRelatedPerson.full_name)).scalars().all()
|
|
dscs=db.execute(select(ClientDigitalSignature,ClientRelatedPerson).join(ClientRelatedPerson).where(ClientDigitalSignature.client_id==client_id).order_by(ClientDigitalSignature.expires_on)).all()
|
|
rules=db.execute(select(RegistrationLifecycleRule).where(or_(RegistrationLifecycleRule.tenant_id.is_(None),RegistrationLifecycleRule.tenant_id==client.tenant_id),RegistrationLifecycleRule.is_active.is_(True))).scalars().all()
|
|
consultants=db.execute(select(ConsultantProfile).where(ConsultantProfile.tenant_id==client.tenant_id,ConsultantProfile.is_active.is_(True))).scalars().all()
|
|
return templates.TemplateResponse("modules/registrations/templates/registrations/client.html",_ctx(request,user,db,client=client,registrations=regs,people=people,dscs=dscs,types=db.execute(select(RegistrationType).where(RegistrationType.is_active.is_(True)).order_by(RegistrationType.sort_order)).scalars().all(),rules=rules,consultants=consultants,can_manage=_can_manage(db,user)))
|
|
|
|
@router.post("/clients/{client_id}/people")
|
|
async def add_person(request:Request,client_id:int,person_type:str=Form(...),full_name:str=Form(...),designation:str=Form(""),pan:str=Form(""),din:str=Form(""),date_of_birth:str=Form(""),appointment_date:str=Form(""),mobile:str=Form(""),email:str=Form(""),authorised_signatory:bool=Form(False),notes:str=Form(""),csrf_token:str=Form(...)):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db);validate_csrf(request,csrf_token);require_permission(db,user,"clients.edit");c=db.get(Client,client_id)
|
|
db.add(ClientRelatedPerson(tenant_id=c.tenant_id,client_id=c.id,person_type=person_type,full_name=full_name.strip(),designation=designation or None,pan=pan.strip().upper() or None,din=din or None,date_of_birth=_d(date_of_birth),appointment_date=_d(appointment_date),mobile=mobile or None,email=email or None,authorised_signatory=authorised_signatory,notes=notes or None,created_by_user_id=user.id));db.commit();return RedirectResponse(f'/registrations/clients/{client_id}',303)
|
|
|
|
@router.post("/clients/{client_id}/records")
|
|
async def add_registration(request:Request,client_id:int,registration_type_id:int=Form(...),related_person_id:str=Form(""),registration_number:str=Form(...),jurisdiction:str=Form(""),state_code:str=Form(""),issue_date:str=Form(""),effective_from:str=Form(""),valid_until:str=Form(""),next_action_date:str=Form(""),lifecycle_rule_id:str=Form(""),responsible_party:str=Form("firm"),assigned_user_id:str=Form(""),assigned_consultant_id:str=Form(""),auto_create_task:bool=Form(False),notes:str=Form(""),csrf_token:str=Form(...)):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db);validate_csrf(request,csrf_token);require_permission(db,user,"clients.edit");c=db.get(Client,client_id)
|
|
db.add(ClientRegistration(tenant_id=c.tenant_id,branch_id=c.branch_id,client_id=c.id,registration_type_id=registration_type_id,related_person_id=int(related_person_id) if related_person_id else None,registration_number=registration_number.strip().upper(),jurisdiction=jurisdiction or None,state_code=state_code or None,issue_date=_d(issue_date),effective_from=_d(effective_from),valid_until=_d(valid_until),next_action_date=_d(next_action_date),lifecycle_rule_id=int(lifecycle_rule_id) if lifecycle_rule_id else None,responsible_party=responsible_party,assigned_user_id=int(assigned_user_id) if assigned_user_id else c.partner_id,assigned_consultant_id=int(assigned_consultant_id) if assigned_consultant_id else None,auto_create_task=auto_create_task,notes=notes or None,created_by_user_id=user.id));db.commit();run_registration_lifecycle_once(db);return RedirectResponse(f'/registrations/clients/{client_id}',303)
|
|
|
|
@router.post("/clients/{client_id}/dsc")
|
|
async def add_dsc(request:Request,client_id:int,related_person_id:int=Form(...),certificate_serial_number:str=Form(""),provider:str=Form(""),token_make:str=Form(""),class_type:str=Form(""),issued_on:str=Form(""),expires_on:str=Form(...),custody_location:str=Form(""),renewal_responsibility:str=Form("firm"),assigned_consultant_id:str=Form(""),notes:str=Form(""),csrf_token:str=Form(...)):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db);validate_csrf(request,csrf_token);require_permission(db,user,"clients.edit");c=db.get(Client,client_id)
|
|
expiry=_d(expires_on)
|
|
dsc=ClientDigitalSignature(tenant_id=c.tenant_id,client_id=c.id,related_person_id=related_person_id,certificate_serial_number=certificate_serial_number or None,provider=provider or None,token_make=token_make or None,class_type=class_type or None,issued_on=_d(issued_on),expires_on=expiry,custody_location=custody_location or None,renewal_responsibility=renewal_responsibility,assigned_consultant_id=int(assigned_consultant_id) if assigned_consultant_id else None,notes=notes or None,created_by_user_id=user.id)
|
|
db.add(dsc)
|
|
dsc_type=db.execute(select(RegistrationType).where(RegistrationType.code=="DSC")).scalar_one()
|
|
serial=(certificate_serial_number or f"DSC-{client_id}-{related_person_id}-{expiry.isoformat()}").strip().upper()
|
|
existing=db.execute(select(ClientRegistration).where(ClientRegistration.tenant_id==c.tenant_id,ClientRegistration.registration_type_id==dsc_type.id,ClientRegistration.registration_number==serial)).scalar_one_or_none()
|
|
if not existing:
|
|
db.add(ClientRegistration(tenant_id=c.tenant_id,branch_id=c.branch_id,client_id=c.id,registration_type_id=dsc_type.id,related_person_id=related_person_id,registration_number=serial,issue_date=_d(issued_on),effective_from=_d(issued_on),valid_until=expiry,responsible_party=renewal_responsibility,assigned_user_id=c.partner_id,assigned_consultant_id=int(assigned_consultant_id) if assigned_consultant_id else None,auto_create_task=True,notes=notes or None,created_by_user_id=user.id))
|
|
db.commit();run_registration_lifecycle_once(db);return RedirectResponse(f'/registrations/clients/{client_id}',303)
|
|
|
|
@router.get("/tasks/{task_id}",response_class=HTMLResponse)
|
|
def task_detail(request:Request,task_id:int):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db)
|
|
if not user:return RedirectResponse('/login',303)
|
|
task=db.get(RegistrationRenewalTask,task_id)
|
|
if not task or task.tenant_id!=_tenant(request,user):return RedirectResponse('/registrations',303)
|
|
reg=db.get(ClientRegistration,task.registration_id);client=db.get(Client,task.client_id);rt=db.get(RegistrationType,reg.registration_type_id)
|
|
docs=db.execute(select(RegistrationRenewalTaskDocument).where(RegistrationRenewalTaskDocument.renewal_task_id==task.id)).scalars().all()
|
|
actions=db.execute(select(ClientRegistrationAction).where(ClientRegistrationAction.registration_id==reg.id).order_by(ClientRegistrationAction.created_at_utc.desc())).scalars().all()
|
|
return templates.TemplateResponse("modules/registrations/templates/registrations/task.html",_ctx(request,user,db,task=task,registration=reg,client=client,registration_type=rt,documents=docs,actions=actions,can_manage=_can_manage(db,user)))
|
|
|
|
@router.post("/tasks/{task_id}/status")
|
|
async def update_task(request:Request,task_id:int,status:str=Form(...),submitted_on:str=Form(""),acknowledgement_number:str=Form(""),notes:str=Form(""),csrf_token:str=Form(...)):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db);validate_csrf(request,csrf_token);require_permission(db,user,"clients.edit");task=db.get(RegistrationRenewalTask,task_id);task.status=status;task.submitted_on=_d(submitted_on);task.acknowledgement_number=acknowledgement_number or None;task.notes=notes or None;db.commit();return RedirectResponse(f'/registrations/tasks/{task_id}',303)
|
|
|
|
@router.post("/tasks/{task_id}/complete")
|
|
async def complete(request:Request,task_id:int,new_valid_until:str=Form(""),acknowledgement_number:str=Form(""),notes:str=Form(""),csrf_token:str=Form(...)):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db);validate_csrf(request,csrf_token);require_permission(db,user,"clients.edit");task=db.get(RegistrationRenewalTask,task_id);complete_renewal(db,task,new_valid_until=_d(new_valid_until),acknowledgement_number=acknowledgement_number or None,actor_user_id=user.id,notes=notes or None);return RedirectResponse(f'/registrations/tasks/{task_id}',303)
|
|
|
|
@router.post("/run-engine")
|
|
async def run_engine(request:Request,csrf_token:str=Form(...)):
|
|
with CommonSessionLocal() as db:
|
|
user=_user(request,db);validate_csrf(request,csrf_token);require_permission(db,user,"clients.edit");run_registration_lifecycle_once(db);return RedirectResponse('/registrations',303)
|