Skip to main content
Workspaces provide an additional layer of organization within a tenant, allowing multiple business units, departments, or locations to operate independently while sharing the same tenant database.

Workspaces vs Tenants

Understanding the hierarchy:
  • Tenant: Top-level isolation (separate databases, accessed via subdomain)
  • Workspace: Logical separation within a tenant (same database, filtered by workspace_id)
Tenant (acme.optiflow.com.do)
├── Workspace: Main Office
├── Workspace: Warehouse
└── Workspace: Retail Store
While tenants have complete database isolation, workspaces share the same database but maintain logical separation through workspace-scoped queries.

Workspace Model

The App\Models\Workspace model (app/Models/Workspace.php:65) defines workspace properties:
// Key Properties
$workspace->name;          // Workspace name
$workspace->slug;          // URL-friendly identifier
$workspace->description;   // Optional description
$workspace->owner_id;      // User who owns this workspace
$workspace->is_active;     // Active status
$workspace->settings;      // JSON settings array

Creating Workspaces

Using CreateWorkspaceAction

Workspaces are created using the CreateWorkspaceAction (app/Actions/CreateWorkspaceAction.php):
1

Provide Workspace Details

Required information:
  • Name (automatically generates slug)
  • Owner (user who will own the workspace)
  • Optional: description, address, phone
2

Workspace is Created

The action creates the workspace and automatically:
  • Generates a unique slug from the name
  • Sets the creator as the owner
  • Marks the workspace as active
3

Add Initial Members

Use AssignUserToWorkspaceAction to add users:
$action->handle($workspace, $user, $role);

Via API/Controller

The workspace creation flow is handled by workspace controllers in app/Http/Controllers/.

Workspace Isolation

Data is isolated by workspace through several mechanisms:

Database Scoping

Most models are scoped to the current workspace:
// Invoices belong to a workspace
$workspace->invoices; // Only invoices for this workspace

// Prescriptions are workspace-scoped
$workspace->prescriptions;

// Document subtypes can be workspace-preferred
$workspace->documentSubtypes;

Global Scopes

Many models apply automatic workspace filtering when queried in a workspace context.
Always verify that queries include workspace filtering to prevent data leakage between workspaces.

User-Workspace Assignments

Assigning Users to Workspaces

Users can belong to multiple workspaces within a tenant:
// Add user to workspace with role
$workspace->addUser($user, 'member');

// Check if user has access
$workspace->hasUser($user); // returns boolean

// Remove user from workspace
$workspace->removeUser($user);

Workspace Roles

Users have roles within each workspace (stored in pivot table):
  • owner: Full control over workspace
  • admin: Administrative access
  • member: Standard user access
  • Custom roles can be defined
Workspace roles are separate from global user roles. A user can be an admin in one workspace and a member in another.

Workspace Switching

Users can switch between their assigned workspaces:

Current Workspace

Each user has a current_workspace_id that determines their active workspace:
// Get current workspace
$currentWorkspace = $user->currentWorkspace;

// Switch workspace
$user->switchToWorkspace($workspace);

// Check access before switching
if ($user->hasAccessToWorkspace($workspace)) {
    $user->switchToWorkspace($workspace);
}

Using SwitchWorkspaceAction

The recommended way to switch workspaces:
use App\Actions\SwitchWorkspaceAction;

$action = new SwitchWorkspaceAction();
$action->handle($user, $workspace);
This action:
  1. Verifies user has access to the workspace
  2. Updates current_workspace_id
  3. Clears workspace-specific cache
  4. Updates user session

Managing Workspace Members

Adding Members

1

Invite User

Create a user invitation (if user doesn’t exist in tenant):
// UserInvitation model handles invitations
2

Assign to Workspace

Use AssignUserToWorkspaceAction:
$action->handle($workspace, $user, $role);
3

Set Permissions

Configure workspace-specific permissions using Spatie Permission package

Removing Members

use App\Actions\RemoveWorkspaceMemberAction;

$action->handle($workspace, $user);
Workspace owners cannot be removed from their own workspace. Transfer ownership first if needed.

Workspace Settings

Workspaces can store custom settings in the settings JSON column:
// Store settings
$workspace->settings = [
    'default_currency' => 'DOP',
    'tax_rate' => 18,
    'invoice_prefix' => 'INV',
];
$workspace->save();

// Access settings
$taxRate = $workspace->settings['tax_rate'] ?? 18;

Workspace-Specific Configurations

Document Subtypes

Workspaces can have preferred document subtypes (NCF sequences):
// Get preferred document subtype
$preferredSubtype = $workspace->getPreferredDocumentSubtype();

// Set preferred document subtype
use App\Actions\SetWorkspacePreferredDocumentSubtypeAction;
$action->handle($workspace, $documentSubtype);
See Document Subtypes for more details.

Company Details

While company details are tenant-wide in the current implementation, they’re typically used within workspace context for invoices and documents. See Company Details Configuration for more information.

Deleting Workspaces

Using DeleteWorkspaceAction

use App\Actions\DeleteWorkspaceAction;

$action = new DeleteWorkspaceAction();
$action->handle($workspace);
Deleting a workspace will:
  • Remove all user-workspace associations
  • Orphan workspace-specific data (invoices, prescriptions, etc.)
  • This operation cannot be undone
Consider archiving instead of deleting by setting is_active = false.

Best Practices

  1. Naming Convention: Use clear, descriptive workspace names (e.g., “Main Office”, “Warehouse - North”)
  2. Access Control: Regularly audit workspace member lists
  3. Default Workspace: Set a sensible default workspace for new users
  4. Workspace Scoping: Always filter queries by workspace when appropriate
  5. Settings Management: Document custom workspace settings in code comments

Build docs developers (and LLMs) love