diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml
new file mode 100644
index 000000000..b96d6f0ef
--- /dev/null
+++ b/.github/workflows/claude-code-review.yml
@@ -0,0 +1,30 @@
+name: Claude Code Review
+
+on:
+ pull_request:
+ types: [opened, synchronize]
+
+jobs:
+ claude-review:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: read
+ issues: read
+ id-token: write
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+
+ - name: Run Claude Code Review
+ id: claude-review
+ uses: anthropics/claude-code-action@v1
+ with:
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
+ prompt: |
+ Review this pull request. Focus on correctness, potential bugs,
+ security issues, and test coverage. Be concise and specific, and
+ point to file:line where possible. Leave inline comments via the
+ repository's review tools.
diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml
new file mode 100644
index 000000000..337f0be20
--- /dev/null
+++ b/.github/workflows/claude.yml
@@ -0,0 +1,39 @@
+name: Claude Code
+
+on:
+ issue_comment:
+ types: [created]
+ pull_request_review_comment:
+ types: [created]
+ issues:
+ types: [opened, assigned]
+ pull_request_review:
+ types: [submitted]
+
+jobs:
+ claude:
+ # Only run when someone actually mentions @claude, to avoid spending
+ # Actions minutes and API tokens on every comment/issue event.
+ if: |
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: read
+ issues: read
+ id-token: write
+ actions: read
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+
+ - name: Run Claude Code
+ id: claude
+ uses: anthropics/claude-code-action@v1
+ with:
+ anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
diff --git a/client/src/App.vue b/client/src/App.vue
index c2da05a5c..dd6849b1c 100644
--- a/client/src/App.vue
+++ b/client/src/App.vue
@@ -22,6 +22,9 @@
{{ t('nav.demandForecast') }}
+
+ {{ t('nav.restocking') }}
+
Reports
diff --git a/client/src/api.js b/client/src/api.js
index 11cb9db70..3d4b82b11 100644
--- a/client/src/api.js
+++ b/client/src/api.js
@@ -33,6 +33,11 @@ export const api = {
return response.data
},
+ async createOrder(orderData) {
+ const response = await axios.post(`${API_BASE_URL}/orders`, orderData)
+ return response.data
+ },
+
async getDemandForecasts() {
const response = await axios.get(`${API_BASE_URL}/demand`)
return response.data
diff --git a/client/src/locales/en.js b/client/src/locales/en.js
index 03a58fe6e..d7fa7e541 100644
--- a/client/src/locales/en.js
+++ b/client/src/locales/en.js
@@ -6,6 +6,7 @@ export default {
orders: 'Orders',
finance: 'Finance',
demandForecast: 'Demand Forecast',
+ restocking: 'Restocking',
companyName: 'Catalyst Components',
subtitle: 'Inventory Management System'
},
@@ -106,12 +107,14 @@ export default {
title: 'Orders',
description: 'View and manage customer orders',
allOrders: 'All Orders',
+ submittedOrders: 'Submitted Orders',
totalOrders: 'Total Orders',
totalRevenue: 'Total Revenue',
avgOrderValue: 'Avg Order Value',
onTimeDelivery: 'On-Time Delivery',
itemsCount: '{count} items',
quantity: 'Qty',
+ leadTimeDays: '{days} days',
table: {
orderNumber: 'Order Number',
orderId: 'Order ID',
@@ -125,7 +128,8 @@ export default {
totalValue: 'Total Value',
status: 'Status',
expectedDelivery: 'Expected Delivery',
- actualDelivery: 'Actual Delivery'
+ actualDelivery: 'Actual Delivery',
+ leadTime: 'Lead Time'
}
},
@@ -204,11 +208,37 @@ export default {
shipped: 'Shipped',
processing: 'Processing',
backordered: 'Backordered',
+ submitted: 'Submitted',
inStock: 'In Stock',
lowStock: 'Low Stock',
adequate: 'Adequate'
},
+ // Restocking
+ restocking: {
+ title: 'Restocking',
+ description: 'Set a budget and place restock orders based on the demand forecast',
+ budgetLabel: 'Available Budget',
+ budgetHelp: 'Drag to set how much you can spend. Recommendations update automatically.',
+ recommended: 'Recommended Restock',
+ itemsRecommended: 'Items Recommended',
+ totalCost: 'Total Cost',
+ budgetRemaining: 'Budget Remaining',
+ placeOrder: 'Place Order',
+ placing: 'Placing order...',
+ orderPlaced: 'Order {orderNumber} submitted. Expected delivery {date}.',
+ noRecommendations: 'Budget is too low to restock any item. Increase the budget to see recommendations.',
+ table: {
+ item: 'Item',
+ trend: 'Trend',
+ gap: 'Forecast Gap',
+ quantity: 'Restock Qty',
+ unitCost: 'Unit Cost',
+ lineCost: 'Line Cost',
+ leadTime: 'Lead Time'
+ }
+ },
+
// Trends
trends: {
increasing: 'increasing',
diff --git a/client/src/locales/ja.js b/client/src/locales/ja.js
index db33223ac..be6813a59 100644
--- a/client/src/locales/ja.js
+++ b/client/src/locales/ja.js
@@ -6,6 +6,7 @@ export default {
orders: '注文',
finance: '財務',
demandForecast: '需要予測',
+ restocking: '補充',
companyName: '触媒コンポーネンツ',
subtitle: '在庫管理システム'
},
@@ -106,12 +107,14 @@ export default {
title: '注文',
description: '顧客注文の表示と管理',
allOrders: 'すべての注文',
+ submittedOrders: '送信済み注文',
totalOrders: '総注文数',
totalRevenue: '総収益',
avgOrderValue: '平均注文額',
onTimeDelivery: '定時配達',
itemsCount: '{count}件',
quantity: '数量',
+ leadTimeDays: '{days}日',
table: {
orderNumber: '注文番号',
orderId: '注文ID',
@@ -125,7 +128,8 @@ export default {
totalValue: '合計金額',
status: 'ステータス',
expectedDelivery: '予定配達日',
- actualDelivery: '実際の配達日'
+ actualDelivery: '実際の配達日',
+ leadTime: 'リードタイム'
}
},
@@ -204,11 +208,37 @@ export default {
shipped: '出荷済み',
processing: '処理中',
backordered: 'バックオーダー',
+ submitted: '送信済み',
inStock: '在庫あり',
lowStock: '在庫僅少',
adequate: '適量'
},
+ // Restocking
+ restocking: {
+ title: '補充',
+ description: '予算を設定し、需要予測に基づいて補充注文を行います',
+ budgetLabel: '利用可能な予算',
+ budgetHelp: 'ドラッグして使用可能額を設定します。推奨は自動的に更新されます。',
+ recommended: '推奨補充',
+ itemsRecommended: '推奨品目数',
+ totalCost: '合計費用',
+ budgetRemaining: '残り予算',
+ placeOrder: '注文する',
+ placing: '注文を送信中...',
+ orderPlaced: '注文 {orderNumber} を送信しました。予定配達日 {date}。',
+ noRecommendations: '予算が不足しているため、補充できる品目がありません。予算を増やしてください。',
+ table: {
+ item: '品目',
+ trend: '傾向',
+ gap: '予測ギャップ',
+ quantity: '補充数量',
+ unitCost: '単価',
+ lineCost: '小計',
+ leadTime: 'リードタイム'
+ }
+ },
+
// Trends
trends: {
increasing: '増加',
diff --git a/client/src/main.js b/client/src/main.js
index 477c2d966..8884eea63 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/Orders.vue b/client/src/views/Orders.vue
index 7413f6e66..4d995d98e 100644
--- a/client/src/views/Orders.vue
+++ b/client/src/views/Orders.vue
@@ -27,6 +27,54 @@
+
+
+
+
+
+
+ | {{ t('orders.table.orderNumber') }} |
+ {{ t('orders.table.items') }} |
+ {{ t('orders.table.status') }} |
+ {{ t('orders.table.orderDate') }} |
+ {{ t('orders.table.expectedDelivery') }} |
+ {{ t('orders.table.leadTime') }} |
+ {{ t('orders.table.totalValue') }} |
+
+
+
+
+ | {{ order.order_number }} |
+
+
+
+ {{ t('orders.itemsCount', { count: order.items.length }) }}
+
+
+
+ {{ translateProductName(item.name) }}
+ {{ t('orders.quantity') }}: {{ item.quantity }} @ {{ currencySymbol }}{{ item.unit_price }}
+
+
+
+ |
+
+
+ {{ t(`status.${order.status.toLowerCase()}`) }}
+
+ |
+ {{ formatDate(order.order_date) }} |
+ {{ formatDate(order.expected_delivery) }} |
+ {{ t('orders.leadTimeDays', { days: getLeadTime(order) }) }} |
+ {{ currencySymbol }}{{ order.total_value.toLocaleString() }} |
+
+
+
+
+
+