Skip to main content

Overview

The E-commerce API is built around several core models that represent products, orders, customers, and promotional offers. Understanding these models and their relationships is essential for effective API integration.

Product Catalog

Product Model

The central model for product information. Location: catalogue/models.py:38

Key Fields

name
string
required
Product name (unique, indexed)
category
ForeignKey
required
Product category reference
description
text
required
Detailed product description
store
ForeignKey
Store/vendor that owns this product
base_price
decimal
required
Base price (10 digits, 2 decimal places)
shipping_fee
decimal
Shipping cost (6 digits, 2 decimal places)
rating
float
Average rating calculated from reviews
is_standalone
boolean
default:"true"
Whether product has variants. False if product has multiple variants.
total_stock_level
integer
required
Total stock across all variants
total_sold
integer
default:"0"
Total units sold across all variants
is_available
boolean
default:"true"
Product availability status

Important Methods

# Check if product has variants
product.has_variants  # Property: returns bool

# Update stock levels from variants
product.update_stock_status()

# Calculate and update rating from reviews
product.update_rating()

# Get active promotional offers
product.get_active_offers()

# Find best applicable offer for customer
product.find_best_offer(customer)

Database Indexes

indexes = [
    models.Index(fields=["category", "is_available"])
]

Category Model

Organizes products into hierarchical categories. Location: catalogue/models.py:20
name
string
required
Category name (max 50 chars, indexed)
slug
slug
URL-friendly identifier (auto-generated from name)

ProductVariant Model

Represents different variations of a product (e.g., size, color). Location: catalogue/models.py:147

Key Fields

product
ForeignKey
required
Parent product
sku
string
required
Stock Keeping Unit (unique, max 20 chars, indexed)
is_default
boolean
default:"false"
Whether this is the default variant
price_adjustment
decimal
default:"0.00"
Amount to add/subtract from base price
stock_level
integer
required
Available stock for this variant
quantity_sold
integer
default:"0"
Total units sold

Pricing Logic

# Calculate actual price
variant.actual_price  # base_price + price_adjustment

# Get discounted price for customer
variant.get_discount_price(customer)

# Get final price (with or without discount)
variant.get_final_price(customer)
Standalone products must have exactly one default variant. Products with is_standalone=False can have multiple variants.

ProductAttribute & VariantAttribute

Define customizable attributes for products and their variants. Location: catalogue/models.py:127-210

ProductAttribute

Defines available attributes for a product (e.g., “Size”, “Color”).
class ProductAttribute(models.Model):
    product = ForeignKey(Product, related_name="attributes")
    attribute = ForeignKey(Attribute)
    name = CharField(max_length=255)

VariantAttribute

Assigns specific values to variant attributes (e.g., “Size: Large”).
class VariantAttribute(models.Model):
    variant = ForeignKey(ProductVariant, related_name="attributes")
    attribute = ForeignKey(ProductAttribute)
    value = CharField(max_length=255)

ProductMedia Model

Handles images and videos for products with validation. Location: catalogue/models.py:212
product
ForeignKey
required
Associated product
file
FileField
required
Image or video file (validated)
is_primary
boolean
default:"false"
Whether this is the primary media

Supported Formats

Images:
  • JPEG (.jpg)
  • PNG (.png)
  • WebP (.webp)
Videos:
  • MP4 (.mp4)
  • WebM (.webm)

Review Model

Customer reviews and ratings for products. Location: catalogue/models.py:286
user
ForeignKey
required
Customer who wrote the review
product
ForeignKey
required
Product being reviewed
review_text
text
required
Review content
rating
integer
required
Rating (1-5): 1=Very Bad, 2=Unsatisfied, 3=Just There, 4=Satisfied, 5=Very Satisfied
sentiment
string
Sentiment analysis result: POSITIVE, Neutral, or Negative
sentiment_score
float
Numerical sentiment score
Reviews automatically update the product’s average rating on save.

Orders

Order Model

Represents a customer’s order. Location: orders/models.py:16

Key Fields

id
UUID
required
Unique order identifier (auto-generated)
customer
ForeignKey
required
Customer who placed the order
billing_address
ForeignKey
Billing address reference
status
string
required
Order status: paid, awaiting_payment, delivered, or cancelled
offer
ForeignKey
Applied order-level offer
voucher
OneToOneField
Applied voucher code (one per order)
discount_amount
decimal
default:"0.00"
Total discount from voucher
total_amount
decimal
Final order total (calculated on save)

Order Calculations

# Check if order is paid
order.is_paid  # Property: status == 'paid'

# Get total item count
order.items_count  # Sum of all item quantities

# Pricing calculations
order.subtotal             # Sum of all item prices
order.total_shipping       # Sum of all shipping fees
order.savings_on_items     # Discounts from product offers
order.discount_amount      # Discount from voucher
order.overall_savings      # Total discounts
order.total_amount         # subtotal + shipping - discounts

Database Indexes

indexes = [
    models.Index(fields=["customer", "-created"]),
    models.Index(fields=["status"]),
]

OrderItem Model

