2026-03-20 09:43:50 +08:00
|
|
|
/**
|
|
|
|
|
* [MOCK-FULFILLMENT] Unified Fulfillment DataSource
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
export interface UnifiedOrder {
|
|
|
|
|
id: string;
|
|
|
|
|
platformOrderId: string;
|
|
|
|
|
platform: string;
|
|
|
|
|
customerId: string;
|
|
|
|
|
items: OrderItem[];
|
|
|
|
|
totalAmount: number;
|
|
|
|
|
currency: string;
|
|
|
|
|
status: 'pending' | 'confirmed' | 'processing' | 'shipped' | 'delivered' | 'cancelled';
|
|
|
|
|
shippingAddress: Record<string, any>;
|
|
|
|
|
fulfillmentStatus: 'unfulfilled' | 'partial' | 'fulfilled';
|
|
|
|
|
createdAt: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface OrderItem {
|
|
|
|
|
productId: string;
|
|
|
|
|
skuId: string;
|
|
|
|
|
quantity: number;
|
|
|
|
|
unitPrice: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface FulfillmentRoute {
|
|
|
|
|
orderId: string;
|
|
|
|
|
warehouseId: string;
|
|
|
|
|
priority: number;
|
|
|
|
|
estimatedShipDate: string;
|
|
|
|
|
estimatedDeliveryDate: string;
|
|
|
|
|
cost: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface FulfillmentStatus {
|
|
|
|
|
orderId: string;
|
|
|
|
|
status: 'pending' | 'picked' | 'packed' | 'shipped' | 'delivered';
|
|
|
|
|
trackingNumber?: string;
|
|
|
|
|
carrier?: string;
|
|
|
|
|
events: FulfillmentEvent[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface FulfillmentEvent {
|
|
|
|
|
timestamp: string;
|
|
|
|
|
status: string;
|
|
|
|
|
location?: string;
|
|
|
|
|
description: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface IUnifiedFulfillmentDataSource {
|
|
|
|
|
unifyOrders(platformOrders: Array<{ platform: string; orderId: string; data: Record<string, any> }>): Promise<UnifiedOrder[]>;
|
|
|
|
|
routeOrder(orderId: string, inventoryData: Array<{ warehouseId: string; available: number }>): Promise<FulfillmentRoute>;
|
|
|
|
|
manageFulfillment(orderId: string, action: 'pick' | 'pack' | 'ship' | 'deliver', params: Record<string, any>): Promise<FulfillmentStatus>;
|
|
|
|
|
syncStatus(orderId: string, status: string): Promise<{ success: boolean; message: string }>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MockUnifiedFulfillmentDataSource implements IUnifiedFulfillmentDataSource {
|
|
|
|
|
async unifyOrders(platformOrders: Array<{ platform: string; orderId: string; data: Record<string, any> }>): Promise<UnifiedOrder[]> {
|
|
|
|
|
return platformOrders.map((po, i) => ({
|
|
|
|
|
id: `order_${Date.now()}_${i}`,
|
|
|
|
|
platformOrderId: po.orderId,
|
|
|
|
|
platform: po.platform,
|
|
|
|
|
customerId: `cust_${i}`,
|
|
|
|
|
items: po.data.items || [],
|
|
|
|
|
totalAmount: po.data.totalAmount || 100,
|
|
|
|
|
currency: 'USD',
|
|
|
|
|
status: 'pending' as const,
|
|
|
|
|
shippingAddress: po.data.shippingAddress || {},
|
|
|
|
|
fulfillmentStatus: 'unfulfilled' as const,
|
|
|
|
|
createdAt: new Date().toISOString(),
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async routeOrder(orderId: string, inventoryData: Array<{ warehouseId: string; available: number }>): Promise<FulfillmentRoute> {
|
|
|
|
|
return {
|
|
|
|
|
orderId,
|
|
|
|
|
warehouseId: inventoryData[0]?.warehouseId || 'default_warehouse',
|
|
|
|
|
priority: 0,
|
|
|
|
|
estimatedShipDate: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
|
|
|
|
|
estimatedDeliveryDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
|
|
|
|
|
cost: 5.99,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async manageFulfillment(orderId: string, action: 'pick' | 'pack' | 'ship' | 'deliver', params: Record<string, any>): Promise<FulfillmentStatus> {
|
|
|
|
|
const statusMap: Record<string, FulfillmentStatus['status']> = {
|
|
|
|
|
pick: 'picked',
|
|
|
|
|
pack: 'packed',
|
|
|
|
|
ship: 'shipped',
|
|
|
|
|
deliver: 'delivered',
|
|
|
|
|
};
|
|
|
|
|
return {
|
|
|
|
|
orderId,
|
|
|
|
|
status: statusMap[action],
|
|
|
|
|
trackingNumber: params.trackingNumber,
|
|
|
|
|
carrier: params.carrier,
|
|
|
|
|
events: [{ timestamp: new Date().toISOString(), status: statusMap[action], description: `Order ${action}ed` }],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async syncStatus(orderId: string, status: string): Promise<{ success: boolean; message: string }> {
|
|
|
|
|
return { success: true, message: `Status synced to ${status}` };
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ApiUnifiedFulfillmentDataSource implements IUnifiedFulfillmentDataSource {
|
|
|
|
|
private baseUrl = '/api/omnichannel';
|
|
|
|
|
|
|
|
|
|
async unifyOrders(platformOrders: Array<{ platform: string; orderId: string; data: Record<string, any> }>): Promise<UnifiedOrder[]> {
|
|
|
|
|
const res = await fetch(`${this.baseUrl}/fulfillment/orders/unify`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
body: JSON.stringify({ platformOrders }),
|
|
|
|
|
});
|
|
|
|
|
const data = await res.json();
|
|
|
|
|
return data.data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async routeOrder(orderId: string, inventoryData: Array<{ warehouseId: string; available: number }>): Promise<FulfillmentRoute> {
|
|
|
|
|
const res = await fetch(`${this.baseUrl}/fulfillment/order/${orderId}/route`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
body: JSON.stringify({ inventoryData }),
|
|
|
|
|
});
|
|
|
|
|
const data = await res.json();
|
|
|
|
|
return data.data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async manageFulfillment(orderId: string, action: 'pick' | 'pack' | 'ship' | 'deliver', params: Record<string, any>): Promise<FulfillmentStatus> {
|
|
|
|
|
const res = await fetch(`${this.baseUrl}/fulfillment/order/${orderId}/manage`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
body: JSON.stringify({ action, params }),
|
|
|
|
|
});
|
|
|
|
|
const data = await res.json();
|
|
|
|
|
return data.data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async syncStatus(orderId: string, status: string): Promise<{ success: boolean; message: string }> {
|
|
|
|
|
const res = await fetch(`${this.baseUrl}/fulfillment/order/${orderId}/sync-status`, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
body: JSON.stringify({ status }),
|
|
|
|
|
});
|
|
|
|
|
const data = await res.json();
|
|
|
|
|
return data.data;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-23 12:41:35 +08:00
|
|
|
const useMock = process.env.NODE_ENV === 'development' || process.env.REACT_APP_USE_MOCK === 'true';
|
2026-03-20 09:43:50 +08:00
|
|
|
export const unifiedFulfillmentDataSource: IUnifiedFulfillmentDataSource = useMock
|
|
|
|
|
? new MockUnifiedFulfillmentDataSource()
|
|
|
|
|
: new ApiUnifiedFulfillmentDataSource();
|