176 lines
6.2 KiB
PHP
176 lines
6.2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\InventoryTransaction;
|
|
use App\Models\Item;
|
|
use App\Models\Warehouse;
|
|
use App\Models\Project;
|
|
use App\Models\Currency;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class InventoryTransactionController extends Controller
|
|
{
|
|
public function index(Request $request)
|
|
{
|
|
$tenantId = tenant_id() ?? Auth::user()?->tenant_id;
|
|
$query = InventoryTransaction::when($tenantId, function($q) use ($tenantId) {
|
|
$q->where('tenant_id', $tenantId);
|
|
})->with(['item', 'warehouse', 'project', 'currency', 'createdBy']);
|
|
|
|
if ($request->filled('type')) {
|
|
$query->where('type', $request->type);
|
|
}
|
|
|
|
if ($request->filled('item_id')) {
|
|
$query->where('item_id', $request->item_id);
|
|
}
|
|
|
|
if ($request->filled('warehouse_id')) {
|
|
$query->where('warehouse_id', $request->warehouse_id);
|
|
}
|
|
|
|
if ($request->filled('project_id')) {
|
|
$query->where('project_id', $request->project_id);
|
|
}
|
|
|
|
if ($request->filled('from_date')) {
|
|
$query->where('date', '>=', $request->from_date);
|
|
}
|
|
|
|
if ($request->filled('to_date')) {
|
|
$query->where('date', '<=', $request->to_date);
|
|
}
|
|
|
|
$transactions = $query->orderBy('date', 'desc')->orderBy('created_at', 'desc')->paginate(20)->appends($request->query());
|
|
|
|
$items = Item::when($tenantId, function($q) use ($tenantId) {
|
|
$q->where('tenant_id', $tenantId);
|
|
})->orderBy('name')->get();
|
|
|
|
$warehouses = Warehouse::when($tenantId, function($q) use ($tenantId) {
|
|
$q->where('tenant_id', $tenantId);
|
|
})->where('is_active', true)->orderBy('name')->get();
|
|
|
|
$projects = Project::when($tenantId, function($q) use ($tenantId) {
|
|
$q->where('tenant_id', $tenantId);
|
|
})->whereIn('status', ['planning', 'in_progress'])->get();
|
|
|
|
$types = ['in', 'out', 'return', 'adjustment'];
|
|
|
|
return view('inventory-transactions.index', compact('transactions', 'items', 'warehouses', 'projects', 'types'));
|
|
}
|
|
|
|
public function create()
|
|
{
|
|
$tenantId = tenant_id() ?? Auth::user()?->tenant_id;
|
|
$warehouses = Warehouse::when($tenantId, function($q) use ($tenantId) {
|
|
$q->where('tenant_id', $tenantId);
|
|
})->orderBy('name')->get();
|
|
|
|
$warehouses = Warehouse::when($tenantId, function($q) use ($tenantId) {
|
|
$q->where('tenant_id', $tenantId);
|
|
})->where('is_active', true)->orderBy('name')->get();
|
|
|
|
$projects = Project::when($tenantId, function($q) use ($tenantId) {
|
|
$q->where('tenant_id', $tenantId);
|
|
})->whereIn('status', ['planning', 'in_progress'])->get();
|
|
|
|
$currencies = Currency::all();
|
|
$types = ['in' => 'in', 'out' => 'out', 'return' => 'return', 'adjustment' => 'adjustment'];
|
|
|
|
return view('inventory-transactions.form', compact('items', 'warehouses', 'projects', 'currencies', 'types'));
|
|
}
|
|
|
|
public function store(Request $request)
|
|
{
|
|
$tenantId = tenant_id() ?? Auth::user()?->tenant_id;
|
|
|
|
$validated = $request->validate([
|
|
'type' => 'required|in:in,out,return,adjustment',
|
|
'item_id' => 'required|exists:items,id',
|
|
'warehouse_id' => 'required|exists:warehouses,id',
|
|
'project_id' => 'nullable|exists:projects,id',
|
|
'quantity' => 'required|numeric|min:0.01',
|
|
'unit_price' => 'nullable|numeric|min:0',
|
|
'currency_id' => 'nullable|exists:currencies,id',
|
|
'date' => 'required|date',
|
|
'reference' => 'nullable|string|max:100',
|
|
'description' => 'nullable|string',
|
|
]);
|
|
|
|
// بررسی موجودی برای خروج
|
|
if ($validated['type'] === 'out') {
|
|
$currentStock = $this->getCurrentStock($validated['item_id'], $validated['warehouse_id']);
|
|
if ($currentStock < $validated['quantity']) {
|
|
return back()->withErrors(['quantity' => __('inventory.insufficient_stock')])
|
|
->withInput();
|
|
}
|
|
}
|
|
|
|
$validated['tenant_id'] = $tenantId;
|
|
$validated['created_by'] = Auth::id();
|
|
|
|
if (!empty($validated['unit_price']) && !empty($validated['quantity'])) {
|
|
$validated['total_price'] = $validated['unit_price'] * $validated['quantity'];
|
|
}
|
|
|
|
InventoryTransaction::create($validated);
|
|
|
|
return redirect()
|
|
->route('inventory-transactions.index')
|
|
->with('success', __('inventory.transaction_created_successfully'));
|
|
}
|
|
|
|
public function show(InventoryTransaction $inventoryTransaction)
|
|
{
|
|
$inventoryTransaction->load(['item', 'warehouse', 'project', 'currency', 'createdBy']);
|
|
|
|
return view('inventory-transactions.show', compact('inventoryTransaction'));
|
|
}
|
|
|
|
public function destroy(InventoryTransaction $inventoryTransaction)
|
|
{
|
|
$inventoryTransaction->delete();
|
|
|
|
return redirect()
|
|
->route('inventory-transactions.index')
|
|
->with('success', __('inventory.transaction_deleted_successfully'));
|
|
}
|
|
|
|
public function currentStock(Request $request)
|
|
{
|
|
$request->validate([
|
|
'item_id' => 'required|exists:items,id',
|
|
'warehouse_id' => 'required|exists:warehouses,id',
|
|
]);
|
|
|
|
$stock = $this->getCurrentStock($request->item_id, $request->warehouse_id);
|
|
|
|
return response()->json([
|
|
'current_stock' => $stock,
|
|
]);
|
|
}
|
|
|
|
private function getCurrentStock(int $itemId, int $warehouseId): float
|
|
{
|
|
$totalIn = InventoryTransaction::where('item_id', $itemId)
|
|
->where('warehouse_id', $warehouseId)
|
|
->whereIn('type', ['in', 'return'])
|
|
->sum('quantity');
|
|
|
|
$totalOut = InventoryTransaction::where('item_id', $itemId)
|
|
->where('warehouse_id', $warehouseId)
|
|
->where('type', 'out')
|
|
->sum('quantity');
|
|
|
|
$adjustments = InventoryTransaction::where('item_id', $itemId)
|
|
->where('warehouse_id', $warehouseId)
|
|
->where('type', 'adjustment')
|
|
->sum('quantity');
|
|
|
|
return (float) ($totalIn - $totalOut + $adjustments);
|
|
}
|
|
} |