Skip to content

Market

Overview

The Market app powers Jend-Z's e-commerce functionality, enabling users to create stores, list products, process orders, and manage customer reviews. The system supports location-based commerce, allowing users to discover local businesses and products within their geographic area or specific communities.

Data Models

Store Model

The central Store model represents business storefronts on the platform.

Core Fields

  • id (UUID): Unique identifier
  • name (CharField): Store display name (max 255 characters)
  • owner (ForeignKey): Store owner (CustomUser)
  • slug (SlugField): Unique URL identifier (max 50 characters)
  • description (TextField): Store description (optional)
  • created_at (DateTimeField): Store creation timestamp
  • updated_at (DateTimeField): Last modification timestamp

Verification & Social

  • is_verified (BooleanField): Official verification status
  • instagram_url (URLField): Instagram profile link (validated format)

Location Fields

  • latitude (DecimalField): Geographic latitude coordinate
  • longitude (DecimalField): Geographic longitude coordinate
  • location (ForeignKey): Reference to Location model
  • community (ForeignKey): Reference to Community model (optional)

Media Fields

  • logo (ImageField): Store logo image
  • banner (ImageField): Store banner/cover image

Automatic Behaviors

  • Location Inheritance: If no coordinates provided, inherits owner's location
  • Slug Validation: Ensures unique, URL-safe store identifiers

Product Model

Represents items available for sale in stores.

Core Fields

  • id (UUID): Unique identifier
  • store (ForeignKey): Associated store
  • name (CharField): Product name (max 255 characters)
  • description (TextField): Product description (optional)
  • created_at (DateTimeField): Product creation timestamp
  • updated_at (DateTimeField): Last modification timestamp

Categorization

  • category (CharField): Product category from predefined choices

Available Categories:

electronics - "Electronics & Gadgets"
apparel - "Apparel & Accessories"
home_garden - "Home & Garden"
food_beverage - "Food & Beverage"
health_beauty - "Health & Beauty"
sports_outdoors - "Sports & Outdoors"
toys_games - "Toys & Games"
arts_crafts - "Arts, Crafts & Collectibles"
books_music - "Books, Music & Media"
automotive - "Automotive"
misc - "Miscellaneous / Other"

Pricing System

  • price_type (CharField): Pricing model
  • fixed: Fixed price
  • negotiable: Price open to negotiation
  • variable: Variable pricing
  • price (DecimalField): Product price (required for fixed pricing)

Inventory

  • stock (PositiveIntegerField): Available quantity

ProductImage Model

Supports multiple images per product.

Fields

  • id (UUID): Unique identifier
  • product (ForeignKey): Associated product
  • image (ImageField): Product image file

Storage: Images stored in products/images/ directory

Order Model

Tracks customer purchases and order status.

Core Fields

  • id (UUID): Unique identifier
  • user (ForeignKey): Customer who placed order
  • product (ForeignKey): Ordered product
  • quantity (PositiveIntegerField): Number of items ordered
  • total_price (DecimalField): Total order amount
  • created_at (DateTimeField): Order placement timestamp

Order Status

  • status (CharField): Current order status
  • pending: Order placed, awaiting processing
  • processing: Order being prepared
  • shipped: Order dispatched
  • delivered: Order completed

Review Model

Customer feedback and ratings system.

Fields

  • id (UUID): Unique identifier
  • user (ForeignKey): Review author
  • product (ForeignKey): Reviewed product
  • rating (PositiveIntegerField): Numeric rating
  • comment (TextField): Review text (optional)
  • created_at (DateTimeField): Review submission timestamp

API Endpoints

Store Management

1. List Stores

Endpoint: GET /api/stores/stores/

Description: Retrieve all stores with filtering and search capabilities.

Query Parameters:

  • location (UUID): Filter by location ID
  • slug (string): Filter by specific store slug
  • search (string): Search in store name and description
  • page (integer): Page number for pagination
  • page_size (integer): Items per page (default: 50, max: 100)

Response:

{
  "count": 25,
  "next": "http://api.example.com/api/stores/stores/?page=2",
  "previous": null,
  "results": [
    {
      "id": "store-uuid",
      "name": "Local Coffee Shop",
      "slug": "local-coffee-shop",
      "owner": {
        "username": "coffeelover",
        "display_name": "Coffee Lover"
      },
      "description": "Best coffee in the neighborhood, freshly roasted daily",
      "instagram_url": "https://instagram.com/localcoffeeshop",
      "location": {
        "id": "location-uuid",
        "name": "Downtown District"
      },
      "community": null,
      "logo": "https://example.com/media/stores/logos/coffee-logo.jpg",
      "banner": "https://example.com/media/stores/banners/coffee-banner.jpg",
      "created_at": "2024-01-15T10:30:00Z"
    }
  ]
}

2. Create Store

Endpoint: POST /api/stores/stores/

Authentication: Bearer token required

Content-Type: multipart/form-data (for image uploads)

Request Body:

{
  "name": "My Awesome Store",
  "slug": "my-awesome-store",
  "description": "We sell amazing products for everyone",
  "instagram_url": "https://instagram.com/myawesomestore",
  "location": "location-uuid",
  "community": "community-uuid",
  "logo": "logo_image_file",
  "banner": "banner_image_file"
}

Required Fields:

  • name: Store name
  • slug: Unique URL identifier

Slug Validation Rules:

  • Must be unique across all stores
  • Only letters, numbers, hyphens, and underscores allowed
  • Maximum 50 characters

Success Response:

{
  "id": "new-store-uuid",
  "name": "My Awesome Store",
  "slug": "my-awesome-store",
  "owner": {
    "username": "storeowner",
    "display_name": "Store Owner"
  },
  "description": "We sell amazing products for everyone",
  "instagram_url": "https://instagram.com/myawesomestore",
  "location": {
    "id": "location-uuid",
    "name": "Location Name"
  },
  "community": null,
  "logo": "https://example.com/media/stores/logos/logo.jpg",
  "banner": "https://example.com/media/stores/banners/banner.jpg",
  "created_at": "2024-01-15T15:45:00Z"
}

3. Get Store Details

Endpoint: GET /api/stores/stores/{store_id}/

Response: Same format as create store response.

4. Update Store

Endpoint: PUT /api/stores/stores/{store_id}/ or PATCH /api/stores/stores/{store_id}/

Authentication: Bearer token required (must be store owner)

Note: The is_verified field cannot be updated through this endpoint.

5. Delete Store

Endpoint: DELETE /api/stores/stores/{store_id}/

Authentication: Bearer token required (must be store owner)

6. Get My Stores

Endpoint: GET /api/stores/stores/my_store/

Authentication: Bearer token required

Description: Returns all stores owned by the current user.

Response:

[
  {
    "id": "store-uuid",
    "name": "My Store",
    "slug": "my-store",
    "owner": {
      "username": "current_user",
      "display_name": "Current User"
    },
    "description": "My store description",
    "instagram_url": null,
    "location": {
      "id": "location-uuid",
      "name": "Location Name"
    },
    "community": null,
    "logo": null,
    "banner": null,
    "created_at": "2024-01-15T10:30:00Z"
  }
]

7. Sync Store Location

Endpoint: PATCH /api/stores/stores/{store_id}/sync_location/

Authentication: Bearer token required (must be store owner)

Description: Synchronizes store location with owner's current location.

Prerequisites: User must have a valid location set.

Success Response:

{
  "id": "store-uuid",
  "name": "Store Name",
  "slug": "store-slug",
  "owner": {
    "username": "owner",
    "display_name": "Owner Name"
  },
  "location": {
    "id": "updated-location-uuid",
    "name": "Updated Location"
  }
}

Error Responses:

{
  "detail": "You do not have a valid location set."
}
{
  "detail": "You do not own this store."
}

Product Management

1. List Products

Endpoint: GET /api/stores/products/

Description: Retrieve products with filtering and search capabilities.

