diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 00000000..599166b9 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,18 @@ +{ + "hooks": { + "PostToolUse": [ + { + "matcher": "Write|Edit", + "hooks": [ + { + "type": "agent", + "prompt": "Analyze the Vue component that was just modified: ${tool_input.file_path}\n\nProvide a detailed report covering:\n\n1. **Performance Issues**\n - Check for unnecessary reactivity (too many reactive properties)\n - Identify expensive watchers or computed properties\n - Look for missing keys in v-for loops\n - Detect potential re-render issues\n - Check component lifecycle optimization\n\n2. **Code Reuse Opportunities**\n - Suggest extractable sub-components\n - Recommend composable functions for shared logic\n - Identify duplicated code patterns\n - Propose shared utility functions\n\n3. **Vue 3 Best Practices**\n - Check for proper use of Composition API\n - Verify reactive data is properly scoped\n - Look for deprecated patterns\n - Check component registration and imports\n - Verify proper use of script setup syntax\n\n4. **Actionable Recommendations**\n - Prioritize by impact (high/medium/low)\n - Provide specific code examples where helpful\n - Include refactoring suggestions\n\nFormat the report as a concise markdown document.", + "if": "Write|Edit(.vue)", + "statusMessage": "Analyzing Vue component structure...", + "timeout": 120 + } + ] + } + ] + } +} diff --git a/CLAUDE.md b/CLAUDE.md index d2086efa..01d89e0e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -72,3 +72,8 @@ npm install && npm run dev - Status: green/blue/yellow/red - Charts: Custom SVG, CSS Grid for layouts - No emojis in UI + +## Code Style & Documentation +- **Comments**: Only add comments for non-obvious logic. Explain the *why*, not the *what*. Well-named code is better than comments explaining what it does. +- Document tricky filtering logic, workarounds, or non-standard patterns +- Don't comment obvious operations or implementations that follow standard patterns diff --git a/architecture.html b/architecture.html new file mode 100644 index 00000000..be37ba83 --- /dev/null +++ b/architecture.html @@ -0,0 +1,798 @@ + + + + + + Factory Inventory Management System - Architecture + + + +
+
+

Factory Inventory Management System

+

System Architecture & Technical Documentation

+
+ +
+ +
+

Technology Stack

+ +
+
+

+
🎨
+ Frontend +

+
    +
  • Vue 3 (Composition API)
  • +
  • Vite (Build tool)
  • +
  • Axios (HTTP client)
  • +
  • Port 3000
  • +
  • Responsive Design (CSS Grid/Flexbox)
  • +
+
+ +
+

+
⚙️
+ Backend +

+
    +
  • Python FastAPI
  • +
  • Uvicorn (ASGI server)
  • +
  • Pydantic (Data validation)
  • +
  • Port 8001
  • +
  • CORS enabled for development
  • +
+
+ +
+

+
💾
+ Data Layer +

+
    +
  • In-memory mock data
  • +
  • JSON files (no database)
  • +
  • Loaded at server startup
  • +
  • Real-time filtering
  • +
  • Pydantic model validation
  • +
+
+
+
+ + +
+

System Architecture

+ +
+
+
📁 JSON Data Files
inventory, orders, spending, etc.
+
+
+
+
FastAPI Backend
Port 8001
+
+
+
+
Vue 3 Frontend
Port 3000
+
+
+ +
+
    +
  • Frontend makes HTTP requests via Axios to RESTful API endpoints
  • +
  • Backend loads JSON files into memory on startup
  • +
  • All filtering happens server-side using Pydantic models
  • +
  • No database or persistence - data resets on server restart
  • +
  • CORS middleware allows cross-origin requests from frontend
  • +
  • Automatic API documentation available at /docs endpoint
  • +
+
+
+ + +
+

Data Flow

