CommonCatalogController.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Http\Controllers;
  4. use App\Http\Requests\StoreCommonCatalogItemRequest;
  5. use App\Jobs\Export\ExportCommonCatalogJob;
  6. use App\Jobs\Import\ImportJob;
  7. use App\Models\CommonCatalogItem;
  8. use App\Models\File;
  9. use App\Models\Import;
  10. use App\Services\FileService;
  11. use Illuminate\Contracts\View\View;
  12. use Illuminate\Http\RedirectResponse;
  13. use Illuminate\Http\Request;
  14. use Illuminate\Support\Facades\Storage;
  15. use Illuminate\Support\Str;
  16. use Throwable;
  17. class CommonCatalogController extends Controller
  18. {
  19. protected array $data = [
  20. 'active' => 'common_catalog',
  21. 'title' => 'Каталог общий',
  22. 'id' => 'common_catalog_items',
  23. 'header' => [
  24. 'id' => 'ID',
  25. 'image' => 'Внешний вид',
  26. 'article' => 'Артикул',
  27. 'calculator_name' => 'Наименование по калькулятору',
  28. 'kind' => 'Вид',
  29. 'dimensions' => 'Габаритные размеры',
  30. 'fall_height' => 'Высота падения',
  31. 'additional_info' => 'Дополнительные сведения',
  32. 'dimension_unit' => 'Единица измерения габаритов',
  33. 'weight' => 'Вес, кг.',
  34. 'volume' => 'Объем, м3',
  35. 'places' => 'Места',
  36. 'composition' => 'Состав',
  37. 'age_group' => 'Возрастная группа',
  38. 'max_users' => 'Макс. кол-во пользователей',
  39. 'unit' => 'Ед.',
  40. 'series' => 'Серия',
  41. 'trademark' => 'ТМ',
  42. 'note' => 'Примечание',
  43. ],
  44. 'searchFields' => [
  45. 'article',
  46. 'calculator_name',
  47. 'kind',
  48. 'dimensions',
  49. 'additional_info',
  50. 'composition',
  51. 'series',
  52. 'trademark',
  53. 'note',
  54. ],
  55. ];
  56. public function index(Request $request): View
  57. {
  58. session(['gp_common_catalog' => $request->query()]);
  59. $nav = $this->startNavigationContext($request);
  60. $model = new CommonCatalogItem;
  61. $this->createFilters(
  62. $model,
  63. 'kind',
  64. 'dimension_unit',
  65. 'age_group',
  66. 'unit',
  67. 'series',
  68. 'trademark',
  69. );
  70. $this->createRangeFilters(
  71. $model,
  72. 'fall_height',
  73. 'weight',
  74. 'volume',
  75. 'places',
  76. 'max_users',
  77. );
  78. $query = CommonCatalogItem::query()->with('imageFile');
  79. $this->acceptFilters($query, $request);
  80. $this->acceptSearch($query, $request);
  81. $this->setSortAndOrderBy($model, $request);
  82. $this->applyStableSorting($query);
  83. $this->data['items'] = $query->paginate($this->data['per_page'])->withQueryString();
  84. $this->data['nav'] = $nav;
  85. return view('common_catalog.index', $this->data);
  86. }
  87. public function create(Request $request): View
  88. {
  89. return $this->itemView($request);
  90. }
  91. public function show(Request $request, CommonCatalogItem $commonCatalogItem): View
  92. {
  93. return $this->itemView(
  94. $request,
  95. $commonCatalogItem->load(['imageFile', 'documents']),
  96. );
  97. }
  98. public function store(StoreCommonCatalogItemRequest $request): RedirectResponse
  99. {
  100. $item = CommonCatalogItem::query()->create($request->validated());
  101. return redirect()
  102. ->route('common-catalog.show', $this->withNav(
  103. ['commonCatalogItem' => $item],
  104. $this->resolveNavToken($request),
  105. ))
  106. ->with('success', 'Позиция общего каталога создана.');
  107. }
  108. public function update(
  109. StoreCommonCatalogItemRequest $request,
  110. CommonCatalogItem $commonCatalogItem,
  111. ): RedirectResponse {
  112. $commonCatalogItem->update($request->validated());
  113. return $this->redirectToItem($request, $commonCatalogItem)
  114. ->with('success', 'Позиция общего каталога обновлена.');
  115. }
  116. public function destroy(
  117. Request $request,
  118. CommonCatalogItem $commonCatalogItem,
  119. FileService $fileService,
  120. ): RedirectResponse {
  121. $commonCatalogItem->load(['imageFile', 'documents']);
  122. $files = $commonCatalogItem->documents;
  123. if ($commonCatalogItem->imageFile) {
  124. $files->push($commonCatalogItem->imageFile);
  125. }
  126. $commonCatalogItem->documents()->detach();
  127. $commonCatalogItem->update(['image_file_id' => null]);
  128. $commonCatalogItem->delete();
  129. foreach ($files->unique('id') as $file) {
  130. $fileService->deleteFileWithThumbnail($file);
  131. $file->delete();
  132. }
  133. return redirect()
  134. ->route('common-catalog.index', session('gp_common_catalog'))
  135. ->with('success', 'Позиция общего каталога удалена.');
  136. }
  137. public function uploadImage(
  138. Request $request,
  139. CommonCatalogItem $commonCatalogItem,
  140. FileService $fileService,
  141. ): RedirectResponse {
  142. $data = $request->validate([
  143. 'image' => ['required', 'image', 'mimes:jpg,jpeg,png,webp', 'max:10240'],
  144. ]);
  145. try {
  146. $oldImage = $commonCatalogItem->imageFile;
  147. $image = $fileService->saveUploadedFile(
  148. "common_catalog/items/{$commonCatalogItem->id}/image",
  149. $data['image'],
  150. );
  151. $commonCatalogItem->update(['image_file_id' => $image->id]);
  152. if ($oldImage) {
  153. $fileService->deleteFileWithThumbnail($oldImage);
  154. $oldImage->delete();
  155. }
  156. } catch (Throwable $exception) {
  157. report($exception);
  158. return $this->redirectToItem($request, $commonCatalogItem)
  159. ->with('error', 'Не удалось загрузить изображение.');
  160. }
  161. return $this->redirectToItem($request, $commonCatalogItem)
  162. ->with('success', 'Изображение загружено.');
  163. }
  164. public function deleteImage(
  165. Request $request,
  166. CommonCatalogItem $commonCatalogItem,
  167. FileService $fileService,
  168. ): RedirectResponse {
  169. $image = $commonCatalogItem->imageFile;
  170. if ($image) {
  171. $commonCatalogItem->update(['image_file_id' => null]);
  172. $fileService->deleteFileWithThumbnail($image);
  173. $image->delete();
  174. }
  175. return $this->redirectToItem($request, $commonCatalogItem)
  176. ->with('success', 'Изображение удалено.');
  177. }
  178. public function uploadDocument(
  179. Request $request,
  180. CommonCatalogItem $commonCatalogItem,
  181. FileService $fileService,
  182. ): RedirectResponse {
  183. $data = $request->validate([
  184. 'document' => ['required', 'file', 'max:20480'],
  185. ]);
  186. try {
  187. $document = $fileService->saveUploadedFile(
  188. "common_catalog/items/{$commonCatalogItem->id}/documents",
  189. $data['document'],
  190. );
  191. $commonCatalogItem->documents()->attach($document);
  192. } catch (Throwable $exception) {
  193. report($exception);
  194. return $this->redirectToItem($request, $commonCatalogItem)
  195. ->with('error', 'Не удалось загрузить документ.');
  196. }
  197. return $this->redirectToItem($request, $commonCatalogItem)
  198. ->with('success', 'Документ загружен.');
  199. }
  200. public function deleteDocument(
  201. Request $request,
  202. CommonCatalogItem $commonCatalogItem,
  203. File $file,
  204. FileService $fileService,
  205. ): RedirectResponse {
  206. abort_unless($commonCatalogItem->documents()->whereKey($file->getKey())->exists(), 404);
  207. $commonCatalogItem->documents()->detach($file);
  208. $fileService->deleteFileWithThumbnail($file);
  209. $file->delete();
  210. return $this->redirectToItem($request, $commonCatalogItem)
  211. ->with('success', 'Документ удалён.');
  212. }
  213. public function export(Request $request): RedirectResponse
  214. {
  215. ExportCommonCatalogJob::dispatch((int) $request->user()->getKey());
  216. return redirect()
  217. ->route('common-catalog.index', session('gp_common_catalog'))
  218. ->with('success', 'Задача экспорта общего каталога создана.');
  219. }
  220. public function import(Request $request): RedirectResponse
  221. {
  222. $data = $request->validate([
  223. 'import_file' => ['required', 'file', 'mimes:xlsx', 'max:20480'],
  224. ]);
  225. $path = Str::random(2).'/'.Str::uuid().'.xlsx';
  226. Storage::disk('upload')->put($path, $data['import_file']->getContent());
  227. $import = Import::query()->create([
  228. 'type' => 'common_catalog',
  229. 'year' => null,
  230. 'filename' => $path,
  231. 'status' => 'new',
  232. 'user_id' => $request->user()->getKey(),
  233. 'original_filename' => $data['import_file']->getClientOriginalName(),
  234. ]);
  235. ImportJob::dispatch($import, (int) $request->user()->getKey());
  236. return redirect()
  237. ->route('common-catalog.index', session('gp_common_catalog'))
  238. ->with('success', 'Задача импорта общего каталога создана.');
  239. }
  240. private function itemView(Request $request, ?CommonCatalogItem $item = null): View
  241. {
  242. $nav = $this->resolveNavToken($request);
  243. $this->rememberNavigation($request, $nav);
  244. $this->data['nav'] = $nav;
  245. $this->data['back_url'] = $this->navigationBackUrl(
  246. $request,
  247. $nav,
  248. route('common-catalog.index', session('gp_common_catalog')),
  249. );
  250. $this->data['item'] = $item;
  251. return view('common_catalog.edit', $this->data);
  252. }
  253. private function redirectToItem(
  254. Request $request,
  255. CommonCatalogItem $commonCatalogItem,
  256. ): RedirectResponse {
  257. return redirect()->route('common-catalog.show', $this->withNav(
  258. ['commonCatalogItem' => $commonCatalogItem],
  259. $this->resolveNavToken($request),
  260. ));
  261. }
  262. }