edit.blade.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. @extends('layouts.app')
  2. @section('content')
  3. <div class="container-fluid">
  4. <div class="row">
  5. <div class="col-md-6">
  6. <h2>{{ $spare_part_order ? 'Заказ детали #' . $spare_part_order->id : 'Новый заказ детали' }}</h2>
  7. <form action="{{ $spare_part_order ? route('spare_part_orders.update', $spare_part_order) : route('spare_part_orders.store') }}"
  8. method="POST">
  9. @csrf
  10. @if($spare_part_order)
  11. @method('PUT')
  12. @endif
  13. <input type="hidden" name="previous_url" value="{{ $previous_url ?? url()->previous() }}">
  14. @if($spare_part_order && $spare_part_order->sparePart && $spare_part_order->sparePart->image)
  15. <div class="mb-3">
  16. <img src="{{ $spare_part_order->sparePart->image }}" alt="{{ $spare_part_order->sparePart->article }}" class="img-fluid" style="max-width: 150px;">
  17. </div>
  18. @endif
  19. <div class="mb-3">
  20. <label for="spare_part_id" class="form-label">Артикул <span class="text-danger">*</span></label>
  21. <select class="form-select" id="spare_part_id" name="spare_part_id" required {{ $spare_part_order ? 'disabled' : '' }}>
  22. <option value="">Выберите...</option>
  23. @foreach($spare_parts as $sp)
  24. <option value="{{ $sp->id }}"
  25. {{ old('spare_part_id', $spare_part_order->spare_part_id ?? '') == $sp->id ? 'selected' : '' }}>
  26. {{ $sp->article }} - {{ $sp->used_in_maf }}
  27. </option>
  28. @endforeach
  29. </select>
  30. @if($spare_part_order)
  31. <input type="hidden" name="spare_part_id" value="{{ $spare_part_order->spare_part_id }}">
  32. @endif
  33. </div>
  34. <div class="mb-3">
  35. <label for="source_text" class="form-label">Источник заказа</label>
  36. <input type="text" class="form-control" id="source_text" name="source_text"
  37. value="{{ old('source_text', $spare_part_order->source_text ?? '') }}">
  38. </div>
  39. <div class="mb-3">
  40. <label for="status" class="form-label">Статус <span class="text-danger">*</span></label>
  41. <select class="form-select" id="status" name="status" required>
  42. @foreach(\App\Models\SparePartOrder::STATUS_NAMES as $key => $name)
  43. <option value="{{ $key }}"
  44. {{ old('status', $spare_part_order->status ?? '') == $key ? 'selected' : '' }}>
  45. {{ $name }}
  46. </option>
  47. @endforeach
  48. </select>
  49. </div>
  50. <div class="mb-3">
  51. <label for="ordered_quantity" class="form-label">Заказано <span class="text-danger">*</span></label>
  52. <input type="number" class="form-control" id="ordered_quantity" name="ordered_quantity"
  53. value="{{ old('ordered_quantity', $spare_part_order->ordered_quantity ?? '') }}"
  54. min="1" required>
  55. </div>
  56. @if($spare_part_order)
  57. <div class="mb-3">
  58. <label class="form-label">Остаток</label>
  59. <input type="text" class="form-control" value="{{ $spare_part_order->available_qty }}" readonly>
  60. @if($spare_part_order->reserved_qty > 0)
  61. <small class="text-warning">Зарезервировано: {{ $spare_part_order->reserved_qty }} шт.</small>
  62. @endif
  63. </div>
  64. @endif
  65. <div class="mb-3">
  66. <div class="form-check">
  67. <input class="form-check-input" type="checkbox" id="with_documents" name="with_documents" value="1"
  68. {{ old('with_documents', $spare_part_order->with_documents ?? false) ? 'checked' : '' }}>
  69. <label class="form-check-label" for="with_documents">
  70. С документами
  71. </label>
  72. </div>
  73. </div>
  74. <div class="mb-3">
  75. <label for="note" class="form-label">Примечание</label>
  76. <textarea class="form-control" id="note" name="note" rows="3">{{ old('note', $spare_part_order->note ?? '') }}</textarea>
  77. </div>
  78. <div class="mb-3">
  79. <button type="submit" class="btn btn-success">Сохранить</button>
  80. <a href="{{ $previous_url ?? route('spare_part_orders.index') }}" class="btn btn-secondary">Назад</a>
  81. @if($spare_part_order && $spare_part_order->status === 'ordered' && hasRole('admin,manager'))
  82. <form action="{{ route('spare_part_orders.set_in_stock', $spare_part_order) }}" method="POST" class="d-inline">
  83. @csrf
  84. <button type="submit" class="btn btn-info">Поступило на склад</button>
  85. </form>
  86. @endif
  87. @if($spare_part_order && hasRole('admin'))
  88. <button type="button" class="btn btn-danger float-end" data-bs-toggle="modal" data-bs-target="#deleteModal">
  89. Удалить
  90. </button>
  91. @endif
  92. </div>
  93. </form>
  94. </div>
  95. @if($spare_part_order)
  96. <div class="col-md-6">
  97. {{-- Резервы --}}
  98. @if($spare_part_order->reservations->where('status', 'active')->count() > 0)
  99. <h3>Активные резервы</h3>
  100. <table class="table table-sm table-striped">
  101. <thead>
  102. <tr>
  103. <th>Кол-во</th>
  104. <th>Рекламация</th>
  105. <th>Дата</th>
  106. <th></th>
  107. </tr>
  108. </thead>
  109. <tbody>
  110. @foreach($spare_part_order->reservations->where('status', 'active') as $reservation)
  111. <tr>
  112. <td>{{ $reservation->reserved_qty }}</td>
  113. <td>
  114. @if($reservation->reclamation)
  115. <a href="{{ route('reclamations.show', $reservation->reclamation->id) }}">#{{ $reservation->reclamation->id }}</a>
  116. @else
  117. -
  118. @endif
  119. </td>
  120. <td>{{ $reservation->created_at->format('d.m.Y H:i') }}</td>
  121. <td>
  122. @if(hasRole('admin,manager'))
  123. <form action="{{ route('spare_part_reservations.issue', $reservation) }}" method="POST" class="d-inline">
  124. @csrf
  125. <button type="submit" class="btn btn-sm btn-success" title="Списать">
  126. <i class="fas fa-check"></i>
  127. </button>
  128. </form>
  129. <form action="{{ route('spare_part_reservations.cancel', $reservation) }}" method="POST" class="d-inline">
  130. @csrf
  131. <button type="submit" class="btn btn-sm btn-warning" title="Отменить резерв">
  132. <i class="fas fa-times"></i>
  133. </button>
  134. </form>
  135. @endif
  136. </td>
  137. </tr>
  138. @endforeach
  139. </tbody>
  140. </table>
  141. @endif
  142. {{-- История движений --}}
  143. <h3>История движений</h3>
  144. @if($spare_part_order->status === 'in_stock' && $spare_part_order->free_qty > 0 && hasRole('admin,manager'))
  145. <button type="button" class="btn btn-warning mb-3" data-bs-toggle="modal" data-bs-target="#shipModal">
  146. Отгрузить
  147. </button>
  148. @if(hasRole('admin'))
  149. <button type="button" class="btn btn-secondary mb-3" data-bs-toggle="modal" data-bs-target="#correctModal">
  150. Коррекция
  151. </button>
  152. @endif
  153. @endif
  154. @if($spare_part_order->movements->count() > 0)
  155. <table class="table table-striped">
  156. <thead>
  157. <tr>
  158. <th>Дата</th>
  159. <th>Тип</th>
  160. <th>Кол-во</th>
  161. <th>Примечание</th>
  162. <th>Пользователь</th>
  163. </tr>
  164. </thead>
  165. <tbody>
  166. @foreach($spare_part_order->movements->sortByDesc('created_at') as $movement)
  167. <tr class="@if($movement->movement_type === 'issue') table-danger @elseif($movement->movement_type === 'reserve') table-warning @elseif($movement->movement_type === 'reserve_cancel') table-info @endif">
  168. <td>{{ $movement->created_at->format('d.m.Y H:i') }}</td>
  169. <td>{{ $movement->type_name }}</td>
  170. <td>{{ $movement->qty }}</td>
  171. <td>
  172. {{ $movement->note }}
  173. @if($movement->source_type === 'reclamation' && $movement->source_id)
  174. <br><small><a href="{{ route('reclamations.show', $movement->source_id) }}">Рекламация #{{ $movement->source_id }}</a></small>
  175. @endif
  176. </td>
  177. <td>{{ $movement->user->name ?? '-' }}</td>
  178. </tr>
  179. @endforeach
  180. </tbody>
  181. </table>
  182. @else
  183. <p class="text-muted">Движений пока нет</p>
  184. @endif
  185. </div>
  186. @endif
  187. </div>
  188. </div>
  189. @if($spare_part_order && hasRole('admin,manager'))
  190. {{-- Модальное окно отгрузки --}}
  191. <div class="modal fade" id="shipModal" tabindex="-1">
  192. <div class="modal-dialog">
  193. <div class="modal-content">
  194. <form action="{{ route('spare_part_orders.ship', $spare_part_order) }}" method="POST">
  195. @csrf
  196. <div class="modal-header">
  197. <h5 class="modal-title">Отгрузка</h5>
  198. <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
  199. </div>
  200. <div class="modal-body">
  201. <div class="alert alert-info">
  202. Доступно: {{ $spare_part_order->available_qty }} шт.
  203. @if($spare_part_order->reserved_qty > 0)
  204. <br>Зарезервировано: {{ $spare_part_order->reserved_qty }} шт.
  205. <br><strong>Свободно: {{ $spare_part_order->free_qty }} шт.</strong>
  206. @endif
  207. </div>
  208. <div class="mb-3">
  209. <label for="quantity" class="form-label">Количество <span class="text-danger">*</span></label>
  210. <input type="number" class="form-control" id="quantity" name="quantity"
  211. min="1" max="{{ $spare_part_order->free_qty }}" required>
  212. </div>
  213. <div class="mb-3">
  214. <label for="ship_note" class="form-label">Примечание (куда/для чего) <span class="text-danger">*</span></label>
  215. <textarea class="form-control" id="ship_note" name="note" rows="3" required></textarea>
  216. </div>
  217. </div>
  218. <div class="modal-footer">
  219. <button type="submit" class="btn btn-primary">Отгрузить</button>
  220. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
  221. </div>
  222. </form>
  223. </div>
  224. </div>
  225. </div>
  226. @endif
  227. @if($spare_part_order && hasRole('admin'))
  228. {{-- Модальное окно коррекции --}}
  229. <div class="modal fade" id="correctModal" tabindex="-1">
  230. <div class="modal-dialog">
  231. <div class="modal-content">
  232. <form action="{{ route('spare_part_orders.correct', $spare_part_order) }}" method="POST">
  233. @csrf
  234. <div class="modal-header">
  235. <h5 class="modal-title">Коррекция остатка</h5>
  236. <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
  237. </div>
  238. <div class="modal-body">
  239. <div class="alert alert-warning">
  240. Текущий остаток: {{ $spare_part_order->available_qty }} шт.
  241. </div>
  242. <div class="mb-3">
  243. <label for="new_quantity" class="form-label">Новый остаток <span class="text-danger">*</span></label>
  244. <input type="number" class="form-control" id="new_quantity" name="new_quantity"
  245. min="0" value="{{ $spare_part_order->available_qty }}" required>
  246. </div>
  247. <div class="mb-3">
  248. <label for="reason" class="form-label">Причина коррекции <span class="text-danger">*</span></label>
  249. <textarea class="form-control" id="reason" name="reason" rows="3" required
  250. placeholder="Укажите причину изменения остатка"></textarea>
  251. </div>
  252. </div>
  253. <div class="modal-footer">
  254. <button type="submit" class="btn btn-primary">Применить</button>
  255. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
  256. </div>
  257. </form>
  258. </div>
  259. </div>
  260. </div>
  261. {{-- Модальное окно удаления --}}
  262. <div class="modal fade" id="deleteModal" tabindex="-1">
  263. <div class="modal-dialog">
  264. <div class="modal-content">
  265. <div class="modal-header">
  266. <h5 class="modal-title">Подтверждение удаления</h5>
  267. <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
  268. </div>
  269. <div class="modal-body">
  270. Вы действительно хотите удалить заказ #{{ $spare_part_order->id }}?
  271. @if($spare_part_order->reservations->where('status', 'active')->count() > 0)
  272. <div class="alert alert-danger mt-2">
  273. Внимание: есть активные резервы!
  274. </div>
  275. @endif
  276. </div>
  277. <div class="modal-footer">
  278. <form action="{{ route('spare_part_orders.destroy', $spare_part_order) }}" method="POST">
  279. @csrf
  280. @method('DELETE')
  281. <button type="submit" class="btn btn-danger">Удалить</button>
  282. <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
  283. </form>
  284. </div>
  285. </div>
  286. </div>
  287. </div>
  288. @endif
  289. @endsection