PhoenixKitEcommerce.Product (PhoenixKitEcommerce v0.2.0)

Copy Markdown View Source

Product schema for e-commerce shop.

Supports both physical and digital products with JSONB flexibility.

Fields

  • title - Product title (required)
  • slug - URL-friendly identifier (unique)
  • description - Short description
  • body_html - Full rich text description
  • status - draft | active | archived

  • product_type - physical | digital

  • vendor - Brand/manufacturer
  • tags - JSONB array of tags
  • price - Base price (required)
  • compare_at_price - Original price for discounts
  • cost_per_item - Cost for profit calculation
  • currency - ISO currency code (default: USD)
  • taxable - Subject to tax
  • weight_grams - Weight for shipping
  • requires_shipping - Needs physical delivery
  • made_to_order - Always available regardless of inventory
  • images - JSONB array of image objects
  • featured_image - Main image URL
  • seo_title - SEO title
  • seo_description - SEO description
  • file_uuid - Storage file reference (digital products)
  • download_limit - Max downloads (digital)
  • download_expiry_days - Days until download expires
  • metadata - JSONB for custom fields

Summary

Functions

Returns true if product is active.

Changeset for product creation and updates.

Returns true if product is digital.

Calculates discount percentage.

Returns the display price (compare_at_price if set, otherwise price).

Returns the list of localized field names.

Returns true if product has a discount (compare_at_price > price).

Returns true if product is physical.

Returns true if product requires shipping.

Slug generation for per-language slugs. Public because the AI translation adapter (AITranslatable.slug_base/3) derives a slug from a translated title.

Types

t()

@type t() :: %PhoenixKitEcommerce.Product{
  __meta__: term(),
  body_html: term(),
  category: term(),
  category_uuid: term(),
  compare_at_price: term(),
  cost_per_item: term(),
  created_by_user: term(),
  created_by_uuid: term(),
  currency: term(),
  description: term(),
  download_expiry_days: term(),
  download_limit: term(),
  featured_image: term(),
  featured_image_uuid: term(),
  file_uuid: term(),
  image_uuids: term(),
  images: term(),
  inserted_at: term(),
  made_to_order: term(),
  metadata: term(),
  price: term(),
  product_type: term(),
  requires_shipping: term(),
  seo_description: term(),
  seo_title: term(),
  slug: term(),
  status: term(),
  tags: term(),
  taxable: term(),
  title: term(),
  updated_at: term(),
  uuid: term(),
  vendor: term(),
  weight_grams: term()
}

Functions

active?(arg1)

Returns true if product is active.

changeset(product, attrs)

Changeset for product creation and updates.

digital?(arg1)

Returns true if product is digital.

discount_percentage(product)

Calculates discount percentage.

display_price(product)

Returns the display price (compare_at_price if set, otherwise price).

localized_fields()

Returns the list of localized field names.

on_sale?(product)

Returns true if product has a discount (compare_at_price > price).

physical?(arg1)

Returns true if product is physical.

requires_shipping?(product)

Returns true if product requires shipping.

slugify(text, lang \\ nil)

Slug generation for per-language slugs. Public because the AI translation adapter (AITranslatable.slug_base/3) derives a slug from a translated title.

lang is the language the text is IN, and it changes the answer: German ö expands to oe while Estonian ö folds to o, and Ukrainian Cyrillic follows Ukraine's own romanization rather than Russian's. The reduce above had lang bound and was discarding it, so every language got the neutral rule — a German title slugged grosse where German orthography wants groesse.

Passing nil still produces a correct slug, just not locale-tuned.