Skip to main content

Sales Controller

Path: internal/api/v1/funnels/controllers/sale.controller.js
Service: salesService
Module: Funnels


Overview

The Sales controller tracks and manages payment transactions from funnel checkout pages. It integrates with Stripe and Square payment providers to record sales, retrieve transaction details, and export sales data.

Key Capabilities

  • Sales Tracking: Record all funnel payment transactions
  • Transaction Details: Retrieve Stripe/Square charge information
  • Sales Reporting: View sales by funnel with date filtering
  • Charge Management: Update charge metadata and notes
  • Sales Export: Export sales data as CSV

Methods

getSales()

Retrieves all sales for a funnel with date filtering and pagination.

Route: GET /v1/funnels/:id/sales
Auth: Required (account-scoped)

Request Parameters

{
id: string; // Funnel ID
}

Request Query Parameters

{
start_date?: string; // Filter from date (ISO 8601)
end_date?: string; // Filter to date (ISO 8601)
limit?: number; // Results per page (default: 10)
page?: number; // Page number (0-indexed)
}

Response

{
"success": true,
"message": "SUCCESS",
"data": [
{
"_id": "60d5ec49f1b2c72e8c8e4b50",
"funnel_id": "60d5ec49f1b2c72e8c8e4b1a",
"step_id": "60d5ec49f1b2c72e8c8e4b1e",
"charge_id": "ch_3MmlLr2eZvKYlo2C0b7lzxVZ",
"amount": 99.99,
"currency": "usd",
"status": "succeeded",
"payment_method": "stripe",
"customer": {
"id": "cus_NZlw7J6RdPXJ4Y",
"email": "customer@example.com",
"name": "John Doe"
},
"metadata": {
"product_name": "Premium Plan",
"quantity": 1
},
"created_at": "2024-01-22T14:30:00Z",
"updated_at": "2024-01-22T14:30:05Z"
},
{
"_id": "60d5ec49f1b2c72e8c8e4b51",
"funnel_id": "60d5ec49f1b2c72e8c8e4b1a",
"step_id": "60d5ec49f1b2c72e8c8e4b1e",
"charge_id": "sq0idp-xyz789",
"amount": 149.99,
"currency": "usd",
"status": "succeeded",
"payment_method": "square",
"customer": {
"id": "CUSTOMER_ID_123",
"email": "jane@example.com",
"name": "Jane Smith"
},
"metadata": {
"product_name": "Enterprise Plan",
"quantity": 1
},
"created_at": "2024-01-22T15:45:00Z",
"updated_at": "2024-01-22T15:45:10Z"
}
],
"pagination": {
"total": 142,
"page": 1,
"limit": 10,
"pages": 15
}
}

MongoDB Collections

CollectionOperationPurpose
funnel_salesfind with date rangeQuery sales transactions
funnelsfindOneVerify funnel ownership

getSale()

Retrieves detailed information for specific sale transactions.

Route: GET /v1/funnels/:id/sales/:step_id
Auth: Required (account-scoped, Stripe config required)

Request Parameters

{
id: string; // Funnel ID
step_id: string; // Step ID where sale occurred
}

Request Query Parameters

{
charges: string; // Comma-separated charge IDs
}

Response

{
"success": true,
"message": "SUCCESS",
"data": {
"charges": [
{
"id": "ch_3MmlLr2eZvKYlo2C0b7lzxVZ",
"amount": 9999,
"amount_captured": 9999,
"amount_refunded": 0,
"currency": "usd",
"status": "succeeded",
"paid": true,
"refunded": false,
"customer": {
"id": "cus_NZlw7J6RdPXJ4Y",
"email": "customer@example.com",
"name": "John Doe",
"phone": "+1 555-0123"
},
"payment_method_details": {
"type": "card",
"card": {
"brand": "visa",
"last4": "4242",
"exp_month": 12,
"exp_year": 2025,
"funding": "credit"
}
},
"billing_details": {
"address": {
"city": "San Francisco",
"country": "US",
"line1": "123 Main St",
"postal_code": "94102",
"state": "CA"
}
},
"receipt_url": "https://pay.stripe.com/receipts/...",
"created": 1674403800,
"metadata": {
"funnel_id": "60d5ec49f1b2c72e8c8e4b1a",
"step_id": "60d5ec49f1b2c72e8c8e4b1e",
"product_name": "Premium Plan"
}
}
],
"total_amount": 99.99,
"total_refunded": 0.0,
"net_amount": 99.99
}
}

