Archive, Delete, and Restore Flow.
This file explains how archiving, soft delete, and restore currently work in the project.Table of Contents
- Overview
- The Two Different States
- User Archive Flow
- User Delete Flow
- User Restore Flow
- Self Delete Flow
- Role of the
ArchivableTrait - Important Testing Notes
1. Overview
This project uses two separate mechanisms:- custom archive state through
archived_at - Laravel soft delete through
deleted_at
2. The Two Different States
Archive State
- controlled by the custom
Archivabletrait - stored in
archived_at - archived records are hidden by the trait’s global scope
- archived records can be brought back with
unarchive()
Soft Delete State
- controlled by Laravel
SoftDeletes - stored in
deleted_at - soft-deleted records are not physically removed from the database
- soft-deleted records can be restored with Laravel
restore()
3. User Archive Flow
Endpoint:Success Response
- the controller finds the user
- it calls
$user->archive() - the
Archivabletrait setsarchived_at = now()
4. User Delete Flow
Endpoint:Success Response
- despite the response message, the controller calls:
- this is a Laravel soft delete
- the row is not hard-deleted from the database
- it can still be restored later
- this endpoint only works on users fetched from
User::onlyArchived() - so the intended flow is usually:
- archive the user first
- then call delete
5. User Restore Flow
There are two different restore behaviors in the project.Unarchive Archived User
Endpoint:Success Response
archived_at
Restore Soft-Deleted User
Endpoint:Success Response
deleted_at
6. Self Delete Flow
Endpoint:Request JSON
Success Response
- password is verified
- all current personal access tokens are deleted
- the user row is soft-deleted with Laravel
delete()
- admins
- super-admins
- instructors
7. Role of the Archivable Trait
The custom trait lives in:
- adds a global scope that hides archived rows where
archived_atis not null - provides
archive() - provides
unarchive() - provides
scopeOnlyArchived() - provides
scopeWithArchived()
- normal queries may hide archived rows automatically
onlyArchived()is required when you want archived rows back
8. Important Testing Notes
archiveanddeleteare different operations.unarchiveandrestoreare different operations.- the message
User force deleted successfully.is misleading because the controller performs a soft delete. - if you want to test the full admin lifecycle in Postman, a safe order is:
POST /api/user/{id}/archivePOST /api/user/{id}/unarchivePOST /api/user/{id}/archiveDELETE /api/user/{id}/deletePOST /api/users/{userId}/restore