All checks were successful
- Add centralized _is_noqa_suppressed() to BaseValidator with normalization (accepts both SEC001 and SEC-001 formats for ruff compatibility) - Wire noqa support into all 21 security and 18 performance check functions - Add ruff external config for SEC/PERF/MOD/EXC codes in pyproject.toml - Convert all 280 Python noqa comments to dashless format (ruff-compatible) - Add site/ to IGNORE_PATTERNS (excludes mkdocs build output) - Suppress 152 false positive findings (test passwords, seed data, validator self-references, Apple Wallet SHA1, etc.) - Security: 79 errors → 0, 60 warnings → 0 - Performance: 80 warnings → 77 (3 test script suppressions) - Add proposal doc with noqa inventory and remaining findings recommendations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
275 lines
10 KiB
Python
Executable File
275 lines
10 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Create a dummy Letzshop order for testing purposes.
|
|
|
|
This script creates a realistic Letzshop order in the database without
|
|
calling the actual Letzshop API. Useful for testing the order UI and workflow.
|
|
|
|
Usage:
|
|
python scripts/create_dummy_letzshop_order.py --store-id 1
|
|
python scripts/create_dummy_letzshop_order.py --store-id 1 --status confirmed
|
|
python scripts/create_dummy_letzshop_order.py --store-id 1 --with-tracking
|
|
"""
|
|
|
|
import argparse
|
|
import random
|
|
import string
|
|
import sys
|
|
from datetime import UTC, datetime, timedelta
|
|
from pathlib import Path
|
|
|
|
# Add project root to path
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
from app.core.database import SessionLocal
|
|
from app.modules.catalog.models import Product
|
|
from app.modules.orders.models import Order, OrderItem
|
|
from app.modules.tenancy.models import Store
|
|
|
|
|
|
def generate_order_number():
|
|
"""Generate a realistic Letzshop order number like R532332163."""
|
|
return f"R{random.randint(100000000, 999999999)}" # noqa: SEC042
|
|
|
|
|
|
def generate_shipment_number():
|
|
"""Generate a realistic shipment number like H74683403433."""
|
|
return f"H{random.randint(10000000000, 99999999999)}" # noqa: SEC042
|
|
|
|
|
|
def generate_hash_id():
|
|
"""Generate a realistic hash ID like nvDv5RQEmCwbjo."""
|
|
chars = string.ascii_letters + string.digits
|
|
return "".join(random.choice(chars) for _ in range(14)) # noqa: SEC042
|
|
|
|
|
|
def create_dummy_order(
|
|
db,
|
|
store_id: int,
|
|
status: str = "pending",
|
|
with_tracking: bool = False,
|
|
carrier: str = "greco",
|
|
items_count: int = 2,
|
|
):
|
|
"""Create a dummy Letzshop order with realistic data."""
|
|
|
|
# Verify store exists
|
|
store = db.query(Store).filter(Store.id == store_id).first()
|
|
if not store:
|
|
print(f"Error: Store with ID {store_id} not found")
|
|
return None
|
|
|
|
# Get some products from the store (or create placeholder if none exist)
|
|
products = db.query(Product).filter(
|
|
Product.store_id == store_id,
|
|
Product.is_active == True
|
|
).limit(items_count).all()
|
|
|
|
if not products:
|
|
print(f"Warning: No active products found for store {store_id}, creating placeholder")
|
|
# Create placeholder products with prices in cents
|
|
products = [
|
|
Product(
|
|
store_id=store_id,
|
|
store_sku="TEST-001",
|
|
gtin="4006381333931",
|
|
gtin_type="ean13",
|
|
price_cents=2999, # €29.99
|
|
is_active=True,
|
|
is_featured=False,
|
|
),
|
|
Product(
|
|
store_id=store_id,
|
|
store_sku="TEST-002",
|
|
gtin="5901234123457",
|
|
gtin_type="ean13",
|
|
price_cents=4999, # €49.99
|
|
is_active=True,
|
|
is_featured=False,
|
|
),
|
|
]
|
|
for p in products:
|
|
db.add(p)
|
|
db.flush()
|
|
|
|
# Generate order data
|
|
order_number = generate_order_number()
|
|
shipment_number = generate_shipment_number()
|
|
hash_id = generate_hash_id()
|
|
order_date = datetime.now(UTC) - timedelta(days=random.randint(0, 7)) # noqa: SEC042
|
|
|
|
# Customer data
|
|
first_names = ["Jean", "Marie", "Pierre", "Sophie", "Michel", "Anne", "Thomas", "Claire"]
|
|
last_names = ["Dupont", "Martin", "Bernard", "Dubois", "Thomas", "Robert", "Richard", "Petit"]
|
|
cities = ["Luxembourg", "Esch-sur-Alzette", "Differdange", "Dudelange", "Ettelbruck"]
|
|
|
|
customer_first = random.choice(first_names) # noqa: SEC042
|
|
customer_last = random.choice(last_names) # noqa: SEC042
|
|
customer_email = f"{customer_first.lower()}.{customer_last.lower()}@example.lu"
|
|
|
|
# Calculate totals in cents
|
|
subtotal_cents = sum((p.price_cents or 0) * random.randint(1, 3) for p in products[:items_count]) # noqa: SEC042
|
|
shipping_cents = 595 # €5.95
|
|
total_cents = subtotal_cents + shipping_cents
|
|
|
|
# Create the order
|
|
order = Order(
|
|
store_id=store_id,
|
|
customer_id=1, # Placeholder customer ID
|
|
order_number=f"LS-{store_id}-{order_number}",
|
|
channel="letzshop",
|
|
external_order_id=f"gid://letzshop/Order/{random.randint(10000, 99999)}", # noqa: SEC042
|
|
external_order_number=order_number,
|
|
external_shipment_id=hash_id,
|
|
shipment_number=shipment_number,
|
|
shipping_carrier=carrier,
|
|
status=status,
|
|
subtotal_cents=subtotal_cents,
|
|
tax_amount_cents=0,
|
|
shipping_amount_cents=shipping_cents,
|
|
discount_amount_cents=0,
|
|
total_amount_cents=total_cents,
|
|
currency="EUR",
|
|
# Customer snapshot
|
|
customer_first_name=customer_first,
|
|
customer_last_name=customer_last,
|
|
customer_email=customer_email,
|
|
customer_phone=f"+352 {random.randint(600000, 699999)}", # noqa: SEC042
|
|
customer_locale="fr",
|
|
# Shipping address
|
|
ship_first_name=customer_first,
|
|
ship_last_name=customer_last,
|
|
ship_company=None,
|
|
ship_address_line_1=f"{random.randint(1, 200)} Rue du Test", # noqa: SEC042
|
|
ship_address_line_2=None,
|
|
ship_city=random.choice(cities), # noqa: SEC042
|
|
ship_postal_code=f"L-{random.randint(1000, 9999)}", # noqa: SEC042
|
|
ship_country_iso="LU",
|
|
# Billing address (same as shipping)
|
|
bill_first_name=customer_first,
|
|
bill_last_name=customer_last,
|
|
bill_company=None,
|
|
bill_address_line_1=f"{random.randint(1, 200)} Rue du Test", # noqa: SEC042
|
|
bill_address_line_2=None,
|
|
bill_city=random.choice(cities), # noqa: SEC042
|
|
bill_postal_code=f"L-{random.randint(1000, 9999)}", # noqa: SEC042
|
|
bill_country_iso="LU",
|
|
# Timestamps
|
|
order_date=order_date,
|
|
)
|
|
|
|
# Set status-specific timestamps
|
|
if status in ["processing", "shipped", "delivered"]:
|
|
order.confirmed_at = order_date + timedelta(hours=random.randint(1, 24)) # noqa: SEC042
|
|
if status in ["shipped", "delivered"]:
|
|
order.shipped_at = order.confirmed_at + timedelta(days=random.randint(1, 3)) # noqa: SEC042
|
|
if status == "delivered":
|
|
order.delivered_at = order.shipped_at + timedelta(days=random.randint(1, 5)) # noqa: SEC042
|
|
if status == "cancelled":
|
|
order.cancelled_at = order_date + timedelta(hours=random.randint(1, 48)) # noqa: SEC042
|
|
|
|
# Add tracking if requested
|
|
if with_tracking or status == "shipped":
|
|
order.tracking_number = f"LU{random.randint(100000000, 999999999)}" # noqa: SEC042
|
|
order.tracking_provider = carrier
|
|
if carrier == "greco":
|
|
order.tracking_url = f"https://dispatchweb.fr/Tracky/Home/{shipment_number}"
|
|
|
|
db.add(order)
|
|
db.flush()
|
|
|
|
# Create order items with prices in cents
|
|
for _i, product in enumerate(products[:items_count]):
|
|
quantity = random.randint(1, 3) # noqa: SEC042
|
|
unit_price_cents = product.price_cents or 0
|
|
product_name = product.get_title("en") or f"Product {product.id}"
|
|
item = OrderItem(
|
|
order_id=order.id,
|
|
product_id=product.id,
|
|
product_name=product_name,
|
|
product_sku=product.store_sku,
|
|
gtin=product.gtin,
|
|
gtin_type=product.gtin_type,
|
|
quantity=quantity,
|
|
unit_price_cents=unit_price_cents,
|
|
total_price_cents=unit_price_cents * quantity,
|
|
external_item_id=f"gid://letzshop/InventoryUnit/{random.randint(10000, 99999)}", # noqa: SEC042
|
|
item_state="confirmed_available" if status != "pending" else None,
|
|
inventory_reserved=status != "pending",
|
|
inventory_fulfilled=status in ["shipped", "delivered"],
|
|
needs_product_match=False,
|
|
)
|
|
db.add(item)
|
|
|
|
db.commit()
|
|
db.refresh(order)
|
|
|
|
return order
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Create a dummy Letzshop order for testing")
|
|
parser.add_argument("--store-id", type=int, required=True, help="Store ID to create order for")
|
|
parser.add_argument(
|
|
"--status",
|
|
choices=["pending", "processing", "shipped", "delivered", "cancelled"],
|
|
default="pending",
|
|
help="Order status (default: pending)"
|
|
)
|
|
parser.add_argument(
|
|
"--carrier",
|
|
choices=["greco", "colissimo", "xpresslogistics"],
|
|
default="greco",
|
|
help="Shipping carrier (default: greco)"
|
|
)
|
|
parser.add_argument("--with-tracking", action="store_true", help="Add tracking information")
|
|
parser.add_argument("--items", type=int, default=2, help="Number of items in order (default: 2)")
|
|
|
|
args = parser.parse_args()
|
|
|
|
db = SessionLocal()
|
|
try:
|
|
print(f"Creating dummy Letzshop order for store {args.store_id}...")
|
|
print(f" Status: {args.status}")
|
|
print(f" Carrier: {args.carrier}")
|
|
print(f" Items: {args.items}")
|
|
print(f" With tracking: {args.with_tracking}")
|
|
print()
|
|
|
|
order = create_dummy_order(
|
|
db,
|
|
store_id=args.store_id,
|
|
status=args.status,
|
|
with_tracking=args.with_tracking,
|
|
carrier=args.carrier,
|
|
items_count=args.items,
|
|
)
|
|
|
|
if order:
|
|
print("Order created successfully!")
|
|
print()
|
|
print("Order Details:")
|
|
print(f" ID: {order.id}")
|
|
print(f" Internal Number: {order.order_number}")
|
|
print(f" Letzshop Order Number: {order.external_order_number}")
|
|
print(f" Shipment Number: {order.shipment_number}")
|
|
print(f" Hash ID: {order.external_shipment_id}")
|
|
print(f" Carrier: {order.shipping_carrier}")
|
|
print(f" Status: {order.status}")
|
|
print(f" Total: {order.total_amount} {order.currency}")
|
|
print(f" Customer: {order.customer_first_name} {order.customer_last_name}")
|
|
print(f" Email: {order.customer_email}")
|
|
print(f" Items: {len(order.items)}")
|
|
if order.tracking_number:
|
|
print(f" Tracking: {order.tracking_number}")
|
|
if order.tracking_url:
|
|
print(f" Tracking URL: {order.tracking_url}")
|
|
print()
|
|
print(f"View order at: http://localhost:8000/admin/letzshop/orders/{order.id}")
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|