新增單位管理以及一些功能修正

This commit is contained in:
2026-01-08 11:52:25 +08:00
parent eca2f38395
commit 48115082e5
19 changed files with 872 additions and 246 deletions

View File

@@ -3,6 +3,7 @@
namespace App\Http\Controllers;
use App\Models\Product;
use App\Models\Unit;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
@@ -14,7 +15,7 @@ class ProductController extends Controller
*/
public function index(Request $request): Response
{
$query = Product::with('category');
$query = Product::with(['category', 'baseUnit', 'largeUnit', 'purchaseUnit']);
if ($request->filled('search')) {
$search = $request->search;
@@ -61,8 +62,10 @@ class ProductController extends Controller
$categories = \App\Models\Category::where('is_active', true)->get();
return Inertia::render('Product/Index', [
'products' => $products,
'products' => $products,
'categories' => $categories,
'units' => Unit::all(),
'filters' => $request->only(['search', 'category_id', 'per_page', 'sort_field', 'sort_direction']),
]);
}
@@ -77,15 +80,17 @@ class ProductController extends Controller
'category_id' => 'required|exists:categories,id',
'brand' => 'nullable|string|max:255',
'specification' => 'nullable|string',
'base_unit' => 'required|string|max:50',
'large_unit' => 'nullable|string|max:50',
'conversion_rate' => 'required_with:large_unit|nullable|numeric|min:0.0001',
'purchase_unit' => 'nullable|string|max:50',
'base_unit_id' => 'required|exists:units,id',
'large_unit_id' => 'nullable|exists:units,id',
'conversion_rate' => 'required_with:large_unit_id|nullable|numeric|min:0.0001',
'purchase_unit_id' => 'nullable|exists:units,id',
], [
'name.required' => '商品名稱為必填',
'category_id.required' => '請選擇分類',
'category_id.exists' => '所選分類不存在',
'base_unit.required' => '基本庫存單位為必填',
'base_unit_id.required' => '基本庫存單位為必填',
'base_unit_id.exists' => '所選基本單位不存在',
'conversion_rate.required_with' => '填寫大單位時,換算率為必填',
'conversion_rate.numeric' => '換算率必須為數字',
'conversion_rate.min' => '換算率最小為 0.0001',
@@ -109,14 +114,24 @@ class ProductController extends Controller
*/
public function update(Request $request, Product $product)
{
$validated = $request->validate([
$validated = $request->validate([
'name' => 'required|string|max:255',
'category_id' => 'required|exists:categories,id',
'brand' => 'nullable|string|max:255',
'specification' => 'nullable|string',
'base_unit' => 'required|string|max:50',
'large_unit' => 'nullable|string|max:50',
'conversion_rate' => 'required_with:large_unit|nullable|numeric|min:0.0001',
'base_unit_id' => 'required|exists:units,id',
'large_unit_id' => 'nullable|exists:units,id',
'conversion_rate' => 'required_with:large_unit_id|nullable|numeric|min:0.0001',
'purchase_unit_id' => 'nullable|exists:units,id',
], [
'name.required' => '商品名稱為必填',
'category_id.required' => '請選擇分類',
'category_id.exists' => '所選分類不存在',
'base_unit_id.required' => '基本庫存單位為必填',
'base_unit_id.exists' => '所選基本單位不存在',
'conversion_rate.required_with' => '填寫大單位時,換算率為必填',
'conversion_rate.numeric' => '換算率必須為數字',
'conversion_rate.min' => '換算率最小為 0.0001',
]);
$product->update($validated);

View File

@@ -0,0 +1,70 @@
<?php
namespace App\Http\Controllers;
use App\Models\Unit;
use App\Models\Product; // Import Product to check for usage
use Illuminate\Http\Request;
class UnitController extends Controller
{
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255|unique:units,name',
'code' => 'nullable|string|max:50',
], [
'name.required' => '單位名稱為必填項目',
'name.unique' => '該單位名稱已存在',
'name.max' => '單位名稱不能超過 255 個字元',
'code.max' => '單位代碼不能超過 50 個字元',
]);
Unit::create($validated);
return redirect()->back()->with('success', '單位已建立');
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, Unit $unit)
{
$validated = $request->validate([
'name' => 'required|string|max:255|unique:units,name,' . $unit->id,
'code' => 'nullable|string|max:50',
], [
'name.required' => '單位名稱為必填項目',
'name.unique' => '該單位名稱已存在',
'name.max' => '單位名稱不能超過 255 個字元',
'code.max' => '單位代碼不能超過 50 個字元',
]);
$unit->update($validated);
return redirect()->back()->with('success', '單位已更新');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(Unit $unit)
{
// Check if unit is used in any product
$isUsed = Product::where('base_unit_id', $unit->id)
->orWhere('large_unit_id', $unit->id)
->orWhere('purchase_unit_id', $unit->id)
->exists();
if ($isUsed) {
return redirect()->back()->with('error', '該單位已被商品使用,無法刪除');
}
$unit->delete();
return redirect()->back()->with('success', '單位已刪除');
}
}

View File

@@ -40,6 +40,10 @@ class HandleInertiaRequests extends Middleware
'auth' => [
'user' => $request->user(),
],
'flash' => [
'success' => $request->session()->get('success'),
'error' => $request->session()->get('error'),
],
];
}
}

View File

@@ -17,10 +17,10 @@ class Product extends Model
'category_id',
'brand',
'specification',
'base_unit',
'large_unit',
'base_unit_id',
'large_unit_id',
'conversion_rate',
'purchase_unit',
'purchase_unit_id',
];
protected $casts = [
@@ -35,6 +35,21 @@ class Product extends Model
return $this->belongsTo(Category::class);
}
public function baseUnit(): BelongsTo
{
return $this->belongsTo(Unit::class, 'base_unit_id');
}
public function largeUnit(): BelongsTo
{
return $this->belongsTo(Unit::class, 'large_unit_id');
}
public function purchaseUnit(): BelongsTo
{
return $this->belongsTo(Unit::class, 'purchase_unit_id');
}
public function vendors(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{
return $this->belongsToMany(Vendor::class)->withPivot('last_price')->withTimestamps();

17
app/Models/Unit.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Unit extends Model
{
/** @use HasFactory<\Database\Factories\UnitFactory> */
use HasFactory;
protected $fillable = [
'name',
'code',
];
}