+ +
+
+
1
+
+ User Interaction + User selects filters (warehouse, category, status, month) or navigates to a view in Vue frontend +
+
+ +
+
2
+
+ Frontend API Call + Vue component calls api.js which constructs query parameters and makes Axios HTTP GET request +
+
+ +
+
3
+
+ Backend Receives Request + FastAPI router receives request, extracts query parameters, validates with Pydantic +
+
+ +
+
4
+
+ Data Filtering + Python applies filter functions: filter_by_month(), apply_filters() on in-memory JSON data +
+
+ +
+
5
+
+ Response Serialization + FastAPI serializes filtered results using Pydantic models (List[Order], List[InventoryItem], etc.) +
+
+ +
+
6
+
+ Frontend Receives & Displays + Vue component receives JSON response, updates reactive refs, computed properties recalculate, UI re-renders +
+
+
+
+ + +
+

REST API Endpoints

+

All endpoints return JSON. Base URL: http://localhost:8001/api

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodEndpointDescriptionFilters
GET/inventoryList all inventory itemswarehouse, category
GET/inventory/{item_id}Get specific inventory item
GET/ordersList all orderswarehouse, category, status, month
GET/orders/{order_id}Get specific order
GET/dashboard/summaryDashboard statistics & KPIswarehouse, category, status, month
GET/demandDemand forecasts
GET/backlogBacklog items with PO status
GET/spending/summarySpending summary statistics
GET/spending/monthlyMonthly spending breakdown
GET/spending/categoriesSpending by category
GET/spending/transactionsRecent transactions
GET/reports/quarterlyQuarterly performance reports
GET/reports/monthly-trendsMonth-over-month trends
+
+ + +
+

Filter System

+

Global filters apply to relevant endpoints. All filters default to "All" and accept 'all' as value to reset.

+ +
+
+

Time Period

+
    +
  • All Months (default)
  • +
  • January - December
  • +
  • Quarters (Q1-Q4 2025)
  • +
+
+ +
+

Warehouse

+
    +
  • All (default)
  • +
  • San Francisco
  • +
  • London
  • +
  • Tokyo
  • +
+
+ +
+

Category

+
    +
  • All (default)
  • +
  • Circuit Boards
  • +
  • Sensors
  • +
  • Actuators
  • +
  • Controllers
  • +
  • Power Supplies
  • +
+
+ +
+

Order Status

+
    +
  • All (default)
  • +
  • Delivered
  • +
  • Shipped
  • +
  • Processing
  • +
  • Backordered
  • +
+
+
+ +
+
    +
  • Filters stored in global composable (useFilters) for reactive updates across all views
  • +
  • Month filter only applies to order data (inventory has no time dimension)
  • +
  • Quarterly filtering uses QUARTER_MAP lookup on server side
  • +
  • Multiple filters combine with AND logic (e.g., SF + Sensors = SF warehouses with Sensors category)
  • +
+
+
+ + +
+

Frontend Views & Components

+ +
+
+ Dashboard + KPIs, order health, inventory by category, shortages, top products +
+
+ Inventory + Browse all items, stock levels, reorder points, unit costs +
+
+ Orders + Order list, customer details, status, delivery dates, total values +
+
+ Demand Forecast + Demand trends, current vs forecasted, trend analysis +
+
+ Finance (Spending) + Spending summary, monthly breakdown, category analysis, transactions +
+
+ Reports + Quarterly performance, monthly trends, order fulfillment rates +
+
+ Backlog + Shortages, delayed items, priority levels, purchase order creation +
+
+ Filter Bar + Global filters: period, warehouse, category, status +
+
+
+ + +
+

Core Data Models

+ +
+
+

InventoryItem

+
    +
  • id, sku, name, category
  • +
  • warehouse, quantity_on_hand
  • +
  • reorder_point, unit_cost
  • +
  • location, last_updated
  • +
+
+ +
+

Order

+
    +
  • id, order_number, customer, items
  • +
  • status, order_date, expected_delivery
  • +
  • total_value, actual_delivery
  • +
  • warehouse, category
  • +
+
+ +
+

BacklogItem

+
    +
  • id, order_id, item_sku, item_name
  • +
  • quantity_needed, quantity_available
  • +
  • days_delayed, priority
  • +
  • has_purchase_order
  • +
+
+ +
+

DemandForecast

+
    +
  • id, item_sku, item_name
  • +
  • current_demand, forecasted_demand
  • +
  • trend (up/down/stable)
  • +
  • period (month)
  • +
