import { VeeqoClient } from '../clients/veeqoClient';
import { EasyPostClient } from '../clients/easypostClient';
import { RpcBaseError } from '../utils/errors';
import { createLogger } from '../utils/logger';
import { AuthService } from '../utils/auth';
const logger = createLogger();
const veeqoClient = new VeeqoClient();
const easypostClient = new EasyPostClient();
export interface DashboardStats {
totalOrders: number;
pendingShipments: number;
lowStockItems: number;
revenue: number;
recentOrders: any[];
}
export interface LoginParams {
username: string;
password: string;
}
export interface ChangePasswordParams {
oldPassword: string;
newPassword: string;
}
export const webMethods = {
async login(params: LoginParams): Promise<{ token: string; user: any }> {
try {
if (!params.username || !params.password) {
throw new RpcBaseError('VALIDATION_ERROR', 'Username and password are required');
}
const user = await AuthService.authenticate(params.username, params.password);
if (!user) {
throw new RpcBaseError('AUTHENTICATION_ERROR', 'Invalid credentials');
}
const token = AuthService.generateToken(user);
return {
token,
user: {
id: user.id,
username: user.username,
role: user.role
}
};
} catch (error) {
logger.error('Error in web.login', { error });
if (error instanceof RpcBaseError) throw error;
throw new RpcBaseError('WEB_LOGIN_ERROR', 'Failed to login', error);
}
},
async changePassword(params: ChangePasswordParams, userId: string): Promise<{ success: boolean }> {
try {
// In a real implementation, we would look up the username by userId
// For this example, we'll assume admin user
const success = await AuthService.changePassword('admin', params.oldPassword, params.newPassword);
if (!success) {
throw new RpcBaseError('PASSWORD_CHANGE_ERROR', 'Failed to change password');
}
return { success: true };
} catch (error) {
logger.error('Error in web.changePassword', { error });
if (error instanceof RpcBaseError) throw error;
throw new RpcBaseError('WEB_CHANGE_PASSWORD_ERROR', 'Failed to change password', error);
}
},
async getDashboardStats(): Promise<DashboardStats> {
try {
// Get recent orders
const ordersResponse = await veeqoClient.listOrders(1, 10);
// Get inventory
const inventoryItems = await veeqoClient.syncInventory();
// Calculate stats
const totalOrders = ordersResponse.total_count;
const pendingShipments = ordersResponse.orders.filter(o => o.status === 'pending').length;
const lowStockItems = inventoryItems.filter(i => i.available < 5).length;
const revenue = ordersResponse.orders.reduce((sum, order) => sum + 0, 0); // Simplified
return {
totalOrders,
pendingShipments,
lowStockItems,
revenue,
recentOrders: ordersResponse.orders.slice(0, 5)
};
} catch (error) {
logger.error('Error in web.getDashboardStats', { error });
if (error instanceof RpcBaseError) throw error;
throw new RpcBaseError('WEB_GET_DASHBOARD_STATS_ERROR', 'Failed to get dashboard stats', error);
}
},
async searchOrders(params: { query: string; status?: string; page?: number; limit?: number }): Promise<any> {
try {
const page = params.page || 1;
const limit = params.limit || 20;
// Get orders
const response = await veeqoClient.listOrders(page, limit);
// Filter by query and status if provided
let filteredOrders = response.orders;
if (params.query) {
filteredOrders = filteredOrders.filter(order =>
order.number?.includes(params.query) ||
order.channel_order_code?.includes(params.query)
);
}
if (params.status) {
filteredOrders = filteredOrders.filter(order => order.status === params.status);
}
return {
orders: filteredOrders,
pagination: {
page,
limit,
total: response.total_count
}
};
} catch (error) {
logger.error('Error in web.searchOrders', { error });
if (error instanceof RpcBaseError) throw error;
throw new RpcBaseError('WEB_SEARCH_ORDERS_ERROR', 'Failed to search orders', error);
}
},
async getLowStockItems(): Promise<any> {
try {
const inventoryItems = await veeqoClient.syncInventory();
const lowStockItems = inventoryItems.filter(i => i.available < 5);
return {
items: lowStockItems.map(item => ({
id: item.id,
product_id: item.product_id,
sellable_id: item.sellable_id,
quantity: item.quantity,
available: item.available,
allocated: item.allocated
}))
};
} catch (error) {
logger.error('Error in web.getLowStockItems', { error });
if (error instanceof RpcBaseError) throw error;
throw new RpcBaseError('WEB_GET_LOW_STOCK_ITEMS_ERROR', 'Failed to get low stock items', error);
}
}
};