Activity Logging System - Cart Activities
Overview
This document explains how cart-related activities are logged using Spatie Activity Log and displayed in Filament.
Where to access
Activity logs are viewed in the EasyOTC admin panel:
| Surface | Staging URL | Local URL |
|---|---|---|
| Admin panel (Activity Logs) | https://stage-api.easyotc.com/admin | http://localhost:8000/admin |
You must sign in with a user that holds the OTC_ONE_ADMIN role (see app/Enums/RoleEnum.php). See /access for the full URL and credential list.
Where this lives
- Logging service:
app/Services/AuditService.php - Auto-logging in cart flows:
app/Services/CartItemService.php - Activity enum:
app/Enums/ActivitiesEnum.php - Filament resources:
app/Filament/Resources/ActivityResource.php,app/Filament/Resources/Products/RelationManagers/ActivitiesRelationManager.php,app/Filament/Resources/Users/RelationManagers/CartActivitiesRelationManager.php
Architecture & Design Decisions
The Challenge
When logging cart activities, we have 4 models involved:
- User (Agent) - Who performs the action
- Member - Whose cart is being modified
- Cart - The shopping cart container
- Product - The item being added/removed/updated
Spatie Activity Log only allows:
- One
causer(who did it) - One
subject(what was affected) - Properties (additional data stored as JSON)
The Solution
We strategically chose which model to use as the subject based on query patterns:
| Activity | Causer | Subject | Why Subject? |
|---|---|---|---|
| Cart Item Added | Agent | Product | Query "cart history for this product" |
| Cart Item Updated | Agent | Product | Same - product is the focus |
| Cart Item Removed | Agent | Product | Same - product is the focus |
| Cart Created | Agent | Cart | Cart is the primary entity |
Key Insight: We store all other IDs (member_id, cart_id, agent_id) in the properties JSON field for cross-referencing.
Database Structure
activity_log table (from Spatie):
├── id
├── log_name (e.g., 'cart_item_added')
├── description (human-readable)
├── subject_type (e.g., 'App\Models\Product')
├── subject_id (Product ID)
├── causer_type ('App\Models\User')
├── causer_id (Agent/User ID)
├── properties (JSON with cart_id, member_id, quantity, etc.)
└── created_atImplementation
1. Logging Methods in AuditService
logCartItemAdded()
$auditService->logCartItemAdded(
product: $product, // Subject
agent: $agent, // Causer
cartId: $cart->id, // In properties
memberId: $cart->member_id, // In properties
quantity: $quantity, // In properties
purseId: $purseId, // In properties
);Stored As:
subject= Product modelcauser= Agent/User modelproperties={cart_id, member_id, agent_id, quantity, purse_id, unit_price, total_price}
logCartItemUpdated()
Tracks quantity changes with old/new values.
logCartItemRemoved()
Logs when items are removed from cart.
logCartCreation()
Logs when a new cart is created for a member.
2. Automatic Logging in CartItemService
The CartItemService automatically logs activities:
public function addItem(Cart $cart, Product $product, ?int $purseId, int $quantity): CartItem
{
// ... add logic ...
// Automatically log the addition
$this->auditService->logCartItemAdded(
product: $product,
agent: request()->user(),
cartId: $cart->id,
memberId: $cart->member_id,
quantity: $quantity,
purseId: $purseId
);
}No manual logging needed - it's built into the service methods!
3. Model Relationships
Product Model
public function activities()
{
return $this->morphMany(Activity::class, 'subject');
}User Model
public function causedActivities()
{
return $this->morphMany(Activity::class, 'causer');
}Viewing Activity in Filament
1. Product Cart History
When viewing a Product in Filament:
Products → View Product → "Cart Activity History" TabShows:
- ✅ All times this product was added to carts
- ✅ Quantity updates for this product
- ✅ Times this product was removed
- ✅ Which agent performed each action
- ✅ Which member's cart it was
- ✅ When it happened
Filament File: app/Filament/Resources/Products/RelationManagers/ActivitiesRelationManager.php
2. Agent Activity
When viewing a User/Agent in Filament:
Users → View User → "Cart Activity (Agent Actions)" TabShows:
- ✅ All cart actions performed by this agent
- ✅ Carts created by this agent
- ✅ Items added/updated/removed by this agent
- ✅ Which members they served
- ✅ Which products they worked with
Filament File: app/Filament/Resources/Users/RelationManagers/CartActivitiesRelationManager.php
3. Global Activity Log
View ALL activities across the system:
Logs → Activity LogsFilter by:
- Log name (cart_item_added, cart_item_updated, etc.)
- Date range
- Subject type (Product, Cart, etc.)
- Event type
Filament File: app/Filament/Resources/ActivityResource.php
Query Examples
Find All Cart Additions for a Product
use Spatie\Activitylog\Models\Activity;
use App\Enums\ActivitiesEnum;
$product = Product::find(1);
$additions = Activity::query()
->where('subject_type', Product::class)
->where('subject_id', $product->id)
->where('log_name', ActivitiesEnum::CART_ITEM_ADDED->value)
->get();Find All Actions by an Agent
$agent = User::find(5);
$actions = Activity::query()
->where('causer_type', User::class)
->where('causer_id', $agent->id)
->whereIn('log_name', [
ActivitiesEnum::CART_CREATION->value,
ActivitiesEnum::CART_ITEM_ADDED->value,
ActivitiesEnum::CART_ITEM_UPDATED->value,
ActivitiesEnum::CART_ITEM_REMOVED->value,
])
->get();Find All Activities for a Specific Member
$memberId = 10;
$memberActivities = Activity::query()
->whereIn('log_name', [
ActivitiesEnum::CART_CREATION->value,
ActivitiesEnum::CART_ITEM_ADDED->value,
ActivitiesEnum::CART_ITEM_UPDATED->value,
ActivitiesEnum::CART_ITEM_REMOVED->value,
])
->where('properties->member_id', $memberId)
->get();Find All Activities for a Specific Cart
$cartId = 25;
$cartActivities = Activity::query()
->where('properties->cart_id', $cartId)
->orWhere(function ($query) use ($cartId) {
$query->where('subject_type', Cart::class)
->where('subject_id', $cartId);
})
->get();Properties Schema
Cart Item Added
{
"cart_id": 123,
"member_id": 456,
"agent_id": 789,
"quantity": 2,
"purse_id": 10,
"unit_price": 1500,
"total_price": 3000
}Cart Item Updated
{
"cart_id": 123,
"member_id": 456,
"agent_id": 789,
"old_quantity": 2,
"new_quantity": 5,
"quantity_change": 3,
"purse_id": 10,
"unit_price": 1500
}Cart Item Removed
{
"cart_id": 123,
"member_id": 456,
"agent_id": 789,
"quantity": 2,
"cart_item_id": 999,
"unit_price": 1500,
"total_price": 3000
}Cart Creation
{
"member_id": 456,
"agent_id": 789,
"cart_uuid": "550e8400-e29b-41d4-a716-446655440000",
"carrier_id": 5
}Activity Enum
All cart activities are defined in app/Enums/ActivitiesEnum.php:
case CART_CREATION = 'cart_creation';
case CART_ITEM_ADDED = 'cart_item_added';
case CART_ITEM_UPDATED = 'cart_item_updated';
case CART_ITEM_REMOVED = 'cart_item_removed';Each has:
label()- Display namecolor()- Filament badge coloricon()- Heroicon for display
Benefits
✅ Product-centric queries - Easily see cart history for any product ✅ Agent accountability - Track all actions by each agent ✅ Member activity - View all cart actions for a member ✅ Comprehensive audit trail - Full history with timestamps ✅ Filament integration - Beautiful UI without custom queries ✅ Automatic logging - No manual calls needed in controllers ✅ JSON properties - Flexible data storage for cross-referencing
Best Practices
- Always log through
AuditService- Don't callactivity()directly - Use typed enums - Use
ActivitiesEnumfor consistency - Include context in properties - Store IDs for cross-referencing
- Descriptive messages - Make
descriptionhuman-readable - Query via relationships - Use
$product->activities()when possible
Future Enhancements
If needed, you could add:
- Statistics/analytics dashboards
- Activity export functionality
- Advanced filtering by date ranges
- Member-specific activity views in MemberResource
- Cart-specific activity views in CartResource
- Real-time activity notifications
- Activity rollback/undo features
Related Files
app/Services/AuditService.php- Logging methodsapp/Services/CartItemService.php- Automatic loggingapp/Enums/ActivitiesEnum.php- Activity type definitionsapp/Models/Product.php- Activities relationshipapp/Models/User.php- Caused activities relationshipapp/Filament/Resources/Products/RelationManagers/ActivitiesRelationManager.phpapp/Filament/Resources/Users/RelationManagers/CartActivitiesRelationManager.phpapp/Filament/Resources/ActivityResource.php- Global activity log