External API Integration

  • Calls Stripe API: stripe.charges.retrieve(charge_id)
  • Uses account's Stripe API key from req.auth.stripe_config.token
  • Returns raw Stripe charge objects with full details

updateSale()

Updates sale metadata and notes.

Route: PUT /v1/funnels/:id/sales/:step_id
Auth: Required (account-scoped, Stripe config required)

Request Parameters

{
id: string; // Funnel ID
step_id: string; // Step ID
}

Request Body

{
"charge": {
"id": "ch_3MmlLr2eZvKYlo2C0b7lzxVZ",
"metadata": {
"order_number": "ORD-12345",
"fulfillment_status": "pending",
"notes": "Rush delivery requested"
}
}
}

Response

{
"success": true,
"message": "SUCCESS",
"data": {
"id": "ch_3MmlLr2eZvKYlo2C0b7lzxVZ",
"metadata": {
"funnel_id": "60d5ec49f1b2c72e8c8e4b1a",
"step_id": "60d5ec49f1b2c72e8c8e4b1e",
"product_name": "Premium Plan",
"order_number": "ORD-12345",
"fulfillment_status": "pending",
"notes": "Rush delivery requested"
},
"updated": true
}
}

External API Integration

  • Calls Stripe API: stripe.charges.update(charge_id, { metadata })
  • Updates charge metadata in Stripe system
  • Does NOT modify amount or payment status

exportSales()

Exports sales data as CSV file.

Route: GET /v1/funnels/:id/sales/export
Auth: Required (account-scoped)

Request Parameters

{
id: string; // Funnel ID
}

Request Query Parameters

{
start_date?: string; // Filter from date (ISO 8601)
end_date?: string; // Filter to date (ISO 8601)
}

Response

  • Content-Type: text/csv
  • Filename: Sales-2024-01-22-19-30-00.csv

CSV Format

Date,Transaction ID,Customer Name,Customer Email,Amount,Currency,Status,Payment Method,Product
2024-01-22 14:30:00,ch_3MmlLr2eZvKYlo2C0b7lzxVZ,John Doe,customer@example.com,99.99,USD,succeeded,stripe,Premium Plan
2024-01-22 15:45:00,sq0idp-xyz789,Jane Smith,jane@example.com,149.99,USD,succeeded,square,Enterprise Plan

MongoDB Collections

CollectionOperationPurpose
funnel_salesfind with date rangeQuery all sales for export

Data Models

Sale Document

{
_id: ObjectId;
funnel_id: ObjectId;
step_id: ObjectId;
account_id: ObjectId;

// Payment provider details
payment_method: 'stripe' | 'square' | 'paypal';
charge_id: string; // Provider's transaction ID

// Transaction details
amount: number; // Amount in dollars (e.g., 99.99)
currency: string; // ISO currency code (e.g., "usd")
status: 'succeeded' | 'pending' | 'failed' | 'refunded';

// Customer info
customer: {
id: string; // Provider's customer ID
email?: string;
name?: string;
phone?: string;
};

// Product/metadata
metadata?: {
product_name?: string;
product_id?: string;
quantity?: number;
order_number?: string;
fulfillment_status?: string;
notes?: string;
[key: string]: any;
};

// Attribution
visitor_id?: string; // Analytics visitor ID
utm_source?: string;
utm_medium?: string;
utm_campaign?: string;

// Timestamps
created_at: Date; // When sale was recorded
updated_at: Date; // Last metadata update
payment_date: Date; // Actual payment timestamp
}

