288:class Attachment(Base, TimestampMixin): 289- __tablename__ = "attachments" 290- id = Column(Integer, primary_key=True) 291- user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True) 292- name = Column(String(300), nullable=False) 293- filename = Column(String(300), nullable=False) 294- stored_path = Column(String(500), nullable=False) # relative path under uploads/ 295- mime_type = Column(String(120), default="application/octet-stream") 296- size_bytes = Column(Integer, default=0) 297- kind = Column(String(30), default="file") # text|html|pdf|image|file 298- description = Column(Text, default="") 299- is_html_attachment = Column(Boolean, default=False) 300- html_attachment_body = Column(Text, default="") # for 'html' kind attachments (variable-substituted) 301: html_source_template_id = Column(Integer, ForeignKey("html_templates.id", ondelete="SET NULL")) 302- file_sha256 = Column(String(64), default="") 303- 304- user = relationship("User") 305- 306- 307-class CompanyPhoneNumber(Base, TimestampMixin): 308- __tablename__ = "company_phone_numbers" 309- id = Column(Integer, primary_key=True) 310- user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True) 311- label = Column(String(150), default="") 312- phone = Column(String(60), nullable=False) 313- is_active = Column(Boolean, default=True, nullable=False) 314- use_count = Column(Integer, default=0) 315- 316- 317-class SendJob(Base, TimestampMixin): 63:async def log_audit(db: AsyncSession, user_id: Optional[int], action: str, 63:async def log_audit(db: AsyncSession, user_id: Optional[int], action: str, 64- entity: Optional[str] = None, entity_id: Optional[int] = None, 65- detail: Optional[dict] = None, ip: Optional[str] = None) -> None: 66- """Audit log with automatic secret redaction. Imported lazily to avoid cycles.""" 67- from app.models import AuditLog 68- db.add(AuditLog( 69- user_id=user_id, action=action, entity=entity, entity_id=entity_id, 70- detail=sanitize_log_payload(detail or {}), ip_address=ip, 71- created_at=datetime.now(timezone.utc), 72- )) 73- await db.commit() 74- 75-