Merge pull request #19160 from grokability/added-changed-log-meta-to-accessories-and-licenses

Logging: Fixed FD-55757 - Added changed log meta to accessories and licenses
This commit is contained in:
snipe
2026-06-08 22:37:59 +01:00
committed by GitHub
7 changed files with 271 additions and 12 deletions
+21 -6
View File
@@ -14,12 +14,27 @@ class AccessoryObserver
*/
public function updated(Accessory $accessory)
{
$logAction = new Actionlog;
$logAction->item_type = Accessory::class;
$logAction->item_id = $accessory->id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
$logAction->logaction('update');
$changed = [];
foreach ($accessory->getRawOriginal() as $key => $value) {
if ($key === 'updated_at') {
continue;
}
if ($accessory->getRawOriginal()[$key] != $accessory->getAttributes()[$key]) {
$changed[$key]['old'] = $accessory->getRawOriginal()[$key];
$changed[$key]['new'] = $accessory->getAttributes()[$key];
}
}
if (count($changed) > 0) {
$logAction = new Actionlog;
$logAction->item_type = Accessory::class;
$logAction->item_id = $accessory->id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
$logAction->log_meta = json_encode($changed);
$logAction->logaction('update');
}
}
/**
+2
View File
@@ -15,6 +15,8 @@ class ComponentObserver
public function updated(Component $component)
{
$changed = [];
foreach ($component->getRawOriginal() as $key => $value) {
// Check and see if the value changed
if ($component->getRawOriginal()[$key] != $component->getAttributes()[$key]) {
+21 -6
View File
@@ -14,12 +14,27 @@ class LicenseObserver
*/
public function updated(License $license)
{
$logAction = new Actionlog;
$logAction->item_type = License::class;
$logAction->item_id = $license->id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
$logAction->logaction('update');
$changed = [];
foreach ($license->getRawOriginal() as $key => $value) {
if ($key === 'updated_at') {
continue;
}
if ($license->getRawOriginal()[$key] != $license->getAttributes()[$key]) {
$changed[$key]['old'] = $license->getRawOriginal()[$key];
$changed[$key]['new'] = $license->getAttributes()[$key];
}
}
if (count($changed) > 0) {
$logAction = new Actionlog;
$logAction->item_type = License::class;
$logAction->item_id = $license->id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
$logAction->log_meta = json_encode($changed);
$logAction->logaction('update');
}
}
/**
@@ -3,6 +3,7 @@
namespace Tests\Feature\Accessories\Api;
use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Category;
use App\Models\Company;
use App\Models\Location;
@@ -137,4 +138,47 @@ class UpdateAccessoryTest extends TestCase implements TestsFullMultipleCompanies
$this->assertEquals($manufacturerB->id, $accessory->manufacturer_id);
$this->assertEquals($supplierB->id, $accessory->supplier_id);
}
public function test_update_logs_changed_fields_in_log_meta()
{
$accessory = Accessory::factory()->create(['qty' => 5, 'name' => 'Old Name']);
$this->actingAsForApi(User::factory()->editAccessories()->create())
->patchJson(route('api.accessories.update', $accessory), ['qty' => 10, 'name' => 'New Name']);
$log = Actionlog::where('item_type', Accessory::class)
->where('item_id', $accessory->id)
->where('action_type', 'update')
->latest()
->first();
$this->assertNotNull($log, 'No update log entry was created');
$this->assertNotNull($log->log_meta, 'log_meta was not stored');
$meta = json_decode($log->log_meta, true);
$this->assertEquals('5', $meta['qty']['old']);
$this->assertEquals('10', $meta['qty']['new']);
$this->assertEquals('Old Name', $meta['name']['old']);
$this->assertEquals('New Name', $meta['name']['new']);
}
public function test_no_op_update_does_not_create_log_entry()
{
$accessory = Accessory::factory()->create(['qty' => 5, 'name' => 'Same Name']);
$before = Actionlog::where('item_type', Accessory::class)
->where('item_id', $accessory->id)
->where('action_type', 'update')
->count();
$this->actingAsForApi(User::factory()->editAccessories()->create())
->patchJson(route('api.accessories.update', $accessory), ['qty' => 5, 'name' => 'Same Name']);
$after = Actionlog::where('item_type', Accessory::class)
->where('item_id', $accessory->id)
->where('action_type', 'update')
->count();
$this->assertEquals($before, $after, 'A spurious log entry was created for a no-op update');
}
}
@@ -3,6 +3,7 @@
namespace Tests\Feature\Accessories\Ui;
use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Category;
use App\Models\Company;
use App\Models\Location;
@@ -124,4 +125,67 @@ class UpdateAccessoryTest extends TestCase
'notes' => 'A new note',
]);
}
public function test_update_logs_changed_fields_in_log_meta()
{
$accessory = Accessory::factory()->create([
'qty' => 5,
'name' => 'Old Name',
'model_number' => null,
'location_id' => null,
]);
$this->actingAs(User::factory()->editAccessories()->create())
->put(route('accessories.update', $accessory), [
'redirect_option' => 'index',
'name' => 'New Name',
'qty' => '10',
'category_id' => (string) $accessory->category_id,
]);
$log = Actionlog::where('item_type', Accessory::class)
->where('item_id', $accessory->id)
->where('action_type', 'update')
->latest()
->first();
$this->assertNotNull($log, 'No update log entry was created');
$this->assertNotNull($log->log_meta, 'log_meta was not stored');
$meta = json_decode($log->log_meta, true);
$this->assertEquals('5', $meta['qty']['old']);
$this->assertEquals('10', $meta['qty']['new']);
$this->assertEquals('Old Name', $meta['name']['old']);
$this->assertEquals('New Name', $meta['name']['new']);
}
public function test_no_op_update_does_not_create_log_entry()
{
$accessory = Accessory::factory()->create([
'qty' => 5,
'name' => 'Same Name',
'model_number' => null,
'location_id' => null,
]);
$before = Actionlog::where('item_type', Accessory::class)
->where('item_id', $accessory->id)
->where('action_type', 'update')
->count();
$this->actingAs(User::factory()->editAccessories()->create())
->put(route('accessories.update', $accessory), [
'redirect_option' => 'index',
'name' => 'Same Name',
'qty' => '5',
'category_id' => (string) $accessory->category_id,
]);
$after = Actionlog::where('item_type', Accessory::class)
->where('item_id', $accessory->id)
->where('action_type', 'update')
->count();
$this->assertEquals($before, $after, 'A spurious log entry was created for a no-op update');
}
}
@@ -0,0 +1,59 @@
<?php
namespace Tests\Feature\Licenses\Api;
use App\Models\Actionlog;
use App\Models\License;
use App\Models\User;
use Tests\TestCase;
class UpdateLicenseTest extends TestCase
{
public function test_update_logs_changed_fields_in_log_meta()
{
$license = License::factory()->create(['name' => 'Old Name', 'seats' => 5]);
$this->actingAsForApi(User::factory()->editLicenses()->create())
->patchJson(route('api.licenses.update', $license), [
'name' => 'New Name',
'seats' => 10,
'category_id' => $license->category_id,
]);
$log = Actionlog::where('item_type', License::class)
->where('item_id', $license->id)
->where('action_type', 'update')
->latest()
->first();
$this->assertNotNull($log, 'No update log entry was created');
$this->assertNotNull($log->log_meta, 'log_meta was not stored');
$meta = json_decode($log->log_meta, true);
$this->assertEquals('Old Name', $meta['name']['old']);
$this->assertEquals('New Name', $meta['name']['new']);
}
public function test_no_op_update_does_not_create_log_entry()
{
$license = License::factory()->create(['name' => 'Same Name']);
$before = Actionlog::where('item_type', License::class)
->where('item_id', $license->id)
->where('action_type', 'update')
->count();
$this->actingAsForApi(User::factory()->editLicenses()->create())
->patchJson(route('api.licenses.update', $license), [
'name' => 'Same Name',
'category_id' => $license->category_id,
]);
$after = Actionlog::where('item_type', License::class)
->where('item_id', $license->id)
->where('action_type', 'update')
->count();
$this->assertEquals($before, $after, 'A spurious log entry was created for a no-op update');
}
}
@@ -2,6 +2,7 @@
namespace Tests\Feature\Licenses\Ui;
use App\Models\Actionlog;
use App\Models\Category;
use App\Models\License;
use App\Models\User;
@@ -99,4 +100,63 @@ class UpdateLicenseTest extends TestCase
$this->assertEquals($license->licenseseats()->count(), $license->seats);
$this->assertEquals($license->licenseseats()->count(), 5000);
}
public function test_update_logs_changed_fields_in_log_meta()
{
$license = License::factory()->create(['name' => 'Old Name', 'seats' => 5]);
$this->actingAs(User::factory()->editLicenses()->create())
->put(route('licenses.update', $license), [
'name' => 'New Name',
'seats' => 10,
'category_id' => $license->category_id,
]);
$log = Actionlog::where('item_type', License::class)
->where('item_id', $license->id)
->where('action_type', 'update')
->latest()
->first();
$this->assertNotNull($log, 'No update log entry was created');
$this->assertNotNull($log->log_meta, 'log_meta was not stored');
$meta = json_decode($log->log_meta, true);
$this->assertEquals('Old Name', $meta['name']['old']);
$this->assertEquals('New Name', $meta['name']['new']);
}
public function test_no_op_update_does_not_create_log_entry()
{
$license = License::factory()->create([
'name' => 'Same Name',
'seats' => 5,
'license_email' => null,
'notes' => null,
'order_number' => null,
'purchase_date' => null,
'reassignable' => 0,
'serial' => null,
'supplier_id' => null,
]);
$before = Actionlog::where('item_type', License::class)
->where('item_id', $license->id)
->where('action_type', 'update')
->count();
$this->actingAs(User::factory()->editLicenses()->create())
->put(route('licenses.update', $license), [
'name' => 'Same Name',
'seats' => 5,
'category_id' => $license->category_id,
]);
$after = Actionlog::where('item_type', License::class)
->where('item_id', $license->id)
->where('action_type', 'update')
->count();
$this->assertEquals($before, $after, 'A spurious log entry was created for a no-op update');
}
}