Skip to content

Design Review System

This document describes the hybrid design review workflow for custom designs.

Overview

The design review system uses a hybrid approach: - Auto-approve: Designs containing only text and clipart are automatically finalized - Manual review: Designs with user-uploaded images require staff review for print quality

This balances customer experience (fast turnaround for simple designs) with quality control (uploaded images need resolution/quality checks).

Design Status Workflow

draft → pending_review → finalized → in_production
         (optional)
Status Description When Used
draft Design is being edited Default status, active editing
pending_review Awaiting staff review Design has uploaded images
finalized Approved for production After staff approval or auto-approve
in_production Being manufactured Order is being fulfilled

Email Notifications

Design Pending Review

Trigger: Design status changes to pending_review

Template: design_pending_review.html / .txt

Subject: Je ontwerp voor {product_name} wordt beoordeeld

Content: - Explains uploaded images are being checked for print quality - Sets expectation: review within 24 hours - Preview thumbnail of the design - Link to view/edit the design

Design Approved

Trigger: Design status changes to finalized

Template: design_approved.html / .txt

Subject: Je ontwerp voor {product_name} is goedgekeurd!

Content: - Confirms design is approved and ready for production - Preview thumbnail - Link to designer or cart

Email Recipient Logic

The system uses a fallback pattern for email recipients:

def get_recipient_email(design):
    # 1. Prefer user's account email
    if design.user:
        return design.user.email

    # 2. Fallback to order email for guest checkout
    order_item = design.orderitem_set.select_related('order').first()
    if order_item and order_item.order:
        return order_item.order.email

    return None

This ensures guests who checkout without an account still receive design status emails.

Detecting User Uploads

The has_user_uploaded_images() method checks if a design contains user-uploaded images:

def has_user_uploaded_images(self):
    for view in ["front", "back", "left", "right"]:
        view_json = getattr(self, f"design_json_{view}", {})
        for obj in view_json.get("objects", []):
            if obj.get("type") in ("image", "Image"):
                src = obj.get("src", "")
                # User uploads in /uploads/, clipart in /clipart/
                if "/uploads/" in src or src.startswith("data:"):
                    return True
    return False

Detection logic: - User uploads are stored in /uploads/ directory - Clipart is stored in /clipart/ directory - Base64 data URLs (data:) are treated as user uploads

Frontend Components

ImageTab Info Banner

Location: frontend/components/ProductDesigner/components/tabs/ImageTab.tsx

A blue info banner warns users that uploaded images require review:

Let op: Geuploade afbeeldingen worden door ons team gecontroleerd op printkwaliteit. Je ontvangt binnen 24 uur een e-mail zodra je ontwerp is goedgekeurd.

Order Progress Stepper

Location: frontend/components/orders/OrderProgressStepper.tsx

Shows order fulfillment progress:

Betaald → In behandeling → Wordt bedrukt → Verzonden → Afgeleverd

Also displays: - Design review notice when status is pending_review - Waiting for payment notice when status is pending

Design Status Badges

On the order detail page, each order item shows a design status badge: - 🔍 Ontwerp wordt beoordeeld - pending_review - ✓ Ontwerp goedgekeurd - finalized

Admin Workflow

  1. Navigate to Django Admin → Designs → Custom Designs
  2. Filter by status: pending_review
  3. Review the design preview images
  4. Check uploaded image quality/resolution
  5. If approved: Change status to finalized
  6. Email is automatically sent to customer

API Endpoints

No new API endpoints were added. The existing design endpoints work with the new status:

PATCH /api/designs/{id}/
{
  "status": "pending_review"  // or "finalized"
}

Database Changes

Migration: 0007_add_pending_review_status

Adds pending_review to STATUS_CHOICES:

STATUS_CHOICES = [
    ("draft", "Draft"),
    ("pending_review", "Pending Review"),  # NEW
    ("finalized", "Finalized"),
    ("in_production", "In Production"),
]

Testing

Backend Tests

cd backend
python manage.py test apps.designs.tests -v 2

Frontend Tests

cd frontend
npm test -- --testPathPatterns="OrderDetailPage"

Manual E2E Test

  1. Upload image in designer → see info banner
  2. Checkout as guest → design gets pending_review status
  3. Check email received at order email address
  4. Admin: change design status to finalized
  5. Check approval email received
  6. Order detail page shows progress stepper

Configuration

No additional configuration is required. The feature uses existing environment variables:

Variable Purpose
FRONTEND_URL Base URL for designer links in emails
Email settings Existing Anymail/SMTP configuration