Skip to main content

Order Management

The Order Management submodule handles order tracking, product-specific fulfillment timelines, onboarding status management, and invoice retrieval for the DashClicks Store platform.

API Endpoints Overview

MethodEndpointDescription
GET/v1/store/ordersGet orders with advanced filtering
GET/v1/store/orders/my-ordersGet my orders with onboarding status
GET/v1/store/orders/my-formsGet onboarding forms for sub-account
GET/v1/store/orders/:idGet specific order details
GET/v1/store/orders/:id/timelineGet order fulfillment timeline
GET/v1/store/orders/:id/statusGet current order status
GET/v1/store/orders/:id/invoicesGet all invoices for order's subscription

MongoDB Collections Used

Primary Collections

  • _store.orders - Order records with product and fulfillment data
  • _store.subscriptions - Linked subscriptions for orders
  • _store.products - Product information
  • _store.prices - Pricing details
  • _accounts - Account relationships
  • crm.contacts - Business contact information
  • projects-typeforms - Onboarding form requests
  • projects-typeform.responses - Form submission data
  • _store.invoices - Invoice records
  • queues - Fulfillment job status
  • projects.tasks - Service delivery tasks
  • projects.pulse - Project status updates

Core Order Workflows

Order Creation Flow

graph TD
A[Checkout Complete] --> B[Create Order Record]
B --> C[Link Subscription]
C --> D[Store Product Metadata]
D --> E[Initialize Status: pending]
E --> F{Requires Onboarding?}
F -->|Yes| G[Create Typeform Request]
F -->|No| H[Queue Fulfillment Job]
G --> I[Send Onboarding Invite]
I --> H
H --> J[Update Status: processing]
J --> K[Track Fulfillment Progress]

Onboarding Status Flow

graph TD
A[Order Created] --> B{Onboarding Required?}
B -->|No| C[Status: approved]
B -->|Yes| D[Create Typeform]
D --> E[Status: pending]
E --> F[Send Invite Email]
F --> G{Form Submitted?}
G -->|No| H[Status: sent]
G -->|Yes| I[Status: received]
I --> J{Needs Review?}
J -->|Yes| K[Status: verification]
J -->|No| L[Status: approved]
K --> M{Issues Found?}
M -->|Yes| N[Status: issues]
M -->|No| L
N --> O[Request Revision]
O --> I

Service Methods & Functionality

Order Retrieval

getMyOrders(req, res, next) - Retrieve orders with advanced filtering

  • Purpose: Get orders with comprehensive filtering, pagination, and onboarding status

  • Query Parameters:

    • start_date (String): Start date for date range filter
    • end_date (String): End date for date range filter
    • onboarding_status (String): Filter by onboarding stage
      • pending: Form not sent or not submitted
      • verification: Form submitted, awaiting review
      • issues: Issues found in submission
      • approved: Approved and ready for fulfillment
    • product (String): Filter by product type
    • order_status (String): Filter by order status
    • search (String): Text search across order fields
    • sort_by (String): Sort field (default: created_at)
    • order (String): Sort direction (asc | desc)
    • page (Number): Page number for pagination
    • limit (Number): Items per page
  • Business Logic:

    1. Complex Aggregation Pipeline:

      [
      // Filter by account
      { $match: { account_id: ObjectId(account_id) } },

      // Lookup subscription
      {
      $lookup: {
      from: '_store.subscriptions',
      localField: 'subscription',
      foreignField: '_id',
      as: 'subscription_data',
      },
      },

      // Lookup product
      {
      $lookup: {
      from: '_store.products',
      localField: 'product',
      foreignField: '_id',
      as: 'product_data',
      },
      },

      // Lookup typeform requests
      {
      $lookup: {
      from: 'projects-typeforms',
      localField: '_id',
      foreignField: 'order',
      as: 'typeform_requests',
      },
      },

      // Lookup typeform responses
      {
      $lookup: {
      from: 'projects-typeform.responses',
      localField: 'typeform_requests._id',
      foreignField: 'request',
      as: 'typeform_responses',
      },
      },
      ];
    2. Onboarding Status Calculation:

      • pending: No typeform request OR request sent but no response
      • verification: Response received (response.status: 'pending')
      • issues: Response has issues flagged
      • approved: Response approved OR no onboarding required
    3. Website Reactivation Eligibility:

      • Checks if canceled website can be reactivated
      • Verifies domain still available
      • Adds can_reactivate: true flag
    4. Missing Metadata Update:

      • If order missing product/price metadata
      • Fetches from subscription and updates order
      • Ensures data consistency
    5. Result Grouping:

      {
      orders: [...], // Paginated order array
      total: 150, // Total orders matching filters
      page: 1, // Current page
      limit: 20, // Items per page
      status_counts: { // Filter statistics
      pending: 25,
      verification: 10,
      issues: 5,
      approved: 110
      }
      }
  • Returns: Paginated orders with status counts

