analytics/examples/nestjs-backend/order.service.ts
2026-01-29 08:20:58 -08:00

194 lines
5.2 KiB
TypeScript

/**
* OrderService - Example service with analytics tracking
*
* Demonstrates tracking events from within a service (not just controllers).
*/
import { Injectable, Inject } from '@nestjs/common';
import { BackendAnalyticsClient } from '@analytics/client';
import { ANALYTICS_CLIENT } from './analytics.module';
// ─────────────────────────────────────────────────────────────────────────────
// Types
// ─────────────────────────────────────────────────────────────────────────────
interface OrderItem {
productId: string;
name: string;
price: number;
quantity: number;
}
interface Order {
id: string;
userId: string;
items: OrderItem[];
total: number;
status: 'pending' | 'paid' | 'shipped' | 'delivered' | 'cancelled';
createdAt: Date;
}
interface CreateOrderDto {
userId: string;
items: OrderItem[];
sessionId?: string;
}
// ─────────────────────────────────────────────────────────────────────────────
// Service
// ─────────────────────────────────────────────────────────────────────────────
@Injectable()
export class OrderService {
constructor(
@Inject(ANALYTICS_CLIENT)
private readonly analytics: BackendAnalyticsClient,
) {}
/**
* Create a new order with analytics tracking.
*/
async createOrder(dto: CreateOrderDto): Promise<Order> {
const order: Order = {
id: `ord_${Date.now()}`,
userId: dto.userId,
items: dto.items,
total: dto.items.reduce((sum, item) => sum + item.price * item.quantity, 0),
status: 'pending',
createdAt: new Date(),
};
// Track order creation
this.analytics.trackEngagement({
sessionId: dto.sessionId || 'server',
userId: dto.userId,
type: 'commerce',
action: 'order_created',
metadata: {
orderId: order.id,
orderTotal: order.total,
itemCount: order.items.length,
products: order.items.map((item) => ({
productId: item.productId,
name: item.name,
price: item.price,
quantity: item.quantity,
})),
},
});
return order;
}
/**
* Process payment with conversion tracking.
*/
async processPayment(orderId: string, paymentMethod: string): Promise<Order> {
// Fetch order (mock)
const order: Order = {
id: orderId,
userId: 'usr_123',
items: [],
total: 99.99,
status: 'paid',
createdAt: new Date(),
};
// Track successful payment (conversion event)
this.analytics.trackEngagement({
sessionId: 'server',
userId: order.userId,
type: 'commerce',
action: 'payment_completed',
metadata: {
orderId,
orderTotal: order.total,
paymentMethod,
currency: 'USD',
// This is a key conversion metric
isConversion: true,
conversionValue: order.total,
},
});
return order;
}
/**
* Ship order with fulfillment tracking.
*/
async shipOrder(orderId: string, trackingNumber: string): Promise<Order> {
const order: Order = {
id: orderId,
userId: 'usr_123',
items: [],
total: 99.99,
status: 'shipped',
createdAt: new Date(),
};
this.analytics.trackEngagement({
sessionId: 'server',
userId: order.userId,
type: 'fulfillment',
action: 'order_shipped',
metadata: {
orderId,
trackingNumber,
shippedAt: new Date().toISOString(),
},
});
return order;
}
/**
* Cancel order with churn tracking.
*/
async cancelOrder(orderId: string, reason: string): Promise<Order> {
const order: Order = {
id: orderId,
userId: 'usr_123',
items: [],
total: 99.99,
status: 'cancelled',
createdAt: new Date(),
};
// Track cancellation (important for churn analysis)
this.analytics.trackEngagement({
sessionId: 'server',
userId: order.userId,
type: 'commerce',
action: 'order_cancelled',
metadata: {
orderId,
orderTotal: order.total,
cancellationReason: reason,
// Negative conversion for revenue tracking
revenueImpact: -order.total,
},
});
return order;
}
/**
* Track inventory events (server-side only).
*/
async trackLowStock(productId: string, currentStock: number): Promise<void> {
// This is a server-side only event - no user session
this.analytics.trackEngagement({
sessionId: 'system',
type: 'inventory',
action: 'low_stock_alert',
metadata: {
productId,
currentStock,
threshold: 10,
alertedAt: new Date().toISOString(),
},
});
}
}