282 lines
9.5 KiB
PHP
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;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
/**
|
|
* * 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): Response
|
|
{
|
|
$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'));
|
|
}
|
|
}
|