getOrders(req, res, next) - Get all orders (admin view)

  • Purpose: Retrieve all orders across accounts with filtering
  • Query Parameters: Same as getMyOrders plus:
    • account_id (ObjectId): Filter by specific account
  • Business Logic: Similar to getMyOrders without account restriction
  • Returns: Paginated orders

getOrder(req, res, next) - Get specific order

  • Purpose: Retrieve single order with full details
  • Parameters: Order ID
  • Business Logic:
    • Populates subscription, product, price
    • Includes typeform requests and responses
    • Calculates current onboarding status
    • Generates onboarding link if applicable
  • Returns: Order object with populated fields

Timeline Management

getOrderTimeline(req, res, next) - Generate fulfillment timeline

  • Purpose: Create product-specific fulfillment timeline with status indicators

  • Parameters: Order ID

  • Business Logic:

    1. Product Type Detection:

      • Retrieves order with product information
      • Determines product category (Content, Facebook Ads, Google Ads, etc.)
    2. Timeline Templates by Product:

      Content Products:

      [
      {
      stage: 'submit',
      label: 'Onboarding Form Submitted',
      status: 'completed',
      date: '2025-01-01T00:00:00Z',
      },
      {
      stage: 'review',
      label: 'Form Under Review',
      status: 'completed',
      date: '2025-01-02T00:00:00Z',
      },
      {
      stage: 'setup',
      label: 'Account Setup',
      status: 'in_progress',
      date: null,
      },
      {
      stage: 'topic_generation',
      label: 'Topic Ideas Generated',
      status: 'pending',
      date: null,
      },
      {
      stage: 'topic_approval',
      label: 'Topic Approval',
      status: 'pending',
      date: null,
      },
      {
      stage: 'monthly_delivery',
      label: 'Monthly Content Delivery',
      status: 'pending',
      date: null,
      recurring: true,
      },
      ];

      Facebook Ads / Google Ads:

      [
      {
      stage: 'submit',
      label: 'Onboarding Form Submitted',
      status: 'completed',
      },
      {
      stage: 'review',
      label: 'Form Review',
      status: 'completed',
      },
      {
      stage: 'setup',
      label: 'Ad Account Setup',
      status: 'in_progress',
      },
      {
      stage: 'buildout',
      label: 'Campaign Buildout',
      status: 'pending',
      },
      {
      stage: 'qa',
      label: 'Quality Assurance',
      status: 'pending',
      },
      {
      stage: 'approval',
      label: 'Client Approval',
      status: 'pending',
      },
      {
      stage: 'launch',
      label: 'Campaign Launch',
      status: 'pending',
      },
      {
      stage: 'monthly_optimization',
      label: 'Monthly Optimization',
      status: 'pending',
      recurring: true,
      },
      ];
    3. Status Determination:

      • completed: Stage finished (has completion date)
      • in_progress: Current stage being worked on
      • pending: Future stage not yet started
      • issues: Stage has problems requiring attention
    4. Date Population:

      • Pulls completion dates from queue records
      • Links to project task completion dates
      • Shows null for future stages
    5. Progress Calculation:

      {
      total_stages: 7,
      completed_stages: 3,
      progress_percentage: 42.86
      }
  • Returns: Timeline array with progress metrics

getOrderStatus(req, res, next) - Get current order status

  • Purpose: Retrieve simplified current status

  • Parameters: Order ID

  • Business Logic:

    • Checks latest queue job status
    • Determines current fulfillment stage
    • Returns user-friendly status message
  • Returns: Status object:

    {
    current_stage: 'setup',
    status: 'in_progress',
    message: 'Your account is being configured',
    estimated_completion: '2025-01-15'
    }

