ultimatepos/Modules/SupplyChain/Http/Controllers/DemandForecastController.php

121 lines
4.4 KiB
PHP

<?php
namespace Modules\SupplyChain\Http\Controllers;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\SupplyChain\Http\Controllers\Concerns\AuthorizesSupplyChain;
use Modules\SupplyChain\Models\DemandForecast;
use Modules\SupplyChain\Services\DemandForecastService;
use Modules\SupplyChain\Utils\SupplyChainUtil;
use Yajra\DataTables\Facades\DataTables;
class DemandForecastController extends Controller
{
use AuthorizesSupplyChain;
public function __construct(
protected SupplyChainUtil $supplyChainUtil,
protected DemandForecastService $forecastService
) {
}
public function index(Request $request)
{
$this->authorizeSupplyChain('supplychain.forecast.view');
$businessId = $this->supplyChainUtil->getBusinessId();
if ($request->ajax()) {
$forecasts = DemandForecast::forBusiness($businessId)
->with(['product', 'variation'])
->orderByDesc('forecast_month');
return DataTables::of($forecasts)
->addColumn('product_name', fn ($row) => $row->product?->name ?? '—')
->addColumn('variation_name', fn ($row) => $row->variation?->sub_sku ?? '—')
->editColumn('forecast_month', fn ($row) => $row->forecast_month->format('Y-m'))
->editColumn('forecast_qty', fn ($row) => number_format((float) $row->forecast_qty, 2))
->editColumn('confidence', fn ($row) => number_format((float) $row->confidence, 1).'%')
->addColumn('action', function ($row) {
return '<a class="btn btn-xs btn-info" href="'.action([self::class, 'show'], $row->id).'"><i class="fa fa-eye"></i></a>';
})
->rawColumns(['action'])
->make(true);
}
return view('supplychain::demand_forecasts.index');
}
public function create()
{
$this->authorizeSupplyChain('supplychain.forecast.create');
return view('supplychain::demand_forecasts.create', [
'products' => $this->supplyChainUtil->getProductsDropdown(),
]);
}
public function store(Request $request)
{
$this->authorizeSupplyChain('supplychain.forecast.create');
$businessId = $this->supplyChainUtil->getBusinessId();
$data = $request->validate([
'product_id' => 'required|integer',
'variation_id' => 'nullable|integer',
'forecast_month' => 'required|date',
'forecast_qty' => 'required|numeric|min:0',
'method' => 'nullable|string|max:50',
'confidence' => 'nullable|numeric|min:0|max:100',
'source' => 'nullable|string|max:50',
]);
DemandForecast::create([
'business_id' => $businessId,
'product_id' => $data['product_id'],
'variation_id' => $data['variation_id'] ?? null,
'forecast_month' => Carbon::parse($data['forecast_month'])->startOfMonth()->toDateString(),
'forecast_qty' => $data['forecast_qty'],
'method' => $data['method'] ?? 'manual',
'confidence' => $data['confidence'] ?? 50,
'source' => $data['source'] ?? 'manual',
]);
return $this->supplyChainUtil->jsonOrRedirect(
$request,
true,
__('supplychain::lang.forecast_created'),
action([self::class, 'index'])
);
}
public function show($id)
{
$this->authorizeSupplyChain('supplychain.forecast.view');
$businessId = $this->supplyChainUtil->getBusinessId();
$forecast = DemandForecast::forBusiness($businessId)->with(['product', 'variation'])->findOrFail($id);
return view('supplychain::demand_forecasts.show', compact('forecast'));
}
public function generate(Request $request)
{
$this->authorizeSupplyChain('supplychain.forecast.create');
$businessId = $this->supplyChainUtil->getBusinessId();
$monthsAhead = (int) $request->input('months_ahead', 3);
$results = $this->forecastService->generateForBusiness($businessId, $monthsAhead);
return $this->supplyChainUtil->jsonOrRedirect(
$request,
true,
__('supplychain::lang.forecasts_generated', ['count' => $results->count()]),
action([self::class, 'index'])
);
}
}