scriptotek /
bibrex
| 1 | <?php |
||||
| 2 | |||||
| 3 | namespace App\Http\Controllers; |
||||
| 4 | |||||
| 5 | use App\Events\LoanTableUpdated; |
||||
| 6 | use App\Http\Requests\CheckinRequest; |
||||
| 7 | use App\Http\Requests\CheckoutRequest; |
||||
| 8 | use App\Item; |
||||
| 9 | use App\Loan; |
||||
| 10 | use App\User; |
||||
| 11 | use Carbon\Carbon; |
||||
| 12 | use Illuminate\Http\Request; |
||||
| 13 | use Illuminate\Http\Response; |
||||
| 14 | use Illuminate\Validation\ValidationException; |
||||
| 15 | use Scriptotek\Alma\Client as AlmaClient; |
||||
| 16 | use Scriptotek\Alma\Bibs\Item as AlmaItem; |
||||
| 17 | use Scriptotek\Alma\Exception\RequestFailed; |
||||
| 18 | use function Stringy\create as s; |
||||
| 19 | |||||
| 20 | class LoansController extends Controller |
||||
| 21 | { |
||||
| 22 | /** |
||||
| 23 | * Validation error messages. |
||||
| 24 | * |
||||
| 25 | * @static array |
||||
| 26 | */ |
||||
| 27 | protected $messages = [ |
||||
| 28 | 'user.required' => 'Trenger enten navn eller låne-ID.', |
||||
| 29 | 'user.id.required_without' => 'Trenger enten navn eller låne-ID.', |
||||
| 30 | 'user.name.required_without' => 'Trenger enten navn eller låne-ID.', |
||||
| 31 | 'thing.required' => 'Uten ting blir det bare ingenting.', |
||||
| 32 | ]; |
||||
| 33 | |||||
| 34 | /* |
||||
| 35 | * Factory for Laravel Auth |
||||
| 36 | */ |
||||
| 37 | protected $auth; |
||||
| 38 | |||||
| 39 | /* |
||||
| 40 | * The currently logged in library |
||||
| 41 | */ |
||||
| 42 | protected $library; |
||||
| 43 | |||||
| 44 | /** |
||||
| 45 | * Display a listing of the resource. |
||||
| 46 | * |
||||
| 47 | * @param Request $request |
||||
| 48 | * @return Response |
||||
| 49 | */ |
||||
| 50 | public function getIndex(Request $request) |
||||
| 51 | { |
||||
| 52 | $user = $request->input('user') |
||||
| 53 | ? ['name' => $request->input('user')] |
||||
| 54 | : $request->session()->get('user'); |
||||
| 55 | |||||
| 56 | $thing = $request->input('thing') |
||||
| 57 | ? ['name' => $request->input('thing')] |
||||
| 58 | : $request->session()->get('thing'); |
||||
| 59 | |||||
| 60 | return response()->view('loans.index', [ |
||||
| 61 | 'library_id' => \Auth::user()->id, |
||||
| 62 | 'user' => $user, |
||||
| 63 | 'thing' => $thing, |
||||
| 64 | ])->header('Cache-Control', 'private, no-store, no-cache, must-revalidate, max-age=0'); |
||||
| 65 | } |
||||
| 66 | |||||
| 67 | /** |
||||
| 68 | * Display a listing of the resource. |
||||
| 69 | * |
||||
| 70 | * @param Request $request |
||||
| 71 | * @return Response |
||||
| 72 | */ |
||||
| 73 | public function json() |
||||
| 74 | { |
||||
| 75 | $library = \Auth::user(); |
||||
| 76 | |||||
| 77 | $loans = Loan::with('item.thing', 'user', 'user.identifiers', 'notifications') |
||||
| 78 | ->where('library_id', $library->id) |
||||
| 79 | ->orderBy('created_at', 'desc')->get(); |
||||
| 80 | |||||
| 81 | return response()->json($loans); |
||||
|
0 ignored issues
–
show
Bug
Best Practice
introduced
by
Loading history...
|
|||||
| 82 | } |
||||
| 83 | |||||
| 84 | /** |
||||
| 85 | * Display the specified resource. |
||||
| 86 | * |
||||
| 87 | * @param Loan $loan |
||||
| 88 | * @return Response |
||||
| 89 | */ |
||||
| 90 | public function getShow(Loan $loan) |
||||
| 91 | { |
||||
| 92 | if ($loan) { |
||||
|
0 ignored issues
–
show
|
|||||
| 93 | return response()->view('loans.show', array('loan' => $loan)); |
||||
| 94 | } else { |
||||
| 95 | return response()->view('errors.404', array('what' => 'Lånet'), 404); |
||||
| 96 | } |
||||
| 97 | } |
||||
| 98 | |||||
| 99 | |||||
| 100 | /** |
||||
| 101 | * Logs the response and returns it. |
||||
| 102 | * |
||||
| 103 | * @param Loan $loan |
||||
| 104 | * @return Response |
||||
| 105 | */ |
||||
| 106 | protected function loggedResponse($data) |
||||
| 107 | { |
||||
| 108 | if (isset($data['error'])) { |
||||
| 109 | \Log::info($data['error'], ['library' => \Auth::user()->name]); |
||||
| 110 | return response()->json($data, 422); |
||||
|
0 ignored issues
–
show
|
|||||
| 111 | } |
||||
| 112 | \Log::info($data['status'], ['library' => \Auth::user()->name]); |
||||
| 113 | return response()->json($data, 200); |
||||
|
0 ignored issues
–
show
|
|||||
| 114 | } |
||||
| 115 | |||||
| 116 | /** |
||||
| 117 | * Store a newly created resource in storage. |
||||
| 118 | * |
||||
| 119 | * @param AlmaClient $alma |
||||
| 120 | * @param CheckoutRequest $request |
||||
| 121 | * @return Response |
||||
| 122 | */ |
||||
| 123 | public function checkout(AlmaClient $alma, CheckoutRequest $request) |
||||
| 124 | { |
||||
| 125 | if (is_a($request->item, AlmaItem::class)) { |
||||
| 126 | return $this->checkoutAlmaItem($alma, $request->item, $request->user, $request); |
||||
| 127 | } |
||||
| 128 | |||||
| 129 | // Create new loan |
||||
| 130 | return $this->checkoutLocalItem($request->item, $request->user, $request); |
||||
|
0 ignored issues
–
show
|
|||||
| 131 | } |
||||
| 132 | |||||
| 133 | public function checkoutLocalItem(Item $item, User $user, Request $request) |
||||
| 134 | { |
||||
| 135 | $loan = Loan::create([ |
||||
| 136 | 'user_id' => $user->id, |
||||
| 137 | 'item_id' => $item->id, |
||||
| 138 | 'due_at' => Carbon::now() |
||||
| 139 | ->addDays($item->thing->properties->loan_time) |
||||
| 140 | ->setTime(0, 0, 0), |
||||
| 141 | 'as_guest' => false, |
||||
| 142 | ]); |
||||
| 143 | if (!$loan) { |
||||
| 144 | return response()->json(['errors' => $loan->errors], 409); |
||||
| 145 | } |
||||
| 146 | |||||
| 147 | $user->loan_count += 1; |
||||
| 148 | $user->last_loan_at = Carbon::now(); |
||||
| 149 | $user->save(); |
||||
| 150 | |||||
| 151 | event(new LoanTableUpdated('checkout', $request, $loan)); |
||||
| 152 | |||||
| 153 | $loan->load('user', 'item', 'item.thing'); |
||||
| 154 | |||||
| 155 | return $this->loggedResponse([ |
||||
| 156 | 'status' => sprintf( |
||||
| 157 | 'Lånte ut %s (<a href="%s">Detaljer</a>).', |
||||
| 158 | $item->thing->properties->get('name_indefinite.nob'), |
||||
| 159 | action('LoansController@getShow', $loan->id) |
||||
| 160 | ), |
||||
| 161 | 'loan' => $loan, |
||||
| 162 | ]); |
||||
| 163 | } |
||||
| 164 | |||||
| 165 | /** |
||||
| 166 | * Show the form for editing the specified resource. |
||||
| 167 | * |
||||
| 168 | * @param Loan $loan |
||||
| 169 | * @return Response |
||||
| 170 | */ |
||||
| 171 | public function edit(Loan $loan) |
||||
| 172 | { |
||||
| 173 | return response()->view('loans.edit', ['loan' => $loan]); |
||||
| 174 | } |
||||
| 175 | |||||
| 176 | /** |
||||
| 177 | * Update the specified resource in storage. |
||||
| 178 | * |
||||
| 179 | * @param Loan $loan |
||||
| 180 | * @param Request $request |
||||
| 181 | * @return void |
||||
| 182 | */ |
||||
| 183 | public function update(Loan $loan, Request $request) |
||||
| 184 | { |
||||
| 185 | $request->validate([ |
||||
| 186 | 'due_at' => 'required|date', |
||||
| 187 | ]); |
||||
| 188 | |||||
| 189 | $oldDate = $loan->due_at; |
||||
| 190 | |||||
| 191 | $loan->due_at = Carbon::parse($request->due_at); |
||||
| 192 | $loan->note = $request->note; |
||||
| 193 | $loan->save(); |
||||
| 194 | |||||
| 195 | if ($oldDate != $loan->due_at) { |
||||
| 196 | \Log::info(sprintf( |
||||
| 197 | 'Endret forfallsdato for <a href="%s">utlånet</a> av %s fra %s til %s.', |
||||
| 198 | action('LoansController@getShow', $loan->id), |
||||
| 199 | $loan->item->thing->properties->get('name_indefinite.nob'), |
||||
| 200 | $oldDate->toDateString(), |
||||
| 201 | $loan->due_at->toDateString() |
||||
| 202 | ), ['library' => \Auth::user()->name]); |
||||
| 203 | } |
||||
| 204 | |||||
| 205 | event(new LoanTableUpdated('update', $request, $loan)); |
||||
| 206 | |||||
| 207 | return redirect()->action('LoansController@getIndex') |
||||
|
0 ignored issues
–
show
|
|||||
| 208 | ->with('status', 'Lånet ble oppdatert'); |
||||
| 209 | } |
||||
| 210 | |||||
| 211 | /** |
||||
| 212 | * Mark the specified resource as lost. |
||||
| 213 | * |
||||
| 214 | * @param Loan $loan |
||||
| 215 | * @param Request $request |
||||
| 216 | * @return Response |
||||
| 217 | */ |
||||
| 218 | public function lost(Loan $loan, Request $request) |
||||
| 219 | { |
||||
| 220 | $loan->lost(); |
||||
| 221 | |||||
| 222 | event(new LoanTableUpdated('lost', $request, $loan)); |
||||
| 223 | |||||
| 224 | return $this->loggedResponse([ |
||||
| 225 | 'status' => sprintf('Registrerte %s som tapt.', $loan->item->formattedLink(false, false)), |
||||
| 226 | 'undoLink' => action('LoansController@restore', $loan->id), |
||||
| 227 | ]); |
||||
| 228 | } |
||||
| 229 | |||||
| 230 | /** |
||||
| 231 | * Checkin the specified loan. |
||||
| 232 | * |
||||
| 233 | * @param AlmaClient $alma |
||||
| 234 | * @param CheckinRequest $request |
||||
| 235 | * @return Response |
||||
| 236 | */ |
||||
| 237 | public function checkin(AlmaClient $alma, CheckinRequest $request) |
||||
| 238 | { |
||||
| 239 | if ($request->loan) { |
||||
| 240 | return $this->checkinLocalLoan($request->loan, $request, $alma); |
||||
| 241 | } |
||||
| 242 | |||||
| 243 | if ($request->almaItem) { |
||||
| 244 | return $this->checkinAlmaItem($alma, $request->almaItem); |
||||
| 245 | } |
||||
| 246 | |||||
| 247 | return response()->json([ |
||||
|
0 ignored issues
–
show
|
|||||
| 248 | 'status' => 'Ingenting har blitt returnert. Det kan argumenteres for at dette var en ' . |
||||
| 249 | 'unødvendig operasjon, men hvem vet.' |
||||
| 250 | ]); |
||||
| 251 | } |
||||
| 252 | |||||
| 253 | /** |
||||
| 254 | * Restores the specified loan. |
||||
| 255 | * |
||||
| 256 | * @param Loan $loan |
||||
| 257 | * @param Request $request |
||||
| 258 | * @return Response |
||||
| 259 | */ |
||||
| 260 | public function restore(Loan $loan, Request $request) |
||||
| 261 | { |
||||
| 262 | if ($loan->is_lost) { |
||||
| 263 | $loan->found(); |
||||
| 264 | } else { |
||||
| 265 | $loan->restore(); |
||||
| 266 | } |
||||
| 267 | |||||
| 268 | event(new LoanTableUpdated('restore', $request, $loan)); |
||||
| 269 | |||||
| 270 | return $this->loggedResponse([ |
||||
| 271 | 'status' => sprintf( |
||||
| 272 | '%s er fortsatt utlånt (<a href="%s">Detaljer</a>).', |
||||
| 273 | s($loan->item->thing->properties->get('name_definite.nob'))->upperCaseFirst(), |
||||
| 274 | action('LoansController@getShow', $loan->id) |
||||
| 275 | ) |
||||
| 276 | ]); |
||||
| 277 | } |
||||
| 278 | |||||
| 279 | /** |
||||
| 280 | * Checkout Alma item without creating a local copy. |
||||
| 281 | * |
||||
| 282 | * @param AlmaClient $client |
||||
| 283 | * @param AlmaItem $item |
||||
| 284 | * @param User $localUser |
||||
| 285 | * @param Request $request |
||||
| 286 | * @return Response |
||||
| 287 | */ |
||||
| 288 | protected function checkoutAlmaItem(AlmaClient $client, AlmaItem $almaItem, User $localUser, Request $request) |
||||
| 289 | { |
||||
| 290 | $library = \Auth::user(); |
||||
| 291 | |||||
| 292 | if (empty($library->library_code)) { |
||||
|
0 ignored issues
–
show
|
|||||
| 293 | return $this->loggedResponse([ |
||||
| 294 | 'error' => 'Alma-utlån krever at bibliotekskode er registrert' |
||||
| 295 | . ' i kontoinnstillingene.', |
||||
| 296 | ]); |
||||
| 297 | } |
||||
| 298 | |||||
| 299 | if ($localUser->in_alma) { |
||||
| 300 | $almaUser = $client->users->get($localUser->alma_primary_id); |
||||
| 301 | } else { |
||||
| 302 | if (empty($library->temporary_barcode)) { |
||||
| 303 | return $this->loggedResponse([ |
||||
| 304 | 'error' => 'Brukeren finnes ikke i Alma. Hvis du vil låne ut på midlertidig lånekort' |
||||
| 305 | . ' må det registreres i kontoinnstillingene.', |
||||
| 306 | ]); |
||||
| 307 | } |
||||
| 308 | |||||
| 309 | $almaUser = $client->users->get($library->temporary_barcode); |
||||
|
0 ignored issues
–
show
|
|||||
| 310 | } |
||||
| 311 | |||||
| 312 | $almaLibrary = $client->libraries[$library->library_code]; |
||||
| 313 | |||||
| 314 | try { |
||||
| 315 | $response = $almaItem->checkOut($almaUser, $almaLibrary); |
||||
| 316 | } catch (RequestFailed $e) { |
||||
| 317 | return $this->loggedResponse([ |
||||
| 318 | 'error' => $e->getMessage(), |
||||
| 319 | ]); |
||||
| 320 | } |
||||
| 321 | |||||
| 322 | if ($response->loan_status != 'ACTIVE') { |
||||
| 323 | return $this->loggedResponse([ |
||||
| 324 | 'error' => 'Utlån av Alma-dokument i Bibrex feilet, prøv i Alma i stedet.', |
||||
| 325 | ]); |
||||
| 326 | } |
||||
| 327 | |||||
| 328 | # The Alma checkout was successful. If the user is not in Alma, we create a |
||||
| 329 | # temporary local item to keep track of the loan. |
||||
| 330 | if (!$localUser->in_alma) { |
||||
| 331 | $localItem = Item::withTrashed()->firstOrNew([ |
||||
| 332 | 'thing_id' => 1, |
||||
| 333 | 'barcode' => $response->item_barcode, |
||||
| 334 | ]); |
||||
| 335 | $localItem->library_id = $library->id; |
||||
| 336 | $localItem->note = $response->title; |
||||
| 337 | $localItem->save(); |
||||
| 338 | |||||
| 339 | \Log::info(sprintf( |
||||
| 340 | 'Opprettet midlertidig Bibrex-eksemplar for Alma-utlån (<a href="%s">Detaljer</a>)', |
||||
| 341 | action('ItemsController@show', $localItem->id) |
||||
| 342 | ), ['library' => \Auth::user()->name]); |
||||
| 343 | |||||
| 344 | return $this->checkoutLocalItem($localItem, $localUser, $request); |
||||
|
0 ignored issues
–
show
|
|||||
| 345 | } |
||||
| 346 | |||||
| 347 | # If the user exists in Alma, we don't create a local item. |
||||
| 348 | return $this->loggedResponse([ |
||||
| 349 | 'status' => sprintf( |
||||
| 350 | '%s (%s) ble lånt ut til %s i Alma. Forfaller: %s', |
||||
| 351 | $response->item_barcode, |
||||
| 352 | $response->title, |
||||
| 353 | $response->user_id, |
||||
| 354 | $response->due_date |
||||
| 355 | ), |
||||
| 356 | ]); |
||||
| 357 | } |
||||
| 358 | |||||
| 359 | /** |
||||
| 360 | * Checkin Alma item. |
||||
| 361 | * |
||||
| 362 | * @param AlmaClient $client |
||||
| 363 | * @param AlmaItem $item |
||||
| 364 | * @return Response |
||||
| 365 | */ |
||||
| 366 | protected function checkinAlmaItem(AlmaClient $client, AlmaItem $item) |
||||
| 367 | { |
||||
| 368 | $library = \Auth::user(); |
||||
| 369 | |||||
| 370 | if (empty($library->library_code)) { |
||||
|
0 ignored issues
–
show
|
|||||
| 371 | return $this->loggedResponse([ |
||||
| 372 | 'error' => 'Alma-innleveringer krever at bibliotekskode er registrert' |
||||
| 373 | . ' i kontoinnstillingene.', |
||||
| 374 | ]); |
||||
| 375 | } |
||||
| 376 | |||||
| 377 | $almaLibrary = $client->libraries[$library->library_code]; |
||||
| 378 | |||||
| 379 | $response = $item->scanIn($almaLibrary, 'DEFAULT_CIRC_DESK', [ |
||||
| 380 | 'place_on_hold_shelf' => 'true', |
||||
| 381 | 'auto_print_slip' => 'true', |
||||
| 382 | ]); |
||||
| 383 | |||||
| 384 | return $this->loggedResponse([ |
||||
| 385 | 'status' => sprintf( |
||||
| 386 | '<small>%s ble skanna inn i Alma, og Alma svarte:</small><br>%s', |
||||
| 387 | $item->item_data->barcode, |
||||
| 388 | $response->getMessage() |
||||
| 389 | ), |
||||
| 390 | ]); |
||||
| 391 | } |
||||
| 392 | |||||
| 393 | /** |
||||
| 394 | * @param Loan $loan |
||||
| 395 | * @param Request $request |
||||
| 396 | * @param AlmaClient $alma |
||||
| 397 | * @return Response |
||||
| 398 | */ |
||||
| 399 | protected function checkinLocalLoan(Loan $loan, Request $request, AlmaClient $alma) |
||||
| 400 | { |
||||
| 401 | $library = \Auth::user(); |
||||
| 402 | |||||
| 403 | if ($loan->is_lost) { |
||||
| 404 | $loan->found(); |
||||
| 405 | return $this->loggedResponse(['status' => sprintf( |
||||
| 406 | '%s var registrert som tapt, men er nå tilbake!', |
||||
| 407 | $loan->item->formattedLink(true) |
||||
| 408 | )]); |
||||
| 409 | } |
||||
| 410 | |||||
| 411 | if ($loan->trashed()) { |
||||
| 412 | if ($loan->item->thing_id == 1 && !empty($library->library_code)) { |
||||
|
0 ignored issues
–
show
|
|||||
| 413 | // Could still be on loan in Alma |
||||
| 414 | $almaItem = $alma->items->fromBarcode($loan->item->barcode); |
||||
| 415 | return $this->checkinAlmaItem($alma, $almaItem); |
||||
|
0 ignored issues
–
show
It seems like
$almaItem can also be of type null; however, parameter $item of App\Http\Controllers\Loa...ller::checkinAlmaItem() does only seem to accept Scriptotek\Alma\Bibs\Item, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 416 | } |
||||
| 417 | |||||
| 418 | return response()->json(['status' => sprintf( |
||||
|
0 ignored issues
–
show
|
|||||
| 419 | '%s var allerede levert (men det går greit).', |
||||
| 420 | $loan->item->formattedLink(true) |
||||
| 421 | )], 200); |
||||
| 422 | } |
||||
| 423 | |||||
| 424 | $loan->checkIn(); |
||||
| 425 | |||||
| 426 | $user = $loan->user; |
||||
| 427 | $user->last_loan_at = Carbon::now(); |
||||
| 428 | $user->save(); |
||||
| 429 | |||||
| 430 | event(new LoanTableUpdated('checkin', $request, $loan)); |
||||
| 431 | |||||
| 432 | if ($loan->item->thing_id == 1 && !empty($library->library_code)) { |
||||
| 433 | $almaItem = $alma->items->fromBarcode($loan->item->barcode); |
||||
| 434 | return $this->checkinAlmaItem($alma, $almaItem); |
||||
| 435 | } |
||||
| 436 | |||||
| 437 | return $this->loggedResponse([ |
||||
| 438 | 'status' => sprintf( |
||||
| 439 | 'Returnerte %s (<a href="%s">Detaljer</a>).', |
||||
| 440 | $loan->item->thing->properties->get('name_indefinite.nob'), |
||||
| 441 | action('LoansController@getShow', $loan->id) |
||||
| 442 | ), |
||||
| 443 | 'undoLink' => action('LoansController@restore', $loan->id), |
||||
| 444 | ]); |
||||
| 445 | } |
||||
| 446 | } |
||||
| 447 |