Files
LT_Janitorial_Quality_Control/app/models/notification_recipient.py
T

80 lines
3.2 KiB
Python

"""
app/models/notification_recipient.py
------------------------------------
Per-contract additional notification recipients.
Each row is ONE extra recipient attached to a Contract (Project) who should be
notified when selected notification events fire within that contract's
facilities — in ADDITION to whoever the global NotificationMatrix already
routes to.
A recipient is either:
- an existing app user (user_id set, email NULL) → in-app notification + email
- a free-form email (email set, user_id NULL) → email only
`event_types` is a JSON list of event_type keys (matching MATRIX_EVENTS) that
this recipient subscribes to for this contract. A recipient is notified only
when the firing event_type is present in this list. An empty list means the
recipient receives nothing (the add form requires at least one event).
Resolution happens centrally in notify_by_matrix() (app/utils/notifications.py),
which derives the contract from the event's facility / issue / inspection.
"""
import json
from app import db
from app.utils.time_utils import now_eastern
class ContractNotificationRecipient(db.Model):
__tablename__ = 'contract_notification_recipients'
id = db.Column(db.Integer, primary_key=True)
project_id = db.Column(
db.Integer,
db.ForeignKey('projects.id', ondelete='CASCADE'),
nullable=False, index=True,
)
# Exactly one of user_id / email is set (enforced in the route, not the DB).
user_id = db.Column(
db.Integer,
db.ForeignKey('users.id', ondelete='CASCADE'),
nullable=True, index=True,
)
email = db.Column(db.String(200), nullable=True)
# JSON list of event_type keys this recipient is subscribed to for this contract.
event_types = db.Column(db.Text, nullable=True) # JSON-encoded list[str]
created_at = db.Column(db.DateTime, nullable=False, default=now_eastern)
project = db.relationship('Project', foreign_keys=[project_id],
backref=db.backref('notification_recipients',
lazy='dynamic',
cascade='all, delete-orphan'))
user = db.relationship('User', foreign_keys=[user_id])
def get_event_types(self) -> list:
"""Return event_types as a Python list of strings."""
if not self.event_types:
return []
try:
result = json.loads(self.event_types)
return [e for e in result if isinstance(e, str) and e.strip()]
except (json.JSONDecodeError, TypeError):
return []
def set_event_types(self, values) -> None:
"""Store a list of event_type keys as a JSON string."""
clean = [v.strip() for v in (values or []) if isinstance(v, str) and v.strip()]
self.event_types = json.dumps(clean)
@property
def display_target(self) -> str:
"""Human-readable recipient label for the UI."""
if self.user_id and self.user:
return f'{self.user.display_name} ({self.user.email})'
return self.email or '—'
def __repr__(self):
who = f'user={self.user_id}' if self.user_id else f'email={self.email}'
return f'<ContractNotificationRecipient project={self.project_id} {who}>'