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
+174
View File
@@ -0,0 +1,174 @@
from __future__ import annotations
from datetime import datetime, timezone
from typing import Iterable
from sqlalchemy import Select, func, select, update
from sqlalchemy.orm import Session
from app.modules.alerts.models import UserAlert
from app.modules.core.iam.models import User
from app.modules.email_integration.event_service import send_alert_created_email
ALERT_PRIORITIES = ("low", "normal", "high", "critical")
ALERT_TYPES = (
"general",
"task_assigned",
"task_due",
"task_overdue",
"task_review",
"document_uploaded",
"clarification",
"attendance",
"leave",
"payroll",
"consultant",
"client",
)
def normalize_priority(priority: str | None) -> str:
value = (priority or "normal").strip().lower()
return value if value in ALERT_PRIORITIES else "normal"
def normalize_alert_type(alert_type: str | None) -> str:
value = (alert_type or "general").strip().lower()
return value or "general"
def create_alert(
db: Session,
*,
user_id: int,
title: str,
message: str | None = None,
tenant_id: int | None = None,
branch_id: int | None = None,
role_context: str | None = None,
alert_type: str = "general",
priority: str = "normal",
target_url: str | None = None,
created_by_user_id: int | None = None,
commit: bool = True,
) -> UserAlert:
alert = UserAlert(
tenant_id=tenant_id,
branch_id=branch_id,
user_id=user_id,
role_context=(role_context or None),
alert_type=normalize_alert_type(alert_type),
priority=normalize_priority(priority),
title=(title or "Alert").strip()[:255],
message=(message or None),
target_url=(target_url or None),
created_by_user_id=created_by_user_id,
)
db.add(alert)
db.flush()
try:
send_alert_created_email(db, alert)
except Exception:
# Email notification must never block in-app alert creation.
pass
if commit:
db.commit()
db.refresh(alert)
return alert
def create_bulk_alerts(
db: Session,
*,
user_ids: Iterable[int],
title: str,
message: str | None = None,
tenant_id: int | None = None,
branch_id: int | None = None,
role_context: str | None = None,
alert_type: str = "general",
priority: str = "normal",
target_url: str | None = None,
created_by_user_id: int | None = None,
) -> list[UserAlert]:
rows: list[UserAlert] = []
for user_id in sorted({int(uid) for uid in user_ids if uid}):
rows.append(
create_alert(
db,
user_id=user_id,
title=title,
message=message,
tenant_id=tenant_id,
branch_id=branch_id,
role_context=role_context,
alert_type=alert_type,
priority=priority,
target_url=target_url,
created_by_user_id=created_by_user_id,
commit=False,
)
)
db.commit()
for row in rows:
db.refresh(row)
return rows
def _user_alert_query(current_user: User) -> Select:
return select(UserAlert).where(UserAlert.user_id == current_user.id)
def list_my_alerts(
db: Session,
current_user: User,
*,
status: str = "all",
priority: str = "all",
limit: int = 100,
) -> list[UserAlert]:
q = _user_alert_query(current_user)
if status == "unread":
q = q.where(UserAlert.is_read.is_(False))
elif status == "read":
q = q.where(UserAlert.is_read.is_(True))
if priority in ALERT_PRIORITIES:
q = q.where(UserAlert.priority == priority)
q = q.order_by(UserAlert.is_read.asc(), UserAlert.created_at_utc.desc()).limit(max(1, min(limit, 500)))
return list(db.execute(q).scalars().all())
def count_unread_alerts(db: Session, current_user: User | None) -> int:
if not current_user:
return 0
value = db.execute(
select(func.count(UserAlert.id)).where(UserAlert.user_id == current_user.id, UserAlert.is_read.is_(False))
).scalar_one()
return int(value or 0)
def get_my_alert_or_404(db: Session, current_user: User, alert_id: int) -> UserAlert | None:
return db.execute(
select(UserAlert).where(UserAlert.id == alert_id, UserAlert.user_id == current_user.id)
).scalar_one_or_none()
def mark_alert_read(db: Session, current_user: User, alert_id: int) -> bool:
alert = get_my_alert_or_404(db, current_user, alert_id)
if not alert:
return False
if not alert.is_read:
alert.is_read = True
alert.read_at_utc = datetime.now(timezone.utc)
db.commit()
return True
def mark_all_alerts_read(db: Session, current_user: User) -> int:
result = db.execute(
update(UserAlert)
.where(UserAlert.user_id == current_user.id, UserAlert.is_read.is_(False))
.values(is_read=True, read_at_utc=datetime.now(timezone.utc))
)
db.commit()
return int(result.rowcount or 0)