Skip to main content
Back to ScopeForged

ScopeForged Documentation

Technical documentation, guides, and feature references for the ScopeForged client portal.

Core Business Features/Project Management

Project Management Guide

Last Updated: 2026-01-12 Status: Implemented Plan Reference: 006-project-management.md, 071-project-management-improvement.md


Overview

The Project Management system allows administrators to create and manage projects for clients. Projects track work progress through status workflows, contain files, and provide a central hub for client collaboration.


Table of Contents

  1. Accessing Projects
  2. Features
  3. Project Status Workflow
  4. How to Use
  5. Technical Architecture
  6. Related Features

Accessing Projects

Access PointLocationURLRole
All ProjectsAdmin sidebar/admin/projectsAdmin
Create ProjectProjects page/admin/projects/createAdmin
View ProjectProject row/admin/projects/{id}Admin
Edit ProjectProject detail/admin/projects/{id}/editAdmin
My ProjectsPortal sidebar/portal/projectsClient User
Project DetailPortal/portal/projects/{id}Client User

Permissions

ActionAdminClient User
View all projects
View client's projects
Create project
Edit project
Delete project
Upload files
Download files✅ (visible only)

Features

Project Details

  • Project name and description
  • Client association
  • Status tracking
  • Start and due dates
  • Budget tracking
  • Notes and internal comments

Project Status

  • Draft → Active → Completed → Archived workflow
  • Color-coded status badges
  • Status change logging

Project Files

  • File uploads and organization
  • Version tracking
  • Client visibility controls
  • Download tracking

Project Statistics

  • File count
  • Time tracked (if enabled)
  • Invoice associations
  • Activity history

Project Status Workflow

Status Enum

Location: app/Enums/ProjectStatus.php

StatusValueDescriptionColor
DraftdraftNot yet startedGray
ActiveactiveCurrently in progressBlue
CompletedcompletedWork finishedGreen
ArchivedarchivedClosed/historicalYellow

Status Transitions

Draft → Active → Completed → Archived
         ↑          ↓
         ←──────────┘ (reopen)

Status Methods

// Check status
$project->status->isDraft();
$project->status->isActive();
$project->status->isCompleted();
$project->status->isArchived();

// Get display values
$project->status->label();  // "Active"
$project->status->color();  // "blue"

How to Use

Creating a New Project

  1. Navigate to Admin → Projects
  2. Click "Create Project"
  3. Fill in required fields:
    • Project Name (required)
    • Client (required, select from dropdown)
  4. Fill in optional fields:
    • Description
    • Start Date
    • Due Date
    • Budget
    • Notes
  5. Set initial status (default: Draft)
  6. Click "Create Project"

Viewing Project Details

  1. Navigate to Admin → Projects or Portal → Projects
  2. Click on project name or "View"
  3. View project information:
    • Basic details
    • Client information
    • File list
    • Activity timeline
    • Related invoices

Editing a Project

  1. Navigate to Admin → Projects → [Project]
  2. Click "Edit" button
  3. Modify fields as needed
  4. Click "Update Project"

Changing Project Status

  1. Navigate to Admin → Projects → [Project]
  2. Click "Edit" or use status dropdown
  3. Select new status
  4. Save changes

Note: Status changes are logged in activity history.

Deleting a Project

  1. Navigate to Admin → Projects → [Project]
  2. Click "Delete" button
  3. Confirm deletion

Warning: Deleting a project removes all associated files.

Managing Project Files

See File Sharing Guide for detailed file management.

  1. Navigate to project detail page
  2. Click "Upload File" or drag-and-drop
  3. Set visibility (admin-only or client-visible)
  4. Files appear in project file list

Advanced Features

Project Templates

Create reusable templates with predefined milestones.

Creating a Template

use App\Models\ProjectTemplate;

$template = ProjectTemplate::create([
    'name' => 'Website Redesign',
    'description' => 'Standard website redesign project',
    'default_status' => 'draft',
    'milestones' => [
        ['title' => 'Discovery & Planning', 'days_offset' => 7],
        ['title' => 'Design Phase', 'days_offset' => 21],
        ['title' => 'Development', 'days_offset' => 42],
        ['title' => 'Testing & Launch', 'days_offset' => 56],
    ],
    'is_active' => true,
    'created_by' => auth()->id(),
]);

Applying a Template to a Project

use App\Services\ProjectTemplateService;

$service = new ProjectTemplateService();

// Apply to existing project
$project = $service->applyTemplate($project, $template);

// Create new project from template
$project = $service->createFromTemplate([
    'client_id' => $client->id,
    'name' => 'Client Website Redesign',
], $template);

Creating a Template from a Project

$template = $service->createFromProject(
    $project,
    'My Template Name',
    auth()->id()
);

Project Cloning

Duplicate a project with its plans and milestones.

  1. Navigate to Admin → Projects → [Project]
  2. Click "Clone" button
  3. Review clone preview showing what will/won't be cloned
  4. Customize new project name and client
  5. Click "Clone Project"
use App\Services\ProjectCloneService;

$service = new ProjectCloneService();

// Preview what will be cloned
$preview = $service->preview($project);
// Returns: ['project' => [...], 'will_clone' => [...], 'will_not_clone' => [...]]

// Clone the project
$clonedProject = $service->clone($project);

