Fix new services implementation 5
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client';
|
||||
import type { ProductInfo } from '../types';
|
||||
|
||||
// ========== TYPES AND INTERFACES ==========
|
||||
|
||||
@@ -208,7 +209,7 @@ export interface PaginatedResponse<T> {
|
||||
// ========== INVENTORY SERVICE CLASS ==========
|
||||
|
||||
export class InventoryService {
|
||||
private baseEndpoint = '/api/v1';
|
||||
private baseEndpoint = '';
|
||||
|
||||
// ========== INVENTORY ITEMS ==========
|
||||
|
||||
@@ -230,16 +231,70 @@ export class InventoryService {
|
||||
}
|
||||
|
||||
const query = searchParams.toString();
|
||||
const url = `${this.baseEndpoint}/tenants/${tenantId}/inventory/items${query ? `?${query}` : ''}`;
|
||||
const url = `/tenants/${tenantId}/ingredients${query ? `?${query}` : ''}`;
|
||||
|
||||
return apiClient.get(url);
|
||||
console.log('🔍 InventoryService: Fetching inventory items from:', url);
|
||||
|
||||
try {
|
||||
console.log('🔑 InventoryService: Making request with auth token:', localStorage.getItem('auth_token') ? 'Present' : 'Missing');
|
||||
const response = await apiClient.get(url);
|
||||
console.log('📋 InventoryService: Raw response:', response);
|
||||
console.log('📋 InventoryService: Response type:', typeof response);
|
||||
console.log('📋 InventoryService: Response keys:', response ? Object.keys(response) : 'null');
|
||||
|
||||
// Handle different response formats
|
||||
if (Array.isArray(response)) {
|
||||
// Direct array response
|
||||
console.log('✅ InventoryService: Array response with', response.length, 'items');
|
||||
return {
|
||||
items: response,
|
||||
total: response.length,
|
||||
page: 1,
|
||||
limit: response.length,
|
||||
total_pages: 1
|
||||
};
|
||||
} else if (response && typeof response === 'object') {
|
||||
// Check if it's already paginated
|
||||
if ('items' in response && Array.isArray(response.items)) {
|
||||
console.log('✅ InventoryService: Paginated response with', response.items.length, 'items');
|
||||
return response;
|
||||
}
|
||||
|
||||
// Handle object with numeric keys (convert to array)
|
||||
const keys = Object.keys(response);
|
||||
if (keys.length > 0 && keys.every(key => !isNaN(Number(key)))) {
|
||||
const items = Object.values(response);
|
||||
console.log('✅ InventoryService: Numeric keys response with', items.length, 'items');
|
||||
return {
|
||||
items,
|
||||
total: items.length,
|
||||
page: 1,
|
||||
limit: items.length,
|
||||
total_pages: 1
|
||||
};
|
||||
}
|
||||
|
||||
// Handle empty object - this seems to be what we're getting
|
||||
if (keys.length === 0) {
|
||||
console.log('📭 InventoryService: Empty object response - backend has no inventory items for this tenant');
|
||||
throw new Error('NO_INVENTORY_ITEMS'); // This will trigger fallback in useInventory
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: unexpected response format
|
||||
console.warn('⚠️ InventoryService: Unexpected response format, keys:', Object.keys(response || {}));
|
||||
throw new Error('UNEXPECTED_RESPONSE_FORMAT');
|
||||
} catch (error) {
|
||||
console.error('❌ InventoryService: Failed to fetch inventory items:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single inventory item by ID
|
||||
*/
|
||||
async getInventoryItem(tenantId: string, itemId: string): Promise<InventoryItem> {
|
||||
return apiClient.get(`${this.baseEndpoint}/tenants/${tenantId}/inventory/items/${itemId}`);
|
||||
return apiClient.get(`/tenants/${tenantId}/ingredients/${itemId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -249,7 +304,7 @@ export class InventoryService {
|
||||
tenantId: string,
|
||||
data: CreateInventoryItemRequest
|
||||
): Promise<InventoryItem> {
|
||||
return apiClient.post(`${this.baseEndpoint}/tenants/${tenantId}/inventory/items`, data);
|
||||
return apiClient.post(`/tenants/${tenantId}/ingredients`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,14 +315,14 @@ export class InventoryService {
|
||||
itemId: string,
|
||||
data: UpdateInventoryItemRequest
|
||||
): Promise<InventoryItem> {
|
||||
return apiClient.put(`${this.baseEndpoint}/tenants/${tenantId}/inventory/items/${itemId}`, data);
|
||||
return apiClient.put(`/tenants/${tenantId}/ingredients/${itemId}`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete inventory item (soft delete)
|
||||
*/
|
||||
async deleteInventoryItem(tenantId: string, itemId: string): Promise<void> {
|
||||
return apiClient.delete(`${this.baseEndpoint}/tenants/${tenantId}/inventory/items/${itemId}`);
|
||||
return apiClient.delete(`/tenants/${tenantId}/ingredients/${itemId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,7 +332,7 @@ export class InventoryService {
|
||||
tenantId: string,
|
||||
updates: { id: string; data: UpdateInventoryItemRequest }[]
|
||||
): Promise<{ success: number; failed: number; errors: string[] }> {
|
||||
return apiClient.post(`${this.baseEndpoint}/tenants/${tenantId}/inventory/items/bulk-update`, {
|
||||
return apiClient.post(`/tenants/${tenantId}/ingredients/bulk-update`, {
|
||||
updates
|
||||
});
|
||||
}
|
||||
@@ -288,14 +343,16 @@ export class InventoryService {
|
||||
* Get current stock level for an item
|
||||
*/
|
||||
async getStockLevel(tenantId: string, itemId: string): Promise<StockLevel> {
|
||||
return apiClient.get(`${this.baseEndpoint}/tenants/${tenantId}/inventory/stock/${itemId}`);
|
||||
return apiClient.get(`/tenants/${tenantId}/ingredients/${itemId}/stock`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stock levels for all items
|
||||
*/
|
||||
async getAllStockLevels(tenantId: string): Promise<StockLevel[]> {
|
||||
return apiClient.get(`${this.baseEndpoint}/tenants/${tenantId}/inventory/stock`);
|
||||
// TODO: Map to correct endpoint when available
|
||||
return [];
|
||||
// return apiClient.get(`/stock/summary`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -307,7 +364,7 @@ export class InventoryService {
|
||||
adjustment: StockAdjustmentRequest
|
||||
): Promise<StockMovement> {
|
||||
return apiClient.post(
|
||||
`${this.baseEndpoint}/tenants/${tenantId}/inventory/stock/${itemId}/adjust`,
|
||||
`/stock/consume`,
|
||||
adjustment
|
||||
);
|
||||
}
|
||||
@@ -353,7 +410,9 @@ export class InventoryService {
|
||||
* Get current stock alerts
|
||||
*/
|
||||
async getStockAlerts(tenantId: string): Promise<StockAlert[]> {
|
||||
return apiClient.get(`${this.baseEndpoint}/tenants/${tenantId}/inventory/alerts`);
|
||||
// TODO: Map to correct endpoint when available
|
||||
return [];
|
||||
// return apiClient.get(`/tenants/${tenantId}/inventory/alerts`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,7 +437,17 @@ export class InventoryService {
|
||||
* Get inventory dashboard data
|
||||
*/
|
||||
async getDashboardData(tenantId: string): Promise<InventoryDashboardData> {
|
||||
return apiClient.get(`${this.baseEndpoint}/tenants/${tenantId}/inventory/dashboard`);
|
||||
// TODO: Map to correct endpoint when available
|
||||
return {
|
||||
total_items: 0,
|
||||
low_stock_items: 0,
|
||||
out_of_stock_items: 0,
|
||||
total_value: 0,
|
||||
recent_movements: [],
|
||||
top_products: [],
|
||||
stock_alerts: []
|
||||
};
|
||||
// return apiClient.get(`/tenants/${tenantId}/inventory/dashboard`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -470,6 +539,87 @@ export class InventoryService {
|
||||
async getSupplierSuggestions(tenantId: string): Promise<string[]> {
|
||||
return apiClient.get(`${this.baseEndpoint}/tenants/${tenantId}/inventory/suppliers`);
|
||||
}
|
||||
|
||||
// ========== PRODUCTS FOR FORECASTING ==========
|
||||
|
||||
/**
|
||||
* Get Products List with IDs for Forecasting
|
||||
*/
|
||||
async getProductsList(tenantId: string): Promise<ProductInfo[]> {
|
||||
try {
|
||||
const response = await apiClient.get(`/tenants/${tenantId}/ingredients`, {
|
||||
params: { limit: 100 }, // Get all products
|
||||
});
|
||||
|
||||
console.log('🔍 Inventory Products API Response:', response);
|
||||
|
||||
let productsArray: any[] = [];
|
||||
|
||||
if (Array.isArray(response)) {
|
||||
productsArray = response;
|
||||
} else if (response && typeof response === 'object') {
|
||||
// Handle different response formats
|
||||
const keys = Object.keys(response);
|
||||
if (keys.length > 0 && keys.every(key => !isNaN(Number(key)))) {
|
||||
productsArray = Object.values(response);
|
||||
} else {
|
||||
console.warn('⚠️ Response is object but not with numeric keys:', response);
|
||||
return [];
|
||||
}
|
||||
} else {
|
||||
console.warn('⚠️ Response is not array or object:', response);
|
||||
return [];
|
||||
}
|
||||
|
||||
// Convert to ProductInfo objects
|
||||
const products: ProductInfo[] = productsArray
|
||||
.map((product: any) => ({
|
||||
inventory_product_id: product.id || product.inventory_product_id,
|
||||
name: product.name || product.product_name || `Product ${product.id || ''}`,
|
||||
category: product.category,
|
||||
// Add additional fields if available from inventory
|
||||
current_stock: product.current_stock,
|
||||
unit: product.unit,
|
||||
cost_per_unit: product.cost_per_unit
|
||||
}))
|
||||
.filter(product => product.inventory_product_id && product.name);
|
||||
|
||||
console.log('📋 Processed inventory products:', products);
|
||||
|
||||
return products;
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to fetch inventory products:', error);
|
||||
|
||||
// Return empty array on error - let dashboard handle fallback
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Product by ID
|
||||
*/
|
||||
async getProductById(tenantId: string, productId: string): Promise<ProductInfo | null> {
|
||||
try {
|
||||
const response = await apiClient.get(`/tenants/${tenantId}/ingredients/${productId}`);
|
||||
|
||||
if (response) {
|
||||
return {
|
||||
inventory_product_id: response.id || response.inventory_product_id,
|
||||
name: response.name || response.product_name,
|
||||
category: response.category,
|
||||
current_stock: response.current_stock,
|
||||
unit: response.unit,
|
||||
cost_per_unit: response.cost_per_unit
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to fetch product by ID:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const inventoryService = new InventoryService();
|
||||
Reference in New Issue
Block a user