feat: 補齊生產管理與進貨單權限、功能實作及 UI 優化
This commit is contained in:
@@ -23,6 +23,11 @@ class ActivityLogController extends Controller
|
||||
'App\Modules\Inventory\Models\Warehouse' => '倉庫',
|
||||
'App\Modules\Inventory\Models\Inventory' => '庫存',
|
||||
'App\Modules\Finance\Models\UtilityFee' => '公共事業費',
|
||||
'App\Modules\Inventory\Models\GoodsReceipt' => '進貨單',
|
||||
'App\Modules\Production\Models\ProductionOrder' => '生產工單',
|
||||
'App\Modules\Production\Models\Recipe' => '生產配方',
|
||||
'App\Modules\Production\Models\RecipeItem' => '配方品項',
|
||||
'App\Modules\Production\Models\ProductionOrderItem' => '工單品項',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -178,8 +178,12 @@ class RoleController extends Controller
|
||||
'inventory' => '庫存管理',
|
||||
'vendors' => '廠商資料管理',
|
||||
'purchase_orders' => '採購單管理',
|
||||
'goods_receipts' => '進貨單管理',
|
||||
'production_orders' => '生產工單管理',
|
||||
'recipes' => '配方管理',
|
||||
'users' => '使用者管理',
|
||||
'roles' => '角色與權限',
|
||||
'system' => '系統管理',
|
||||
'utility_fees' => '公共事業費管理',
|
||||
'accounting' => '會計報表',
|
||||
];
|
||||
|
||||
@@ -228,4 +228,21 @@ class GoodsReceiptController extends Controller
|
||||
|
||||
return response()->json($vendors);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刪除進貨單
|
||||
*/
|
||||
public function destroy(GoodsReceipt $goodsReceipt)
|
||||
{
|
||||
// 只有有權限的人可以刪除
|
||||
if (!auth()->user()->can('goods_receipts.delete')) {
|
||||
return redirect()->back()->with('error', '您沒有權限刪除進貨單');
|
||||
}
|
||||
|
||||
// 簡單刪除邏輯:刪除進貨單(品項由資料庫級聯刪除或手動處理)
|
||||
// 注意:實務上可能需要處理已入庫的庫存回滾,但在這個簡易 ERP 中通常是行政刪除
|
||||
$goodsReceipt->delete();
|
||||
|
||||
return redirect()->route('goods-receipts.index')->with('success', '進貨單已刪除');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,10 +37,25 @@ class PermissionSeeder extends Seeder
|
||||
'inventory.view_cost', // 查看成本與價值
|
||||
'inventory.adjust',
|
||||
'inventory.transfer',
|
||||
'inventory.delete',
|
||||
|
||||
// 進貨單管理
|
||||
'goods_receipts.view',
|
||||
'goods_receipts.create',
|
||||
'goods_receipts.edit',
|
||||
'goods_receipts.delete',
|
||||
|
||||
// 生產工單管理
|
||||
'production_orders.view',
|
||||
'production_orders.create',
|
||||
'production_orders.edit',
|
||||
'production_orders.delete',
|
||||
|
||||
// 配方管理
|
||||
'recipes.view',
|
||||
'recipes.create',
|
||||
'recipes.edit',
|
||||
'recipes.delete',
|
||||
|
||||
// 供應商管理
|
||||
'vendors.view',
|
||||
@@ -101,8 +116,10 @@ class PermissionSeeder extends Seeder
|
||||
'products.view', 'products.create', 'products.edit', 'products.delete',
|
||||
'purchase_orders.view', 'purchase_orders.create', 'purchase_orders.edit',
|
||||
'purchase_orders.delete', 'purchase_orders.publish',
|
||||
'inventory.view', 'inventory.view_cost', 'inventory.adjust', 'inventory.transfer',
|
||||
'goods_receipts.view', 'goods_receipts.create',
|
||||
'inventory.view', 'inventory.view_cost', 'inventory.adjust', 'inventory.transfer', 'inventory.delete',
|
||||
'goods_receipts.view', 'goods_receipts.create', 'goods_receipts.edit', 'goods_receipts.delete',
|
||||
'production_orders.view', 'production_orders.create', 'production_orders.edit', 'production_orders.delete',
|
||||
'recipes.view', 'recipes.create', 'recipes.edit', 'recipes.delete',
|
||||
'vendors.view', 'vendors.create', 'vendors.edit', 'vendors.delete',
|
||||
'warehouses.view', 'warehouses.create', 'warehouses.edit', 'warehouses.delete',
|
||||
'users.view', 'users.create', 'users.edit',
|
||||
@@ -115,8 +132,9 @@ class PermissionSeeder extends Seeder
|
||||
// warehouse-manager 管理庫存與倉庫
|
||||
$warehouseManager->givePermissionTo([
|
||||
'products.view',
|
||||
'inventory.view', 'inventory.adjust', 'inventory.transfer',
|
||||
'goods_receipts.view', 'goods_receipts.create',
|
||||
'inventory.view', 'inventory.adjust', 'inventory.transfer', 'inventory.delete',
|
||||
'goods_receipts.view', 'goods_receipts.create', 'goods_receipts.edit', 'goods_receipts.delete',
|
||||
'production_orders.view', 'production_orders.create', 'production_orders.edit',
|
||||
'warehouses.view', 'warehouses.create', 'warehouses.edit',
|
||||
]);
|
||||
|
||||
|
||||
@@ -114,10 +114,24 @@ const fieldLabels: Record<string, string> = {
|
||||
transaction_date: '費用日期',
|
||||
category: '費用類別',
|
||||
amount: '金額',
|
||||
// 進貨單欄位
|
||||
gr_number: '進貨單號',
|
||||
received_date: '入庫日期',
|
||||
type: '入庫類型',
|
||||
remarks: '備註',
|
||||
// 生產管理欄位
|
||||
production_number: '工單編號',
|
||||
production_date: '生產日期',
|
||||
actual_quantity: '實際產量',
|
||||
consumption_status: '物料消耗狀態',
|
||||
recipe_id: '生產配方',
|
||||
recipe_name: '配方名稱',
|
||||
yield_quantity: '預期產量',
|
||||
};
|
||||
|
||||
// 採購單狀態對照表
|
||||
// 狀態翻譯對照表
|
||||
const statusMap: Record<string, string> = {
|
||||
// 採購單狀態
|
||||
draft: '草稿',
|
||||
pending: '待審核',
|
||||
approved: '已核准',
|
||||
@@ -125,6 +139,10 @@ const statusMap: Record<string, string> = {
|
||||
received: '已收貨',
|
||||
cancelled: '已取消',
|
||||
completed: '已完成',
|
||||
// 生產工單狀態
|
||||
planned: '已計畫',
|
||||
in_progress: '生產中',
|
||||
// completed 已定義
|
||||
};
|
||||
|
||||
// 庫存品質狀態對照表
|
||||
|
||||
@@ -71,10 +71,13 @@ export default function RoleCreate({ groupedPermissions }: Props) {
|
||||
'edit': '編輯',
|
||||
'delete': '刪除',
|
||||
'publish': '發布',
|
||||
'adjust': '新增 / 調整',
|
||||
'adjust': '調整',
|
||||
'transfer': '調撥',
|
||||
'safety_stock': '安全庫存設定',
|
||||
'export': '匯出',
|
||||
'complete': '完成',
|
||||
'view_cost': '檢視成本',
|
||||
'view_logs': '檢視日誌',
|
||||
};
|
||||
|
||||
return map[action] || action;
|
||||
|
||||
@@ -78,10 +78,13 @@ export default function RoleEdit({ role, groupedPermissions, currentPermissions
|
||||
'edit': '編輯',
|
||||
'delete': '刪除',
|
||||
'publish': '發布',
|
||||
'adjust': '新增 / 調整',
|
||||
'adjust': '調整',
|
||||
'transfer': '調撥',
|
||||
'safety_stock': '安全庫存設定',
|
||||
'export': '匯出',
|
||||
'complete': '完成',
|
||||
'view_cost': '檢視成本',
|
||||
'view_logs': '檢視日誌',
|
||||
};
|
||||
|
||||
return map[action] || action;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { Plus, Factory, Search, RotateCcw, Eye, Pencil } from 'lucide-react';
|
||||
import { Plus, Factory, Search, RotateCcw, Eye, Pencil, Trash2 } from 'lucide-react';
|
||||
import { Button } from "@/Components/ui/button";
|
||||
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
|
||||
import { Head, router, Link } from "@inertiajs/react";
|
||||
@@ -266,6 +266,21 @@ export default function ProductionIndex({ productionOrders, filters }: Props) {
|
||||
</Button>
|
||||
</Link>
|
||||
</Can>
|
||||
<Can permission="production_orders.delete">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="button-outlined-error"
|
||||
title="刪除"
|
||||
onClick={() => {
|
||||
if (confirm('確定要刪除此生產工單嗎?')) {
|
||||
router.delete(route('production-orders.destroy', order.id));
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
</Can>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -298,6 +313,6 @@ export default function ProductionIndex({ productionOrders, filters }: Props) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AuthenticatedLayout>
|
||||
</AuthenticatedLayout >
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,12 +110,14 @@ export default function RecipeIndex({ recipes, filters }: Props) {
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<Link href={route('recipes.create')}>
|
||||
<Button className="gap-2 button-filled-primary">
|
||||
<Plus className="h-4 w-4" />
|
||||
新增配方
|
||||
</Button>
|
||||
</Link>
|
||||
<Can permission="recipes.create">
|
||||
<Link href={route('recipes.create')}>
|
||||
<Button className="gap-2 button-filled-primary">
|
||||
<Plus className="h-4 w-4" />
|
||||
新增配方
|
||||
</Button>
|
||||
</Link>
|
||||
</Can>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user