Query Parameters:

  • category (string): Filter by product category
  • price (decimal): Filter by exact price
  • store (UUID): Filter by store ID
  • search (string): Search in product name and description
  • page (integer): Page number for pagination
  • page_size (integer): Items per page (default: 20, max: 100)

Response:

{
  "count": 45,
  "next": "http://api.example.com/api/stores/products/?page=2",
  "previous": null,
  "results": [
    {
      "id": "product-uuid",
      "store": {
        "id": "store-uuid",
        "name": "Local Coffee Shop",
        "slug": "local-coffee-shop",
        "owner": {
          "username": "coffeelover",
          "display_name": "Coffee Lover"
        },
        "description": "Best coffee in town",
        "location": {
          "id": "location-uuid",
          "name": "Downtown District"
        }
      },
      "name": "Premium Coffee Beans",
      "description": "Freshly roasted arabica beans from Colombia",
      "category": "food_beverage",
      "price_type": "fixed",
      "price": "25.99",
      "stock": 50,
      "images": [
        {
          "id": "image-uuid",
          "image": "https://example.com/media/products/images/coffee-beans.jpg"
        }
      ],
      "created_at": "2024-01-15T12:00:00Z"
    }
  ]
}

2. Get Products by Location

Endpoint: GET /api/stores/products/by-location/

Description: Discover products available in a specific geographic area using location hierarchy.

Query Parameters:

  • location_id (UUID, required): Target location ID
  • search (string, optional): Search in product name and description
  • categories (string, optional): Comma-separated list of categories to filter

Location Hierarchy Search: The system searches through the location hierarchy to find the best match with available products, starting from the most specific level.

Response:

{
  "count": 15,
  "next": "http://api.example.com/api/stores/products/by-location/?page=2",
  "previous": null,
  "location_name": "Downtown District",
  "products": [
    {
      "id": "product-uuid",
      "store": {
        "id": "store-uuid",
        "name": "Local Boutique",
        "slug": "local-boutique"
      },
      "name": "Handmade Jewelry",
      "description": "Beautiful handcrafted jewelry pieces",
      "category": "arts_crafts",
      "price_type": "fixed",
      "price": "45.00",
      "stock": 12,
      "images": [
        {
          "id": "image-uuid",
          "image": "https://example.com/media/products/images/jewelry.jpg"
        }
      ],
      "created_at": "2024-01-15T14:20:00Z"
    }
  ]
}

Filter Examples:

GET /api/stores/products/by-location/?location_id=uuid&categories=electronics,apparel
GET /api/stores/products/by-location/?location_id=uuid&search=coffee&categories=food_beverage

No Products Response:

{
  "location_name": null,
  "products": []
}

3. Create Product

Endpoint: POST /api/stores/products/

Authentication: Bearer token required

Content-Type: multipart/form-data (for image uploads)

Request Body:

{
  "store_id": "store-uuid",
  "name": "Amazing Product",
  "description": "This product will change your life",
  "category": "electronics",
  "price_type": "fixed",
  "price": "99.99",
  "stock": 25,
  "uploaded_images": ["image1.jpg", "image2.jpg"]
}

Required Fields:

  • store_id: UUID of the store (must be owned by current user)
  • name: Product name
  • category: Product category from available choices
  • stock: Available quantity
  • price: Required when price_type is "fixed"

Price Type Rules:

  • Fixed: Must provide a price value
  • Negotiable: Price is optional, customers can negotiate
  • Variable: Price can vary based on options/customization

Success Response:

{
  "id": "new-product-uuid",
  "store": {
    "id": "store-uuid",
    "name": "My Store",
    "slug": "my-store"
  },
  "name": "Amazing Product",
  "description": "This product will change your life",
  "category": "electronics",
  "price_type": "fixed",
  "price": "99.99",
  "stock": 25,
  "images": [
    {
      "id": "image-uuid-1",
      "image": "https://example.com/media/products/images/image1.jpg"
    },
    {
      "id": "image-uuid-2",
      "image": "https://example.com/media/products/images/image2.jpg"
    }
  ],
  "created_at": "2024-01-15T16:30:00Z"
}

