fix: correct tojson|safe usage in templates and update validator
- Remove |safe from |tojson in HTML attributes (x-data) - quotes must become " for browsers to parse correctly - Update LANG-002 and LANG-003 architecture rules to document correct |tojson usage patterns: - HTML attributes: |tojson (no |safe) - Script blocks: |tojson|safe - Fix validator to warn when |tojson|safe is used in x-data (breaks HTML attribute parsing) - Improve code quality across services, APIs, and tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
4
app/api/v1/vendor/analytics.py
vendored
4
app/api/v1/vendor/analytics.py
vendored
@@ -39,7 +39,9 @@ def get_vendor_analytics(
|
||||
period=data["period"],
|
||||
start_date=data["start_date"],
|
||||
imports=VendorAnalyticsImports(count=data["imports"]["count"]),
|
||||
catalog=VendorAnalyticsCatalog(products_added=data["catalog"]["products_added"]),
|
||||
catalog=VendorAnalyticsCatalog(
|
||||
products_added=data["catalog"]["products_added"]
|
||||
),
|
||||
inventory=VendorAnalyticsInventory(
|
||||
total_locations=data["inventory"]["total_locations"]
|
||||
),
|
||||
|
||||
5
app/api/v1/vendor/auth.py
vendored
5
app/api/v1/vendor/auth.py
vendored
@@ -25,7 +25,6 @@ from app.exceptions import InvalidCredentialsException
|
||||
from app.services.auth_service import auth_service
|
||||
from middleware.vendor_context import get_current_vendor
|
||||
from models.database.user import User
|
||||
from models.database.vendor import Vendor
|
||||
from models.schema.auth import LogoutResponse, UserLogin, VendorUserResponse
|
||||
|
||||
router = APIRouter(prefix="/auth")
|
||||
@@ -95,9 +94,7 @@ def vendor_login(
|
||||
f"User {user.username} attempted login to vendor {vendor.vendor_code} "
|
||||
f"but is not authorized"
|
||||
)
|
||||
raise InvalidCredentialsException(
|
||||
"You do not have access to this vendor"
|
||||
)
|
||||
raise InvalidCredentialsException("You do not have access to this vendor")
|
||||
else:
|
||||
# No vendor context - find which vendor this user belongs to
|
||||
vendor, vendor_role = auth_service.find_user_vendor(user)
|
||||
|
||||
4
app/api/v1/vendor/customers.py
vendored
4
app/api/v1/vendor/customers.py
vendored
@@ -90,7 +90,9 @@ def get_customer_orders(
|
||||
- Return order details
|
||||
"""
|
||||
vendor = vendor_service.get_vendor_by_id(db, current_user.token_vendor_id) # noqa: F841
|
||||
return CustomerOrdersResponse(orders=[], message="Customer orders coming in Slice 5")
|
||||
return CustomerOrdersResponse(
|
||||
orders=[], message="Customer orders coming in Slice 5"
|
||||
)
|
||||
|
||||
|
||||
@router.put("/{customer_id}", response_model=CustomerMessageResponse)
|
||||
|
||||
25
app/api/v1/vendor/inventory.py
vendored
25
app/api/v1/vendor/inventory.py
vendored
@@ -5,6 +5,7 @@ Vendor inventory management endpoints.
|
||||
Vendor Context: Uses token_vendor_id from JWT token (authenticated vendor API pattern).
|
||||
The get_current_vendor_api dependency guarantees token_vendor_id is present.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
@@ -36,7 +37,9 @@ def set_inventory(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Set exact inventory quantity (replaces existing)."""
|
||||
result = inventory_service.set_inventory(db, current_user.token_vendor_id, inventory)
|
||||
result = inventory_service.set_inventory(
|
||||
db, current_user.token_vendor_id, inventory
|
||||
)
|
||||
db.commit()
|
||||
return result
|
||||
|
||||
@@ -48,7 +51,9 @@ def adjust_inventory(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Adjust inventory (positive to add, negative to remove)."""
|
||||
result = inventory_service.adjust_inventory(db, current_user.token_vendor_id, adjustment)
|
||||
result = inventory_service.adjust_inventory(
|
||||
db, current_user.token_vendor_id, adjustment
|
||||
)
|
||||
db.commit()
|
||||
return result
|
||||
|
||||
@@ -60,7 +65,9 @@ def reserve_inventory(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Reserve inventory for an order."""
|
||||
result = inventory_service.reserve_inventory(db, current_user.token_vendor_id, reservation)
|
||||
result = inventory_service.reserve_inventory(
|
||||
db, current_user.token_vendor_id, reservation
|
||||
)
|
||||
db.commit()
|
||||
return result
|
||||
|
||||
@@ -72,7 +79,9 @@ def release_reservation(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Release reserved inventory (cancel order)."""
|
||||
result = inventory_service.release_reservation(db, current_user.token_vendor_id, reservation)
|
||||
result = inventory_service.release_reservation(
|
||||
db, current_user.token_vendor_id, reservation
|
||||
)
|
||||
db.commit()
|
||||
return result
|
||||
|
||||
@@ -84,7 +93,9 @@ def fulfill_reservation(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Fulfill reservation (complete order, remove from stock)."""
|
||||
result = inventory_service.fulfill_reservation(db, current_user.token_vendor_id, reservation)
|
||||
result = inventory_service.fulfill_reservation(
|
||||
db, current_user.token_vendor_id, reservation
|
||||
)
|
||||
db.commit()
|
||||
return result
|
||||
|
||||
@@ -96,7 +107,9 @@ def get_product_inventory(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Get inventory summary for a product."""
|
||||
return inventory_service.get_product_inventory(db, current_user.token_vendor_id, product_id)
|
||||
return inventory_service.get_product_inventory(
|
||||
db, current_user.token_vendor_id, product_id
|
||||
)
|
||||
|
||||
|
||||
@router.get("/inventory", response_model=InventoryListResponse)
|
||||
|
||||
16
app/api/v1/vendor/letzshop.py
vendored
16
app/api/v1/vendor/letzshop.py
vendored
@@ -323,9 +323,7 @@ def get_order(
|
||||
order_service = get_order_service(db)
|
||||
|
||||
try:
|
||||
order = order_service.get_order_or_raise(
|
||||
current_user.token_vendor_id, order_id
|
||||
)
|
||||
order = order_service.get_order_or_raise(current_user.token_vendor_id, order_id)
|
||||
except OrderNotFoundError:
|
||||
raise ResourceNotFoundException("LetzshopOrder", str(order_id))
|
||||
|
||||
@@ -396,7 +394,9 @@ def import_orders(
|
||||
orders_imported += 1
|
||||
|
||||
except Exception as e:
|
||||
errors.append(f"Error processing shipment {shipment.get('id')}: {e}")
|
||||
errors.append(
|
||||
f"Error processing shipment {shipment.get('id')}: {e}"
|
||||
)
|
||||
|
||||
db.commit()
|
||||
creds_service.update_sync_status(
|
||||
@@ -475,9 +475,7 @@ def confirm_order(
|
||||
return FulfillmentOperationResponse(
|
||||
success=True,
|
||||
message=f"Confirmed {len(inventory_unit_ids)} inventory units",
|
||||
confirmed_units=[
|
||||
u.get("id") for u in result.get("inventoryUnits", [])
|
||||
],
|
||||
confirmed_units=[u.get("id") for u in result.get("inventoryUnits", [])],
|
||||
)
|
||||
|
||||
except LetzshopClientError as e:
|
||||
@@ -699,7 +697,9 @@ def list_fulfillment_queue(
|
||||
|
||||
@router.get("/export")
|
||||
def export_products_letzshop(
|
||||
language: str = Query("en", description="Language for title/description (en, fr, de)"),
|
||||
language: str = Query(
|
||||
"en", description="Language for title/description (en, fr, de)"
|
||||
),
|
||||
include_inactive: bool = Query(False, description="Include inactive products"),
|
||||
current_user: User = Depends(get_current_vendor_api),
|
||||
db: Session = Depends(get_db),
|
||||
|
||||
24
app/api/v1/vendor/products.py
vendored
24
app/api/v1/vendor/products.py
vendored
@@ -181,18 +181,20 @@ def toggle_product_active(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Toggle product active status."""
|
||||
product = product_service.get_product(
|
||||
db, current_user.token_vendor_id, product_id
|
||||
)
|
||||
product = product_service.get_product(db, current_user.token_vendor_id, product_id)
|
||||
|
||||
product.is_active = not product.is_active
|
||||
db.commit()
|
||||
db.refresh(product)
|
||||
|
||||
status = "activated" if product.is_active else "deactivated"
|
||||
logger.info(f"Product {product_id} {status} for vendor {current_user.token_vendor_code}")
|
||||
logger.info(
|
||||
f"Product {product_id} {status} for vendor {current_user.token_vendor_code}"
|
||||
)
|
||||
|
||||
return ProductToggleResponse(message=f"Product {status}", is_active=product.is_active)
|
||||
return ProductToggleResponse(
|
||||
message=f"Product {status}", is_active=product.is_active
|
||||
)
|
||||
|
||||
|
||||
@router.put("/{product_id}/toggle-featured", response_model=ProductToggleResponse)
|
||||
@@ -202,15 +204,17 @@ def toggle_product_featured(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Toggle product featured status."""
|
||||
product = product_service.get_product(
|
||||
db, current_user.token_vendor_id, product_id
|
||||
)
|
||||
product = product_service.get_product(db, current_user.token_vendor_id, product_id)
|
||||
|
||||
product.is_featured = not product.is_featured
|
||||
db.commit()
|
||||
db.refresh(product)
|
||||
|
||||
status = "featured" if product.is_featured else "unfeatured"
|
||||
logger.info(f"Product {product_id} {status} for vendor {current_user.token_vendor_code}")
|
||||
logger.info(
|
||||
f"Product {product_id} {status} for vendor {current_user.token_vendor_code}"
|
||||
)
|
||||
|
||||
return ProductToggleResponse(message=f"Product {status}", is_featured=product.is_featured)
|
||||
return ProductToggleResponse(
|
||||
message=f"Product {status}", is_featured=product.is_featured
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user