pounce/backend/app/models/price_alert.py
yves.gugger 8de107f5ee
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled
feat: Complete all missing features
Priorität 1 (Kritisch):
- Pricing Page: Stripe Checkout-Button mit API-Anbindung
- TLD Price Alert API + Frontend-Integration mit Toggle
- Blog Newsletter-Formular mit API-Anbindung

Priorität 2 (Wichtig):
- Favicon + Manifest.json für PWA-Support
- Dashboard: Stripe Billing Portal Link für zahlende Kunden
- Upgrade-Button für Scout-User

Priorität 3 (CI/CD):
- GitHub Actions CI Pipeline (lint, build, docker, security)
- GitHub Actions Deploy Pipeline (automated SSH deployment)

Neue Backend-Features:
- Price Alert Model + API (/api/v1/price-alerts)
- Toggle, Status-Check, CRUD-Operationen

Updates:
- README.md mit vollständiger API-Dokumentation
- Layout mit korrektem Manifest-Pfad
2025-12-08 14:55:41 +01:00

57 lines
2.1 KiB
Python

"""Price Alert model for TLD price notifications."""
from datetime import datetime
from typing import Optional
from sqlalchemy import String, Float, Boolean, DateTime, Integer, ForeignKey, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.database import Base
class PriceAlert(Base):
"""
Price Alert model for tracking user's TLD price subscriptions.
Users can subscribe to price alerts for specific TLDs and get notified
when prices change by a certain threshold.
"""
__tablename__ = "price_alerts"
__table_args__ = (
UniqueConstraint('user_id', 'tld', name='unique_user_tld_alert'),
)
id: Mapped[int] = mapped_column(primary_key=True, index=True)
# User who created the alert
user_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"), nullable=False)
# TLD to monitor (without dot, e.g., "com", "io")
tld: Mapped[str] = mapped_column(String(50), index=True, nullable=False)
# Alert settings
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
# Optional: only alert if price drops below this threshold
target_price: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
# Optional: only alert if price changes by this percentage
threshold_percent: Mapped[float] = mapped_column(Float, default=5.0) # 5% default
# Track last notification to avoid spam
last_notified_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
last_notified_price: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
# Timestamps
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
updated_at: Mapped[datetime] = mapped_column(
DateTime, default=datetime.utcnow, onupdate=datetime.utcnow
)
# Relationship to user
user: Mapped["User"] = relationship("User", backref="price_alerts")
def __repr__(self) -> str:
status = "active" if self.is_active else "paused"
return f"<PriceAlert user={self.user_id} tld=.{self.tld} ({status})>"