feat: 實作銷售單匯入權限控管並全面精簡權限顯示名稱
This commit is contained in:
@@ -191,6 +191,7 @@ class RoleController extends Controller
|
|||||||
'production_orders' => '生產工單管理',
|
'production_orders' => '生產工單管理',
|
||||||
'utility_fees' => '公共事業費管理',
|
'utility_fees' => '公共事業費管理',
|
||||||
'accounting' => '會計報表',
|
'accounting' => '會計報表',
|
||||||
|
'sales_imports' => '銷售單匯入管理',
|
||||||
'users' => '使用者管理',
|
'users' => '使用者管理',
|
||||||
'roles' => '角色與權限',
|
'roles' => '角色與權限',
|
||||||
'system' => '系統管理',
|
'system' => '系統管理',
|
||||||
|
|||||||
@@ -4,10 +4,14 @@ use Illuminate\Support\Facades\Route;
|
|||||||
use App\Modules\Sales\Controllers\SalesImportController;
|
use App\Modules\Sales\Controllers\SalesImportController;
|
||||||
|
|
||||||
Route::middleware(['auth', 'verified'])->prefix('sales')->name('sales-imports.')->group(function () {
|
Route::middleware(['auth', 'verified'])->prefix('sales')->name('sales-imports.')->group(function () {
|
||||||
Route::get('/imports', [SalesImportController::class, 'index'])->name('index');
|
Route::middleware('permission:sales_imports.view')->group(function () {
|
||||||
Route::get('/imports/create', [SalesImportController::class, 'create'])->name('create');
|
Route::get('/imports', [SalesImportController::class, 'index'])->name('index');
|
||||||
Route::post('/imports', [SalesImportController::class, 'store'])->name('store');
|
Route::get('/imports/{import}', [SalesImportController::class, 'show'])->name('show');
|
||||||
Route::get('/imports/{import}', [SalesImportController::class, 'show'])->name('show');
|
});
|
||||||
Route::post('/imports/{import}/confirm', [SalesImportController::class, 'confirm'])->name('confirm');
|
|
||||||
Route::delete('/imports/{import}', [SalesImportController::class, 'destroy'])->name('destroy');
|
Route::post('/imports', [SalesImportController::class, 'store'])->middleware('permission:sales_imports.create')->name('store');
|
||||||
|
Route::get('/imports/create', [SalesImportController::class, 'create'])->middleware('permission:sales_imports.create')->name('create');
|
||||||
|
|
||||||
|
Route::post('/imports/{import}/confirm', [SalesImportController::class, 'confirm'])->middleware('permission:sales_imports.confirm')->name('confirm');
|
||||||
|
Route::delete('/imports/{import}', [SalesImportController::class, 'destroy'])->middleware('permission:sales_imports.delete')->name('destroy');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('permissions', function (Blueprint $table) {
|
||||||
|
$table->string('display_name')->nullable()->after('name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('permissions', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('display_name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('permissions', function (Blueprint $table) {
|
||||||
|
$table->string('display_name')->nullable()->after('name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('permissions', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('display_name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -20,108 +20,116 @@ class PermissionSeeder extends Seeder
|
|||||||
// 建立權限
|
// 建立權限
|
||||||
$permissions = [
|
$permissions = [
|
||||||
// 產品管理
|
// 產品管理
|
||||||
'products.view',
|
'products.view' => '檢視',
|
||||||
'products.create',
|
'products.create' => '建立',
|
||||||
'products.edit',
|
'products.edit' => '編輯',
|
||||||
'products.delete',
|
'products.delete' => '刪除',
|
||||||
|
|
||||||
// 採購單管理
|
// 採購單管理
|
||||||
'purchase_orders.view',
|
'purchase_orders.view' => '檢視',
|
||||||
'purchase_orders.create',
|
'purchase_orders.create' => '建立',
|
||||||
'purchase_orders.edit',
|
'purchase_orders.edit' => '編輯',
|
||||||
'purchase_orders.delete',
|
'purchase_orders.delete' => '刪除',
|
||||||
'purchase_orders.approve', // 核准權限
|
'purchase_orders.approve' => '核准',
|
||||||
'purchase_orders.cancel', // 作廢權限(原取消)
|
'purchase_orders.cancel' => '作廢',
|
||||||
|
|
||||||
|
|
||||||
// 庫存管理
|
// 庫存管理
|
||||||
'inventory.view',
|
'inventory.view' => '檢視',
|
||||||
'inventory.view_cost', // 查看成本與價值
|
'inventory.view_cost' => '檢視成本',
|
||||||
'inventory.delete',
|
'inventory.delete' => '刪除',
|
||||||
|
|
||||||
// 庫存盤點 (Stock Counting)
|
// 庫存盤點 (Stock Counting)
|
||||||
'inventory_count.view',
|
'inventory_count.view' => '檢視',
|
||||||
'inventory_count.create',
|
'inventory_count.create' => '建立',
|
||||||
'inventory_count.edit',
|
'inventory_count.edit' => '編輯',
|
||||||
'inventory_count.delete',
|
'inventory_count.delete' => '刪除',
|
||||||
|
|
||||||
// 庫存調整 (Stock Adjustment)
|
// 庫存調整 (Stock Adjustment)
|
||||||
'inventory_adjust.view',
|
'inventory_adjust.view' => '檢視',
|
||||||
'inventory_adjust.create',
|
'inventory_adjust.create' => '建立',
|
||||||
'inventory_adjust.edit',
|
'inventory_adjust.edit' => '編輯',
|
||||||
'inventory_adjust.delete',
|
'inventory_adjust.delete' => '刪除',
|
||||||
|
|
||||||
// 庫存調撥 (Stock Transfer)
|
// 庫存調撥 (Stock Transfer)
|
||||||
'inventory_transfer.view',
|
'inventory_transfer.view' => '檢視',
|
||||||
'inventory_transfer.create',
|
'inventory_transfer.create' => '建立',
|
||||||
'inventory_transfer.edit',
|
'inventory_transfer.edit' => '編輯',
|
||||||
'inventory_transfer.delete',
|
'inventory_transfer.delete' => '刪除',
|
||||||
|
|
||||||
// 進貨單管理
|
// 進貨單管理
|
||||||
'goods_receipts.view',
|
'goods_receipts.view' => '檢視',
|
||||||
'goods_receipts.create',
|
'goods_receipts.create' => '建立',
|
||||||
'goods_receipts.edit',
|
'goods_receipts.edit' => '編輯',
|
||||||
'goods_receipts.delete',
|
'goods_receipts.delete' => '刪除',
|
||||||
|
|
||||||
// 出貨單管理 (Delivery Notes / Shipping Orders)
|
// 出貨單管理 (Delivery Notes / Shipping Orders)
|
||||||
'delivery_notes.view',
|
'delivery_notes.view' => '檢視',
|
||||||
'delivery_notes.create',
|
'delivery_notes.create' => '建立',
|
||||||
'delivery_notes.edit',
|
'delivery_notes.edit' => '編輯',
|
||||||
'delivery_notes.delete',
|
'delivery_notes.delete' => '刪除',
|
||||||
|
|
||||||
// 生產工單管理
|
// 生產工單管理
|
||||||
'production_orders.view',
|
'production_orders.view' => '檢視',
|
||||||
'production_orders.create',
|
'production_orders.create' => '建立',
|
||||||
'production_orders.edit',
|
'production_orders.edit' => '編輯',
|
||||||
'production_orders.delete',
|
'production_orders.delete' => '刪除',
|
||||||
|
|
||||||
// 配方管理
|
// 配方管理
|
||||||
'recipes.view',
|
'recipes.view' => '檢視',
|
||||||
'recipes.create',
|
'recipes.create' => '建立',
|
||||||
'recipes.edit',
|
'recipes.edit' => '編輯',
|
||||||
'recipes.delete',
|
'recipes.delete' => '刪除',
|
||||||
|
|
||||||
// 供應商管理
|
// 供應商管理
|
||||||
'vendors.view',
|
'vendors.view' => '檢視',
|
||||||
'vendors.create',
|
'vendors.create' => '建立',
|
||||||
'vendors.edit',
|
'vendors.edit' => '編輯',
|
||||||
'vendors.delete',
|
'vendors.delete' => '刪除',
|
||||||
|
|
||||||
// 倉庫管理
|
// 倉庫管理
|
||||||
'warehouses.view',
|
'warehouses.view' => '檢視',
|
||||||
'warehouses.create',
|
'warehouses.create' => '建立',
|
||||||
'warehouses.edit',
|
'warehouses.edit' => '編輯',
|
||||||
'warehouses.delete',
|
'warehouses.delete' => '刪除',
|
||||||
|
|
||||||
// 使用者管理
|
// 使用者管理
|
||||||
'users.view',
|
'users.view' => '檢視',
|
||||||
'users.create',
|
'users.create' => '建立',
|
||||||
'users.edit',
|
'users.edit' => '編輯',
|
||||||
'users.delete',
|
'users.delete' => '刪除',
|
||||||
'users.activate', // 啟用/停用使用者
|
'users.activate' => '狀態管理',
|
||||||
|
|
||||||
// 角色權限管理
|
// 角色權限管理
|
||||||
'roles.view',
|
'roles.view' => '檢視',
|
||||||
'roles.create',
|
'roles.create' => '建立',
|
||||||
'roles.edit',
|
'roles.edit' => '編輯',
|
||||||
'roles.delete',
|
'roles.delete' => '刪除',
|
||||||
|
|
||||||
// 系統日誌
|
// 系統日誌
|
||||||
'system.view_logs',
|
'system.view_logs' => '檢視日誌',
|
||||||
|
|
||||||
// 公共事業費管理
|
// 公共事業費管理
|
||||||
'utility_fees.view',
|
'utility_fees.view' => '檢視',
|
||||||
'utility_fees.create',
|
'utility_fees.create' => '建立',
|
||||||
'utility_fees.edit',
|
'utility_fees.edit' => '編輯',
|
||||||
'utility_fees.delete',
|
'utility_fees.delete' => '刪除',
|
||||||
|
|
||||||
// 會計報表
|
// 會計報表
|
||||||
'accounting.view',
|
'accounting.view' => '檢視',
|
||||||
'accounting.export',
|
'accounting.export' => '匯出',
|
||||||
|
|
||||||
|
// 銷售匯入管理
|
||||||
|
'sales_imports.view' => '檢視',
|
||||||
|
'sales_imports.create' => '建立',
|
||||||
|
'sales_imports.confirm' => '確認',
|
||||||
|
'sales_imports.delete' => '刪除',
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($permissions as $permission) {
|
foreach ($permissions as $name => $displayName) {
|
||||||
Permission::firstOrCreate(['name' => $permission]);
|
Permission::updateOrCreate(
|
||||||
|
['name' => $name],
|
||||||
|
['display_name' => $displayName]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 建立角色
|
// 建立角色
|
||||||
@@ -156,6 +164,7 @@ class PermissionSeeder extends Seeder
|
|||||||
'system.view_logs',
|
'system.view_logs',
|
||||||
'utility_fees.view', 'utility_fees.create', 'utility_fees.edit', 'utility_fees.delete',
|
'utility_fees.view', 'utility_fees.create', 'utility_fees.edit', 'utility_fees.delete',
|
||||||
'accounting.view', 'accounting.export',
|
'accounting.view', 'accounting.export',
|
||||||
|
'sales_imports.view', 'sales_imports.create', 'sales_imports.confirm', 'sales_imports.delete',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// warehouse-manager 管理庫存與倉庫
|
// warehouse-manager 管理庫存與倉庫
|
||||||
|
|||||||
Binary file not shown.
@@ -165,14 +165,14 @@ export default function AuthenticatedLayout({
|
|||||||
id: "sales-management",
|
id: "sales-management",
|
||||||
label: "銷售管理",
|
label: "銷售管理",
|
||||||
icon: <TrendingUp className="h-5 w-5" />,
|
icon: <TrendingUp className="h-5 w-5" />,
|
||||||
// permission: ["sales.view_imports"], // Temporarily disabled for immediate visibility
|
permission: "sales_imports.view",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
id: "sales-import-list",
|
id: "sales-import-list",
|
||||||
label: "銷售單匯入",
|
label: "銷售單匯入",
|
||||||
icon: <FileUp className="h-4 w-4" />,
|
icon: <FileUp className="h-4 w-4" />,
|
||||||
route: "/sales/imports",
|
route: "/sales/imports",
|
||||||
// permission: "sales.view_imports",
|
permission: "sales_imports.view",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { ChevronsDown, ChevronsUp } from "lucide-react";
|
|||||||
export interface Permission {
|
export interface Permission {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
|
display_name?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupedPermission {
|
export interface GroupedPermission {
|
||||||
@@ -104,7 +105,7 @@ export default function PermissionSelector({ groupedPermissions, selectedPermiss
|
|||||||
|
|
||||||
// Filter permissions that match
|
// Filter permissions that match
|
||||||
const matchingPermissions = group.permissions.filter(p => {
|
const matchingPermissions = group.permissions.filter(p => {
|
||||||
const translatedName = translateAction(p.name);
|
const translatedName = p.display_name || translateAction(p.name);
|
||||||
return translatedName.includes(searchQuery) ||
|
return translatedName.includes(searchQuery) ||
|
||||||
p.name.toLowerCase().includes(searchQuery.toLowerCase());
|
p.name.toLowerCase().includes(searchQuery.toLowerCase());
|
||||||
});
|
});
|
||||||
@@ -306,7 +307,7 @@ function PermissionItem({ permission, selectedPermissions, onToggle, translate }
|
|||||||
htmlFor={permission.name}
|
htmlFor={permission.name}
|
||||||
className="text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 cursor-pointer text-gray-700 hover:text-primary-main transition-colors"
|
className="text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 cursor-pointer text-gray-700 hover:text-primary-main transition-colors"
|
||||||
>
|
>
|
||||||
{translate(permission.name)}
|
{permission.display_name || translate(permission.name)}
|
||||||
</label>
|
</label>
|
||||||
<p className="text-[10px] text-gray-400 font-mono">
|
<p className="text-[10px] text-gray-400 font-mono">
|
||||||
{permission.name}
|
{permission.name}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import { format } from 'date-fns';
|
|||||||
import Pagination from "@/Components/shared/Pagination";
|
import Pagination from "@/Components/shared/Pagination";
|
||||||
import { SearchableSelect } from "@/Components/ui/searchable-select";
|
import { SearchableSelect } from "@/Components/ui/searchable-select";
|
||||||
import { router } from "@inertiajs/react";
|
import { router } from "@inertiajs/react";
|
||||||
|
import { usePermission } from "@/hooks/usePermission";
|
||||||
|
|
||||||
interface ImportBatch {
|
interface ImportBatch {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -51,6 +52,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function SalesImportIndex({ batches, filters = {} }: Props) {
|
export default function SalesImportIndex({ batches, filters = {} }: Props) {
|
||||||
|
const { can } = usePermission();
|
||||||
const [perPage, setPerPage] = useState(filters?.per_page?.toString() || "10");
|
const [perPage, setPerPage] = useState(filters?.per_page?.toString() || "10");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -88,12 +90,14 @@ export default function SalesImportIndex({ batches, filters = {} }: Props) {
|
|||||||
匯入並管理銷售出貨紀錄
|
匯入並管理銷售出貨紀錄
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Link href={route('sales-imports.create')}>
|
{can('sales_imports.create') && (
|
||||||
<Button className="button-filled-primary gap-2">
|
<Link href={route('sales-imports.create')}>
|
||||||
<Plus className="h-4 w-4" />
|
<Button className="button-filled-primary gap-2">
|
||||||
新增匯入
|
<Plus className="h-4 w-4" />
|
||||||
</Button>
|
新增匯入
|
||||||
</Link>
|
</Button>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-white rounded-lg border shadow-sm overflow-hidden">
|
<div className="bg-white rounded-lg border shadow-sm overflow-hidden">
|
||||||
@@ -142,7 +146,7 @@ export default function SalesImportIndex({ batches, filters = {} }: Props) {
|
|||||||
<Eye className="h-4 w-4" />
|
<Eye className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
{batch.status === 'pending' && (
|
{batch.status === 'pending' && can('sales_imports.delete') && (
|
||||||
<AlertDialog>
|
<AlertDialog>
|
||||||
<AlertDialogTrigger asChild>
|
<AlertDialogTrigger asChild>
|
||||||
<Button variant="outline" size="sm" className="button-outlined-error" title="刪除">
|
<Button variant="outline" size="sm" className="button-outlined-error" title="刪除">
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import { Badge } from "@/Components/ui/badge";
|
|||||||
import { ArrowLeft, CheckCircle, Trash2, Printer } from 'lucide-react';
|
import { ArrowLeft, CheckCircle, Trash2, Printer } from 'lucide-react';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import Pagination from "@/Components/shared/Pagination";
|
import Pagination from "@/Components/shared/Pagination";
|
||||||
|
import { usePermission } from "@/hooks/usePermission";
|
||||||
|
|
||||||
interface ImportItem {
|
interface ImportItem {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -76,6 +77,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function SalesImportShow({ import: batch, items, filters = {} }: Props) {
|
export default function SalesImportShow({ import: batch, items, filters = {} }: Props) {
|
||||||
|
const { can } = usePermission();
|
||||||
const { post, processing } = useForm({});
|
const { post, processing } = useForm({});
|
||||||
const [perPage, setPerPage] = useState(filters?.per_page?.toString() || "10");
|
const [perPage, setPerPage] = useState(filters?.per_page?.toString() || "10");
|
||||||
|
|
||||||
@@ -139,65 +141,74 @@ export default function SalesImportShow({ import: batch, items, filters = {} }:
|
|||||||
{batch.status === 'confirmed' ? '已確認' : '待確認'}
|
{batch.status === 'confirmed' ? '已確認' : '待確認'}
|
||||||
</Badge>
|
</Badge>
|
||||||
{batch.status === 'pending' && (
|
{batch.status === 'pending' && (
|
||||||
<>
|
<div className="flex gap-3">
|
||||||
<AlertDialog>
|
{can('sales_imports.delete') && (
|
||||||
<AlertDialogTrigger asChild>
|
<AlertDialog>
|
||||||
<Button
|
<AlertDialogTrigger asChild>
|
||||||
variant="outline"
|
<Button
|
||||||
className="gap-2 button-outlined-error"
|
variant="outline"
|
||||||
>
|
className="button-outlined-error gap-2 h-10 px-6"
|
||||||
<Trash2 className="h-4 w-4" />
|
|
||||||
刪除批次
|
|
||||||
</Button>
|
|
||||||
</AlertDialogTrigger>
|
|
||||||
<AlertDialogContent>
|
|
||||||
<AlertDialogHeader>
|
|
||||||
<AlertDialogTitle>確認刪除匯入紀錄</AlertDialogTitle>
|
|
||||||
<AlertDialogDescription>
|
|
||||||
確定要刪除此筆匯入紀錄(#{batch.id})嗎?此操作將會移除所有相關的明細資料且無法復原。
|
|
||||||
</AlertDialogDescription>
|
|
||||||
</AlertDialogHeader>
|
|
||||||
<AlertDialogFooter>
|
|
||||||
<AlertDialogCancel>取消</AlertDialogCancel>
|
|
||||||
<AlertDialogAction
|
|
||||||
className="bg-red-600 hover:bg-red-700"
|
|
||||||
onClick={handleDelete}
|
|
||||||
>
|
>
|
||||||
確認刪除
|
<Trash2 className="h-4 w-4" />
|
||||||
</AlertDialogAction>
|
刪除匯入
|
||||||
</AlertDialogFooter>
|
</Button>
|
||||||
</AlertDialogContent>
|
</AlertDialogTrigger>
|
||||||
</AlertDialog>
|
<AlertDialogContent>
|
||||||
|
<AlertDialogHeader>
|
||||||
|
<AlertDialogTitle>確認刪除匯入紀錄</AlertDialogTitle>
|
||||||
|
<AlertDialogDescription>
|
||||||
|
確定要刪除此筆匯入紀錄嗎?此操作將會移除所有明細資料且無法復原。
|
||||||
|
</AlertDialogDescription>
|
||||||
|
</AlertDialogHeader>
|
||||||
|
<AlertDialogFooter>
|
||||||
|
<AlertDialogCancel>取消</AlertDialogCancel>
|
||||||
|
<AlertDialogAction
|
||||||
|
className="bg-red-600 hover:bg-red-700"
|
||||||
|
onClick={handleDelete}
|
||||||
|
>
|
||||||
|
確認刪除
|
||||||
|
</AlertDialogAction>
|
||||||
|
</AlertDialogFooter>
|
||||||
|
</AlertDialogContent>
|
||||||
|
</AlertDialog>
|
||||||
|
)}
|
||||||
|
|
||||||
<AlertDialog>
|
{can('sales_imports.confirm') && (
|
||||||
<AlertDialogTrigger asChild>
|
<AlertDialog>
|
||||||
<Button
|
<AlertDialogTrigger asChild>
|
||||||
className="button-filled-primary gap-2"
|
<Button
|
||||||
disabled={processing}
|
className="button-filled-primary gap-2 h-10 px-8 shadow-md hover:shadow-lg transition-all"
|
||||||
>
|
disabled={processing}
|
||||||
<CheckCircle className="h-4 w-4" />
|
|
||||||
{processing ? '處理中...' : '確認並扣庫'}
|
|
||||||
</Button>
|
|
||||||
</AlertDialogTrigger>
|
|
||||||
<AlertDialogContent>
|
|
||||||
<AlertDialogHeader>
|
|
||||||
<AlertDialogTitle>確認執行庫存扣取</AlertDialogTitle>
|
|
||||||
<AlertDialogDescription>
|
|
||||||
確認要執行扣庫嗎?系統將會根據此匯入內容減少對應倉庫的商品庫存。此操作無法復原。
|
|
||||||
</AlertDialogDescription>
|
|
||||||
</AlertDialogHeader>
|
|
||||||
<AlertDialogFooter>
|
|
||||||
<AlertDialogCancel>取消</AlertDialogCancel>
|
|
||||||
<AlertDialogAction
|
|
||||||
className="button-filled-primary"
|
|
||||||
onClick={handleConfirm}
|
|
||||||
>
|
>
|
||||||
確認執行
|
<CheckCircle className="h-4 w-4" />
|
||||||
</AlertDialogAction>
|
{processing ? '處理中...' : '確認扣庫並入帳'}
|
||||||
</AlertDialogFooter>
|
</Button>
|
||||||
</AlertDialogContent>
|
</AlertDialogTrigger>
|
||||||
</AlertDialog>
|
<AlertDialogContent className="sm:max-w-md">
|
||||||
</>
|
<AlertDialogHeader>
|
||||||
|
<AlertDialogTitle>確認匯入並扣減庫存</AlertDialogTitle>
|
||||||
|
<AlertDialogDescription className="text-gray-600 leading-relaxed">
|
||||||
|
按下「確認」後,系統將依據此匯入清冊進行庫存扣點。
|
||||||
|
<div className="bg-amber-50 border-l-4 border-amber-400 p-4 mt-3 rounded">
|
||||||
|
<p className="text-amber-800 text-sm font-medium">
|
||||||
|
注意:此操作無法復原,請確保匯入資料正確無誤。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</AlertDialogDescription>
|
||||||
|
</AlertDialogHeader>
|
||||||
|
<AlertDialogFooter className="mt-4">
|
||||||
|
<AlertDialogCancel>我再看看</AlertDialogCancel>
|
||||||
|
<AlertDialogAction
|
||||||
|
className="bg-primary-main hover:bg-primary-dark text-white px-8"
|
||||||
|
onClick={handleConfirm}
|
||||||
|
>
|
||||||
|
確認並執行
|
||||||
|
</AlertDialogAction>
|
||||||
|
</AlertDialogFooter>
|
||||||
|
</AlertDialogContent>
|
||||||
|
</AlertDialog>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{batch.status === 'confirmed' && (
|
{batch.status === 'confirmed' && (
|
||||||
<Button variant="outline" className="gap-2 button-outlined-primary">
|
<Button variant="outline" className="gap-2 button-outlined-primary">
|
||||||
|
|||||||
Reference in New Issue
Block a user