E-commerce Example
A comprehensive e-commerce application demonstrating complex models and relationships.
Overview​
This example demonstrates:
- Complex model relationships (OneToOne, ForeignKey, ManyToMany)
- All PostgreSQL data types
- Hierarchical categories
- Product variants and inventory
- Orders and payments
Key Models​
Product​
type Product struct {
schema.BaseSchema
}
func (Product) Fields() []schema.Field {
return []schema.Field{
schema.Int64("id").Primary().AutoIncrement().Build(),
schema.String("name").Required().MaxLength(200).Build(),
schema.String("sku").Unique().MaxLength(100).Build(),
schema.Text("description").Build(),
schema.Decimal("price").
MaxDigits(10).
DecimalPlaces(2).
Required().
Build(),
schema.Bool("active").Default(true).Build(),
schema.Time("created_at").AutoNowAdd().Build(),
}
}
func (Product) Relations() []schema.Relation {
return []schema.Relation{
relations.ForeignKey("brand", "Brand").
OnDelete(schema.SetNull),
relations.ForeignKey("supplier", "Supplier").
OnDelete(schema.SetNull),
relations.ManyToMany("categories", "Category").
Through("product_categories"),
relations.OneToMany("variants", "ProductVariant").
RelatedName("product"),
}
}
Order​
type Order struct {
schema.BaseSchema
}
func (Order) Fields() []schema.Field {
return []schema.Field{
schema.Int64("id").Primary().AutoIncrement().Build(),
schema.String("order_number").Unique().MaxLength(50).Build(),
schema.Decimal("total").
MaxDigits(10).
DecimalPlaces(2).
Required().
Build(),
schema.String("status").
Choices("pending", "processing", "shipped", "delivered", "cancelled").
Default("pending").
Build(),
schema.Time("created_at").AutoNowAdd().Build(),
}
}
func (Order) Relations() []schema.Relation {
return []schema.Relation{
relations.ForeignKey("customer", "Customer").
Required().
OnDelete(schema.Cascade),
relations.ForeignKey("billing_address", "Address").
Required(),
relations.ForeignKey("shipping_address", "Address").
Required(),
relations.OneToMany("items", "OrderItem").
RelatedName("order"),
relations.OneToOne("payment", "Payment"),
relations.OneToOne("shipping", "Shipping"),
}
}
Customer with Profile​
type Customer struct {
schema.BaseSchema
}
func (Customer) Fields() []schema.Field {
return []schema.Field{
schema.Int64("id").Primary().AutoIncrement().Build(),
schema.String("email").Unique().Required().MaxLength(255).Build(),
schema.String("password_hash").Required().MaxLength(255).Build(),
schema.Bool("is_active").Default(true).Build(),
schema.Time("created_at").AutoNowAdd().Build(),
}
}
func (Customer) Relations() []schema.Relation {
return []schema.Relation{
relations.OneToOne("profile", "CustomerProfile").
OnDelete(schema.Cascade),
relations.OneToMany("addresses", "Address").
RelatedName("customer"),
relations.OneToMany("orders", "Order").
RelatedName("customer"),
}
}
type CustomerProfile struct {
schema.BaseSchema
}
func (CustomerProfile) Fields() []schema.Field {
return []schema.Field{
schema.Int64("id").Primary().AutoIncrement().Build(),
schema.String("first_name").MaxLength(100).Build(),
schema.String("last_name").MaxLength(100).Build(),
schema.String("phone").MaxLength(20).Build(),
schema.Date("date_of_birth").Build(),
}
}
func (CustomerProfile) Relations() []schema.Relation {
return []schema.Relation{
relations.ForeignKey("customer", "Customer").
Required().
Unique().
OnDelete(schema.Cascade),
}
}
Hierarchical Categories​
type Category struct {
schema.BaseSchema
}
func (Category) Fields() []schema.Field {
return []schema.Field{
schema.Int64("id").Primary().AutoIncrement().Build(),
schema.String("name").Required().MaxLength(100).Build(),
schema.String("slug").Unique().MaxLength(100).Build(),
schema.Text("description").Build(),
}
}
func (Category) Relations() []schema.Relation {
return []schema.Relation{
relations.ForeignKey("parent", "Category").
OnDelete(schema.Cascade).
RelatedName("children"),
}
}
Product Variants and Inventory​
type ProductVariant struct {
schema.BaseSchema
}
func (ProductVariant) Fields() []schema.Field {
return []schema.Field{
schema.Int64("id").Primary().AutoIncrement().Build(),
schema.String("sku").Unique().MaxLength(100).Build(),
schema.String("name").MaxLength(200).Build(),
schema.Decimal("price").
MaxDigits(10).
DecimalPlaces(2).
Build(),
schema.JSON("attributes").Build(), // Size, color, etc.
}
}
func (ProductVariant) Relations() []schema.Relation {
return []schema.Relation{
relations.ForeignKey("product", "Product").
Required().
OnDelete(schema.Cascade),
relations.OneToMany("inventory", "Inventory").
RelatedName("variant"),
}
}
type Inventory struct {
schema.BaseSchema
}
func (Inventory) Fields() []schema.Field {
return []schema.Field{
schema.Int64("id").Primary().AutoIncrement().Build(),
schema.Int32("quantity").Required().Default(0).Build(),
schema.Int32("reserved").Default(0).Build(),
}
}
func (Inventory) Relations() []schema.Relation {
return []schema.Relation{
relations.ForeignKey("product", "Product").
Required().
OnDelete(schema.Cascade),
relations.ForeignKey("variant", "ProductVariant").
OnDelete(schema.Cascade),
relations.ForeignKey("warehouse", "Warehouse").
Required().
OnDelete(schema.Cascade),
}
}
Usage Examples​
Create Order with Items​
order := &models.Order{
OrderNumber: generateOrderNumber(),
Customer: customer,
BillingAddress: billingAddress,
ShippingAddress: shippingAddress,
Status: "pending",
Total: calculateTotal(items),
}
err := models.Order.Objects.Create(ctx, order)
// Create order items
for _, item := range items {
orderItem := &models.OrderItem{
Order: order,
Product: item.Product,
Variant: item.Variant,
Quantity: item.Quantity,
Price: item.Price,
}
err := models.OrderItem.Objects.Create(ctx, orderItem)
}
Get Products by Category​
products, err := models.Product.Objects.
Filter(models.Product.Fields.Categories.Contains(categoryID)).
Filter(models.Product.Fields.Active.Equals(true)).
PrefetchRelated("brand", "variants").
All(ctx)
Check Inventory​
inventory, err := models.Inventory.Objects.
Filter(models.Inventory.Fields.Product.Equals(productID)).
Filter(models.Inventory.Fields.Variant.Equals(variantID)).
Filter(models.Inventory.Fields.Warehouse.Equals(warehouseID)).
First(ctx)
available := inventory.Quantity - inventory.Reserved
See Also​
- E-commerce Website Sample - Run the full sample locally and explore the UI.
- Models Guide - Model definitions
- Relations Reference - Relationship types
- Library Example - Another complex example