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:
@@ -16,24 +16,19 @@ import string
|
||||
from datetime import datetime, timezone
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import func, or_
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.exceptions import (
|
||||
UserNotFoundException,
|
||||
UserStatusChangeException,
|
||||
CannotModifySelfException,
|
||||
VendorNotFoundException,
|
||||
VendorAlreadyExistsException,
|
||||
VendorVerificationException,
|
||||
AdminOperationException,
|
||||
ValidationException,
|
||||
)
|
||||
from app.exceptions import (AdminOperationException, CannotModifySelfException,
|
||||
UserNotFoundException, UserStatusChangeException,
|
||||
ValidationException, VendorAlreadyExistsException,
|
||||
VendorNotFoundException,
|
||||
VendorVerificationException)
|
||||
from models.database.marketplace_import_job import MarketplaceImportJob
|
||||
from models.database.user import User
|
||||
from models.database.vendor import Role, Vendor, VendorUser
|
||||
from models.schema.marketplace_import_job import MarketplaceImportJobResponse
|
||||
from models.schema.vendor import VendorCreate
|
||||
from models.database.marketplace_import_job import MarketplaceImportJob
|
||||
from models.database.vendor import Vendor, Role, VendorUser
|
||||
from models.database.user import User
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -52,12 +47,11 @@ class AdminService:
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to retrieve users: {str(e)}")
|
||||
raise AdminOperationException(
|
||||
operation="get_all_users",
|
||||
reason="Database query failed"
|
||||
operation="get_all_users", reason="Database query failed"
|
||||
)
|
||||
|
||||
def toggle_user_status(
|
||||
self, db: Session, user_id: int, current_admin_id: int
|
||||
self, db: Session, user_id: int, current_admin_id: int
|
||||
) -> Tuple[User, str]:
|
||||
"""Toggle user active status."""
|
||||
user = self._get_user_by_id_or_raise(db, user_id)
|
||||
@@ -72,7 +66,7 @@ class AdminService:
|
||||
user_id=user_id,
|
||||
current_status="admin",
|
||||
attempted_action="toggle status",
|
||||
reason="Cannot modify another admin user"
|
||||
reason="Cannot modify another admin user",
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -95,7 +89,7 @@ class AdminService:
|
||||
user_id=user_id,
|
||||
current_status="active" if original_status else "inactive",
|
||||
attempted_action="toggle status",
|
||||
reason="Database update failed"
|
||||
reason="Database update failed",
|
||||
)
|
||||
|
||||
# ============================================================================
|
||||
@@ -103,7 +97,7 @@ class AdminService:
|
||||
# ============================================================================
|
||||
|
||||
def create_vendor_with_owner(
|
||||
self, db: Session, vendor_data: VendorCreate
|
||||
self, db: Session, vendor_data: VendorCreate
|
||||
) -> Tuple[Vendor, User, str]:
|
||||
"""
|
||||
Create vendor with owner user account.
|
||||
@@ -118,17 +112,23 @@ class AdminService:
|
||||
"""
|
||||
try:
|
||||
# Check if vendor code already exists
|
||||
existing_vendor = db.query(Vendor).filter(
|
||||
func.upper(Vendor.vendor_code) == vendor_data.vendor_code.upper()
|
||||
).first()
|
||||
existing_vendor = (
|
||||
db.query(Vendor)
|
||||
.filter(
|
||||
func.upper(Vendor.vendor_code) == vendor_data.vendor_code.upper()
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
if existing_vendor:
|
||||
raise VendorAlreadyExistsException(vendor_data.vendor_code)
|
||||
|
||||
# Check if subdomain already exists
|
||||
existing_subdomain = db.query(Vendor).filter(
|
||||
func.lower(Vendor.subdomain) == vendor_data.subdomain.lower()
|
||||
).first()
|
||||
existing_subdomain = (
|
||||
db.query(Vendor)
|
||||
.filter(func.lower(Vendor.subdomain) == vendor_data.subdomain.lower())
|
||||
.first()
|
||||
)
|
||||
|
||||
if existing_subdomain:
|
||||
raise ValidationException(
|
||||
@@ -140,15 +140,14 @@ class AdminService:
|
||||
|
||||
# Create owner user with owner_email
|
||||
from middleware.auth import AuthManager
|
||||
|
||||
auth_manager = AuthManager()
|
||||
|
||||
owner_username = f"{vendor_data.subdomain}_owner"
|
||||
owner_email = vendor_data.owner_email # ✅ For User authentication
|
||||
|
||||
# Check if user with this email already exists
|
||||
existing_user = db.query(User).filter(
|
||||
User.email == owner_email
|
||||
).first()
|
||||
existing_user = db.query(User).filter(User.email == owner_email).first()
|
||||
|
||||
if existing_user:
|
||||
# Use existing user as owner
|
||||
@@ -215,17 +214,17 @@ class AdminService:
|
||||
logger.error(f"Failed to create vendor: {str(e)}")
|
||||
raise AdminOperationException(
|
||||
operation="create_vendor_with_owner",
|
||||
reason=f"Failed to create vendor: {str(e)}"
|
||||
reason=f"Failed to create vendor: {str(e)}",
|
||||
)
|
||||
|
||||
def get_all_vendors(
|
||||
self,
|
||||
db: Session,
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
search: Optional[str] = None,
|
||||
is_active: Optional[bool] = None,
|
||||
is_verified: Optional[bool] = None
|
||||
self,
|
||||
db: Session,
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
search: Optional[str] = None,
|
||||
is_active: Optional[bool] = None,
|
||||
is_verified: Optional[bool] = None,
|
||||
) -> Tuple[List[Vendor], int]:
|
||||
"""Get paginated list of all vendors with filtering."""
|
||||
try:
|
||||
@@ -238,7 +237,7 @@ class AdminService:
|
||||
or_(
|
||||
Vendor.name.ilike(search_term),
|
||||
Vendor.vendor_code.ilike(search_term),
|
||||
Vendor.subdomain.ilike(search_term)
|
||||
Vendor.subdomain.ilike(search_term),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -255,8 +254,7 @@ class AdminService:
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to retrieve vendors: {str(e)}")
|
||||
raise AdminOperationException(
|
||||
operation="get_all_vendors",
|
||||
reason="Database query failed"
|
||||
operation="get_all_vendors", reason="Database query failed"
|
||||
)
|
||||
|
||||
def get_vendor_by_id(self, db: Session, vendor_id: int) -> Vendor:
|
||||
@@ -290,7 +288,7 @@ class AdminService:
|
||||
raise VendorVerificationException(
|
||||
vendor_id=vendor_id,
|
||||
reason="Database update failed",
|
||||
current_verification_status=original_status
|
||||
current_verification_status=original_status,
|
||||
)
|
||||
|
||||
def toggle_vendor_status(self, db: Session, vendor_id: int) -> Tuple[Vendor, str]:
|
||||
@@ -317,7 +315,7 @@ class AdminService:
|
||||
operation="toggle_vendor_status",
|
||||
reason="Database update failed",
|
||||
target_type="vendor",
|
||||
target_id=str(vendor_id)
|
||||
target_id=str(vendor_id),
|
||||
)
|
||||
|
||||
def delete_vendor(self, db: Session, vendor_id: int) -> str:
|
||||
@@ -345,15 +343,11 @@ class AdminService:
|
||||
db.rollback()
|
||||
logger.error(f"Failed to delete vendor {vendor_id}: {str(e)}")
|
||||
raise AdminOperationException(
|
||||
operation="delete_vendor",
|
||||
reason="Database deletion failed"
|
||||
operation="delete_vendor", reason="Database deletion failed"
|
||||
)
|
||||
|
||||
def update_vendor(
|
||||
self,
|
||||
db: Session,
|
||||
vendor_id: int,
|
||||
vendor_update # VendorUpdate schema
|
||||
self, db: Session, vendor_id: int, vendor_update # VendorUpdate schema
|
||||
) -> Vendor:
|
||||
"""
|
||||
Update vendor information (Admin only).
|
||||
@@ -387,11 +381,18 @@ class AdminService:
|
||||
update_data = vendor_update.model_dump(exclude_unset=True)
|
||||
|
||||
# Check subdomain uniqueness if changing
|
||||
if 'subdomain' in update_data and update_data['subdomain'] != vendor.subdomain:
|
||||
existing = db.query(Vendor).filter(
|
||||
Vendor.subdomain == update_data['subdomain'],
|
||||
Vendor.id != vendor_id
|
||||
).first()
|
||||
if (
|
||||
"subdomain" in update_data
|
||||
and update_data["subdomain"] != vendor.subdomain
|
||||
):
|
||||
existing = (
|
||||
db.query(Vendor)
|
||||
.filter(
|
||||
Vendor.subdomain == update_data["subdomain"],
|
||||
Vendor.id != vendor_id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if existing:
|
||||
raise ValidationException(
|
||||
f"Subdomain '{update_data['subdomain']}' is already taken"
|
||||
@@ -419,17 +420,16 @@ class AdminService:
|
||||
db.rollback()
|
||||
logger.error(f"Failed to update vendor {vendor_id}: {str(e)}")
|
||||
raise AdminOperationException(
|
||||
operation="update_vendor",
|
||||
reason=f"Database update failed: {str(e)}"
|
||||
operation="update_vendor", reason=f"Database update failed: {str(e)}"
|
||||
)
|
||||
|
||||
# Add this NEW method for transferring ownership:
|
||||
|
||||
def transfer_vendor_ownership(
|
||||
self,
|
||||
db: Session,
|
||||
vendor_id: int,
|
||||
transfer_data # VendorTransferOwnership schema
|
||||
self,
|
||||
db: Session,
|
||||
vendor_id: int,
|
||||
transfer_data, # VendorTransferOwnership schema
|
||||
) -> Tuple[Vendor, User, User]:
|
||||
"""
|
||||
Transfer vendor ownership to another user.
|
||||
@@ -466,9 +466,9 @@ class AdminService:
|
||||
old_owner = vendor.owner
|
||||
|
||||
# Get new owner
|
||||
new_owner = db.query(User).filter(
|
||||
User.id == transfer_data.new_owner_user_id
|
||||
).first()
|
||||
new_owner = (
|
||||
db.query(User).filter(User.id == transfer_data.new_owner_user_id).first()
|
||||
)
|
||||
|
||||
if not new_owner:
|
||||
raise UserNotFoundException(str(transfer_data.new_owner_user_id))
|
||||
@@ -487,26 +487,32 @@ class AdminService:
|
||||
|
||||
try:
|
||||
# Get Owner role for this vendor
|
||||
owner_role = db.query(Role).filter(
|
||||
Role.vendor_id == vendor_id,
|
||||
Role.name == "Owner"
|
||||
).first()
|
||||
owner_role = (
|
||||
db.query(Role)
|
||||
.filter(Role.vendor_id == vendor_id, Role.name == "Owner")
|
||||
.first()
|
||||
)
|
||||
|
||||
if not owner_role:
|
||||
raise ValidationException("Owner role not found for vendor")
|
||||
|
||||
# Get Manager role (to demote old owner)
|
||||
manager_role = db.query(Role).filter(
|
||||
Role.vendor_id == vendor_id,
|
||||
Role.name == "Manager"
|
||||
).first()
|
||||
manager_role = (
|
||||
db.query(Role)
|
||||
.filter(Role.vendor_id == vendor_id, Role.name == "Manager")
|
||||
.first()
|
||||
)
|
||||
|
||||
# Remove old owner from Owner role
|
||||
old_owner_link = db.query(VendorUser).filter(
|
||||
VendorUser.vendor_id == vendor_id,
|
||||
VendorUser.user_id == old_owner.id,
|
||||
VendorUser.role_id == owner_role.id
|
||||
).first()
|
||||
old_owner_link = (
|
||||
db.query(VendorUser)
|
||||
.filter(
|
||||
VendorUser.vendor_id == vendor_id,
|
||||
VendorUser.user_id == old_owner.id,
|
||||
VendorUser.role_id == owner_role.id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
if old_owner_link:
|
||||
if manager_role:
|
||||
@@ -525,10 +531,14 @@ class AdminService:
|
||||
)
|
||||
|
||||
# Check if new owner already has a vendor_user link
|
||||
new_owner_link = db.query(VendorUser).filter(
|
||||
VendorUser.vendor_id == vendor_id,
|
||||
VendorUser.user_id == new_owner.id
|
||||
).first()
|
||||
new_owner_link = (
|
||||
db.query(VendorUser)
|
||||
.filter(
|
||||
VendorUser.vendor_id == vendor_id,
|
||||
VendorUser.user_id == new_owner.id,
|
||||
)
|
||||
.first()
|
||||
)
|
||||
|
||||
if new_owner_link:
|
||||
# Update existing link to Owner role
|
||||
@@ -540,7 +550,7 @@ class AdminService:
|
||||
vendor_id=vendor_id,
|
||||
user_id=new_owner.id,
|
||||
role_id=owner_role.id,
|
||||
is_active=True
|
||||
is_active=True,
|
||||
)
|
||||
db.add(new_owner_link)
|
||||
|
||||
@@ -568,10 +578,12 @@ class AdminService:
|
||||
raise
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
logger.error(f"Failed to transfer ownership for vendor {vendor_id}: {str(e)}")
|
||||
logger.error(
|
||||
f"Failed to transfer ownership for vendor {vendor_id}: {str(e)}"
|
||||
)
|
||||
raise AdminOperationException(
|
||||
operation="transfer_vendor_ownership",
|
||||
reason=f"Ownership transfer failed: {str(e)}"
|
||||
reason=f"Ownership transfer failed: {str(e)}",
|
||||
)
|
||||
|
||||
# ============================================================================
|
||||
@@ -579,13 +591,13 @@ class AdminService:
|
||||
# ============================================================================
|
||||
|
||||
def get_marketplace_import_jobs(
|
||||
self,
|
||||
db: Session,
|
||||
marketplace: Optional[str] = None,
|
||||
vendor_name: Optional[str] = None,
|
||||
status: Optional[str] = None,
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
self,
|
||||
db: Session,
|
||||
marketplace: Optional[str] = None,
|
||||
vendor_name: Optional[str] = None,
|
||||
status: Optional[str] = None,
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
) -> List[MarketplaceImportJobResponse]:
|
||||
"""Get filtered and paginated marketplace import jobs."""
|
||||
try:
|
||||
@@ -596,7 +608,9 @@ class AdminService:
|
||||
MarketplaceImportJob.marketplace.ilike(f"%{marketplace}%")
|
||||
)
|
||||
if vendor_name:
|
||||
query = query.filter(MarketplaceImportJob.vendor_name.ilike(f"%{vendor_name}%"))
|
||||
query = query.filter(
|
||||
MarketplaceImportJob.vendor_name.ilike(f"%{vendor_name}%")
|
||||
)
|
||||
if status:
|
||||
query = query.filter(MarketplaceImportJob.status == status)
|
||||
|
||||
@@ -612,8 +626,7 @@ class AdminService:
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to retrieve marketplace import jobs: {str(e)}")
|
||||
raise AdminOperationException(
|
||||
operation="get_marketplace_import_jobs",
|
||||
reason="Database query failed"
|
||||
operation="get_marketplace_import_jobs", reason="Database query failed"
|
||||
)
|
||||
|
||||
# ============================================================================
|
||||
@@ -624,10 +637,7 @@ class AdminService:
|
||||
"""Get recently created vendors."""
|
||||
try:
|
||||
vendors = (
|
||||
db.query(Vendor)
|
||||
.order_by(Vendor.created_at.desc())
|
||||
.limit(limit)
|
||||
.all()
|
||||
db.query(Vendor).order_by(Vendor.created_at.desc()).limit(limit).all()
|
||||
)
|
||||
|
||||
return [
|
||||
@@ -638,7 +648,7 @@ class AdminService:
|
||||
"subdomain": v.subdomain,
|
||||
"is_active": v.is_active,
|
||||
"is_verified": v.is_verified,
|
||||
"created_at": v.created_at
|
||||
"created_at": v.created_at,
|
||||
}
|
||||
for v in vendors
|
||||
]
|
||||
@@ -663,7 +673,7 @@ class AdminService:
|
||||
"vendor_name": j.vendor_name,
|
||||
"status": j.status,
|
||||
"total_processed": j.total_processed or 0,
|
||||
"created_at": j.created_at
|
||||
"created_at": j.created_at,
|
||||
}
|
||||
for j in jobs
|
||||
]
|
||||
@@ -692,47 +702,53 @@ class AdminService:
|
||||
def _generate_temp_password(self, length: int = 12) -> str:
|
||||
"""Generate secure temporary password."""
|
||||
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
|
||||
return ''.join(secrets.choice(alphabet) for _ in range(length))
|
||||
return "".join(secrets.choice(alphabet) for _ in range(length))
|
||||
|
||||
def _create_default_roles(self, db: Session, vendor_id: int):
|
||||
"""Create default roles for a new vendor."""
|
||||
default_roles = [
|
||||
{
|
||||
"name": "Owner",
|
||||
"permissions": ["*"] # Full access
|
||||
},
|
||||
{"name": "Owner", "permissions": ["*"]}, # Full access
|
||||
{
|
||||
"name": "Manager",
|
||||
"permissions": [
|
||||
"products.*", "orders.*", "customers.view",
|
||||
"inventory.*", "team.view"
|
||||
]
|
||||
"products.*",
|
||||
"orders.*",
|
||||
"customers.view",
|
||||
"inventory.*",
|
||||
"team.view",
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Editor",
|
||||
"permissions": [
|
||||
"products.view", "products.edit",
|
||||
"orders.view", "inventory.view"
|
||||
]
|
||||
"products.view",
|
||||
"products.edit",
|
||||
"orders.view",
|
||||
"inventory.view",
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Viewer",
|
||||
"permissions": [
|
||||
"products.view", "orders.view",
|
||||
"customers.view", "inventory.view"
|
||||
]
|
||||
}
|
||||
"products.view",
|
||||
"orders.view",
|
||||
"customers.view",
|
||||
"inventory.view",
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
for role_data in default_roles:
|
||||
role = Role(
|
||||
vendor_id=vendor_id,
|
||||
name=role_data["name"],
|
||||
permissions=role_data["permissions"]
|
||||
permissions=role_data["permissions"],
|
||||
)
|
||||
db.add(role)
|
||||
|
||||
def _convert_job_to_response(self, job: MarketplaceImportJob) -> MarketplaceImportJobResponse:
|
||||
def _convert_job_to_response(
|
||||
self, job: MarketplaceImportJob
|
||||
) -> MarketplaceImportJobResponse:
|
||||
"""Convert database model to response schema."""
|
||||
return MarketplaceImportJobResponse(
|
||||
job_id=job.id,
|
||||
|
||||
Reference in New Issue
Block a user