Invoice Management

getOrderInvoices(req, res, next) - Retrieve subscription invoices

  • Purpose: Get all invoices for order's subscription

  • Parameters: Order ID

  • Business Logic:

    1. Finds order and linked subscription
    2. Retrieves all invoices for subscription from Stripe
    3. Sorts by creation date (newest first)
    4. Includes invoice status and payment details
  • Returns: Invoice array:

    [
    {
    id: 'in_xxx',
    subscription: 'sub_xxx',
    amount_due: 29900,
    amount_paid: 29900,
    status: 'paid',
    created: 1704067200,
    paid_at: 1704067200,
    invoice_pdf: 'https://...',
    },
    ];

Onboarding Forms

getMyForms(req, res, next) - Retrieve onboarding forms

  • Purpose: Get onboarding forms for sub-account

  • Parameters: Sub-account ID (query param)

  • Business Logic:

    1. Access Validation:

      • Verifies sub-account belongs to parent account
      • Checks user has permission to view
    2. Business Lookup:

      • Finds business contact linked to sub-account
    3. Form Aggregation:

      [
      // Match typeform requests for business
      { $match: { business: ObjectId(business_id) } },

      // Lookup latest response
      {
      $lookup: {
      from: 'projects-typeform.responses',
      localField: '_id',
      foreignField: 'request',
      as: 'responses',
      },
      },

      // Lookup subscription
      {
      $lookup: {
      from: '_store.subscriptions',
      localField: 'subscription',
      foreignField: '_id',
      as: 'subscription_data',
      },
      },

      // Lookup business contact
      {
      $lookup: {
      from: 'crm.contacts',
      localField: 'business',
      foreignField: '_id',
      as: 'business_data',
      },
      },
      ];
    4. Form Name Generation:

      • Extracts product name from subscription
      • Formats: "[Product Name] - Onboarding Form"
    5. Response Processing:

      • Gets latest response if multiple exist
      • Includes submission status and date
      • Adds revision history if applicable
  • Returns: Forms array:

    [
    {
    _id: 'typeform_request_id',
    form_name: 'Content Services - Onboarding Form',
    form_url: 'https://dashclicks.typeform.com/to/xxx',
    status: 'pending',
    submitted_at: '2025-01-05T10:30:00Z',
    response: {
    answers: [...],
    status: 'pending',
    issues: []
    },
    business: {
    name: 'Acme Corp',
    email: 'contact@acme.com'
    }
    }
    ]

Technical Implementation Details

Onboarding Status Logic

Status Determination Algorithm:

function determineOnboardingStatus(order) {
const { typeform_requests, typeform_responses } = order;

// No onboarding required
if (!typeform_requests || typeform_requests.length === 0) {
return 'approved';
}

const latestRequest = typeform_requests[typeform_requests.length - 1];
const latestResponse = typeform_responses.find(
r => r.request.toString() === latestRequest._id.toString(),
);

// Form sent but not submitted
if (!latestResponse) {
return latestRequest.sent_at ? 'sent' : 'pending';
}

// Form submitted
if (latestResponse.status === 'pending') {
return 'verification';
}

// Issues found
if (latestResponse.status === 'issues') {
return 'issues';
}

// Approved
return 'approved';
}

Timeline Status Tracking

Queue-Based Progress Tracking:

Orders track fulfillment progress through queue jobs:

const queueJob = await Queue.findOne({
'metadata.order_id': orderId,
type: 'fulfillment',
});

const stageMapping = {
pending: 'submit',
processing: 'setup',
review: 'review',
completed: 'launch',
};

const currentStage = stageMapping[queueJob.status];

Product-Specific Timelines

Timeline Configuration by Product Type:

