style: apply black and isort formatting across entire codebase

- Standardize quote style (single to double quotes)
- Reorder and group imports alphabetically
- Fix line breaks and indentation for consistency
- Apply PEP 8 formatting standards

Also updated Makefile to exclude both venv and .venv from code quality checks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-28 19:30:17 +01:00
parent 13f0094743
commit 21c13ca39b
236 changed files with 8450 additions and 6545 deletions

View File

@@ -5,29 +5,37 @@ Vendor model representing entities that sell products or services.
This module defines the Vendor model along with its relationships to
other models such as User (owner), Product, Customer, Order, and MarketplaceImportJob.
"""
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String, Text, JSON, DateTime
import enum
from sqlalchemy import (JSON, Boolean, Column, DateTime, ForeignKey, Integer,
String, Text)
from sqlalchemy.orm import relationship
from app.core.config import settings
# Import Base from the central database module instead of creating a new one
from app.core.database import Base
from models.database.base import TimestampMixin
from app.core.config import settings
import enum
class Vendor(Base, TimestampMixin):
"""Represents a vendor in the system."""
__tablename__ = "vendors" # Name of the table in the database
id = Column(Integer, primary_key=True, index=True) # Primary key and indexed column for vendor ID
vendor_code = Column(String, unique=True, index=True,
nullable=False) # Unique, indexed, non-nullable vendor code column
subdomain = Column(String(100), unique=True, nullable=False,
index=True) # Unique, non-nullable subdomain column with indexing
id = Column(
Integer, primary_key=True, index=True
) # Primary key and indexed column for vendor ID
vendor_code = Column(
String, unique=True, index=True, nullable=False
) # Unique, indexed, non-nullable vendor code column
subdomain = Column(
String(100), unique=True, nullable=False, index=True
) # Unique, non-nullable subdomain column with indexing
name = Column(String, nullable=False) # Non-nullable name column for the vendor
description = Column(Text) # Optional text description column for the vendor
owner_user_id = Column(Integer, ForeignKey("users.id"),
nullable=False) # Foreign key to user ID of the vendor's owner
owner_user_id = Column(
Integer, ForeignKey("users.id"), nullable=False
) # Foreign key to user ID of the vendor's owner
# Contact information
contact_email = Column(String) # Optional email column for contact information
@@ -40,34 +48,46 @@ class Vendor(Base, TimestampMixin):
letzshop_csv_url_de = Column(String) # URL for German CSV in Letzshop
# Business information
business_address = Column(Text) # Optional text address column for business information
business_address = Column(
Text
) # Optional text address column for business information
tax_number = Column(String) # Optional tax number column for business information
# Status
is_active = Column(Boolean, default=True) # Boolean to indicate if the vendor is active
is_verified = Column(Boolean, default=False) # Boolean to indicate if the vendor is verified
is_active = Column(
Boolean, default=True
) # Boolean to indicate if the vendor is active
is_verified = Column(
Boolean, default=False
) # Boolean to indicate if the vendor is verified
# ========================================================================
# Relationships
# ========================================================================
owner = relationship("User", back_populates="owned_vendors") # Relationship with User model for the vendor's owner
vendor_users = relationship("VendorUser",
back_populates="vendor") # Relationship with VendorUser model for users in this vendor
products = relationship("Product",
back_populates="vendor") # Relationship with Product model for products of this vendor
customers = relationship("Customer",
back_populates="vendor") # Relationship with Customer model for customers of this vendor
orders = relationship("Order",
back_populates="vendor") # Relationship with Order model for orders placed by this vendor
marketplace_import_jobs = relationship("MarketplaceImportJob",
back_populates="vendor") # Relationship with MarketplaceImportJob model for import jobs related to this vendor
owner = relationship(
"User", back_populates="owned_vendors"
) # Relationship with User model for the vendor's owner
vendor_users = relationship(
"VendorUser", back_populates="vendor"
) # Relationship with VendorUser model for users in this vendor
products = relationship(
"Product", back_populates="vendor"
) # Relationship with Product model for products of this vendor
customers = relationship(
"Customer", back_populates="vendor"
) # Relationship with Customer model for customers of this vendor
orders = relationship(
"Order", back_populates="vendor"
) # Relationship with Order model for orders placed by this vendor
marketplace_import_jobs = relationship(
"MarketplaceImportJob", back_populates="vendor"
) # Relationship with MarketplaceImportJob model for import jobs related to this vendor
domains = relationship(
"VendorDomain",
back_populates="vendor",
cascade="all, delete-orphan",
order_by="VendorDomain.is_primary.desc()"
order_by="VendorDomain.is_primary.desc()",
) # Relationship with VendorDomain model for custom domains of the vendor
# Single theme relationship (ONE vendor = ONE theme)
@@ -77,14 +97,12 @@ class Vendor(Base, TimestampMixin):
"VendorTheme",
back_populates="vendor",
uselist=False,
cascade="all, delete-orphan"
cascade="all, delete-orphan",
) # Relationship with VendorTheme model for the active theme of the vendor
# Content pages relationship (vendor can override platform default pages)
content_pages = relationship(
"ContentPage",
back_populates="vendor",
cascade="all, delete-orphan"
"ContentPage", back_populates="vendor", cascade="all, delete-orphan"
) # Relationship with ContentPage model for vendor-specific content pages
def __repr__(self):
@@ -121,23 +139,16 @@ class Vendor(Base, TimestampMixin):
"accent": "#ec4899",
"background": "#ffffff",
"text": "#1f2937",
"border": "#e5e7eb"
},
"fonts": {
"heading": "Inter, sans-serif",
"body": "Inter, sans-serif"
"border": "#e5e7eb",
},
"fonts": {"heading": "Inter, sans-serif", "body": "Inter, sans-serif"},
"branding": {
"logo": None,
"logo_dark": None,
"favicon": None,
"banner": None
},
"layout": {
"style": "grid",
"header": "fixed",
"product_card": "modern"
"banner": None,
},
"layout": {"style": "grid", "header": "fixed", "product_card": "modern"},
"social_links": {},
"custom_css": None,
"css_variables": {
@@ -149,18 +160,22 @@ class Vendor(Base, TimestampMixin):
"--color-border": "#e5e7eb",
"--font-heading": "Inter, sans-serif",
"--font-body": "Inter, sans-serif",
}
},
}
def get_primary_color(self) -> str:
"""Get primary color from active theme."""
theme = self.get_effective_theme()
return theme.get("colors", {}).get("primary", "#6366f1") # Default to default theme if not found
return theme.get("colors", {}).get(
"primary", "#6366f1"
) # Default to default theme if not found
def get_logo_url(self) -> str:
"""Get logo URL from active theme."""
theme = self.get_effective_theme()
return theme.get("branding", {}).get("logo") # Return None or the logo URL if found
return theme.get("branding", {}).get(
"logo"
) # Return None or the logo URL if found
# ========================================================================
# Domain Helper Methods
@@ -177,7 +192,9 @@ class Vendor(Base, TimestampMixin):
@property
def all_domains(self):
"""Get all active domains (subdomain + custom domains)."""
domains = [f"{self.subdomain}.{settings.platform_domain}"] # Start with the main subdomain
domains = [
f"{self.subdomain}.{settings.platform_domain}"
] # Start with the main subdomain
for domain in self.domains:
if domain.is_active:
domains.append(domain.domain) # Add other active custom domains
@@ -186,6 +203,7 @@ class Vendor(Base, TimestampMixin):
class VendorUserType(str, enum.Enum):
"""Types of vendor users."""
OWNER = "owner" # Vendor owner (full access to vendor area)
TEAM_MEMBER = "member" # Team member (role-based access to vendor area)
@@ -222,14 +240,18 @@ class VendorUser(Base, TimestampMixin):
invitation_sent_at = Column(DateTime, nullable=True)
invitation_accepted_at = Column(DateTime, nullable=True)
is_active = Column(Boolean, default=False, nullable=False) # False until invitation accepted
is_active = Column(
Boolean, default=False, nullable=False
) # False until invitation accepted
"""Indicates whether the VendorUser role is active."""
# Relationships
vendor = relationship("Vendor", back_populates="vendor_users")
"""Relationship to the Vendor model, representing the associated vendor."""
user = relationship("User", foreign_keys=[user_id], back_populates="vendor_memberships")
user = relationship(
"User", foreign_keys=[user_id], back_populates="vendor_memberships"
)
"""Relationship to the User model, representing the user who holds this role within the vendor."""
inviter = relationship("User", foreign_keys=[invited_by])
@@ -287,6 +309,7 @@ class VendorUser(Base, TimestampMixin):
if self.is_owner:
# Return all possible permissions
from app.core.permissions import VendorPermissions
return list(VendorPermissions.__members__.values())
if self.role and self.role.permissions:
@@ -294,6 +317,7 @@ class VendorUser(Base, TimestampMixin):
return []
class Role(Base, TimestampMixin):
"""Represents a role within a vendor's system."""