4. Update Product

Endpoint: PUT /api/stores/products/{product_id}/ or PATCH /api/stores/products/{product_id}/

Authentication: Bearer token required (must be store owner)

Request Body: Same as create product, with additional image management:

{
  "name": "Updated Product Name",
  "description": "Updated description",
  "price": "89.99",
  "stock": 30,
  "uploaded_images": ["new_image.jpg"],
  "images_to_delete": ["image-uuid-to-delete"]
}

Image Management:

  • uploaded_images: New images to add
  • images_to_delete: Array of image UUIDs to remove

5. Delete Product

Endpoint: DELETE /api/stores/products/{product_id}/

Authentication: Bearer token required (must be store owner)

Automatic Cleanup: All associated product images are automatically deleted from storage.

Order Management

1. List Orders

Endpoint: GET /api/stores/orders/

Authentication: Bearer token required

Description: Returns orders for the current user.

Response:

{
  "count": 8,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "order-uuid",
      "user": "user-uuid",
      "product": "product-uuid",
      "quantity": 2,
      "total_price": "49.98",
      "status": "delivered",
      "created_at": "2024-01-10T14:30:00Z"
    }
  ]
}

2. Create Order

Endpoint: POST /api/stores/orders/

Authentication: Bearer token required

Request Body:

{
  "product": "product-uuid",
  "quantity": 2
}

Automatic Calculation: Total price is automatically calculated as product.price * quantity.

Success Response:

{
  "id": "new-order-uuid",
  "user": "user-uuid",
  "product": "product-uuid",
  "quantity": 2,
  "total_price": "49.98",
  "status": "pending",
  "created_at": "2024-01-15T16:45:00Z"
}

3. Update Order Status

Endpoint: PATCH /api/stores/orders/{order_id}/

Authentication: Bearer token required

Request Body:

{
  "status": "shipped"
}

Available Status Values:

  • pending: Order placed, awaiting processing
  • processing: Order being prepared
  • shipped: Order dispatched
  • delivered: Order completed

Review System

1. List Reviews

Endpoint: GET /api/stores/reviews/

Authentication: Bearer token required

Response:

{
  "count": 12,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "review-uuid",
      "user": "user-uuid",
      "product": "product-uuid",
      "rating": 5,
      "comment": "Excellent product! Highly recommend.",
      "created_at": "2024-01-12T09:15:00Z"
    }
  ]
}

2. Create Review

Endpoint: POST /api/stores/reviews/

Authentication: Bearer token required

Request Body:

{
  "product": "product-uuid",
  "rating": 5,
  "comment": "Amazing quality and fast delivery!"
}

Required Fields:

  • product: UUID of the reviewed product
  • rating: Numeric rating (positive integer)

Success Response:

{
  "id": "new-review-uuid",
  "user": "user-uuid",
  "product": "product-uuid",
  "rating": 5,
  "comment": "Amazing quality and fast delivery!",
  "created_at": "2024-01-15T17:00:00Z"
}

Location Integration

Geographic Commerce

The market system integrates deeply with Jend-Z's location hierarchy to enable local commerce discovery.

Store Location Behavior

  • Automatic Location: Stores inherit owner's location if none specified
  • Location Sync: Owners can update store location to match their current location
  • Community Association: Stores can be associated with specific communities

Product Discovery

The location-based product search follows this hierarchy:

  1. Exact Location Match: Products in stores at the specified location
  2. Hierarchical Fallback: Searches broader geographic areas
  3. No Results: Returns empty response if no products found at any level

Location Hierarchy (most specific to least):

amenity → building → commercial → road → neighbourhood →
quarter → borough → suburb → municipality → hamlet →
village → town → city → district → county → state → country

Search Strategy

When searching for products by location, the system:

  1. Starts with the most specific location level available
  2. Finds all locations matching that level
  3. Returns products from stores in those locations
  4. If no products found, moves to the next broader level
  5. Continues until products are found or all levels exhausted

