Add bulk client registration addition
This commit is contained in:
@@ -3,11 +3,12 @@ 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
|
||||
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
|
||||
@@ -81,6 +82,319 @@ async def create_doc_template(request:Request,registration_type_id:int=Form(...)
|
||||
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)
|
||||
|
||||
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,
|
||||
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:
|
||||
|
||||
Reference in New Issue
Block a user