diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml
new file mode 100644
index 000000000..3d3795ff8
--- /dev/null
+++ b/.github/workflows/claude.yml
@@ -0,0 +1,23 @@
+name: Claude Code
+on:
+ issue_comment:
+ types: [created]
+ pull_request_review_comment:
+ types: [created]
+jobs:
+ claude:
+ if: contains(github.event.comment.body, '@claude')
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pull-requests: write
+ issues: write
+ id-token: write
+ actions: read
+ steps:
+ - uses: actions/checkout@v6
+ with:
+ fetch-depth: 1
+ - 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..5f98b7c10 100644
--- a/client/src/api.js
+++ b/client/src/api.js
@@ -94,6 +94,16 @@ export const api = {
return response.data
},
+ async getRestockOrders() {
+ const response = await axios.get(`${API_BASE_URL}/restock-orders`)
+ return response.data
+ },
+
+ async createRestockOrder(restockOrderData) {
+ const response = await axios.post(`${API_BASE_URL}/restock-orders`, restockOrderData)
+ return response.data
+ },
+
async createPurchaseOrder(purchaseOrderData) {
const response = await axios.post(`${API_BASE_URL}/purchase-orders`, purchaseOrderData)
return response.data
diff --git a/client/src/locales/en.js b/client/src/locales/en.js
index 03a58fe6e..4a411306e 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'
},
@@ -112,6 +113,18 @@ export default {
onTimeDelivery: 'On-Time Delivery',
itemsCount: '{count} items',
quantity: 'Qty',
+ submittedOrders: 'Submitted Orders',
+ submittedEmpty: 'No restocking orders submitted yet. Create one from the Restocking tab.',
+ submittedTable: {
+ orderNumber: 'Order Number',
+ items: 'Items',
+ submitted: 'Submitted',
+ leadTime: 'Lead Time',
+ expectedDelivery: 'Expected Delivery',
+ totalValue: 'Total Value',
+ status: 'Status'
+ },
+ leadTimeDays: '{count} days',
table: {
orderNumber: 'Order Number',
orderId: 'Order ID',
@@ -189,6 +202,43 @@ export default {
},
// Filters
+ restocking: {
+ title: 'Restocking',
+ description: 'Set a budget and restock the items with the largest forecast shortfall',
+ budget: 'Available Budget',
+ budgetHint: 'Drag to set how much you can spend this cycle',
+ fullCoverage: 'Full coverage',
+ recommended: 'Recommended Restock',
+ recommendedCount: '{count} of {total} items recommended',
+ allocated: 'Allocated',
+ remaining: 'Remaining',
+ itemsSelected: 'Items',
+ longestLeadTime: 'Longest Lead Time',
+ placeOrder: 'Place Order',
+ submitting: 'Submitting...',
+ orderPlaced: 'Order {orderNumber} submitted. Expected delivery {date}.',
+ viewInOrders: 'View in Orders',
+ nothingAffordable: 'This budget is too small to cover a full unit of any shortfall item. Increase the budget to see recommendations.',
+ noShortfall: 'No item is forecast to exceed its current demand, so there is nothing to restock.',
+ partial: 'Partial',
+ partialHint: 'Budget covers {quantity} of {needed} units',
+ fullHint: 'Covers the full shortfall',
+ excluded: 'Not recommended',
+ excludedNoShortfall: 'Forecast is at or below current demand',
+ excludedNoBudget: 'Budget exhausted before this item',
+ days: '{count} days',
+ table: {
+ sku: 'SKU',
+ itemName: 'Item Name',
+ shortfall: 'Shortfall',
+ unitCost: 'Unit Cost',
+ quantity: 'Restock Qty',
+ lineTotal: 'Line Total',
+ leadTime: 'Lead Time',
+ coverage: 'Coverage'
+ }
+ },
+
filters: {
timePeriod: 'Time Period',
location: 'Location',
diff --git a/client/src/locales/ja.js b/client/src/locales/ja.js
index db33223ac..3f80d2fb8 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: '在庫管理システム'
},
@@ -112,6 +113,18 @@ export default {
onTimeDelivery: '定時配達',
itemsCount: '{count}件',
quantity: '数量',
+ submittedOrders: '送信済み発注',
+ submittedEmpty: '送信済みの補充発注はまだありません。補充発注タブから作成してください。',
+ submittedTable: {
+ orderNumber: '発注番号',
+ items: '品目',
+ submitted: '送信日',
+ leadTime: 'リードタイム',
+ expectedDelivery: '納品予定日',
+ totalValue: '合計金額',
+ status: 'ステータス'
+ },
+ leadTimeDays: '{count}日',
table: {
orderNumber: '注文番号',
orderId: '注文ID',
@@ -189,6 +202,43 @@ export default {
},
// Filters
+ restocking: {
+ title: '補充発注',
+ description: '予算を設定し、予測不足量が最も大きい品目を補充します',
+ budget: '利用可能予算',
+ budgetHint: 'このサイクルで使用できる金額をドラッグして設定します',
+ fullCoverage: '全量充当',
+ recommended: '推奨補充リスト',
+ recommendedCount: '{total}件中{count}件を推奨',
+ allocated: '割当額',
+ remaining: '残額',
+ itemsSelected: '品目数',
+ longestLeadTime: '最長リードタイム',
+ placeOrder: '発注する',
+ submitting: '送信中...',
+ orderPlaced: '発注 {orderNumber} を送信しました。納品予定日は {date} です。',
+ viewInOrders: '注文タブで確認',
+ nothingAffordable: 'この予算では不足品目を1単位も充当できません。予算を増やしてください。',
+ noShortfall: '現在の需要を上回る予測の品目がないため、補充対象はありません。',
+ partial: '一部',
+ partialHint: '予算で{needed}単位中{quantity}単位を充当',
+ fullHint: '不足量を全量充当',
+ excluded: '推奨対象外',
+ excludedNoShortfall: '予測が現在の需要以下です',
+ excludedNoBudget: 'この品目の前に予算を使い切りました',
+ days: '{count}日',
+ table: {
+ sku: 'SKU',
+ itemName: '品目名',
+ shortfall: '不足量',
+ unitCost: '単価',
+ quantity: '補充数量',
+ lineTotal: '小計',
+ leadTime: 'リードタイム',
+ coverage: '充当状況'
+ }
+ },
+
filters: {
timePeriod: '期間',
location: '場所',
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..656e9ac1f 100644
--- a/client/src/views/Orders.vue
+++ b/client/src/views/Orders.vue
@@ -27,6 +27,58 @@
+
+
+
{{ restockOrdersError }}
+
+ {{ t('orders.submittedEmpty') }}
+
+
+
+
+
+ | {{ t('orders.submittedTable.orderNumber') }} |
+ {{ t('orders.submittedTable.items') }} |
+ {{ t('orders.submittedTable.submitted') }} |
+ {{ t('orders.submittedTable.leadTime') }} |
+ {{ t('orders.submittedTable.expectedDelivery') }} |
+ {{ t('orders.submittedTable.totalValue') }} |
+ {{ t('orders.submittedTable.status') }} |
+
+
+
+
+ | {{ restockOrder.order_number }} |
+
+
+
+ {{ t('orders.itemsCount', { count: restockOrder.items.length }) }}
+
+
+
+ {{ translateProductName(item.item_name) }}
+ {{ t('orders.quantity') }}: {{ item.quantity }} @ {{ currencySymbol }}{{ item.unit_cost }}
+
+
+
+ |
+ {{ formatDate(restockOrder.submitted_date) }} |
+ {{ t('orders.leadTimeDays', { count: restockOrder.lead_time_days }) }} |
+ {{ formatDate(restockOrder.expected_delivery) }} |
+ {{ currencySymbol }}{{ restockOrder.total_value.toLocaleString() }} |
+
+
+ {{ restockOrder.status }}
+
+ |
+
+
+
+
+
+