Individual items within an order. Location: orders/models.py:150
order
ForeignKey
required
Parent order
variant
ForeignKey
required
Product variant purchased
product
ForeignKey
required
Product reference
unit_price
decimal
required
Price per unit (editable=False)
quantity
integer
default:"1"
Number of units
shipping
decimal
Shipping fee for this item
offer
ForeignKey
Product-level offer applied
discount_amount
decimal
default:"0.00"
Discount from product offer
total_price
decimal
required
Total price for this line item (editable=False)

Creating from Cart

# Bulk create order items from cart
OrderItem.create_from_cart(order, cart)

Customers

Customer Model

Custom user model using email authentication. Location: customers/models.py:32
email
email
required
Email address (unique, indexed, used for login)
first_name
string
required
Customer’s first name
last_name
string
required
Customer’s last name
slug
AutoSlugField
URL-friendly identifier (auto-generated from full name)
date_of_birth
date
Customer’s birth date
address
OneToOneField
Primary address
is_vendor
boolean
default:"false"
Whether customer is also a vendor
last_purchase_date
datetime
Date of most recent purchase
products_bought_count
integer
default:"0"
Total number of unique products purchased
total_units_bought
integer
default:"0"
Total units purchased across all orders
products_bought
ManyToManyField
Product variants the customer has purchased
redeemed_vouchers
ManyToManyField
Vouchers the customer has used

Customer Properties

# Check if customer has made purchases
customer.is_first_time_buyer  # Property: no products_bought
Username field is disabled. Use email for authentication.

Address Model

Shipping and billing addresses. Location: customers/models.py:14
street_address
string
required
Street address (max 30 chars)
postal_code
integer
required
Postal/ZIP code
city
string
required
City name (max 50 chars)
state
string
required
State/province (max 50 chars)
country
string
required
Country name (max 30 chars)

Discounts & Promotions

Offer Model

Promotional offers applicable to products or orders. Location: discount/models.py:23

Key Fields

title
string
required
Offer title (max 50 chars)
store
ForeignKey
Store offering the promotion
offer_type
string
required
Type: product (product-level) or order (order-level)
discount_type
string
required
Type: percentage or fixed
discount_value
decimal
required
Discount amount (percentage or fixed value)
requires_voucher
boolean
default:"false"
Whether a voucher code is required
total_discount_offered
decimal
default:"0.00"
Total discount given (tracks usage)
max_discount_allowed
decimal
required
Maximum total discount this offer can provide
valid_from
datetime
required
Offer start date/time
valid_to
datetime
required
Offer end date/time
claimed_by
ManyToManyField
Customers who have claimed this offer

Offer Methods

# Check if offer is expired
offer.is_expired  # Property

# Apply discount to price
new_price = offer.apply_discount(original_price)

# Check if conditions are satisfied
valid, message = offer.satisfies_conditions(
    customer=customer,
    product=product,  # For product offers
    order=order,      # For order offers
    voucher=voucher   # If required
)

# Validate for specific context
offer.valid_for_customer(customer)
offer.valid_for_product(product, customer)
offer.valid_for_order(order)

Database Indexes

indexes = [
    models.Index(fields=["valid_from", "valid_to"]),
    models.Index(fields=["store"]),
]

OfferCondition Model

Defines eligibility criteria for offers. Location: discount/models.py:317
condition_type
string
required
Type: specific_products, specific_categories, customer_groups, or min_order_value
offer
ForeignKey
required
Associated offer
min_order_value
decimal
Minimum order value (for min_order_value type)
eligible_customers
string
Customer group: first_time_buyers or all_customers
eligible_products
ManyToManyField
Specific products (for specific_products type)
eligible_categories
ManyToManyField
Specific categories (for specific_categories type)
Each offer can have multiple conditions. All conditions must be satisfied for the offer to apply.

Voucher Model

Discount codes that customers can apply at checkout. Location: discount/models.py:413
name
string
required
Voucher name
description
text
required
Voucher description
code
string
required
Voucher code (unique, indexed, auto-uppercased)
offer
ForeignKey
required
Associated offer
usage_type
string
required
Type: single (one time), multiple (reusable), or once_per_customer
max_usage_limit
integer
required
Maximum number of times voucher can be used
num_of_usage
integer
default:"0"
Current usage count
valid_from
datetime
required
Voucher validity start
valid_to
datetime
required
Voucher validity end

Voucher Validation

# Check if voucher is valid
valid, message = voucher.is_valid(
    customer=customer,
    order_value=order_value
)

# Redeem voucher
voucher.redeem(customer, order_value)

# Check usage limits
voucher.within_usage_limits(customer)

# Check validity period
voucher.within_validity_period()

Database Indexes

indexes = [
    models.Index(fields=["code", "valid_to"]),
    models.Index(fields=["offer", "usage_type"]),
]

Model Relationships

Product Catalog Relationships

Order Relationships

Discount Relationships

Next Steps

Architecture

Learn about the overall architecture and design patterns

Filtering & Pagination

Learn how to filter, search, and paginate API results

Build docs developers (and LLMs) love