Integration Points

Stripe Integration

  • Purpose: Process credit card payments
  • Configuration: Account-level Stripe API key (req.auth.stripe_config.token)
  • Operations: Retrieve charges, update metadata
  • Webhooks: Record sales from Stripe webhook events

Square Integration

  • Purpose: Process credit card payments (alternative to Stripe)
  • Configuration: Account-level Square access token
  • Operations: Retrieve orders, update order metadata
  • Webhooks: Record sales from Square webhook events

Business Logic & Workflows

Sale Recording Flow

sequenceDiagram
participant Checkout
participant Stripe
participant Webhook
participant Sales
participant Database

Checkout->>Stripe: Process payment
Stripe-->>Checkout: Payment succeeded
Stripe->>Webhook: payment_intent.succeeded event
Webhook->>Sales: Record sale
Sales->>Database: Insert sale document
Database-->>Sales: Sale recorded
Sales-->>Webhook: Success

Sale Export Flow

sequenceDiagram
participant User
participant Sales
participant Database
participant CSV

User->>Sales: GET /sales/export
Sales->>Database: Query sales (date range)
Database-->>Sales: Sale records
Sales->>CSV: Generate CSV
CSV-->>Sales: CSV data
Sales-->>User: Download CSV file

Performance Considerations

Pagination

  • Default limit: 10 sales per page
  • Uses skip/limit for efficiency
  • Total count calculated once per query

Date Range Queries

  • Indexed by created_at field
  • Optimized for recent date ranges (last 30/90 days)
  • Full export uses streaming for large datasets

External API Calls

  • Stripe API calls cached for 5 minutes
  • Batch charge retrieval when possible
  • Rate limiting: 100 requests/second (Stripe limit)

Security

Multi-Tenant Isolation

  • All queries filtered by account_id (via funnel ownership)
  • Stripe API key scoped to account
  • Cannot access other accounts' sales data

Sensitive Data Handling

  • Full card numbers never stored (only last4)
  • CVV never stored
  • PCI compliance through Stripe/Square

API Key Security

  • Stripe keys stored encrypted in database
  • Never exposed in API responses
  • Validated before each external API call

Error Handling

Common Errors

// No Stripe configuration
{
"success": false,
"message": "Stripe configuration required",
"statusCode": 400
}

// Charge not found
{
"success": false,
"message": "Charge not found",
"data": {
"charge_id": "ch_invalid"
},
"statusCode": 404
}

// Stripe API error
{
"success": false,
"message": "Stripe API error: invalid_request_error",
"data": {
"stripe_error": "No such charge: ch_invalid"
},
"statusCode": 500
}

// Invalid date range
{
"success": false,
"message": "start_date must be before end_date",
"statusCode": 400
}

Best Practices

When to Use This Controller

  • ✅ Building sales dashboards
  • ✅ Tracking funnel revenue
  • ✅ Exporting transaction data
  • ✅ Managing order fulfillment
  • ✅ Analyzing payment performance

Common Patterns

  1. Date range filtering: Default to last 30 days
  2. Metadata updates: Use for order management (fulfillment, tracking)
  3. Export for accounting: Regular CSV exports for financial records
  4. Charge retrieval: Fetch full details only when needed (lazy loading)

Edge Cases

  • Refunds: Sale document persists but status updated to "refunded"
  • Partial refunds: metadata tracks refund amount
  • Failed payments: Recorded with status "failed" for analytics
  • Multiple charges: Query parameter accepts comma-separated IDs

  • Funnels Controller: Funnel checkout pages
  • Stripe Webhooks: Automated sale recording
  • Square Webhooks: Alternative payment recording
  • Analytics Controller: Revenue attribution and metrics

Last Updated: January 2025
API Version: v1
Maintained By: DashClicks Engineering

💬

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