new init
This commit is contained in:
29
apps/backend/app/models/audit_log.py
Normal file
29
apps/backend/app/models/audit_log.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from app.core.database import Base
|
||||
from sqlalchemy import Column, Integer, String, DateTime, Enum, ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
import enum
|
||||
|
||||
|
||||
class AuditAction(enum.Enum):
|
||||
booking_create = "booking_create"
|
||||
booking_delete = "booking_delete"
|
||||
topup_create = "topup_create"
|
||||
# Weitere Aktionen können hier ergänzt werden, z. B.:
|
||||
# topup_confirm = "topup_confirm"
|
||||
# user_update = "user_update"
|
||||
|
||||
|
||||
class AuditLog(Base):
|
||||
__tablename__ = "audit_logs"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
action = Column(String, nullable=False)
|
||||
amount_cents = Column(Integer, nullable=True)
|
||||
old_balance_cents = Column(Integer, nullable=True)
|
||||
new_balance_cents = Column(Integer, nullable=True)
|
||||
info = Column(String, nullable=True)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
|
||||
user = relationship("User")
|
18
apps/backend/app/models/booking.py
Normal file
18
apps/backend/app/models/booking.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from sqlalchemy import Column, Integer, ForeignKey, DateTime, String
|
||||
from sqlalchemy.orm import relationship
|
||||
from app.core.database import Base
|
||||
from datetime import datetime
|
||||
|
||||
class Booking(Base):
|
||||
__tablename__ = "bookings"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
product_id = Column(Integer, ForeignKey("products.id"), nullable=False)
|
||||
amount = Column(Integer, nullable=False) # Anzahl der Produkte in dieser Buchung
|
||||
total_cents = Column(Integer, nullable=False) # Gesamtsumme in Cent (Preis * Anzahl)
|
||||
comment = Column(String, nullable=True)
|
||||
timestamp = Column(DateTime, default=datetime.utcnow, nullable=False) # Zeitpunkt der Buchung
|
||||
|
||||
user = relationship("User")
|
||||
product = relationship("Product")
|
11
apps/backend/app/models/config.py
Normal file
11
apps/backend/app/models/config.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from sqlalchemy import Column, String, Text, DateTime, func
|
||||
from app.core.database import Base
|
||||
|
||||
class Config(Base):
|
||||
__tablename__ = "config"
|
||||
|
||||
key = Column(String(64), primary_key=True, index=True)
|
||||
value = Column(Text, nullable=False, default="")
|
||||
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)
|
22
apps/backend/app/models/delivery.py
Normal file
22
apps/backend/app/models/delivery.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from app.core.database import Base
|
||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Text
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
|
||||
class Delivery(Base):
|
||||
__tablename__ = "deliveries"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
product_id = Column(Integer, ForeignKey("products.id", ondelete="CASCADE"), nullable=False, index=True)
|
||||
|
||||
amount = Column(Integer, nullable=False, default=0) # gelieferte Menge (Stück / Einheiten)
|
||||
price_cents = Column(Integer, nullable=False, default=0) # Einkaufspreis in Cent (gesamt oder pro Einheit – je nach Modell)
|
||||
delivered_at = Column(DateTime(timezone=True), nullable=True) # Lieferdatum
|
||||
supplier = Column(String, nullable=True) # Lieferant (frei)
|
||||
invoice_number = Column(String, nullable=True) # Rechnungsnummer
|
||||
created_by = Column(Integer, nullable=True) # optional: User-ID, der die Lieferung erfasst hat
|
||||
deposit_return_cents = Column(Integer, nullable=False, server_default="0")
|
||||
note = Column(Text, nullable=True) # oder String(1000)
|
||||
|
||||
# Rückverknüpfung zum Produkt
|
||||
product = relationship("Product", back_populates="deliveries")
|
31
apps/backend/app/models/product.py
Normal file
31
apps/backend/app/models/product.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from sqlalchemy import Column, Integer, String, Boolean, DateTime
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.orm import relationship
|
||||
from app.core.database import Base
|
||||
|
||||
class Product(Base):
|
||||
__tablename__ = "products"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String, nullable=False, unique=True, index=True)
|
||||
category = Column(String, nullable=True, index=True)
|
||||
volume_ml = Column(Integer, nullable=False)
|
||||
price_cents = Column(Integer, nullable=False)
|
||||
supplier_number = Column(String, nullable=True)
|
||||
image_url = Column(String, nullable=True)
|
||||
|
||||
stock = Column(Integer, nullable=False, default=0)
|
||||
is_active = Column(Boolean, default=True)
|
||||
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
||||
|
||||
pack_size = Column(Integer, nullable=False, default=1) # z.B. 6, 12, 24
|
||||
purchase_price_cents = Column(Integer, nullable=False, default=0)
|
||||
# >>> NEU: Gegenbeziehung zur Delivery-Relation
|
||||
deliveries = relationship(
|
||||
"Delivery",
|
||||
back_populates="product",
|
||||
cascade="all, delete-orphan",
|
||||
lazy="selectin",
|
||||
)
|
14
apps/backend/app/models/session.py
Normal file
14
apps/backend/app/models/session.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from app.core.database import Base
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey, DateTime
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
|
||||
class Session(Base):
|
||||
__tablename__ = "sessions"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
token = Column(String(64), unique=True, nullable=False, index=True)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
|
||||
user = relationship("User")
|
25
apps/backend/app/models/topup.py
Normal file
25
apps/backend/app/models/topup.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from app.core.database import Base
|
||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Enum
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
import enum
|
||||
|
||||
class TopupStatus(enum.Enum):
|
||||
pending = "pending"
|
||||
confirmed = "confirmed"
|
||||
rejected = "rejected"
|
||||
|
||||
class Topup(Base):
|
||||
__tablename__ = "topups"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
amount_cents = Column(Integer, nullable=False)
|
||||
status = Column(Enum(TopupStatus), default=TopupStatus.pending, nullable=False)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
confirmed_at = Column(DateTime, nullable=True)
|
||||
paypal_email = Column(String, nullable=True)
|
||||
note = Column(String, nullable=True)
|
||||
|
||||
|
||||
user = relationship("User")
|
42
apps/backend/app/models/user.py
Normal file
42
apps/backend/app/models/user.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from app.core.database import Base
|
||||
from sqlalchemy import Column, Integer, String, Boolean, DateTime, Enum, JSON
|
||||
import enum
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class UserRole(enum.Enum):
|
||||
user = "user"
|
||||
manager = "manager"
|
||||
admin = "admin"
|
||||
|
||||
|
||||
class User(Base):
|
||||
__tablename__ = "users"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String, nullable=False)
|
||||
email = Column(String, nullable=False, unique=True, index=True)
|
||||
hashed_password = Column(String, nullable=False)
|
||||
# Hinweis: hashed_pin als unique kann problematisch sein, falls None – in deiner DB ist es gesetzt.
|
||||
hashed_pin = Column(String, nullable=False, unique=True, index=True)
|
||||
|
||||
# Sichtbarkeit/Alias für die Stats-Seite
|
||||
alias = Column(String, nullable=True, unique=True)
|
||||
public_stats = Column(Boolean, nullable=False, default=False) # <— NEU: Opt-in
|
||||
|
||||
paypal_email = Column(String, nullable=True)
|
||||
role = Column(Enum(UserRole), nullable=False, default=UserRole.user)
|
||||
is_active = Column(Boolean, default=True)
|
||||
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
balance_cents = Column(Integer, nullable=False, default=0)
|
||||
favorites = Column(JSON, nullable=False, default=list)
|
||||
avatar_url = Column(String, nullable=True)
|
||||
|
||||
# PIN-Sicherheit (Lockout etc.)
|
||||
from sqlalchemy import String as SQLAString
|
||||
pin_lookup = Column(SQLAString(64), index=True, nullable=True) # HMAC-SHA256(PEPPER, pin)
|
||||
pin_fail_count = Column(Integer, nullable=False, default=0)
|
||||
pin_locked_until = Column(DateTime, nullable=True)
|
Reference in New Issue
Block a user