// Clone with overrides
$clonedProject = $service->clone($project, [
    'name' => 'Custom Name',
    'client_id' => $otherClient->id,
]);

What gets cloned:

  • Project details
  • Project plans
  • Milestones (reset to "Not Started")

What does NOT get cloned:

  • Files
  • Conversations
  • Approvals

Bulk Status Operations

Update multiple project statuses at once via configuration.

Configuration

Project management settings in config/project-management.php:

return [
    'templates' => [
        'enabled' => true,
        'max_milestones' => 20,
    ],
    'cloning' => [
        'enabled' => true,
        'include_plans' => true,
        'include_milestones' => true,
        'reset_milestone_status' => true,
    ],
    'bulk' => [
        'enabled' => true,
        'max_projects' => 50,
        'operations' => [
            'activate' => true,
            'complete' => true,
            'archive' => true,
            'delete' => true,
        ],
    ],
    'defaults' => [
        'status' => 'draft',
    ],
];

Technical Architecture

Model

Location: app/Models/Project.php

class Project extends Model
{
    protected $fillable = [
        'client_id',
        'name',
        'description',
        'status',
        'start_date',
        'due_date',
        'budget',
        'notes',
    ];

    protected $casts = [
        'status' => ProjectStatus::class,
        'start_date' => 'date',
        'due_date' => 'date',
        'budget' => 'decimal:2',
    ];
}

Relationships

// Project model
public function client(): BelongsTo
{
    return $this->belongsTo(Client::class);
}

public function files(): HasMany
{
    return $this->hasMany(ProjectFile::class);
}

public function invoices(): HasMany
{
    return $this->hasMany(Invoice::class);
}

public function timeEntries(): HasMany
{
    return $this->hasMany(TimeEntry::class);
}

Controller

Location: app/Http/Controllers/Admin/ProjectController.php

MethodRouteDescription
index()GET /admin/projectsList projects
create()GET /admin/projects/createCreate form
store()POST /admin/projectsCreate project
show()GET /admin/projects/{project}View project
edit()GET /admin/projects/{project}/editEdit form
update()PUT /admin/projects/{project}Update project
destroy()DELETE /admin/projects/{project}Delete project

Routes

// Admin routes
Route::prefix('admin')->middleware(['auth', 'admin'])->group(function () {
    Route::resource('projects', Admin\ProjectController::class);
});

// Portal routes
Route::prefix('portal')->middleware(['auth'])->group(function () {
    Route::get('projects', [Portal\ProjectController::class, 'index'])->name('portal.projects.index');
    Route::get('projects/{project}', [Portal\ProjectController::class, 'show'])->name('portal.projects.show');
});

Database Schema

Table: projects

ColumnTypeDescription
idbigintPrimary key
client_idbigintForeign key to clients
namestringProject name
descriptiontextProject description
statusstringStatus enum value
start_datedateProject start date
due_datedateProject due date
budgetdecimalBudget amount
notestextInternal notes
created_attimestampCreation date
updated_attimestampLast update

Views

ViewPathPurpose
Indexresources/views/admin/projects/index.blade.phpProject list
Createresources/views/admin/projects/create.blade.phpCreate form
Showresources/views/admin/projects/show.blade.phpProject details
Editresources/views/admin/projects/edit.blade.phpEdit form
Portal Indexresources/views/portal/projects/index.blade.phpClient's projects
Portal Showresources/views/portal/projects/show.blade.phpClient's view

Form Validation

// app/Http/Requests/ProjectRequest.php
public function rules(): array
{
    return [
        'client_id' => 'required|exists:clients,id',
        'name' => 'required|string|max:255',
        'description' => 'nullable|string',
        'status' => 'required|in:draft,active,completed,archived',
        'start_date' => 'nullable|date',
        'due_date' => 'nullable|date|after_or_equal:start_date',
        'budget' => 'nullable|numeric|min:0',
        'notes' => 'nullable|string',
    ];
}

Scopes and Query Helpers

Available Scopes

// By status
Project::status(ProjectStatus::Active)->get();

// Active projects only
Project::active()->get();

// For a specific client
Project::forClient($client)->get();

// With relationships
Project::with(['client', 'files'])->get();

// With counts
Project::withCount('files')->get();

// Overdue projects
Project::overdue()->get();

// Search
Project::search('website redesign')->get();

Dependencies

FeatureRelationship
Client ManagementProjects belong to clients
AuthorizationProjectPolicy controls access

Complementary Features

FeatureDescription
File SharingProject file management
InvoicingProject-related invoices
Time TrackingTrack time on projects
Activity LoggingProject change history
Workflow AutomationAutomated status updates

Best Practices

For Administrators

  1. Use clear project names that identify the work
  2. Set realistic due dates for expectations
  3. Update status regularly to reflect progress
  4. Archive completed projects to keep lists clean
  5. Use description for client-visible summary
  6. Use notes for internal information

For Developers

  1. Use ProjectStatus enum instead of strings
  2. Eager load client relationship for lists
  3. Use policies for all authorization
  4. Scope queries for client users

Troubleshooting

IssueSolution
Project not visible to clientCheck client association
Can't change statusVerify admin permissions
Files not showingCheck file visibility settings
Due date validation errorEnsure due date is after start date

See Also