Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/api/exports.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from api.security import require_write_token
from api.storage_dependencies import get_storage_client
from backend.services.storage import StorageClient, StoredObject
from services.cnc_service import CNCService
from backend.services.cnc_service import CNCService
Comment on lines 26 to +27

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Badge Fix CNC service import path

The new import from backend.services.cnc_service import CNCService assumes the project root is on PYTHONPATH so backend is a package. The backend Dockerfile (and most local runs) execute uvicorn api.main:app with the working directory set to backend/, where only modules like api and services are importable. Under that setup the process raises ModuleNotFoundError: No module named 'backend' at startup, preventing any API routes—including the docs OpenAPI generation—from loading. The previous relative import from services.cnc_service import CNCService worked regardless of working directory. Revert to a relative import or adjust the runtime path so the server can start.

Useful? React with 👍 / 👎.


logger = logging.getLogger(__name__)
router = APIRouter(
Expand Down
2 changes: 1 addition & 1 deletion backend/api/routes_orders.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from api import models
from api.db import get_db
from api.schemas import Order, OrderCreate, OrderUpdate
from api.schemas import Order, OrderCreate, OrderResponse, OrderUpdate
from schemas.pricing import QuoteTotals

router = APIRouter(prefix="/api/orders", tags=["orders"])
Expand Down
31 changes: 28 additions & 3 deletions backend/api/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,23 @@ class OrderCheckoutPreferences(BaseModel):
cancel_url: AnyUrl | None = None


class OrderPayment(BaseModel):
provider: str | None = Field(default=None, max_length=50)
reference: str | None = Field(default=None, max_length=128)
status: str | None = Field(default=None, max_length=50)
amount: float | None = None
currency: str | None = Field(default=None, max_length=3)
processed_at: datetime | None = None
metadata: dict[str, Any] | None = Field(default=None, alias="metadata_", serialization_alias="metadata")


class OrderDesign(BaseModel):
step_url: AnyUrl | None = Field(default=None, alias="step_url")
ifc_url: AnyUrl | None = Field(default=None, alias="ifc_url")
preview_url: AnyUrl | None = Field(default=None, alias="preview_url")
metadata: dict[str, Any] | None = Field(default=None, alias="metadata_", serialization_alias="metadata")


class OrderBase(BaseModel):
quote_id: str
channel: OrderChannel = Field(default=OrderChannel.SHOPIFY)
Expand Down Expand Up @@ -249,12 +266,12 @@ class Order(OrderBase):
status: str | None = None
checkout_url: str | None = None
shopify_order_id: str | None = None
totals: OrderTotals
totals: QuoteTotals
created_at: datetime
updated_at: datetime


class OrderResponse(OrderSummary):
class OrderResponse(Order):
customer: OrderCustomer | None = None
shipping_address: OrderAddress | None = None
billing_address: OrderAddress | None = None
Expand All @@ -267,5 +284,13 @@ class OrderResponse(OrderSummary):


class OrderListResponse(BaseModel):
items: List[OrderSummary]
items: List[Order]
next_cursor: str | None = None


# Ensure forward references between order schemas are resolved for OpenAPI generation
Order.model_rebuild()
OrderCreate.model_rebuild()
OrderUpdate.model_rebuild()
OrderResponse.model_rebuild()
OrderListResponse.model_rebuild()
2 changes: 1 addition & 1 deletion backend/models/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import uuid
from datetime import datetime
from enum import Enum
from typing import Any
from typing import Any, TYPE_CHECKING

from sqlalchemy import (
Enum as SqlEnum,
Expand Down
16 changes: 15 additions & 1 deletion backend/scripts/generate_openapi.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
#!/usr/bin/env python3
from __future__ import annotations

import json
from pathlib import Path
import sys

# Ensure the project root is on the Python path when executing directly
PROJECT_ROOT = Path(__file__).resolve().parents[2]
BACKEND_ROOT = PROJECT_ROOT / "backend"

for path in (PROJECT_ROOT, BACKEND_ROOT):
path_str = str(path)
if path_str in sys.path:
sys.path.remove(path_str)
sys.path.insert(0, path_str)

from api.main import app

if __name__ == "__main__":
# Use FastAPI's baked schema to include all route/reg metadata
spec = app.openapi()
print(json.dumps(spec, indent=2))
print(json.dumps(spec, indent=2))
55 changes: 41 additions & 14 deletions build-docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,59 @@ npm install
npm run build
cd ..

# Create template-ui directory in docs/assets
echo "Setting up template UI in docs..."
mkdir -p docs/assets/template-ui
cp -r frontend/out/* docs/assets/template-ui/
# Create template-ui directory in docs/assets if static export exists
if [ -d frontend/out ]; then
echo "Setting up template UI in docs..."
mkdir -p docs/assets/template-ui
cp -r frontend/out/* docs/assets/template-ui/

# Ensure images are available in multiple locations
mkdir -p docs/assets/template-ui/images
cp -r frontend/public/images/* docs/assets/template-ui/images/
# Ensure images are available in multiple locations
mkdir -p docs/assets/template-ui/images
cp -r frontend/public/images/* docs/assets/template-ui/images/

# Also copy images to root of template-ui
cp -r frontend/public/images/* docs/assets/template-ui/
# Also copy images to root of template-ui
cp -r frontend/public/images/* docs/assets/template-ui/

# And to assets directory
mkdir -p docs/assets/images
cp -r frontend/public/images/* docs/assets/images/
# And to assets directory
mkdir -p docs/assets/images
cp -r frontend/public/images/* docs/assets/images/
else
echo "Warning: frontend/out not found; skipping template UI asset copy." >&2
fi

# Build MkDocs site (which will include the template UI)
echo "Building MkDocs site..."

# Ensure the backend virtualenv is activated before generating the OpenAPI spec
if [ -d "backend/.venv" ]; then
# shellcheck disable=SC1091
source backend/.venv/bin/activate
else
echo "Error: backend virtualenv not found at backend/.venv" >&2
exit 1
fi

export HYGRAPH_WEBHOOK_SECRET="${HYGRAPH_WEBHOOK_SECRET:-dummy-hygraph-secret}"
export SHOPIFY_STORE="${SHOPIFY_STORE:-dummy-store}"
export SHOPIFY_TOKEN="${SHOPIFY_TOKEN:-dummy-shopify-token}"
export SHOPIFY_WEBHOOK_SECRET="${SHOPIFY_WEBHOOK_SECRET:-dummy-shopify-webhook}"
export PYTHONPATH="${PWD}${PYTHONPATH:+:$PYTHONPATH}"

python backend/scripts/generate_openapi.py > docs/API_SPEC.md

# Deactivate the virtualenv to avoid affecting subsequent commands
deactivate

mkdocs build

# Copy images to multiple locations in the site directory
mkdir -p site/assets/template-ui/images
cp -r frontend/public/images/* site/assets/template-ui/images/

# Copy to root of template-ui
cp -r frontend/public/images/* site/assets/template-ui/
# Copy to root of template-ui if available
if [ -d frontend/out ]; then
cp -r frontend/public/images/* site/assets/template-ui/
fi

# Copy to site/assets/images
mkdir -p site/assets/images
Expand Down
Loading
Loading