Delivery Feature

The ice cream shop is so successful that delivery orders are flooding in! Now we need to manage delivery orders. A delivery driver can deliver multiple orders at once, which means we need to create a relationship between deliveries and orders. This is a classic one-to-many relationship - one Delivery contains many IcecreamOrders.
In this tutorial, you'll learn how to:
🔗
Define relationships between models using embedded references
Trigger side effects when related data is created
🎨
Build UI components for selecting and displaying related data

Create Delivery Module

First, let's create the Delivery module using the CLI. This module will connect multiple ice cream orders into a single delivery batch.
Terminal

Define Relationship

Now let's define the Delivery model with a relationship to IcecreamOrder. The key is using LightIcecreamOrder as the field type - this creates an embedded reference that stores the essential order data directly in the delivery document.
apps/koyo/lib/delivery/delivery.constant.ts
Let's understand the key relationship pattern:
🔗field([LightIcecreamOrder], { minlength: 1 })
This defines a one-to-many relationship by embedding an array of LightIcecreamOrder. The "Light" version contains only essential fields (serveType, size, toppings, status) - perfect for embedding without duplicating entire documents.
📦Embedded vs Referenced
By embedding LightIcecreamOrder, the delivery document contains all necessary order info without additional database queries. This is ideal for data that's read together frequently.
Add dictionary entries for the Delivery model:
apps/koyo/lib/delivery/delivery.dictionary.ts
Now let's implement the service layer with lifecycle hooks. When a delivery is created, all associated orders should be marked as finished:
apps/koyo/lib/delivery/delivery.service.ts
Key service patterns for related data:
🔌service<srv.IcecreamOrderService>()
Injects the IcecreamOrderService so DeliveryService can interact with orders. This enables cross-model operations.
_postCreate
A lifecycle hook that runs after a delivery is created. It iterates through all linked orders and marks them as finished - perfect for cascading updates.
🚫_preUpdate
Prevents updates to deliveries by throwing a Revert error. Once a delivery is created, it becomes immutable - ensuring data integrity.
Now let's create the Template component for selecting related orders. The Field.Children component is designed specifically for selecting related data:
apps/koyo/lib/delivery/Delivery.Template.tsx
Key features of Field.Children:
📋
sliceName: Specifies which slice provides the selectable options. Here it's 'icecreamOrderInDelivery' - a slice filtered for delivery-eligible orders.
🎯
initArgs: Initial arguments passed to the slice query. ["served"] filters to only show orders ready for delivery.
🎨
renderOption: Custom render function for each selectable option. Shows order ID for easy identification.
Add a new slice to IcecreamOrder specifically for the delivery selection UI. This filters orders by status and serve type:
apps/koyo/lib/icecreamOrder/icecreamOrder.signal.ts
Add arguments to support serveType filtering in the byStatuses query declaration in the document.
apps/koyo/lib/icecreamOrder/icecreamOrder.document.ts
Add dictionary entries for the new slice:
apps/koyo/lib/icecreamOrder/icecreamOrder.dictionary.ts
Now let's create the Unit component to display deliveries with their related orders. This shows how embedded data can be rendered together:
apps/koyo/lib/delivery/Delivery.Unit.tsx
Notice how we iterate through delivery.icecreamOrders and render each one using the IcecreamOrder.Unit.Card component. The embedded data is immediately available without additional queries!
Create the Zone component with a modal for creating new deliveries:
apps/koyo/lib/delivery/Delivery.Zone.tsx
The submitOption.onSuccess callback updates the local state with the finished orders, keeping the UI in sync with the database changes.
Finally, let's integrate everything into the main page using Tab components to organize orders and deliveries:
apps/koyo/app/[lang]/page.tsx
Key features of this integrated page:
📑
Tab: Organizes related content into switchable panels. Users can easily navigate between orders and deliveries.
Promise.all: Loads both icecreamOrder and delivery data in parallel for optimal performance.

Summary

🎉 What You've Accomplished:
  • Created a Delivery module with one-to-many relationship to IcecreamOrder
  • Used LightModel pattern for efficient embedded references
  • Implemented _postCreate hook for cascading updates across related data
  • Built Field.Children component for selecting related records
  • Displayed embedded related data without additional queries
  • Organized multiple models with Tab navigation
💡Best Practices
  • Use LightModel for embedded data to avoid document bloat
  • Embed data that's frequently read together
  • Use lifecycle hooks for maintaining data consistency
  • Create dedicated slices for relationship selection UIs
Congratulations! You've completed all the core tutorials. You now have a solid foundation for building complex applications with akanjs. Explore the System Architecture section to dive deeper into how everything works together.
Released under the MIT License
Official Akan.js Consulting onAkansoft
Copyright © 2025 Akan.js. All rights reserved.
System managed bybassman