+
+
+
+ + +
+

Key Features

+ +
+
    +
  • Real-time filtering across 4 dimensions (time, location, category, status)
  • +
  • Dynamic KPI calculations (inventory turnover, fill rates, revenue goals)
  • +
  • Inventory shortage detection with priority levels
  • +
  • Purchase order creation for backlog items
  • +
  • Demand forecasting with trend analysis
  • +
  • Quarterly and monthly performance reporting
  • +
  • Spending analysis by month and category
  • +
  • Responsive design that works on desktop, tablet, mobile
  • +
  • Multi-language support (i18n) for internationalization
  • +
  • Profile menu and task management features
  • +
+
+
+ + +
+

Development Notes

+ +
+
    +
  • Server must be restarted to reload JSON data from disk
  • +
  • Changes to mock_data.py require server restart
  • +
  • API documentation auto-generated: http://localhost:8001/docs
  • +
  • Frontend hot-reloading enabled during npm run dev
  • +
  • All data is case-sensitive except category filtering (uses .lower())
  • +
  • Pydantic models enforce data validation on all API responses
  • +
  • Vue Composition API used throughout for better code organization
  • +
  • Axios interceptors can be added for centralized error handling
  • +
  • No database - perfect for prototyping and demos
  • +
+
+
+
+ + +
+ + \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index d13e6e77..88482901 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1370,6 +1370,7 @@ "integrity": "sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -1429,6 +1430,7 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz", "integrity": "sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==", "license": "MIT", + "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.22", "@vue/compiler-sfc": "3.5.22", diff --git a/client/src/App.vue b/client/src/App.vue index c2da05a5..71d9913f 100644 --- a/client/src/App.vue +++ b/client/src/App.vue @@ -22,6 +22,9 @@ {{ t('nav.demandForecast') }} + + Restocking + Reports diff --git a/client/src/api.js b/client/src/api.js index 11cb9db7..58e8d536 100644 --- a/client/src/api.js +++ b/client/src/api.js @@ -102,5 +102,35 @@ export const api = { async getPurchaseOrderByBacklogItem(backlogItemId) { const response = await axios.get(`${API_BASE_URL}/purchase-orders/${backlogItemId}`) return response.data + }, + + async getRestockingOrders() { + const response = await axios.get(`${API_BASE_URL}/restocking-orders`) + return response.data + }, + + async createRestockingOrder(data) { + const response = await axios.post(`${API_BASE_URL}/restocking-orders`, data) + return response.data + }, + + async getQuarterlyReports(filters = {}) { + const params = new URLSearchParams() + if (filters.warehouse && filters.warehouse !== 'all') params.append('warehouse', filters.warehouse) + if (filters.category && filters.category !== 'all') params.append('category', filters.category) + if (filters.month && filters.month !== 'all') params.append('month', filters.month) + + const response = await axios.get(`${API_BASE_URL}/reports/quarterly?${params.toString()}`) + return response.data + }, + + async getMonthlyTrends(filters = {}) { + const params = new URLSearchParams() + if (filters.warehouse && filters.warehouse !== 'all') params.append('warehouse', filters.warehouse) + if (filters.category && filters.category !== 'all') params.append('category', filters.category) + if (filters.month && filters.month !== 'all') params.append('month', filters.month) + + const response = await axios.get(`${API_BASE_URL}/reports/monthly-trends?${params.toString()}`) + return response.data } } diff --git a/client/src/locales/en.js b/client/src/locales/en.js index 03a58fe6..def66c47 100644 --- a/client/src/locales/en.js +++ b/client/src/locales/en.js @@ -188,6 +188,62 @@ export default { } }, + // Backlog + backlog: { + title: 'Backlog Management', + description: 'Track and resolve inventory shortages', + loading: 'Loading backlog...', + noItems: 'No backlog items - all orders can be fulfilled!', + highPriority: 'High Priority', + mediumPriority: 'Medium Priority', + lowPriority: 'Low Priority', + totalItems: 'Total Backlog Items', + itemsTitle: 'Backlog Items', + table: { + orderId: 'Order ID', + sku: 'SKU', + itemName: 'Item Name', + quantityNeeded: 'Quantity Needed', + quantityAvailable: 'Quantity Available', + shortage: 'Shortage', + daysDelayed: 'Days Delayed', + priority: 'Priority', + unitsShort: 'units short', + days: 'days' + } + }, + + // Reports + reports: { + title: 'Performance Reports', + description: 'View quarterly performance metrics and monthly trends', + quarterly: { + title: 'Quarterly Performance' + }, + monthly: { + title: 'Monthly Revenue Trend' + }, + comparison: { + title: 'Month-over-Month Analysis' + }, + quarter: 'Quarter', + month: 'Month', + orders: 'Orders', + totalOrders: 'Total Orders', + revenue: 'Revenue', + totalRevenue: 'Total Revenue', + avgOrderValue: 'Avg Order Value', + change: 'Change', + growthRate: 'Growth Rate', + fulfillmentRate: 'Fulfillment Rate', + stats: { + totalRevenueYTD: 'Total Revenue (YTD)', + avgMonthlyRevenue: 'Avg Monthly Revenue', + totalOrdersYTD: 'Total Orders (YTD)', + bestQuarter: 'Best Performing Quarter' + } + }, + // Filters filters: { timePeriod: 'Time Period', diff --git a/client/src/locales/ja.js b/client/src/locales/ja.js index db33223a..91c5850e 100644 --- a/client/src/locales/ja.js +++ b/client/src/locales/ja.js @@ -188,6 +188,62 @@ export default { } }, + // Backlog + backlog: { + title: 'バックログ管理', + description: '在庫不足を追跡・解決する', + loading: 'バックログを読み込み中...', + noItems: 'バックログアイテムなし - すべての注文を履行できます!', + highPriority: '高優先度', + mediumPriority: '中優先度', + lowPriority: '低優先度', + totalItems: '合計バックログアイテム', + itemsTitle: 'バックログアイテム', + table: { + orderId: '注文ID', + sku: 'SKU', + itemName: '品目名', + quantityNeeded: '必要数量', + quantityAvailable: '利用可能数量', + shortage: '不足', + daysDelayed: '遅延日数', + priority: '優先度', + unitsShort: '単位不足', + days: '日' + } + }, + + // Reports + reports: { + title: 'パフォーマンスレポート', + description: '四半期ごとのパフォーマンス指標と月別トレンドを表示', + quarterly: { + title: '四半期パフォーマンス' + }, + monthly: { + title: '月別売上トレンド' + }, + comparison: { + title: '前月比分析' + }, + quarter: '四半期', + month: '月', + orders: '注文', + totalOrders: '総注文数', + revenue: '売上', + totalRevenue: '総売上', + avgOrderValue: '平均注文額', + change: '変化', + growthRate: '成長率', + fulfillmentRate: '履行率', + stats: { + totalRevenueYTD: '総売上(年初来)', + avgMonthlyRevenue: '平均月別売上', + totalOrdersYTD: '総注文数(年初来)', + bestQuarter: '最高業績四半期' + } + }, + // Filters filters: { timePeriod: '期間', diff --git a/client/src/main.js b/client/src/main.js index 477c2d96..8884eea6 100644 --- a/client/src/main.js +++ b/client/src/main.js @@ -7,6 +7,7 @@ import Orders from './views/Orders.vue' import Demand from './views/Demand.vue' import Spending from './views/Spending.vue' import Reports from './views/Reports.vue' +import Restocking from './views/Restocking.vue' const router = createRouter({ history: createWebHistory(), @@ -16,7 +17,8 @@ const router = createRouter({ { path: '/orders', component: Orders }, { path: '/demand', component: Demand }, { path: '/spending', component: Spending }, - { path: '/reports', component: Reports } + { path: '/reports', component: Reports }, + { path: '/restocking', component: Restocking } ] }) diff --git a/client/src/views/Backlog.vue b/client/src/views/Backlog.vue index bb3bac21..63afbc87 100644 --- a/client/src/views/Backlog.vue +++ b/client/src/views/Backlog.vue @@ -1,53 +1,53 @@