In this article, we’ll explore the integration of system level activity logs with helpdesk modules, providing insights into how these logs can enhance helpdesk functionalities.

Whenever an action such as creating, updating, or deleting occurs within any module, it is recorded in the system level activity logs.

To enable this feature, we utilize the SystemActivityLogsTrait, which is responsible for logging all activity within the system.

Here’s how to implement it:

  1. Use SystemActivityLogsTrait: Incorporate this trait into the desired models.
  2. Define Required Properties: Declare the necessary properties in your model to ensure compatibility with system activity logs.

By simply adding the trait and specifying the required properties, your model becomes equipped to capture and utilize system activity logs seamlessly within the helpdesk modules.

These are the properties defined in the models::

1. $logName[] : First element depicts the name of the module on which activity is getting performed and second element is used while creating description for the activity.

Example : protected array $logName = [‘departments’, ‘department’];
Here the first parameter is defined for the Module name and the second parameter is defined in the Description.


2. $logFields : This depicts the columns for which activity needs to be logged.

Example : protected array $logFields = [‘name’, ‘type_id’, ‘outgoing_email_id’, ‘business_hour_id’];


3. $logUrl[] : First Element depicts the prefix url and second element depicts the suffix url for viewing the module we want to log the activity
Here we are using two parameters for showing the url because between these two parameters we are storing the $activity->subject_id as shown in the below code
” <a href='”. config(‘app.url’) . head($this->logUrl) . $activity->subject_id . last($this->logUrl) . “‘>”

Example : protected array $logUrl = [‘/admin/label/’, ‘/edit’];
Here id will be stored between these two parameters like this -> faveo/public/admin/label/1/edit

4. $logNameColumn : In $lognameColum, the model column data gets picked but it can vary froim table to table

Example : protected string $logNameColumn = ‘title’;
Like for labels table -> title column will get picked,
for user table -> user_name column will get picked,
for department table -> name column will get picked,
for helptopic table -> topic column will get picked.

5. getMappings method : This is used to manipulate the columns name to user readable format for the detailed description in system level activity logs.
This method defines attribute mappings for model fields. This method defines how specific fields in the model should be displayed when generating a user-readable view.
It maps field names to their corresponding human-readable representations.

Example :

protected function getMappings()
{
    return [
      'type_id' => ['type', fn($type) => $type === 1 ? trans('lang.public') :          trans('lang.private')],
      'outgoing_email_id' => ['outgoing email', fn ($id) => Emails::where('id', $id)?->value('email_address')],
      'business_hour_id' => ['business hour', fn ($id) => BusinessHours::where('id', $id)?->value('name')],
    ];
}


Now the following functions of the System activity logs trait will be called in the order they are mentioned below to format and log the activity in the activity_log table


1. getActivitylogOptions method : This method is a part of the Activitylog package and is called whenever any activity is happening.
In this method, multiple methods are chained with each other

i. defaults() : This method is likely setting default options for the activity log. It could include default attributes or configuration settings for logging activities.

ii. logOnly($this->logFields) : This method specifies that only specific fields should be logged. The $this->logFields variable likely contains an array of fields that should be included in the log. This is useful for filtering out unnecessary information and keeping the log concise.

iii. logOnlyDirty() : This method specifies that only changes to model attributes (fields) should be logged. It ensures that only the attributes that have been modified are recorded in the activity log.

iv. dontSubmitEmptyLogs() This method likely prevents logging activities when there is no significant change or action. For example, if an update operation is performed on a model, but none of its attributes are modified, this method would prevent logging it as an activity.

v. useLogName(trans(‘lang.’ . head($this->logName))) : This method sets the name of the log entry. This allows for flexible and localized log names based on language files.

Overall, these methods are used to customize the behavior of the activity logging feature provided by the Spatie Laravel-activitylog package. They allow developers to fine-tune what gets logged, under what conditions, and with what names.

2. tapActivity method : This method is called to format the data before it is getting stored in the activity_log table.
There are two parameters in this method and both of the parameters are coming from the package

a. $activity : This parameter contains information about the user who executed the action, including the name of the module where the action occurred, and the attributes included by the user within that module.
Example :

