feat: 修正庫存與撥補單邏輯並整合文件
1. 修復倉庫統計數據加總與樣式。 2. 修正可用庫存計算邏輯(排除不可銷售倉庫)。 3. 撥補單商品列表加入批號與效期顯示。 4. 修正撥補單儲存邏輯以支援精確批號轉移。 5. 整合 FEATURES.md 至 README.md。
This commit is contained in:
@@ -4,57 +4,30 @@ namespace App\Modules\Finance\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Modules\Finance\Models\UtilityFee;
|
||||
|
||||
use App\Modules\Finance\Contracts\FinanceServiceInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Inertia\Inertia;
|
||||
|
||||
class UtilityFeeController extends Controller
|
||||
{
|
||||
protected $financeService;
|
||||
|
||||
public function __construct(FinanceServiceInterface $financeService)
|
||||
{
|
||||
$this->financeService = $financeService;
|
||||
}
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = UtilityFee::query();
|
||||
|
||||
// Search
|
||||
if ($request->has('search')) {
|
||||
$search = $request->input('search');
|
||||
$query->where(function($q) use ($search) {
|
||||
$q->where('category', 'like', "%{$search}%")
|
||||
->orWhere('invoice_number', 'like', "%{$search}%")
|
||||
->orWhere('description', 'like', "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
// Filtering
|
||||
if ($request->filled('category') && $request->input('category') !== 'all') {
|
||||
$query->where('category', $request->input('category'));
|
||||
}
|
||||
|
||||
if ($request->filled('date_start')) {
|
||||
$query->where('transaction_date', '>=', $request->input('date_start'));
|
||||
}
|
||||
|
||||
if ($request->filled('date_end')) {
|
||||
$query->where('transaction_date', '<=', $request->input('date_end'));
|
||||
}
|
||||
|
||||
// Sorting
|
||||
$sortField = $request->input('sort_field');
|
||||
$sortDirection = $request->input('sort_direction');
|
||||
|
||||
if ($sortField && $sortDirection) {
|
||||
$query->orderBy($sortField, $sortDirection);
|
||||
} else {
|
||||
$query->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
$fees = $query->paginate($request->input('per_page', 10))->withQueryString();
|
||||
|
||||
$availableCategories = UtilityFee::distinct()->pluck('category');
|
||||
$filters = $request->only(['search', 'category', 'date_start', 'date_end', 'sort_field', 'sort_direction', 'per_page']);
|
||||
|
||||
$fees = $this->financeService->getUtilityFees($filters)->withQueryString();
|
||||
$availableCategories = $this->financeService->getUniqueCategories();
|
||||
|
||||
return Inertia::render('UtilityFee/Index', [
|
||||
'fees' => $fees,
|
||||
'availableCategories' => $availableCategories,
|
||||
'filters' => $request->only(['search', 'category', 'date_start', 'date_end', 'sort_field', 'sort_direction', 'per_page']),
|
||||
'filters' => $filters,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -70,19 +43,10 @@ class UtilityFeeController extends Controller
|
||||
|
||||
$fee = UtilityFee::create($validated);
|
||||
|
||||
// Log activity
|
||||
activity()
|
||||
->performedOn($fee)
|
||||
->causedBy(auth()->user())
|
||||
->event('created')
|
||||
->withProperties([
|
||||
'attributes' => $fee->getAttributes(),
|
||||
'snapshot' => [
|
||||
'category' => $fee->category,
|
||||
'amount' => $fee->amount,
|
||||
'transaction_date' => $fee->transaction_date->format('Y-m-d'),
|
||||
]
|
||||
])
|
||||
->log('created');
|
||||
|
||||
return redirect()->back();
|
||||
@@ -98,52 +62,12 @@ class UtilityFeeController extends Controller
|
||||
'description' => 'nullable|string',
|
||||
]);
|
||||
|
||||
// Capture old attributes before update
|
||||
$oldAttributes = $utility_fee->getAttributes();
|
||||
|
||||
$utility_fee->update($validated);
|
||||
|
||||
// Capture new attributes
|
||||
$newAttributes = $utility_fee->getAttributes();
|
||||
|
||||
// Manual logOnlyDirty: Filter attributes to only include changes
|
||||
$changedAttributes = [];
|
||||
$changedOldAttributes = [];
|
||||
|
||||
foreach ($newAttributes as $key => $value) {
|
||||
// Skip timestamps if they are the only change (optional, but good practice)
|
||||
if (in_array($key, ['updated_at'])) continue;
|
||||
|
||||
$oldValue = $oldAttributes[$key] ?? null;
|
||||
|
||||
// Simple comparison (casting to string to handle date objects vs strings if necessary,
|
||||
// but Eloquent attributes are usually consistent if casted.
|
||||
// Using loose comparison != handles most cases correctly)
|
||||
if ($value != $oldValue) {
|
||||
$changedAttributes[$key] = $value;
|
||||
$changedOldAttributes[$key] = $oldValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Only log if there are changes (excluding just updated_at)
|
||||
if (empty($changedAttributes)) {
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
// Log activity with before/after comparison
|
||||
activity()
|
||||
->performedOn($utility_fee)
|
||||
->causedBy(auth()->user())
|
||||
->event('updated')
|
||||
->withProperties([
|
||||
'attributes' => $changedAttributes,
|
||||
'old' => $changedOldAttributes,
|
||||
'snapshot' => [
|
||||
'category' => $utility_fee->category,
|
||||
'amount' => $utility_fee->amount,
|
||||
'transaction_date' => $utility_fee->transaction_date->format('Y-m-d'),
|
||||
]
|
||||
])
|
||||
->log('updated');
|
||||
|
||||
return redirect()->back();
|
||||
@@ -151,24 +75,10 @@ class UtilityFeeController extends Controller
|
||||
|
||||
public function destroy(UtilityFee $utility_fee)
|
||||
{
|
||||
// Capture data snapshot before deletion
|
||||
$snapshot = [
|
||||
'category' => $utility_fee->category,
|
||||
'amount' => $utility_fee->amount,
|
||||
'transaction_date' => $utility_fee->transaction_date->format('Y-m-d'),
|
||||
'invoice_number' => $utility_fee->invoice_number,
|
||||
'description' => $utility_fee->description,
|
||||
];
|
||||
|
||||
// Log activity before deletion
|
||||
activity()
|
||||
->performedOn($utility_fee)
|
||||
->causedBy(auth()->user())
|
||||
->event('deleted')
|
||||
->withProperties([
|
||||
'attributes' => $utility_fee->getAttributes(),
|
||||
'snapshot' => $snapshot
|
||||
])
|
||||
->log('deleted');
|
||||
|
||||
$utility_fee->delete();
|
||||
|
||||
Reference in New Issue
Block a user