Prepare ERP source for Gitea deployment

This commit is contained in:
A R R R Associates
2026-06-20 15:01:44 +05:30
commit 5c75eb6bd9
450 changed files with 67698 additions and 0 deletions
+206
View File
@@ -0,0 +1,206 @@
from __future__ import annotations
from datetime import date
from sqlalchemy import or_, select
from sqlalchemy.orm import Session, selectinload
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
SUBSCRIPTION_STATUSES = [
("draft", "Draft"),
("active", "Active"),
("on_hold", "On Hold"),
("completed", "Completed"),
("cancelled", "Cancelled"),
("inactive", "Inactive"),
]
ASSIGNMENT_ROLE_NAMES = ("Partner", "Branch Manager", "Staff")
def current_financial_year(today: date | None = None) -> str:
today = today or date.today()
if today.month >= 4:
start = today.year
else:
start = today.year - 1
return f"{start}-{str(start + 1)[-2:]}"
def assessment_year_from_financial_year(financial_year: str | None) -> str | None:
if not financial_year or "-" not in financial_year:
return None
start = int(str(financial_year).split("-")[0])
return f"{start + 1}-{str(start + 2)[-2:]}"
def normalize_financial_year(value: str | None) -> str:
value = (value or "").strip()
return value or current_financial_year()
def parse_date(value: str | None) -> date | None:
if not value:
return None
value = value.strip()
if not value:
return None
return date.fromisoformat(value)
def list_subscription_payload(
db: Session,
*,
tenant_id: int,
branch_id: int | None = None,
financial_year: str | None = None,
q: str = "",
include_inactive: bool = True,
):
fy = normalize_financial_year(financial_year)
query = (
select(ClientServiceSubscription)
.options(
selectinload(ClientServiceSubscription.client),
selectinload(ClientServiceSubscription.catalogue),
selectinload(ClientServiceSubscription.assigned_partner),
selectinload(ClientServiceSubscription.assigned_manager),
selectinload(ClientServiceSubscription.assigned_staff),
selectinload(ClientServiceSubscription.review_partner),
selectinload(ClientServiceSubscription.due_date_rule),
)
.where(
ClientServiceSubscription.tenant_id == tenant_id,
ClientServiceSubscription.financial_year == fy,
)
)
if branch_id:
query = query.where(ClientServiceSubscription.branch_id == branch_id)
if not include_inactive:
query = query.where(ClientServiceSubscription.is_active.is_(True))
if q.strip():
term = f"%{q.strip()}%"
query = (
query.join(Client, Client.id == ClientServiceSubscription.client_id)
.join(ServiceCatalogue, ServiceCatalogue.id == ClientServiceSubscription.service_catalogue_id)
.where(
or_(
Client.client_name.ilike(term),
Client.client_code.ilike(term),
ServiceCatalogue.service_code.ilike(term),
ServiceCatalogue.service_name.ilike(term),
)
)
)
return db.execute(
query.order_by(
ClientServiceSubscription.is_locked.asc(),
ClientServiceSubscription.is_active.desc(),
ClientServiceSubscription.id.desc(),
)
).scalars().all()
def get_subscription(db: Session, *, subscription_id: int, tenant_id: int) -> ClientServiceSubscription | None:
return db.execute(
select(ClientServiceSubscription)
.options(
selectinload(ClientServiceSubscription.client),
selectinload(ClientServiceSubscription.catalogue),
selectinload(ClientServiceSubscription.assigned_partner),
selectinload(ClientServiceSubscription.assigned_manager),
selectinload(ClientServiceSubscription.assigned_staff),
selectinload(ClientServiceSubscription.review_partner),
selectinload(ClientServiceSubscription.due_date_rule),
)
.where(
ClientServiceSubscription.id == subscription_id,
ClientServiceSubscription.tenant_id == tenant_id,
)
).scalar_one_or_none()
def get_existing_subscription(
db: Session,
*,
tenant_id: int,
client_id: int,
service_catalogue_id: int,
financial_year: str | None = None,
) -> ClientServiceSubscription | None:
return db.execute(
select(ClientServiceSubscription).where(
ClientServiceSubscription.tenant_id == tenant_id,
ClientServiceSubscription.client_id == client_id,
ClientServiceSubscription.service_catalogue_id == service_catalogue_id,
ClientServiceSubscription.financial_year == normalize_financial_year(financial_year),
)
).scalar_one_or_none()
def list_clients_for_assignment(db: Session, *, tenant_id: int, branch_id: int | None = None, partner_id: int | None = None):
query = select(Client).where(Client.tenant_id == tenant_id)
if branch_id:
query = query.where(Client.branch_id == branch_id)
if partner_id:
query = query.where(Client.partner_id == partner_id)
return db.execute(query.order_by(Client.client_name.asc())).scalars().all()
def list_enabled_services_for_assignment(db: Session, *, tenant_id: int):
return db.execute(
select(FirmServiceSelection)
.join(ServiceCatalogue, ServiceCatalogue.id == FirmServiceSelection.service_catalogue_id)
.options(selectinload(FirmServiceSelection.catalogue))
.where(
FirmServiceSelection.tenant_id == tenant_id,
FirmServiceSelection.is_enabled.is_(True),
ServiceCatalogue.is_active.is_(True),
)
.order_by(ServiceCatalogue.sort_order.asc(), ServiceCatalogue.service_name.asc())
).scalars().all()
def get_enabled_firm_service(db: Session, *, tenant_id: int, service_catalogue_id: int) -> FirmServiceSelection | None:
return db.execute(
select(FirmServiceSelection).where(
FirmServiceSelection.tenant_id == tenant_id,
FirmServiceSelection.service_catalogue_id == service_catalogue_id,
FirmServiceSelection.is_enabled.is_(True),
)
).scalar_one_or_none()
def list_assignable_users(db: Session, *, tenant_id: int, branch_id: int | None = None, role_names: tuple[str, ...] = ASSIGNMENT_ROLE_NAMES):
query = (
select(User)
.join(UserRole, UserRole.user_id == User.id)
.join(Role, Role.id == UserRole.role_id)
.where(User.tenant_id == tenant_id, User.is_active.is_(True), Role.name.in_(role_names))
)
if branch_id:
query = query.where(or_(User.branch_id == branch_id, User.branch_id.is_(None)))
return db.execute(query.order_by(User.full_name.asc(), User.email.asc()).distinct()).scalars().all()
def tenant_requires_review_partner(db: Session, *, tenant_id: int) -> bool:
tenant = db.get(Tenant, tenant_id)
firm_type = (getattr(tenant, "firm_type", None) or "partnership").strip().lower() if tenant else "partnership"
return firm_type == "partnership"
def review_partner_required_for_engagement(db: Session, *, tenant_id: int, engagement_type: str | None) -> bool:
return tenant_requires_review_partner(db, tenant_id=tenant_id) and (engagement_type or "").strip().lower() == "assurance"
def list_review_partners(db: Session, *, tenant_id: int, branch_id: int | None = None):
return list_assignable_users(db, tenant_id=tenant_id, branch_id=branch_id, role_names=("Partner",))