const timelineTemplates = {
content: [
{ stage: 'submit', duration_days: 0 },
{ stage: 'review', duration_days: 1 },
{ stage: 'setup', duration_days: 2 },
{ stage: 'topic_generation', duration_days: 3 },
{ stage: 'topic_approval', duration_days: 1 },
{ stage: 'monthly_delivery', duration_days: 0, recurring: true },
],

facebook_ads: [
{ stage: 'submit', duration_days: 0 },
{ stage: 'review', duration_days: 1 },
{ stage: 'setup', duration_days: 2 },
{ stage: 'buildout', duration_days: 5 },
{ stage: 'qa', duration_days: 2 },
{ stage: 'approval', duration_days: 3 },
{ stage: 'launch', duration_days: 1 },
{ stage: 'monthly_optimization', duration_days: 0, recurring: true },
],

google_ads: [
// Similar to facebook_ads
],

website: [
{ stage: 'submit', duration_days: 0 },
{ stage: 'review', duration_days: 1 },
{ stage: 'design', duration_days: 7 },
{ stage: 'development', duration_days: 7 },
{ stage: 'review_approval', duration_days: 3 },
{ stage: 'launch', duration_days: 1 },
],
};

Estimated Completion Dates

Calculation Based on Timeline:

function calculateEstimatedCompletion(order, timeline) {
const currentStageIndex = timeline.findIndex(t => t.status === 'in_progress');

if (currentStageIndex === -1) return null;

const remainingStages = timeline.slice(currentStageIndex);
const totalDays = remainingStages.reduce((sum, stage) => sum + stage.duration_days, 0);

const estimatedDate = new Date();
estimatedDate.setDate(estimatedDate.getDate() + totalDays);

return estimatedDate;
}

Website Reactivation Check

Eligibility Verification:

async function checkWebsiteReactivation(order) {
if (order.product.type !== 'website') return false;

const subscription = await Subscription.findById(order.subscription);
if (subscription.status !== 'canceled') return false;

// Check if domain still available
const domain = order.metadata.domain;
const domainAvailable = await checkDomainAvailability(domain);

if (!domainAvailable) return false;

// Check if within reactivation window (90 days)
const canceledDate = new Date(subscription.canceled_at);
const daysSinceCancellation = Math.floor((new Date() - canceledDate) / (1000 * 60 * 60 * 24));

return daysSinceCancellation <= 90;
}

Error Handling

Common Error Codes

  • 400 Bad Request: Invalid filter parameters, malformed date range
  • 403 Forbidden: Attempting to access another account's orders
  • 404 Not Found: Order ID not found, subscription not found
  • 422 Unprocessable: Invalid onboarding status filter value
  • 500 Server Error: Database query failures, aggregation errors

Validation Patterns

// Order query validation (Joi)
{
start_date: Joi.date().iso(),
end_date: Joi.date().iso().min(Joi.ref('start_date')),
onboarding_status: Joi.string().valid(
'pending', 'verification', 'issues', 'approved'
),
product: Joi.string(),
order_status: Joi.string(),
search: Joi.string().max(100),
sort_by: Joi.string().valid('created_at', 'updated_at', 'status'),
order: Joi.string().valid('asc', 'desc'),
page: Joi.number().integer().min(1).default(1),
limit: Joi.number().integer().min(1).max(100).default(20)
}

Integration Points

External Services

  • Typeform API: Form creation and response retrieval
  • Email Service: Onboarding invitation emails
  • Queue Manager: Fulfillment job status tracking
  • Project Management: Task and pulse integration

Internal Services

  • Subscription Service: Subscription data and status
  • Product Service: Product metadata and configuration
  • Account Service: Account relationships and permissions
  • Notification Service: Status update notifications

PubSub Events

// Published on status changes
pubsub.publish('store:order:status_changed', {
order_id,
old_status: 'pending',
new_status: 'verification',
timestamp: new Date(),
});

// Published on timeline progression
pubsub.publish('store:order:stage_completed', {
order_id,
stage: 'setup',
next_stage: 'buildout',
timestamp: new Date(),
});

Performance Considerations

Optimization Strategies

  1. Aggregation Pipeline Efficiency:

    • Indexes on account_id, subscription, created_at
    • Early filtering with $match stages
    • Limit result set before expensive $lookup operations
  2. Caching:

    • Timeline templates cached in memory
    • Product metadata cached for timeline generation
    • Status counts cached for 5 minutes
  3. Pagination:

    • Skip-limit pagination for small datasets
    • Cursor-based pagination for large datasets
    • Total count cached when filters unchanged

Database Indexes

// Orders collection indexes
{
account_id: 1,
created_at: -1
}
{
subscription: 1
}
{
'product.type': 1,
status: 1
}
{
business: 1,
created_at: -1
}
💬

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM