ldc-supportweb/app/Http/Controllers/InvoiceController.php
2022-09-05 09:05:09 +02:00

282 lines
9.5 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\Invoice\TaskType;
use App\Http\Requests\Invoice\InvoiceSetDateRequest;
use App\Models\Company;
use App\Models\Invoice;
use App\Models\Package;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
use Kwaadpepper\Enum\Rules\EnumIsValidRule;
/**
* * Because update is denied when invoice is sent to the client
* ForceUpdate On signed date
* ForceUpdate On compta sent date
*/
class InvoiceController extends Controller
{
use CrudController {
index as crudIndex;
show as crudShow;
create as crudCreate;
edit as crudEdit;
}
/** @var \App\Models\Invoice */
public static $modelClass = Invoice::class;
/**
* Crud Layout
*
* @var string
*/
public static $layout = 'layout.app';
/**
* Crud index view
*
* @param \Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudIndex($request);
if ($request->ajax()) {
return $view;
}
if ($request->search and ($models = $view->getData()['models'])->count() === 1) {
return \redirect()->route('invoices.edit', $models->first());
}
return view('invoices.index', $view->getData());
}
/**
* Index query middleware
*
* @param Builder $query
* @return Builder
* @throws \ErrorException If account is missing in url.
*/
public function indexQuery(Builder $query): Builder
{
$query->orderBy('created_at', 'DESC');
return $query->orWhere(function (Builder $q) {
$q->whereHas('site', function ($q) {
$q->where('name', 'LIKE', '%' . \filter_var(request()->search, \FILTER_SANITIZE_STRING) . '%');
})->orWhereHas('company', function ($q) {
$q->where('name', 'LIKE', '%' . \filter_var(request()->search, \FILTER_SANITIZE_STRING) . '%');
})->orWhereHas('companyInvoiced', function ($q) {
$q->where('name', 'LIKE', '%' . \filter_var(request()->search, \FILTER_SANITIZE_STRING) . '%');
});
});
}
/**
* Show model action
*
* @param \Illuminate\Http\Request $request
* @param mixed ...$params
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse
*/
public function show(Request $request, ...$params)
{
/** @var \Illuminate\View\View|\Illuminate\Http\JsonResponse */
$view = call_user_func_array([$this, 'crudShow'], \array_merge([$request], $params));
if ($view instanceof \Illuminate\Http\JsonResponse) {
return $view;
}
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Package> */
$packages = Package::get()->keyBy('id')->all();
return view('invoices.show', \array_merge($view->getData(), ['packages' => $packages]));
}
/**
* Crud create view
*
* @param \Kwaadpepper\CrudPolicies\Http\Requests\CrudIndexRequest $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function create(CrudIndexRequest $request)
{
/** @var \Illuminate\View\View */
$view = $this->crudCreate($request);
$companies = Company::get();
$packages = Package::get();
$taskRowModel = Invoice::getTaskStructure();
return view('invoices.create', \array_merge($view->getData(), [
'companies' => $companies,
'packages' => $packages,
'taskRowModel' => $taskRowModel,
]));
}
/**
* Before store model middleware
*
* @param \App\Models\Invoice $model
* @return void
*/
public function storeModel(Invoice &$model)
{
$this->validateTasks($model);
}
/**
* Before update model middleware
*
* @param \App\Models\Invoice $model
* @return void
* @throws \Illuminate\Validation\ValidationException If invoice is signed.
*/
public function updateModel(Invoice &$model)
{
if ($model->signed_date) {
throw ValidationException::withMessages([
'erreur' => trans('Il n\'est pas possible de mettre a jour un devis qui est signé')
]);
}
$this->validateTasks($model);
}
/**
* Edit model action
*
* @param mixed ...$params
* @return \Illuminate\Contracts\View\View|\Illuminate\Contracts\View\Factory
*/
public function edit(...$params)
{
/** @var \Illuminate\View\View */
$view = call_user_func_array([$this, 'crudEdit'], $params);
$companies = Company::get();
$packages = Package::get();
$taskRowModel = Invoice::getTaskStructure();
return view('invoices.edit', \array_merge($view->getData(), [
'companies' => $companies,
'packages' => $packages,
'taskRowModel' => $taskRowModel,
]));
}
/**
* Validate Tasks
*
* @param \App\Models\Invoice $invoice
* @return void
* @throws \Illuminate\Validation\ValidationException If tasks are not valid.
*/
private function validateTasks(Invoice $invoice): void
{
$tasks = \collect(\json_decode($invoice->tasks, true))
->map(function ($task) {
if (\is_array($task)) {
return \array_intersect_key($task, Invoice::getTaskStructure());
}
});
$invoice->tasks = Validator::make(['tasks' => $tasks->all()], [
'tasks' => 'required|array|min:1',
'tasks.*' => 'required|array',
'tasks.*.days' => 'required|numeric|min:0.125',
'tasks.*.amount' => 'required|numeric|min:0.125',
'tasks.*.desc' => 'required|string|min:10',
'tasks.*.type' => [
'required', new EnumIsValidRule(TaskType::class)
],
'tasks.*.package' => 'required_if:tasks.*.type,' .
TaskType::package()->value . '|nullable|exists:packages,id',
], [], [
'tasks' => trans('Tâches')
])->validated()['tasks'];
}
/**
* Download Invoice
*
* @param \App\Models\Invoice $invoice
* @return \Symfony\Component\HttpFoundation\Response
*/
public function download(Invoice $invoice)
{
$this->authorize($invoice, 'download');
return $invoice->generateInvoice()
->stream(Str::slug(trans('Devis :appname :date - ref :ref', [
'appname' => config('app.name'),
'date' => $invoice->created_at->isoFormat('YYYY-MM-DD'),
'ref' => $invoice->ref,
])) . '.pdf');
}
/**
* Set signed date
*
* @param \App\Http\Requests\Invoice\InvoiceSetDateRequest $request
* @param \App\Models\Invoice $invoice
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Validation\ValidationException If already signed.
*/
public function setSignedDate(InvoiceSetDateRequest $request, Invoice $invoice)
{
if ($invoice->signed_date) {
throw ValidationException::withMessages([
'erreur' => trans('La date de signature est déjà actée.')
]);
}
$invoice->signed_date = $request->date;
$invoice->saveOrFail();
return \back()->with('success', trans('La date de signature à bien été enregistrée'));
}
/**
* Set client signed date
*
* @param \App\Http\Requests\Invoice\InvoiceSetDateRequest $request
* @param \App\Models\Invoice $invoice
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Validation\ValidationException If already signed.
*/
public function setClientSentDate(InvoiceSetDateRequest $request, Invoice $invoice)
{
if ($invoice->sent_client_date) {
throw ValidationException::withMessages([
'erreur' => trans('La date de signature client est déjà actée.')
]);
}
$invoice->sent_client_date = $request->date;
$invoice->saveOrFail();
return \back()->with('success', trans('La date de signature client à bien été enregistrée'));
}
/**
* Set compta signed date
*
* @param \App\Http\Requests\Invoice\InvoiceSetDateRequest $request
* @param \App\Models\Invoice $invoice
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Validation\ValidationException If already signed.
*/
public function setComptaSentDate(InvoiceSetDateRequest $request, Invoice $invoice)
{
if ($invoice->sent_accounting_date) {
throw ValidationException::withMessages([
'erreur' => trans('La date de signature compta est déjà actée.')
]);
}
$invoice->sent_accounting_date = $request->date;
$invoice->saveOrFail();
return \back()->with('success', trans('La date de signature compta à bien été enregistrée'));
}
}