233 lines
7.4 KiB
PHP
233 lines
7.4 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin\Inventory;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\Inventory\ReceiveStockEntryRequest;
|
|
use App\Http\Requests\Inventory\StoreStockEntryRequest;
|
|
use App\Http\Requests\Inventory\UpdateStockEntryRequest;
|
|
use App\Models\Ingredient;
|
|
use App\Models\Location;
|
|
use App\Models\MaterialQuality;
|
|
use App\Models\PackagingItem;
|
|
use App\Models\StockEntry;
|
|
use App\Models\Supplier;
|
|
use App\Repositories\StockEntryRepository;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\View\View;
|
|
|
|
class StockEntryController extends Controller
|
|
{
|
|
public function __construct(
|
|
protected StockEntryRepository $stockEntryRepository
|
|
) {}
|
|
|
|
public function index(): View
|
|
{
|
|
return view('admin.inventory.stock-entries.index', array_merge($this->formSharedData(), [
|
|
'values' => $this->stockEntryRepository->listForIndex(),
|
|
]));
|
|
}
|
|
|
|
public function create(): View|RedirectResponse
|
|
{
|
|
if (! auth()->user()->isAdmin()) {
|
|
return redirect()->route('home');
|
|
}
|
|
|
|
return view('admin.inventory.stock-entries.create', array_merge($this->formSharedData(), [
|
|
'model' => new StockEntry([
|
|
'ordered_at' => now()->toDateString(),
|
|
'entry_type' => 'ingredient',
|
|
]),
|
|
]));
|
|
}
|
|
|
|
public function store(StoreStockEntryRequest $request): RedirectResponse
|
|
{
|
|
if (! $request->user()->isAdmin()) {
|
|
return redirect()->route('home');
|
|
}
|
|
|
|
$data = $request->validatedPayload();
|
|
$data['ordered_by'] = (int) auth()->id();
|
|
|
|
$this->stockEntryRepository->create($data);
|
|
|
|
\Session::flash('alert-save', '1');
|
|
|
|
return redirect()->route('admin.inventory.stock-entries.index');
|
|
}
|
|
|
|
public function show(StockEntry $stockEntry): View
|
|
{
|
|
$stockEntry->load([
|
|
'ingredient',
|
|
'packagingItem.packagingMaterial',
|
|
'supplier',
|
|
'location',
|
|
'quality',
|
|
'orderedByUser.account',
|
|
'receivedByUser.account',
|
|
]);
|
|
|
|
return view('admin.inventory.stock-entries.show', array_merge($this->formSharedData(), [
|
|
'model' => $stockEntry,
|
|
'materialQualities' => MaterialQuality::query()->orderBy('pos')->orderBy('name')->get(),
|
|
]));
|
|
}
|
|
|
|
public function edit(StockEntry $stockEntry): View|RedirectResponse
|
|
{
|
|
if (! auth()->user()->isAdmin()) {
|
|
return redirect()->route('home');
|
|
}
|
|
if (! $stockEntry->isPending()) {
|
|
\Session::flash('alert-error', __('Nur offene Bestellungen können bearbeitet werden.'));
|
|
|
|
return redirect()->route('admin.inventory.stock-entries.show', $stockEntry);
|
|
}
|
|
|
|
$stockEntry->load(['ingredient', 'packagingItem']);
|
|
|
|
return view('admin.inventory.stock-entries.edit', array_merge($this->formSharedData(), [
|
|
'model' => $stockEntry,
|
|
]));
|
|
}
|
|
|
|
public function update(UpdateStockEntryRequest $request, StockEntry $stockEntry): RedirectResponse
|
|
{
|
|
if (! $request->user()->isAdmin()) {
|
|
return redirect()->route('home');
|
|
}
|
|
if (! $stockEntry->isPending()) {
|
|
\Session::flash('alert-error', __('Nur offene Bestellungen können bearbeitet werden.'));
|
|
|
|
return redirect()->route('admin.inventory.stock-entries.show', $stockEntry);
|
|
}
|
|
|
|
$this->stockEntryRepository->update($stockEntry, $request->validatedPayload());
|
|
|
|
\Session::flash('alert-save', '1');
|
|
|
|
return redirect()->route('admin.inventory.stock-entries.index');
|
|
}
|
|
|
|
public function destroy(StockEntry $stockEntry): RedirectResponse
|
|
{
|
|
if (! auth()->user()->isAdmin()) {
|
|
return redirect()->route('home');
|
|
}
|
|
if (! $stockEntry->isPending()) {
|
|
\Session::flash('alert-error', __('Nur offene Bestellungen können gelöscht werden.'));
|
|
|
|
return redirect()->route('admin.inventory.stock-entries.index');
|
|
}
|
|
|
|
$stockEntry->delete();
|
|
|
|
\Session::flash('alert-success', __('Eintrag gelöscht'));
|
|
|
|
return redirect()->route('admin.inventory.stock-entries.index');
|
|
}
|
|
|
|
public function receive(ReceiveStockEntryRequest $request, StockEntry $stockEntry): RedirectResponse
|
|
{
|
|
if (! $stockEntry->isPending()) {
|
|
\Session::flash('alert-error', __('Eintrag nicht mehr offen.'));
|
|
|
|
return redirect()->route('admin.inventory.stock-entries.show', $stockEntry);
|
|
}
|
|
|
|
$data = $request->validated();
|
|
if ($stockEntry->entry_type !== 'ingredient') {
|
|
$data['quality_id'] = null;
|
|
$data['best_before'] = null;
|
|
}
|
|
|
|
$this->stockEntryRepository->receive($stockEntry, $data);
|
|
|
|
\Session::flash('alert-save', '1');
|
|
|
|
return redirect()->route('admin.inventory.stock-entries.show', $stockEntry->fresh());
|
|
}
|
|
|
|
public function searchIngredients(Request $request): JsonResponse
|
|
{
|
|
$term = trim((string) $request->query('q', ''));
|
|
if (mb_strlen($term) < 1) {
|
|
return response()->json(['results' => []]);
|
|
}
|
|
|
|
$rows = Ingredient::query()
|
|
->where('active', true)
|
|
->where(function ($query) use ($term) {
|
|
$query->where('name', 'like', '%'.$term.'%')
|
|
->orWhere('inci', 'like', '%'.$term.'%');
|
|
})
|
|
->orderBy('name')
|
|
->limit(30)
|
|
->get(['id', 'name', 'inci']);
|
|
|
|
$results = $rows->map(function (Ingredient $i) {
|
|
$text = $i->name;
|
|
if ($i->inci) {
|
|
$text .= ' ('.$i->inci.')';
|
|
}
|
|
|
|
return ['id' => $i->id, 'text' => $text];
|
|
})->values()->all();
|
|
|
|
return response()->json(['results' => $results]);
|
|
}
|
|
|
|
public function searchPackagingItems(Request $request): JsonResponse
|
|
{
|
|
$term = trim((string) $request->query('q', ''));
|
|
$entryType = $request->query('entry_type');
|
|
|
|
$categoryMap = [
|
|
'packaging' => 'packaging',
|
|
'shipping' => 'shipping',
|
|
];
|
|
|
|
$query = PackagingItem::query()
|
|
->where('active', true);
|
|
|
|
if ($entryType && isset($categoryMap[$entryType])) {
|
|
$query->where('category', $categoryMap[$entryType]);
|
|
}
|
|
|
|
if (mb_strlen($term) >= 1) {
|
|
$query->where('name', 'like', '%'.$term.'%');
|
|
}
|
|
|
|
$rows = $query->orderBy('name')->limit(30)->get(['id', 'name']);
|
|
|
|
$results = $rows->map(fn (PackagingItem $p) => [
|
|
'id' => $p->id,
|
|
'text' => $p->name,
|
|
])->values()->all();
|
|
|
|
return response()->json(['results' => $results]);
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
protected function formSharedData(): array
|
|
{
|
|
return [
|
|
'suppliers' => Supplier::query()->where('active', true)->orderBy('name')->get(),
|
|
'locations' => Location::query()->where('active', true)->orderBy('name')->get(),
|
|
'materialQualities' => MaterialQuality::query()->orderBy('pos')->orderBy('name')->get(),
|
|
'entryTypeLabels' => [
|
|
'ingredient' => __('Rohstoff'),
|
|
'packaging' => __('Produktverpackung'),
|
|
'shipping' => __('Versandverpackung'),
|
|
],
|
|
];
|
|
}
|
|
}
|