@@ -34,18 +34,13 @@ export default function InventoryHistory({ warehouse, inventory, transactions }:
-
- 倉庫管理
- /
- 庫存管理
- /
- 庫存異動紀錄
-
-
-
庫存異動紀錄
-
+
+
+ 庫存異動紀錄
+
+
商品:{inventory.productName}
{inventory.productCode && ({inventory.productCode})}
diff --git a/resources/js/Pages/Warehouse/SafetyStockSettings.tsx b/resources/js/Pages/Warehouse/SafetyStockSettings.tsx
index d603a4d..80adf3c 100644
--- a/resources/js/Pages/Warehouse/SafetyStockSettings.tsx
+++ b/resources/js/Pages/Warehouse/SafetyStockSettings.tsx
@@ -4,7 +4,7 @@
*/
import { useState, useEffect } from "react";
-import { ArrowLeft, Plus } from "lucide-react";
+import { ArrowLeft, Plus, Shield } from "lucide-react";
import { Button } from "@/Components/ui/button";
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
import { Head, Link, router } from "@inertiajs/react";
@@ -14,6 +14,17 @@ import AddSafetyStockDialog from "@/Components/Warehouse/SafetyStock/AddSafetySt
import EditSafetyStockDialog from "@/Components/Warehouse/SafetyStock/EditSafetyStockDialog";
import { toast } from "sonner";
import { getInventoryBreadcrumbs } from "@/utils/breadcrumb";
+import { Can } from "@/Components/Permission/Can";
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+} from "@/Components/ui/alert-dialog";
interface Props {
warehouse: Warehouse;
@@ -31,6 +42,7 @@ export default function SafetyStockPage({
const [settings, setSettings] = useState
(initialSettings);
const [showAddDialog, setShowAddDialog] = useState(false);
const [editingSetting, setEditingSetting] = useState(null);
+ const [deleteId, setDeleteId] = useState(null);
// 當 Props 更新時同步本地 State
@@ -71,10 +83,16 @@ export default function SafetyStockPage({
});
};
- const handleDelete = (id: string) => {
- router.delete(route('warehouses.safety-stock.destroy', [warehouse.id, id]), {
+ const handleDelete = () => {
+ if (!deleteId) return;
+
+ router.delete(route('warehouses.safety-stock.destroy', [warehouse.id, deleteId]), {
onSuccess: () => {
+ setDeleteId(null);
toast.success("已刪除安全庫存設定");
+ },
+ onError: () => {
+ toast.error("刪除失敗");
}
});
};
@@ -101,18 +119,23 @@ export default function SafetyStockPage({
-
安全庫存設定 - {warehouse.name}
-
+
+
+ 安全庫存設定 - {warehouse.name}
+
+
設定商品的安全庫存量,當庫存低於安全值時將發出警告
-
+
+
+
@@ -121,7 +144,7 @@ export default function SafetyStockPage({
settings={settings}
inventories={inventories}
onEdit={setEditingSetting}
- onDelete={handleDelete}
+ onDelete={setDeleteId}
/>
{/* 新增對話框 */}
@@ -143,6 +166,27 @@ export default function SafetyStockPage({
onSave={handleEdit}
/>
)}
+
+ {/* 刪除確認對話框 */}
+
!open && setDeleteId(null)}>
+
+
+ 確認刪除安全庫存設定
+
+ 您確定要刪除此項商品的安全庫存設定嗎?刪除後系統將不再針對此商品發出庫存不足警告。此動作無法復原。
+
+
+
+ 取消
+
+ 確認刪除
+
+
+
+
);
diff --git a/routes/web.php b/routes/web.php
index 5b05b2e..8ac413d 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -22,75 +22,126 @@ Route::post('/login', [LoginController::class, 'store']);
Route::post('/logout', [LoginController::class, 'destroy'])->name('logout');
Route::middleware('auth')->group(function () {
+ // 儀表板 - 所有登入使用者皆可存取
Route::get('/', [DashboardController::class, 'index'])->name('dashboard');
- // 類別管理 (用於商品對話框)
- Route::get('/categories', [CategoryController::class, 'index'])->name('categories.index');
- Route::post('/categories', [CategoryController::class, 'store'])->name('categories.store');
- Route::put('/categories/{category}', [CategoryController::class, 'update'])->name('categories.update');
- Route::delete('/categories/{category}', [CategoryController::class, 'destroy'])->name('categories.destroy');
+ // 類別管理 (用於商品對話框) - 需要商品權限
+ Route::middleware('permission:products.view')->group(function () {
+ Route::get('/categories', [CategoryController::class, 'index'])->name('categories.index');
+ Route::post('/categories', [CategoryController::class, 'store'])->middleware('permission:products.create')->name('categories.store');
+ Route::put('/categories/{category}', [CategoryController::class, 'update'])->middleware('permission:products.edit')->name('categories.update');
+ Route::delete('/categories/{category}', [CategoryController::class, 'destroy'])->middleware('permission:products.delete')->name('categories.destroy');
+ });
- // 單位管理
- Route::post('/units', [UnitController::class, 'store'])->name('units.store');
- Route::put('/units/{unit}', [UnitController::class, 'update'])->name('units.update');
- Route::delete('/units/{unit}', [UnitController::class, 'destroy'])->name('units.destroy');
+ // 單位管理 - 需要商品權限
+ Route::middleware('permission:products.create|products.edit')->group(function () {
+ Route::post('/units', [UnitController::class, 'store'])->name('units.store');
+ Route::put('/units/{unit}', [UnitController::class, 'update'])->name('units.update');
+ Route::delete('/units/{unit}', [UnitController::class, 'destroy'])->name('units.destroy');
+ });
// 商品管理
- Route::get('/products', [ProductController::class, 'index'])->name('products.index');
- Route::post('/products', [ProductController::class, 'store'])->name('products.store');
- Route::put('/products/{product}', [ProductController::class, 'update'])->name('products.update');
- Route::delete('/products/{product}', [ProductController::class, 'destroy'])->name('products.destroy');
+ Route::middleware('permission:products.view')->group(function () {
+ Route::get('/products', [ProductController::class, 'index'])->name('products.index');
+ Route::post('/products', [ProductController::class, 'store'])->middleware('permission:products.create')->name('products.store');
+ Route::put('/products/{product}', [ProductController::class, 'update'])->middleware('permission:products.edit')->name('products.update');
+ Route::delete('/products/{product}', [ProductController::class, 'destroy'])->middleware('permission:products.delete')->name('products.destroy');
+ });
// 廠商管理
- Route::get('/vendors', [VendorController::class, 'index'])->name('vendors.index');
- Route::get('/vendors/{vendor}', [VendorController::class, 'show'])->name('vendors.show');
- Route::post('/vendors', [VendorController::class, 'store'])->name('vendors.store');
- Route::put('/vendors/{vendor}', [VendorController::class, 'update'])->name('vendors.update');
- Route::delete('/vendors/{vendor}', [VendorController::class, 'destroy'])->name('vendors.destroy');
+ Route::middleware('permission:vendors.view')->group(function () {
+ Route::get('/vendors', [VendorController::class, 'index'])->name('vendors.index');
+ Route::get('/vendors/{vendor}', [VendorController::class, 'show'])->name('vendors.show');
+ Route::post('/vendors', [VendorController::class, 'store'])->middleware('permission:vendors.create')->name('vendors.store');
+ Route::put('/vendors/{vendor}', [VendorController::class, 'update'])->middleware('permission:vendors.edit')->name('vendors.update');
+ Route::delete('/vendors/{vendor}', [VendorController::class, 'destroy'])->middleware('permission:vendors.delete')->name('vendors.destroy');
- // 供貨商品相關路由
- Route::post('/vendors/{vendor}/products', [VendorProductController::class, 'store'])->name('vendors.products.store');
- Route::put('/vendors/{vendor}/products/{product}', [VendorProductController::class, 'update'])->name('vendors.products.update');
- Route::delete('/vendors/{vendor}/products/{product}', [VendorProductController::class, 'destroy'])->name('vendors.products.destroy');
+ // 供貨商品相關路由
+ Route::post('/vendors/{vendor}/products', [VendorProductController::class, 'store'])->middleware('permission:vendors.edit')->name('vendors.products.store');
+ Route::put('/vendors/{vendor}/products/{product}', [VendorProductController::class, 'update'])->middleware('permission:vendors.edit')->name('vendors.products.update');
+ Route::delete('/vendors/{vendor}/products/{product}', [VendorProductController::class, 'destroy'])->middleware('permission:vendors.edit')->name('vendors.products.destroy');
+ });
// 倉庫管理
- Route::get('/warehouses', [WarehouseController::class, 'index'])->name('warehouses.index');
- Route::post('/warehouses', [WarehouseController::class, 'store'])->name('warehouses.store');
- Route::put('/warehouses/{warehouse}', [WarehouseController::class, 'update'])->name('warehouses.update');
- Route::delete('/warehouses/{warehouse}', [WarehouseController::class, 'destroy'])->name('warehouses.destroy');
+ Route::middleware('permission:warehouses.view')->group(function () {
+ Route::get('/warehouses', [WarehouseController::class, 'index'])->name('warehouses.index');
+ Route::post('/warehouses', [WarehouseController::class, 'store'])->middleware('permission:warehouses.create')->name('warehouses.store');
+ Route::put('/warehouses/{warehouse}', [WarehouseController::class, 'update'])->middleware('permission:warehouses.edit')->name('warehouses.update');
+ Route::delete('/warehouses/{warehouse}', [WarehouseController::class, 'destroy'])->middleware('permission:warehouses.delete')->name('warehouses.destroy');
- // 倉庫庫存管理
- Route::get('/warehouses/{warehouse}/inventory', [InventoryController::class, 'index'])->name('warehouses.inventory.index');
- Route::get('/warehouses/{warehouse}/inventory/create', [InventoryController::class, 'create'])->name('warehouses.inventory.create');
- Route::post('/warehouses/{warehouse}/inventory', [InventoryController::class, 'store'])->name('warehouses.inventory.store');
- Route::get('/warehouses/{warehouse}/inventory/{inventoryId}/edit', [InventoryController::class, 'edit'])->name('warehouses.inventory.edit');
- Route::put('/warehouses/{warehouse}/inventory/{inventoryId}', [InventoryController::class, 'update'])->name('warehouses.inventory.update');
- Route::delete('/warehouses/{warehouse}/inventory/{inventoryId}', [InventoryController::class, 'destroy'])->name('warehouses.inventory.destroy');
- Route::get('/warehouses/{warehouse}/inventory/{inventoryId}/history', [InventoryController::class, 'history'])->name('warehouses.inventory.history');
+ // 倉庫庫存管理 - 需要庫存權限
+ Route::middleware('permission:inventory.view')->group(function () {
+ Route::get('/warehouses/{warehouse}/inventory', [InventoryController::class, 'index'])->name('warehouses.inventory.index');
+ Route::get('/warehouses/{warehouse}/inventory/{inventoryId}/history', [InventoryController::class, 'history'])->name('warehouses.inventory.history');
+
+ Route::middleware('permission:inventory.adjust')->group(function () {
+ Route::get('/warehouses/{warehouse}/inventory/create', [InventoryController::class, 'create'])->name('warehouses.inventory.create');
+ Route::post('/warehouses/{warehouse}/inventory', [InventoryController::class, 'store'])->name('warehouses.inventory.store');
+ Route::get('/warehouses/{warehouse}/inventory/{inventoryId}/edit', [InventoryController::class, 'edit'])->name('warehouses.inventory.edit');
+ Route::put('/warehouses/{warehouse}/inventory/{inventoryId}', [InventoryController::class, 'update'])->name('warehouses.inventory.update');
+ Route::delete('/warehouses/{warehouse}/inventory/{inventoryId}', [InventoryController::class, 'destroy'])->name('warehouses.inventory.destroy');
+ });
+ });
- // 安全庫存設定
- Route::get('/warehouses/{warehouse}/safety-stock', [SafetyStockController::class, 'index'])->name('warehouses.safety-stock.index');
- Route::post('/warehouses/{warehouse}/safety-stock', [SafetyStockController::class, 'store'])->name('warehouses.safety-stock.store');
- Route::put('/warehouses/{warehouse}/safety-stock/{inventory}', [SafetyStockController::class, 'update'])->name('warehouses.safety-stock.update');
- Route::delete('/warehouses/{warehouse}/safety-stock/{inventory}', [SafetyStockController::class, 'destroy'])->name('warehouses.safety-stock.destroy');
+ // 安全庫存設定
+ Route::middleware('permission:inventory.view')->group(function () {
+ Route::get('/warehouses/{warehouse}/safety-stock', [SafetyStockController::class, 'index'])->name('warehouses.safety-stock.index');
+ Route::middleware('permission:inventory.safety_stock')->group(function () {
+ Route::post('/warehouses/{warehouse}/safety-stock', [SafetyStockController::class, 'store'])->name('warehouses.safety-stock.store');
+ Route::put('/warehouses/{warehouse}/safety-stock/{inventory}', [SafetyStockController::class, 'update'])->name('warehouses.safety-stock.update');
+ Route::delete('/warehouses/{warehouse}/safety-stock/{inventory}', [SafetyStockController::class, 'destroy'])->name('warehouses.safety-stock.destroy');
+ });
+ });
+ });
// 採購單管理
- Route::get('/purchase-orders', [PurchaseOrderController::class, 'index'])->name('purchase-orders.index');
- Route::get('/purchase-orders/create', [PurchaseOrderController::class, 'create'])->name('purchase-orders.create');
- Route::post('/purchase-orders', [PurchaseOrderController::class, 'store'])->name('purchase-orders.store');
- Route::get('/purchase-orders/{id}', [PurchaseOrderController::class, 'show'])->name('purchase-orders.show');
- Route::get('/purchase-orders/{id}/edit', [PurchaseOrderController::class, 'edit'])->name('purchase-orders.edit');
- Route::put('/purchase-orders/{id}', [PurchaseOrderController::class, 'update'])->name('purchase-orders.update');
- Route::delete('/purchase-orders/{id}', [PurchaseOrderController::class, 'destroy'])->name('purchase-orders.destroy');
+ Route::middleware('permission:purchase_orders.view')->group(function () {
+ Route::get('/purchase-orders', [PurchaseOrderController::class, 'index'])->name('purchase-orders.index');
+
+ Route::middleware('permission:purchase_orders.create')->group(function () {
+ Route::get('/purchase-orders/create', [PurchaseOrderController::class, 'create'])->name('purchase-orders.create');
+ Route::post('/purchase-orders', [PurchaseOrderController::class, 'store'])->name('purchase-orders.store');
+ });
+
+ Route::get('/purchase-orders/{id}', [PurchaseOrderController::class, 'show'])->name('purchase-orders.show');
+
+ Route::get('/purchase-orders/{id}/edit', [PurchaseOrderController::class, 'edit'])->middleware('permission:purchase_orders.edit')->name('purchase-orders.edit');
+ Route::put('/purchase-orders/{id}', [PurchaseOrderController::class, 'update'])->middleware('permission:purchase_orders.edit')->name('purchase-orders.update');
+ Route::delete('/purchase-orders/{id}', [PurchaseOrderController::class, 'destroy'])->middleware('permission:purchase_orders.delete')->name('purchase-orders.destroy');
+ });
// 撥補單 (在庫存調撥時使用)
- Route::post('/transfer-orders', [TransferOrderController::class, 'store'])->name('transfer-orders.store');
- Route::get('/api/warehouses/{warehouse}/inventories', [TransferOrderController::class, 'getWarehouseInventories'])->name('api.warehouses.inventories');
+ Route::middleware('permission:inventory.transfer')->group(function () {
+ Route::post('/transfer-orders', [TransferOrderController::class, 'store'])->name('transfer-orders.store');
+ });
+ Route::get('/api/warehouses/{warehouse}/inventories', [TransferOrderController::class, 'getWarehouseInventories'])
+ ->middleware('permission:inventory.view')
+ ->name('api.warehouses.inventories');
// 系統管理
Route::prefix('admin')->group(function () {
- Route::resource('roles', RoleController::class);
- Route::resource('users', UserController::class);
+ Route::middleware('permission:roles.view')->group(function () {
+ Route::get('/roles', [RoleController::class, 'index'])->name('roles.index');
+ Route::middleware('permission:roles.create')->group(function () {
+ Route::get('/roles/create', [RoleController::class, 'create'])->name('roles.create');
+ Route::post('/roles', [RoleController::class, 'store'])->name('roles.store');
+ });
+ Route::get('/roles/{role}/edit', [RoleController::class, 'edit'])->middleware('permission:roles.edit')->name('roles.edit');
+ Route::put('/roles/{role}', [RoleController::class, 'update'])->middleware('permission:roles.edit')->name('roles.update');
+ Route::delete('/roles/{role}', [RoleController::class, 'destroy'])->middleware('permission:roles.delete')->name('roles.destroy');
+ });
+
+ Route::middleware('permission:users.view')->group(function () {
+ Route::get('/users', [UserController::class, 'index'])->name('users.index');
+ Route::middleware('permission:users.create')->group(function () {
+ Route::get('/users/create', [UserController::class, 'create'])->name('users.create');
+ Route::post('/users', [UserController::class, 'store'])->name('users.store');
+ });
+ Route::get('/users/{user}/edit', [UserController::class, 'edit'])->middleware('permission:users.edit')->name('users.edit');
+ Route::put('/users/{user}', [UserController::class, 'update'])->middleware('permission:users.edit')->name('users.update');
+ Route::delete('/users/{user}', [UserController::class, 'destroy'])->middleware('permission:users.delete')->name('users.destroy');
+ });
});
}); // End of auth middleware group
+