|
@@ -23,7 +23,8 @@ import {
|
|
|
ShopRenterOrder,
|
|
ShopRenterOrder,
|
|
|
ShopRenterCustomer,
|
|
ShopRenterCustomer,
|
|
|
ShopRenterOrderFilters,
|
|
ShopRenterOrderFilters,
|
|
|
- ShopRenterCustomerFilters
|
|
|
|
|
|
|
+ ShopRenterCustomerFilters,
|
|
|
|
|
+ getOrderStatusWithCache
|
|
|
} from '../_shared/shoprenter-client.ts';
|
|
} from '../_shared/shoprenter-client.ts';
|
|
|
import {
|
|
import {
|
|
|
McpTool,
|
|
McpTool,
|
|
@@ -258,11 +259,23 @@ function formatCustomerForLlm(customer: any): LlmCustomer {
|
|
|
* - paymentAddress1, paymentCity, etc.
|
|
* - paymentAddress1, paymentCity, etc.
|
|
|
*
|
|
*
|
|
|
* We preserve the raw data and apply cleanResponseData to remove URLs/empty values
|
|
* We preserve the raw data and apply cleanResponseData to remove URLs/empty values
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param order - The raw order from ShopRenter API
|
|
|
|
|
+ * @param storeId - The store ID (optional, used to resolve status name)
|
|
|
|
|
+ * @param resolvedStatusName - Pre-resolved status name (optional)
|
|
|
*/
|
|
*/
|
|
|
-function formatOrderForLlm(order: any): any {
|
|
|
|
|
|
|
+function formatOrderForLlm(order: any, storeId?: string, resolvedStatusName?: string): any {
|
|
|
// ShopRenter orderExtend API returns the order data in a specific structure
|
|
// ShopRenter orderExtend API returns the order data in a specific structure
|
|
|
// We'll preserve most of the original structure but ensure key fields are present
|
|
// We'll preserve most of the original structure but ensure key fields are present
|
|
|
|
|
|
|
|
|
|
+ // Determine the status - use resolved name if provided, otherwise use raw status
|
|
|
|
|
+ let status: any = order.status || order.orderStatus;
|
|
|
|
|
+
|
|
|
|
|
+ // If we have a resolved status name, use it
|
|
|
|
|
+ if (resolvedStatusName) {
|
|
|
|
|
+ status = { name: resolvedStatusName };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
const formattedOrder: any = {
|
|
const formattedOrder: any = {
|
|
|
id: order.id,
|
|
id: order.id,
|
|
|
orderNumber: order.innerId || order.orderNumber || order.id,
|
|
orderNumber: order.innerId || order.orderNumber || order.id,
|
|
@@ -274,7 +287,7 @@ function formatOrderForLlm(order: any): any {
|
|
|
phone: order.phone || '',
|
|
phone: order.phone || '',
|
|
|
|
|
|
|
|
// Order status and totals
|
|
// Order status and totals
|
|
|
- status: order.status || order.orderStatus,
|
|
|
|
|
|
|
+ status: status,
|
|
|
total: order.total || '0',
|
|
total: order.total || '0',
|
|
|
currency: order.currency || {},
|
|
currency: order.currency || {},
|
|
|
|
|
|
|
@@ -329,6 +342,44 @@ function formatOrderForLlm(order: any): any {
|
|
|
return formattedOrder;
|
|
return formattedOrder;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Resolve order status name from ShopRenter orderStatus href
|
|
|
|
|
+ * Uses caching to avoid repeated API calls for the same status
|
|
|
|
|
+ */
|
|
|
|
|
+async function resolveOrderStatus(storeId: string, order: any): Promise<string | undefined> {
|
|
|
|
|
+ // Check if orderStatus has an href (URL reference)
|
|
|
|
|
+ const orderStatusHref = order.orderStatus?.href;
|
|
|
|
|
+ if (!orderStatusHref) {
|
|
|
|
|
+ return undefined;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // Get the language ID from the order if available
|
|
|
|
|
+ let languageId = '1'; // Default to Hungarian (language_id=1)
|
|
|
|
|
+ if (order.language?.href) {
|
|
|
|
|
+ // Extract language ID from href like: .../languages/bGFuZ3VhZ2UtbGFuZ3VhZ2VfaWQ9MQ==
|
|
|
|
|
+ const langBase64 = order.language.href.split('/').pop();
|
|
|
|
|
+ if (langBase64) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const decoded = atob(langBase64);
|
|
|
|
|
+ const match = decoded.match(/language_id=(\d+)/);
|
|
|
|
|
+ if (match) {
|
|
|
|
|
+ languageId = match[1];
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ // Keep default language ID
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const statusInfo = await getOrderStatusWithCache(storeId, orderStatusHref, languageId);
|
|
|
|
|
+ return statusInfo.name;
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('[MCP ShopRenter] Error resolving order status:', error);
|
|
|
|
|
+ return undefined;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* Format a product as plain text for LLM consumption
|
|
* Format a product as plain text for LLM consumption
|
|
|
*/
|
|
*/
|
|
@@ -704,8 +755,12 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
|
|
|
|
|
|
|
|
console.log('[MCP ShopRenter] Order found:', { innerId: orders[0].innerId || orders[0].id });
|
|
console.log('[MCP ShopRenter] Order found:', { innerId: orders[0].innerId || orders[0].id });
|
|
|
|
|
|
|
|
- // Format for LLM
|
|
|
|
|
- const formattedOrder = formatOrderForLlm(orders[0]);
|
|
|
|
|
|
|
+ // Resolve order status name
|
|
|
|
|
+ const resolvedStatusName = await resolveOrderStatus(shop_id, orders[0]);
|
|
|
|
|
+ console.log('[MCP ShopRenter] Resolved status name:', resolvedStatusName);
|
|
|
|
|
+
|
|
|
|
|
+ // Format for LLM with resolved status name
|
|
|
|
|
+ const formattedOrder = formatOrderForLlm(orders[0], shop_id, resolvedStatusName);
|
|
|
|
|
|
|
|
// Format as plain text
|
|
// Format as plain text
|
|
|
return {
|
|
return {
|
|
@@ -777,8 +832,12 @@ async function handleGetOrder(args: Record<string, any>): Promise<ToolCallResult
|
|
|
|
|
|
|
|
console.log('[MCP ShopRenter] Order found:', { innerId: orders[0].innerId || orders[0].id });
|
|
console.log('[MCP ShopRenter] Order found:', { innerId: orders[0].innerId || orders[0].id });
|
|
|
|
|
|
|
|
- // Format for LLM
|
|
|
|
|
- const formattedOrder = formatOrderForLlm(orders[0]);
|
|
|
|
|
|
|
+ // Resolve order status name
|
|
|
|
|
+ const resolvedStatusName = await resolveOrderStatus(shop_id, orders[0]);
|
|
|
|
|
+ console.log('[MCP ShopRenter] Resolved status name:', resolvedStatusName);
|
|
|
|
|
+
|
|
|
|
|
+ // Format for LLM with resolved status name
|
|
|
|
|
+ const formattedOrder = formatOrderForLlm(orders[0], shop_id, resolvedStatusName);
|
|
|
|
|
|
|
|
// Format as plain text
|
|
// Format as plain text
|
|
|
return {
|
|
return {
|
|
@@ -874,8 +933,14 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
|
|
|
// Apply limit
|
|
// Apply limit
|
|
|
const limitedOrders = orders.slice(0, actualLimit);
|
|
const limitedOrders = orders.slice(0, actualLimit);
|
|
|
|
|
|
|
|
- // Format for LLM (now preserves all ShopRenter fields)
|
|
|
|
|
- const formattedOrders = limitedOrders.map(formatOrderForLlm);
|
|
|
|
|
|
|
+ // Resolve status names for all orders (in parallel for efficiency)
|
|
|
|
|
+ const statusPromises = limitedOrders.map((order: any) => resolveOrderStatus(shop_id, order));
|
|
|
|
|
+ const resolvedStatuses = await Promise.all(statusPromises);
|
|
|
|
|
+
|
|
|
|
|
+ // Format for LLM with resolved status names
|
|
|
|
|
+ const formattedOrders = limitedOrders.map((order: any, index: number) =>
|
|
|
|
|
+ formatOrderForLlm(order, shop_id, resolvedStatuses[index])
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
// Format as plain text
|
|
// Format as plain text
|
|
|
const plainTextOrders = formattedOrders.map(formatOrderAsPlainText).join('\n\n---\n\n');
|
|
const plainTextOrders = formattedOrders.map(formatOrderAsPlainText).join('\n\n---\n\n');
|
|
@@ -972,8 +1037,14 @@ async function handleListOrders(args: Record<string, any>): Promise<ToolCallResu
|
|
|
// Apply limit
|
|
// Apply limit
|
|
|
const limitedOrders = orders.slice(0, actualLimit);
|
|
const limitedOrders = orders.slice(0, actualLimit);
|
|
|
|
|
|
|
|
- // Format for LLM (now preserves all ShopRenter fields)
|
|
|
|
|
- const formattedOrders = limitedOrders.map(formatOrderForLlm);
|
|
|
|
|
|
|
+ // Resolve status names for all orders (in parallel for efficiency)
|
|
|
|
|
+ const statusPromises = limitedOrders.map((order: any) => resolveOrderStatus(shop_id, order));
|
|
|
|
|
+ const resolvedStatuses = await Promise.all(statusPromises);
|
|
|
|
|
+
|
|
|
|
|
+ // Format for LLM with resolved status names
|
|
|
|
|
+ const formattedOrders = limitedOrders.map((order: any, index: number) =>
|
|
|
|
|
+ formatOrderForLlm(order, shop_id, resolvedStatuses[index])
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
// Format as plain text
|
|
// Format as plain text
|
|
|
const plainTextOrders = formattedOrders.map(formatOrderAsPlainText).join('\n\n---\n\n');
|
|
const plainTextOrders = formattedOrders.map(formatOrderAsPlainText).join('\n\n---\n\n');
|