user())->pending()->get(); return view('account/accept.index', compact('acceptances')); } /** * Shows a form to either accept or decline the checkout acceptance * * @param int $id */ public function create($id) : View | RedirectResponse { $acceptance = CheckoutAcceptance::find($id); if (is_null($acceptance)) { return redirect()->route('account.accept')->with('error', trans('admin/hardware/message.does_not_exist')); } if (! $acceptance->isPending()) { return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.asset_already_accepted')); } if (! $acceptance->isCheckedOutTo(auth()->user())) { return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted')); } if (! Company::isCurrentUserHasAccess($acceptance->checkoutable)) { return redirect()->route('account.accept')->with('error', trans('general.error_user_company')); } return view('account/accept.create', compact('acceptance')); } /** * Stores the accept/decline of the checkout acceptance * * @param Request $request * @param int $id */ public function store(Request $request, $id) : RedirectResponse { $acceptance = CheckoutAcceptance::find($id); if (is_null($acceptance)) { return redirect()->route('account.accept')->with('error', trans('admin/hardware/message.does_not_exist')); } if (! $acceptance->isPending()) { return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.asset_already_accepted')); } if (! $acceptance->isCheckedOutTo(auth()->user())) { return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted')); } if (! Company::isCurrentUserHasAccess($acceptance->checkoutable)) { return redirect()->route('account.accept')->with('error', trans('general.insufficient_permissions')); } if (! $request->filled('asset_acceptance')) { return redirect()->back()->with('error', trans('admin/users/message.error.accept_or_decline')); } /** * Get the signature and save it */ if (! Storage::exists('private_uploads/signatures')) { Storage::makeDirectory('private_uploads/signatures', 775); } $item = $acceptance->checkoutable_type::find($acceptance->checkoutable_id); $display_model = ''; $pdf_view_route = ''; $pdf_filename = 'accepted-eula-'.date('Y-m-d-h-i-s').'.pdf'; $sig_filename=''; if ($request->input('asset_acceptance') == 'accepted') { /** * Check for the eula-pdfs directory */ if (! Storage::exists('private_uploads/eula-pdfs')) { Storage::makeDirectory('private_uploads/eula-pdfs', 775); } if (Setting::getSettings()->require_accept_signature == '1') { // Check if the signature directory exists, if not create it if (!Storage::exists('private_uploads/signatures')) { Storage::makeDirectory('private_uploads/signatures', 775); } // The item was accepted, check for a signature if ($request->filled('signature_output')) { $sig_filename = 'siglog-' . Str::uuid() . '-' . date('Y-m-d-his') . '.png'; $data_uri = $request->input('signature_output'); $encoded_image = explode(',', $data_uri); $decoded_image = base64_decode($encoded_image[1]); Storage::put('private_uploads/signatures/' . $sig_filename, (string)$decoded_image); // No image data is present, kick them back. // This mostly only applies to users on super-duper crapola browsers *cough* IE *cough* } else { return redirect()->back()->with('error', trans('general.shitty_browser')); } } $assigned_user = User::find($acceptance->assigned_to_id); // this is horrible switch($acceptance->checkoutable_type){ case 'App\Models\Asset': $pdf_view_route ='account.accept.accept-asset-eula'; $asset_model = AssetModel::find($item->model_id); if (!$asset_model) { return redirect()->back()->with('error', trans('admin/models/message.does_not_exist')); } $display_model = $asset_model->name; break; case 'App\Models\Accessory': $pdf_view_route ='account.accept.accept-accessory-eula'; $accessory = Accessory::find($item->id); $display_model = $accessory->name; break; case 'App\Models\LicenseSeat': $pdf_view_route ='account.accept.accept-license-eula'; $license = License::find($item->license_id); $display_model = $license->name; break; case 'App\Models\Component': $pdf_view_route ='account.accept.accept-component-eula'; $component = Component::find($item->id); $display_model = $component->name; break; case 'App\Models\Consumable': $pdf_view_route ='account.accept.accept-consumable-eula'; $consumable = Consumable::find($item->id); $display_model = $consumable->name; break; } // if ($acceptance->checkoutable_type == 'App\Models\Asset') { // $pdf_view_route ='account.accept.accept-asset-eula'; // $asset_model = AssetModel::find($item->model_id); // $display_model = $asset_model->name; // $assigned_to = User::find($item->assigned_to)->present()->fullName; // // } elseif ($acceptance->checkoutable_type== 'App\Models\Accessory') { // $pdf_view_route ='account.accept.accept-accessory-eula'; // $accessory = Accessory::find($item->id); // $display_model = $accessory->name; // $assigned_to = User::find($item->assignedTo); // // } /** * Gather the data for the PDF. We fire this whether there is a signature required or not, * since we want the moment-in-time proof of what the EULA was when they accepted it. */ $branding_settings = SettingsController::getPDFBranding(); $path_logo = ""; // Check for the PDF logo path and use that, otherwise use the regular logo path if (!is_null($branding_settings->acceptance_pdf_logo)) { $path_logo = public_path() . '/uploads/' . $branding_settings->acceptance_pdf_logo; } elseif (!is_null($branding_settings->logo)) { $path_logo = public_path() . '/uploads/' . $branding_settings->logo; } $data = [ 'item_tag' => $item->asset_tag, 'item_model' => $display_model, 'item_serial' => $item->serial, 'item_status' => $item->assetstatus?->name, 'eula' => $item->getEula(), 'note' => $request->input('note'), 'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d H:i:s'), 'accepted_date' => Carbon::parse($acceptance->accepted_at)->format('Y-m-d H:i:s'), 'assigned_to' => $assigned_user->display_name, 'company_name' => $branding_settings->site_name, 'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null, 'logo' => $path_logo, 'date_settings' => $branding_settings->date_display_format, 'admin' => auth()->user()->present()?->fullName, 'qty' => $acceptance->qty ?? 1, ]; if ($pdf_view_route!='') { // set some language dependent data: $lg = Array(); $lg['a_meta_charset'] = 'UTF-8'; $lg['w_page'] = 'page'; $pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false); // $pdf->SetHeaderData(PDF_HEADER_LOGO, 5, PDF_HEADER_TITLE.' 006', PDF_HEADER_STRING); // $pdf->SetHeaderData('https://snipe-it.test/uploads/snipe-logo.png', '5', $data['company_name'], $item->company?->name); //$pdf->headerText = ('Anything you want ' . date('c')); $pdf->setRTL(false); //$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, $data['company_name'], ''); $pdf->setLanguageArray($lg); $pdf->SetFontSubsetting(true); $pdf->SetCreator('Snipe-IT'); $pdf->SetAuthor($data['assigned_to']); $pdf->SetTitle('Asset Acceptance: '.$data['item_tag']); // $pdf->SetSubject('Document Subject'); //$pdf->SetKeywords('keywords, here'); $pdf->SetFont('dejavusans', '', 8, '', true); // $pdf->SetFont('dejavusans', '', 14); // $pdf->SetPrintHeader(false); $pdf->SetPrintFooter(false); $pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN)); $pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA)); $pdf->AddPage(); $pdf->writeHTML('', true, 0, true, 0, ''); // $pdf->writeHTML(trans('general.date').': '.date($data['date_settings']), true, 0, true, 0, ''); $pdf->writeHTML("".trans('general.asset_tag').': '.$data['item_tag'], true, 0, true, 0, ''); $pdf->writeHTML("".trans('general.asset_model').': '.$data['item_model'], true, 0, true, 0, ''); $pdf->writeHTML("".trans('admin/hardware/form.serial').': '.$data['item_serial'], true, 0, true, 0, ''); $pdf->writeHTML("".trans('general.assigned_date').': '.$data['check_out_date'], true, 0, true, 0, ''); $pdf->writeHTML("".trans('general.assignee').': '.$data['assigned_to'], true, 0, true, 0, ''); $pdf->Ln(); // Break the EULA into lines based on newlines, and check each line for RTL or CJK characters $eula_lines = preg_split("/\r\n|\n|\r/", $item->getEula()); foreach ($eula_lines as $eula_line) { if (Helper::hasRtl($eula_line)) { $pdf->setRTL(true); } else { $pdf->setRTL(false); } if (Helper::isCjk($eula_line)) { $pdf->SetFont('cid0cs', '', 9); } else { $pdf->SetFont('dejavusans', '', 8, '', true); } $pdf->writeHTML(Helper::parseEscapedMarkedown($eula_line), true, 0, true, 0, ''); } $pdf->Ln(); $pdf->Ln(); $pdf->setRTL(false); $pdf->writeHTML('

', true, 0, true, 0, ''); if ($data['note'] != null) { $pdf->writeHTML("".trans('general.notes') . ': ' . $data['note'], true, 0, true, 0, ''); $pdf->Ln(); } if ($data['signature'] != null) { $pdf->writeHTML('', true, 0, true, 0, ''); $pdf->writeHTML('
', true, 0, true, 0, ''); } $pdf->writeHTML("".trans('general.accepted_date').': '.$data['accepted_date'], true, 0, true, 0, ''); $pdf_content = $pdf->Output($pdf_filename, 'S'); Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf_content); } $acceptance->accept($sig_filename, $item->getEula(), $pdf_filename, $request->input('note')); // Send the PDF to the signing user if (($request->input('send_copy') == '1') && ($assigned_user->email !='')) { // Add the attachment for the signing user into the $data array $data['file'] = $pdf_filename; $locale = $assigned_user->locale; try { $assigned_user->notify((new AcceptanceAssetAcceptedToUserNotification($data))->locale($locale)); } catch (\Exception $e) { Log::warning($e); } } try { $acceptance->notify((new AcceptanceAssetAcceptedNotification($data))->locale(Setting::getSettings()->locale)); } catch (\Exception $e) { Log::warning($e); } event(new CheckoutAccepted($acceptance)); $return_msg = trans('admin/users/message.accepted'); } else { /** * Check for the eula-pdfs directory */ if (! Storage::exists('private_uploads/eula-pdfs')) { Storage::makeDirectory('private_uploads/eula-pdfs', 775); } if (Setting::getSettings()->require_accept_signature == '1') { // Check if the signature directory exists, if not create it if (!Storage::exists('private_uploads/signatures')) { Storage::makeDirectory('private_uploads/signatures', 775); } // The item was accepted, check for a signature if ($request->filled('signature_output')) { $sig_filename = 'siglog-' . Str::uuid() . '-' . date('Y-m-d-his') . '.png'; $data_uri = $request->input('signature_output'); $encoded_image = explode(',', $data_uri); $decoded_image = base64_decode($encoded_image[1]); Storage::put('private_uploads/signatures/' . $sig_filename, (string)$decoded_image); // No image data is present, kick them back. // This mostly only applies to users on super-duper crapola browsers *cough* IE *cough* } else { return redirect()->back()->with('error', trans('general.shitty_browser')); } } // Format the data to send the declined notification $branding_settings = SettingsController::getPDFBranding(); // This is the most horriblest switch($acceptance->checkoutable_type){ case 'App\Models\Asset': $asset_model = AssetModel::find($item->model_id); $display_model = $asset_model->name; $assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName; break; case 'App\Models\Accessory': $accessory = Accessory::find($item->id); $display_model = $accessory->name; $assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName; break; case 'App\Models\LicenseSeat': $assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName; break; case 'App\Models\Component': $assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName; break; case 'App\Models\Consumable': $consumable = Consumable::find($item->id); $display_model = $consumable->name; $assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName; break; } $data = [ 'item_tag' => $item->asset_tag, 'item_model' => $display_model, 'item_serial' => $item->serial, 'item_status' => $item->assetstatus?->name, 'note' => $request->input('note'), 'declined_date' => Carbon::parse($acceptance->declined_at)->format('Y-m-d'), 'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null, 'assigned_to' => $assigned_to, 'company_name' => $branding_settings->site_name, 'date_settings' => $branding_settings->date_display_format, 'qty' => $acceptance->qty ?? 1, ]; if ($pdf_view_route!='') { Log::debug($pdf_filename.' is the filename, and the route was specified.'); $pdf = Pdf::loadView($pdf_view_route, $data); Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output()); } for ($i = 0; $i < ($acceptance->qty ?? 1); $i++) { $acceptance->decline($sig_filename, $request->input('note')); } $acceptance->notify(new AcceptanceAssetDeclinedNotification($data)); Log::debug('New event acceptance.'); event(new CheckoutDeclined($acceptance)); $return_msg = trans('admin/users/message.declined'); } if ($acceptance->alert_on_response_id) { try { $recipient = User::find($acceptance->alert_on_response_id); if ($recipient) { Log::debug('Attempting to send email acceptance.'); Mail::to($recipient)->send(new CheckoutAcceptanceResponseMail( $acceptance, $recipient, $request->input('asset_acceptance') === 'accepted', )); Log::debug('Send email notification sucess on checkout acceptance response.'); } } catch (Exception $e) { Log::error($e->getMessage()); Log::warning($e); } } return redirect()->to('account/accept')->with('success', $return_msg); } }