Image Management

Product Images

  • Multiple Images: Each product supports multiple images
  • Automatic Upload: Images processed during product creation/update
  • Storage Path: products/images/
  • Format Support: JPEG, PNG, GIF, WebP
  • URL Generation: Full URLs provided in API responses

Store Images

  • Logo: Square/circular store branding image
  • Banner: Rectangular cover/header image
  • Storage Paths:
  • Logos: stores/logos/
  • Banners: stores/banners/

Image Deletion

  • Automatic Cleanup: Product images deleted when product is removed
  • Selective Deletion: Individual images can be removed via images_to_delete field
  • File System Cleanup: Physical files removed from storage

Pricing System

Price Types

Fixed Pricing

  • Behavior: Set price, no negotiation
  • Validation: price field required
  • Use Case: Standard retail products

Negotiable Pricing

  • Behavior: Listed price is starting point for negotiation
  • Validation: price field optional
  • Use Case: Used goods, custom items, bulk orders

Variable Pricing

  • Behavior: Price depends on customization options
  • Validation: price field optional
  • Use Case: Services, custom orders, configurable products

Currency Handling

  • Decimal Precision: 2 decimal places for currency amounts
  • Storage: Stored as decimal values for precision
  • Display: Format according to local currency conventions

Search & Filtering

Product Search Capabilities

  • Fields: Name and description
  • Behavior: Case-insensitive partial matching
  • Usage: ?search=coffee

Category Filtering

  • Single Category: ?category=electronics
  • Multiple Categories: ?categories=electronics,apparel
  • Exact Match: Category must match predefined choices

Price Filtering

  • Exact Price: ?price=25.99
  • Use Case: Finding products at specific price points

Store Filtering

  • By Store: ?store=store-uuid
  • Use Case: Browse products from specific store

Store Search Capabilities

Text Search

  • Fields: Name and description
  • Usage: ?search=coffee shop

Location Filtering

  • By Location: ?location=location-uuid
  • Use Case: Find stores in specific area

Slug Filtering

  • By Slug: ?slug=my-store
  • Use Case: Direct store lookup

Permissions & Security

Store Permissions

  • Create: Any authenticated user
  • View: Public access
  • Update/Delete: Store owner only
  • Verification: Admin controlled

Product Permissions

  • Create: Store owner only
  • View: Public access
  • Update/Delete: Store owner only
  • Store Validation: Must own the target store

Order Permissions

  • Create: Any authenticated user
  • View: Order participant only (buyer/seller)
  • Update: Seller can update status

Review Permissions

  • Create: Any authenticated user
  • View: Public access
  • Update/Delete: Review author only

Analytics & Insights

Store Analytics

  • Product Count: Number of products per store
  • Order Volume: Track orders and revenue
  • Location Performance: Geographic sales patterns

Product Analytics

  • View Tracking: Monitor product page visits
  • Search Frequency: Track search queries
  • Category Performance: Popular product categories

Market Insights

  • Location Trends: Popular shopping areas
  • Category Demand: Most searched categories
  • Price Analysis: Price distribution by category

Error Handling

Common Error Responses

Store Slug Conflict:

{
  "slug": ["This store identifier is already taken."]
}

Invalid Slug Format:

{
  "slug": [
    "Enter a valid store handle consisting of letters, numbers, underscores, or hyphens."
  ]
}

Permission Denied:

{
  "detail": "You can only add products to your own store."
}

Price Validation Error:

{
  "price": ["Price is required when price_type is fixed."]
}

Store Not Found:

{
  "detail": "Store not found."
}

Location Sync Error:

{
  "detail": "You do not have a valid location set."
}

HTTP Status Codes

  • 200 OK: Successful operation
  • 201 Created: Resource created successfully
  • 400 Bad Request: Validation errors
  • 401 Unauthorized: Authentication required
  • 403 Forbidden: Permission denied
  • 404 Not Found: Resource not found
  • 500 Internal Server Error: Server error