Added custom fields to EULA PDFs

This commit is contained in:
snipe
2026-05-04 12:51:43 +01:00
parent f57d2608c5
commit b63aee2851
12 changed files with 188 additions and 6 deletions
@@ -208,6 +208,30 @@ class AcceptanceController extends Controller
'qty' => $acceptance->qty ?? 1,
];
// Include asset custom fields that are explicitly allowed in outbound emails/PDFs.
if ($item instanceof Asset && $item->model && $item->model->fieldset) {
$customFields = [];
$fields = $item->model->fieldset->fields
->where('show_in_email', true)
->where('field_encrypted', false);
foreach ($fields as $field) {
$dbColumn = $field->db_column;
$value = $item->{$dbColumn};
if (! is_null($value) && $value !== '') {
$customFields[] = [
'label' => $field->name,
'value' => $value,
];
}
}
if (! empty($customFields)) {
$data['custom_fields'] = $customFields;
}
}
if ($request->input('asset_acceptance') === 'accepted') {
$pdf_filename = 'accepted-'.$acceptance->checkoutable_id.'-'.$acceptance->display_checkoutable_type.'-eula-'.date('Y-m-d-h-i-s').'.pdf';
+17
View File
@@ -58,10 +58,26 @@ class CheckinAssetMail extends BaseMailable
{
$this->item->load('status');
$fields = [];
$customFields = [];
// Check if the item has custom fields associated with it
if (($this->item->model) && ($this->item->model->fieldset)) {
$fields = $this->item->model->fieldset->fields;
foreach ($fields as $field) {
if (! $field->show_in_email || $field->field_encrypted == '1') {
continue;
}
$value = $this->item->{$field->db_column_name()};
if (! is_null($value) && $value !== '') {
$customFields[] = [
'label' => $field->name,
'value' => $value,
];
}
}
}
return new Content(
@@ -73,6 +89,7 @@ class CheckinAssetMail extends BaseMailable
'note' => $this->note,
'target' => $this->target,
'fields' => $fields,
'custom_fields' => $customFields,
'expected_checkin' => $this->expected_checkin,
],
);
+17
View File
@@ -75,6 +75,7 @@ class CheckoutAssetMail extends BaseMailable
$eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : '';
$req_accept = $this->requiresAcceptance();
$fields = [];
$customFields = [];
$name = null;
if ($this->target instanceof User) {
@@ -88,6 +89,21 @@ class CheckoutAssetMail extends BaseMailable
// Check if the item has custom fields associated with it
if (($this->item->model) && ($this->item->model->fieldset)) {
$fields = $this->item->model->fieldset->fields;
foreach ($fields as $field) {
if (! $field->show_in_email || $field->field_encrypted == '1') {
continue;
}
$value = $this->item->{$field->db_column_name()};
if (! is_null($value) && $value !== '') {
$customFields[] = [
'label' => $field->name,
'value' => $value,
];
}
}
}
$accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance);
@@ -101,6 +117,7 @@ class CheckoutAssetMail extends BaseMailable
'note' => $this->note,
'target' => $name,
'fields' => $fields,
'custom_fields' => $customFields,
'eula' => $eula,
'req_accept' => $req_accept,
'accept_url' => $accept_url,
+10
View File
@@ -250,6 +250,16 @@ class CheckoutAcceptance extends Model
if ($data['email'] != null) {
$pdf->writeHTML(trans('general.email').': '.e($data['email']), true, 0, true, 0, '');
}
if (! empty($data['custom_fields']) && is_iterable($data['custom_fields'])) {
foreach ($data['custom_fields'] as $customField) {
$label = $customField['label'] ?? null;
$value = $customField['value'] ?? null;
if (($label !== null) && ($value !== null) && ($value !== '')) {
$pdf->writeHTML(e((string) $label).': '.e((string) $value), true, 0, true, 0, '');
}
}
}
$pdf->Ln();
$pdf->writeHTML('<hr>', true, 0, true, 0, '');
@@ -33,6 +33,7 @@ class AcceptanceItemAcceptedNotification extends Notification
$this->file = $params['file'] ?? null;
$this->qty = $params['qty'] ?? null;
$this->note = $params['note'] ?? null;
$this->custom_fields = $params['custom_fields'] ?? [];
}
@@ -76,6 +77,7 @@ class AcceptanceItemAcceptedNotification extends Notification
'assigned_to' => $this->assigned_to,
'company_name' => $this->company_name,
'qty' => $this->qty,
'custom_fields' => $this->custom_fields,
'intro_text' => trans('mail.acceptance_accepted_greeting', ['user' => $this->assigned_to, 'item' => $this->item_name]),
])
->subject('✅ '.trans('mail.acceptance_accepted', ['user' => $this->assigned_to, 'item' => $this->item_name]))
@@ -34,6 +34,7 @@ class AcceptanceItemAcceptedToUserNotification extends Notification
$this->settings = Setting::getSettings();
$this->file = $params['file'] ?? null;
$this->qty = $params['qty'] ?? null;
$this->custom_fields = $params['custom_fields'] ?? [];
}
/**
@@ -72,6 +73,7 @@ class AcceptanceItemAcceptedToUserNotification extends Notification
'assigned_to' => $this->assigned_to,
'company_name' => $this->company_name,
'qty' => $this->qty,
'custom_fields' => $this->custom_fields,
'intro_text' => trans_choice('mail.acceptance_asset_accepted_to_user', $this->qty, ['qty' => $this->qty, 'site_name' => $this->settings->site_name]),
])
->attach($pdf_path)
@@ -37,11 +37,13 @@
@if (isset($status))
| **{{ trans('general.status') }}** | {{ $status }} |
@endif
@foreach($fields as $field)
@if (($item->{ $field->db_column_name() }!='') && ($field->show_in_email) && ($field->field_encrypted=='0'))
| **{{ $field->name }}** | {{ $item->{ $field->db_column_name() } }} |
@if (!empty($custom_fields))
@foreach($custom_fields as $customField)
@if (!empty($customField['label']) && array_key_exists('value', $customField) && $customField['value'] !== '')
| **{{ $customField['label'] }}** | {{ $customField['value'] }} |
@endif
@endforeach
@endif
@if ($admin)
| **{{ trans('general.administrator') }}** | {{ $admin->display_name }} |
@endif
@@ -40,11 +40,13 @@
@if ((isset($expected_checkin)) && ($expected_checkin!=''))
| **{{ trans('mail.expecting_checkin_date') }}** | {{ $expected_checkin }} |
@endif
@foreach($fields as $field)
@if (($item->{ $field->db_column_name() }!='') && ($field->show_in_email) && ($field->field_encrypted=='0'))
| **{{ $field->name }}** | {{ $item->{ $field->db_column_name() } }} |
@if (!empty($custom_fields))
@foreach($custom_fields as $customField)
@if (!empty($customField['label']) && array_key_exists('value', $customField) && $customField['value'] !== '')
| **{{ $customField['label'] }}** | {{ $customField['value'] }} |
@endif
@endforeach
@endif
@if ($admin)
| **{{ trans('general.administrator') }}** | {{ $admin->display_name }} |
@endif
@@ -43,6 +43,13 @@
@if (isset($qty))
| **{{ trans('general.qty') }}** | {{ $qty }} |
@endif
@if (!empty($custom_fields))
@foreach($custom_fields as $customField)
@if (!empty($customField['label']) && array_key_exists('value', $customField) && $customField['value'] !== '')
| **{{ $customField['label'] }}** | {{ $customField['value'] }} |
@endif
@endforeach
@endif
@endcomponent
{{ trans('mail.best_regards') }}
@@ -6,9 +6,12 @@ use App\Events\CheckoutAccepted;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\CheckoutAcceptance;
use App\Models\CustomField;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\AcceptanceItemAcceptedNotification;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
class AssetAcceptanceTest extends TestCase
@@ -204,6 +207,45 @@ class AssetAcceptanceTest extends TestCase
);
}
public function test_acceptance_email_includes_custom_fields_marked_show_in_email_and_not_encrypted(): void
{
Event::fake([CheckoutAccepted::class]);
Notification::fake();
$this->settings->enableAlertEmail();
$customField = CustomField::factory()->create([
'name' => 'Cost Center',
'show_in_email' => '1',
'field_encrypted' => '0',
])->fresh();
$asset = Asset::factory()->hasMultipleCustomFields([$customField])->create();
$asset->{$customField->db_column} = 'ENG-42';
$asset->save();
$checkoutAcceptance = CheckoutAcceptance::factory()
->pending()
->for($asset, 'checkoutable')
->create();
$this->actingAs($checkoutAcceptance->assignedTo)
->post(route('account.store-acceptance', $checkoutAcceptance), [
'asset_acceptance' => 'accepted',
])
->assertRedirectToRoute('account.accept')
->assertSessionHas('success');
Notification::assertSentTo(
$checkoutAcceptance,
function (AcceptanceItemAcceptedNotification $notification) {
$rendered = $notification->toMail()->render();
return str_contains($rendered, 'Cost Center')
&& str_contains($rendered, 'ENG-42');
}
);
}
public function test_admin_can_complete_sign_in_place_acceptance_and_is_redirected_to_selected_destination()
{
Event::fake([CheckoutAccepted::class]);
@@ -7,6 +7,7 @@ use App\Mail\CheckinAssetMail;
use App\Models\Accessory;
use App\Models\Asset;
use App\Models\Consumable;
use App\Models\CustomField;
use App\Models\LicenseSeat;
use App\Models\User;
use Illuminate\Support\Facades\Mail;
@@ -99,6 +100,32 @@ class EmailNotificationsToUserUponCheckinTest extends TestCase
Mail::assertNothingSent();
}
public function test_checkin_email_includes_custom_fields_marked_show_in_email_and_not_encrypted()
{
$customField = CustomField::factory()->create([
'name' => 'Cost Center',
'show_in_email' => '1',
'field_encrypted' => '0',
])->fresh();
$user = User::factory()->create();
$asset = Asset::factory()->hasMultipleCustomFields([$customField])->assignedToUser($user)->create();
$asset->{$customField->db_column} = 'ENG-42';
$asset->save();
$asset->model->category->update(['checkin_email' => true]);
$this->fireCheckInEvent($asset, $user);
Mail::assertSent(CheckinAssetMail::class, function (CheckinAssetMail $mail) use ($user) {
$rendered = $mail->render();
return $mail->hasTo($user->email)
&& str_contains($rendered, 'Cost Center')
&& str_contains($rendered, 'ENG-42');
});
}
private function fireCheckInEvent($asset, $user): void
{
event(new CheckoutableCheckedIn(
@@ -8,6 +8,7 @@ use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Category;
use App\Models\CheckoutAcceptance;
use App\Models\CustomField;
use App\Models\User;
use Illuminate\Support\Facades\Mail;
use PHPUnit\Framework\Attributes\Group;
@@ -106,6 +107,35 @@ class EmailNotificationsToUserUponCheckoutTest extends TestCase
$this->assertUserSentEmail();
}
public function test_email_includes_custom_fields_marked_show_in_email_and_not_encrypted()
{
$customField = CustomField::factory()->create([
'name' => 'Cost Center',
'show_in_email' => '1',
'field_encrypted' => '0',
])->fresh();
$asset = Asset::factory()->hasMultipleCustomFields([$customField])->create();
$asset->{$customField->db_column} = 'ENG-42';
$asset->save();
$this->category = $asset->model->category;
$this->asset = $asset;
$this->user = User::factory()->create();
$this->category->update(['checkin_email' => true]);
$this->fireCheckoutEvent();
Mail::assertSent(CheckoutAssetMail::class, function (CheckoutAssetMail $mail) {
$rendered = $mail->render();
return $mail->hasTo($this->user->email)
&& str_contains($rendered, 'Cost Center')
&& str_contains($rendered, 'ENG-42');
});
}
public function test_handles_user_not_having_email_address_set()
{
$this->category->update(['checkin_email' => true]);