[ 
    "log_name" => "Departments" 
    "properties" => "{
        "attributes": {"type_id":1,"business_hour_id":0},
        "old":   {"type_id":0,"business_hour_id":1}
    }" 
    "causer_id" => 1 
    "causer_type" => "App\User" 
    "batch_uuid" => null 
    "event" => "updated" 
    "subject_id" => 4 
    "subject_type" => "App\Model\helpdesk\Agent\Department" 
]


b. $eventName : Here whatever event is getting performed will show in this parameter
Like “created”, “updated”, “deleted”.

Two methods are getting called from this function
i) generateDescriptionForLogs method
ii) tapActivityLogs method

3. generateDescriptionForLogs method : This method also takes 2 parameters named $activity which is the unchanges $actvity object and $eventName depicting the type if action getting performed created, updated or deleted.
Now 2 methods are getting called from this
i) modifyLogUrl method – This method is used to modify the log url dynamically based on the $logUrl[] property defined in the desired model.
ii) setDescriptionForLogs method

4. setDescriptionForLogs method : This method also takes 2 parameters named $activity which is the unchanges $actvity object and $eventName depicting the type if action getting performed created, updated or deleted.

For deleted event the description is created like this – Department test has been deleted.
where Department is coming from the second element of $logName[] specified in the model,
test is coming from $activity->subject->{$this->logNameColumn} where subject is a MorphTo
relation used to fetch information about the item getting deleted and $this->logNameColumn
is defined in the model and deleted is the event that is happening.

For created or updated event, description is created like this – Department test has been created/updated. Here test is a link that navigates to this particular department page.

To generate the url we use the $logUrl variable defined in the department model.
config(‘app.url’) . head($this->logUrl) . $activity->subject_id . last($this->logUrl).
Here $activity->subject_id gives the id of the department that is getting updated or created.

test link – <a href=”https://meera.localhost/faveo/public/admin/department/1/”


5. tapActivityLogs method : Formats certain attributes in the $activity object for logging purposes based on specified mappings.
It takes a parameter $activity object in which the description has been added which we added in the above method.

$activity object –

[
    "log_name" => "Departments"
    "properties" => "{
           "attributes": {
                "name":"test", "type_id":1,
                "outgoing_email_id":0, "business_hour_id":1
           }
    }"
    "causer_id" => 1
    "causer_type" => "App\User"
    "batch_uuid" => null
    "event" => "created"
    "subject_id" => 4
    "subject_type" => "App\Model\helpdesk\Agent\Department"
    "description" => "Department test has been created"
]

Now here we will change the attribute values to a more meaningful information using the formatLoggingAttributes Method. For example we have a value of 1 in type_id so we will change it to public based on the getMappings method.

getMappingsMethod() –

protected function getMappings()
{
   return [
      'type_id' => ['type', fn($type) => $type === 1 ? trans('lang.public') :    trans('lang.private')],
      'outgoing_email_id' => ['outgoing email', fn ($id) => Emails::where('id', $id)?-   >value('email_address')],
      'business_hour_id' => ['business hour', fn ($id) => BusinessHours::where('id', $id)?->value('name')],
   ];
}

6. formatLoggingAttributes Method: This method is used to format the attribte values based on the getMappings method defined in the model. It takes 2 parameters first is the complete attributes and second id the getMappingsMethod. Inside this method we loop over the attributes and use the getMapping method to make the values more meaningful.

$attributes –

[ 
    "name" => "test2"
    "type_id" => 1
    "outgoing_email_id" => 0
    "business_hour_id" => 1
]

Note – When we are updating a module at that time we have another collection present in the properties key of $activity object by the name “old” which sotres the original values of the columns before getting updated.

Example : I am updating the name of the department from test to test department, in this case the $activtiy object looks like this

[
    "log_name" => "Departments"
    "properties" => "{
        "attributes":{"name":"test department"},
        "old":{"name":"test"}
    }"
    "causer_id" => 1
    "causer_type" => "App\User"
    "batch_uuid" => null
    "event" => "updated"
    "subject_id" => 4
    "subject_type" => "App\Model\helpdesk\Agent\Department"
].

The only difference is the addition of old key in properties in which name holds the original value of name before getting updated and in attributes name holds the value of current name after updating.

Final description – Department test department has been updated