Skip to main content
Back to ScopeForged

ScopeForged Documentation

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

Search & Analytics/Reports

Reports & Data Export Guide

Last Updated: 2026-01-18 Status: Enhanced with Query Optimization, Progress Tracking & Export Architecture Plan Reference: 051-reports-enhancement.md, 083-reports-improvement.md, 143-report-service-architecture.md


Overview

The Reports system provides comprehensive reporting capabilities for analyzing business data. Features include:

  • 11 Built-in Report Types - Financial, Operational, and Activity reports
  • Custom Report Builder - Create user-defined reports with dynamic queries
  • 13 Chart Types - Visual data representation with Chart.js integration
  • Report Scheduling - Automated report generation with flexible frequencies
  • Report Sharing - Token-based access with passwords and permissions
  • Multiple Export Formats - CSV, PDF, Excel exports

Table of Contents

  1. Accessing Reports
  2. Built-in Report Types
  3. Custom Reports
  4. Chart Visualization
  5. Export Formats
  6. Report Scheduling
  7. Report Sharing
  8. Technical Architecture
  9. API Reference
  10. Related Features

Accessing Reports

Access PointLocationURLRole
Reports DashboardAdmin sidebar/admin/reportsAdmin
Report TypesRegistry-based/admin/reports/type/{type}Admin
Custom ReportsReports menu/admin/custom-reportsAdmin
Report SchedulesReports menu/admin/report-schedulesAdmin
Report HistoryReports menu/admin/reports/historyAdmin

Permissions

ActionAdminClient User
View all reportsYesNo
Generate reportsYesNo
Create custom reportsYesNo
Schedule reportsYesNo
Share reportsYesLimited
Export dataYesLimited

Built-in Report Types

Reports are organized into three categories, managed by the ReportRegistry.

Financial Reports

ReportType KeyDescriptionKey Metrics
Revenue ReportrevenueTrack revenue over timeTotal revenue, period comparisons, client breakdown
Profitability ReportprofitabilityProfit margin analysisGross profit, expenses, net margin
Cash Flow Reportcash_flowPayment inflows/outflowsCash in, cash out, net cash flow
Aging ReportagingReceivables by ageCurrent, 30/60/90+ days overdue
Tax Summary Reporttax_summaryTax collected/owedTax by rate, period, region

Operational Reports

ReportType KeyDescriptionKey Metrics
Project Healthproject_healthProject status overviewOn-time %, budget variance, status breakdown
Resource Utilizationresource_utilizationTeam capacity analysisBillable hours, utilization %, availability
Time Trackingtime_trackingTime entry analysisHours by project, client, user
Client Retentionclient_retentionRetention metricsChurn rate, LTV, retention by cohort

Activity Reports

ReportType KeyDescriptionKey Metrics
User Activityuser_activityActions by userLogins, edits, file activity
Client Engagementclient_engagementClient interaction metricsPortal visits, file downloads, response times

Generating a Report

  1. Navigate to Admin → Reports
  2. Select report type from the dashboard or dropdown
  3. Configure parameters:
    • Date Range: Preset or custom dates
    • Filters: Client, status, user filters
    • Grouping: By client, project, period
    • Chart Type: Optional visualization
  4. Click "Preview" to see data on screen
  5. Click "Generate" to create downloadable report

Custom Reports

Custom reports allow users to build their own reports by selecting data sources, columns, filters, and aggregations.

Data Sources

SourceDescriptionAvailable Columns
invoicesInvoice datainvoice_number, total, tax, status, issue_date, due_date, paid_at
projectsProject dataname, status, budget, start_date, end_date, created_at
clientsClient datacompany_name, email, phone, address, is_active, created_at
time_entriesTime trackingdescription, duration, date, billable, rate, user_id

Creating a Custom Report

  1. Navigate to Admin → Custom Reports
  2. Click "Create Report"
  3. Configure:
    • Name: Report identifier
    • Data Source: Select from available sources
    • Columns: Choose which columns to include
    • Filters: Add filter conditions
    • Grouping: Optional group by column
    • Aggregations: Sum, count, average functions
    • Sorting: Order by column
  4. Click "Save Report"

Filter Operators

OperatorDescriptionExample
=Equalsstatus = 'active'
!=Not equalsstatus != 'draft'
>Greater thantotal > 1000
>=Greater than or equaltotal >= 500
<Less thantotal < 10000
<=Less than or equaltotal <= 5000
likeContains patternname like '%Inc%'
not_likeDoes not containname not_like '%Test%'
starts_withStarts with stringname starts with 'Acme'
ends_withEnds with stringemail ends with '.com'
inIn array of valuesstatus in ['active', 'completed']
not_inNot in arraystatus not_in ['draft', 'archived']
betweenBetween two valuescreated_at between ['2024-01-01', '2024-12-31']
is_nullIs nullpaid_at is_null
is_not_nullIs not nullpaid_at is_not_null

Aggregation Functions

FunctionDescriptionExample
sumSum of valuesSum of invoice totals
countCount of recordsNumber of invoices
avgAverage valueAverage invoice amount
minMinimum valueLowest invoice total
maxMaximum valueHighest invoice total

Custom Report Actions

ActionDescription
ViewExecute and display results
EditModify report configuration
DuplicateCreate copy with "(Copy)" suffix
ExportDownload as CSV, PDF, or Excel
ShareCreate shareable link
DeleteRemove report

Chart Visualization

Reports support 13 chart types via the ChartBuilder service for visual data representation.

Available Chart Types

TypeKeyDescriptionBest For
Bar ChartbarVertical bar chartComparing categories
Line ChartlineLine graphTrends over time
Pie ChartpieCircular pie chartProportions
Doughnut ChartdoughnutPie with center holeProportions with space for label
Area ChartareaFilled line chartVolume over time
Stacked Barstacked_barStacked vertical barsComposition comparison
Horizontal Barhorizontal_barHorizontal bar chartLong category names
Combo ChartcomboBar + line combinedMultiple metrics
Gauge ChartgaugeSpeedometer styleProgress/KPIs
HeatmapheatmapColor-coded gridPattern identification
TreemaptreemapHierarchical rectanglesHierarchical data
Scatter PlotscatterPoint distributionCorrelation analysis
Radar ChartradarSpider/radar chartMulti-variable comparison

Adding Charts to Reports

  1. Generate or preview a report
  2. Select "Chart Type" from the options
  3. Configure chart-specific options:
    • Title
    • Legend position
    • Color scheme
  4. Chart renders with report data

Export Formats

CSV Export

  • Comma-separated values
  • Compatible with Excel, Google Sheets
  • Best for data analysis
  • All selected columns included

Excel Export

  • Native .xlsx format
  • Formatted headers
  • Multiple sheets for complex reports
  • Charts included where applicable

PDF Export

  • Print-ready layout
  • Company branding
  • Headers and footers
  • Page numbers
  • Best for sharing/archiving

Export Endpoint

GET /admin/reports/generated/{id}/download/{format}

Supported formats: csv, pdf, excel

Export Architecture

The export system uses a strategy pattern with dedicated exporter classes:

app/Services/Reports/Exporters/
├── ReportExporterInterface.php   # Exporter contract
├── CsvReportExporter.php         # CSV with UTF-8 BOM
├── ExcelReportExporter.php       # XLSX via maatwebsite/excel
├── PdfReportExporter.php         # PDF via DomPDF
└── ReportExportService.php       # Orchestrator

ReportExportService Usage:

use App\Services\Reports\Exporters\ReportExportService;

$exportService = app(ReportExportService::class);

// Check available formats
$formats = $exportService->getAvailableFormats();
// ['csv' => [...], 'xlsx' => [...], 'pdf' => [...]]

// Export a report (must implement ExportableInterface)
$response = $exportService->export($report, 'xlsx');

ExportableInterface Contract:

All exportable reports implement this interface:

interface ExportableInterface
{
    public function toExportArray(): array;      // Data rows
    public function getExportHeaders(): array;   // Column headers
    public function getExportFilename(): string; // File name
    public function getExportMetadata(): array;  // Title, description, etc.
}

Adding Custom Export Format:

// 1. Create exporter implementing ReportExporterInterface
class JsonReportExporter implements ReportExporterInterface
{
    public function getFormat(): string { return 'json'; }
    public function getMimeType(): string { return 'application/json'; }
    public function getFileExtension(): string { return 'json'; }
    public function export(ExportableInterface $report): Response { ... }
}

// 2. Register in ReportExportService constructor
$this->registerExporter(app(JsonReportExporter::class));

Report Scheduling

Schedule automated report generation with flexible frequency options.

Creating a Schedule

  1. Navigate to Admin → Report Schedules
  2. Click "Create Schedule"
  3. Configure:
    • Name: Schedule identifier
    • Report Type: Select built-in report type
    • Parameters: Report-specific parameters
    • Frequency: Daily, Weekly, Monthly, Quarterly, or Custom
    • Recipients: Email addresses for delivery
    • Format: CSV, PDF, or Excel
  4. Click "Create"

Frequency Options

FrequencySchedule TimeDescription
DailyConfigurable timeRuns every day
WeeklyDay of week + timeRuns once per week
MonthlyDay of month + timeRuns once per month
QuarterlyMonth + day + timeRuns once per quarter
CustomCron expressionFull cron flexibility

Custom Cron Expressions

For advanced scheduling, use cron expressions:

# Every Monday at 9 AM
0 9 * * 1

# First day of each month at midnight
0 0 1 * *

# Every weekday at 6 PM
0 18 * * 1-5

Schedule Actions

ActionDescription
ToggleEnable/disable schedule
Run NowExecute immediately
PreviewPreview next run data
EditModify schedule
DeleteRemove schedule

Managing Recipients

Schedules support multiple recipients:

  • User-based: Select portal users by ID
  • Email-based: Enter email addresses directly
  • Mixed: Combine both methods

Report Sharing

Share reports with external users via secure token-based links.

  1. Navigate to report (generated, custom, or scheduled)
  2. Click "Share" button
  3. Configure:
    • Expires At: Optional expiration date
    • Password: Optional password protection
    • Max Views: Optional view limit
    • Permissions: View-only or download enabled
  4. Copy generated link

Share Options

OptionDescriptionDefault
expires_atExpiration date/timeNever
passwordAccess passwordNone
max_viewsMaximum view countUnlimited
max_downloadsMaximum download countUnlimited
permissionsArray of permissions['view']

Available Permissions

PermissionDescription
viewView report data
downloadDownload exports
editModify report

Public Access URL

GET /r/{token}
  • No authentication required
  • Token validated against share record
  • Password prompted if configured
  • View/download counts tracked

Revoking Access

  1. Navigate to Admin → Shared Reports
  2. Find the share record
  3. Click "Revoke" to disable

Technical Architecture

Models

ReportSchedule

// app/Models/ReportSchedule.php
class ReportSchedule extends Model
{
    protected $fillable = [
        'name', 'report_type', 'parameters', 'frequency',
        'schedule_time', 'schedule_day', 'cron_expression',
        'recipients', 'format', 'is_active', 'last_run_at',
        'next_run_at', 'created_by',
    ];

    protected $casts = [
        'parameters' => 'array',
        'recipients' => 'array',
        'is_active' => 'boolean',
        'last_run_at' => 'datetime',
        'next_run_at' => 'datetime',
    ];

    // Key methods
    public function calculateNextRunAt(): Carbon;
    public function markAsRun(): void;
    public function getAllRecipientEmails(): array;
    public static function getFrequencies(): array;
}

CustomReport

// app/Models/CustomReport.php
class CustomReport extends Model
{
    protected $fillable = [
        'name', 'description', 'data_source', 'columns',
        'filters', 'group_by', 'order_by', 'order_direction',
        'aggregations', 'chart_config', 'is_public', 'created_by',
    ];

    protected $casts = [
        'columns' => 'array',
        'filters' => 'array',
        'aggregations' => 'array',
        'chart_config' => 'array',
        'is_public' => 'boolean',
    ];

    // Key methods
    public static function getAvailableDataSources(): array;
    public function scopeAccessibleBy($query, User $user);
}

SharedReport

// app/Models/SharedReport.php
class SharedReport extends Model
{
    protected $fillable = [
        'reportable_type', 'reportable_id', 'token',
        'expires_at', 'password', 'max_views', 'max_downloads',
        'view_count', 'download_count', 'permissions',
        'created_by',
    ];

    // Key methods
    public static function generateToken(): string;
    public function canView(): bool;
    public function canDownload(): bool;
    public function recordView(): void;
}

Services

ReportRegistry

Central registry managing all built-in report types:

// app/Services/Reports/ReportRegistry.php
class ReportRegistry
{
    public function getAvailable(): array;      // All reports with metadata
    public function getByCategory(): array;     // Reports grouped by category
    public function has(string $type): bool;    // Check if type exists
    public function get(string $type): string;  // Get report class
    public function run(string $type, array $params): array;  // Execute report
    public function register(string $type, string $class): void;  // Add custom
}

CustomReportBuilder

Builds and executes custom report queries:

// app/Services/Reports/CustomReportBuilder.php
class CustomReportBuilder
{
    public function build(CustomReport $report): array;
    protected function buildQuery(CustomReport $report): Builder;
    protected function applyFilter(Builder $query, array $filter): Builder;
    protected function applyGrouping(Builder $query, CustomReport $report): Builder;
    protected function applyAggregations(Builder $query, array $aggregations): void;
}

ChartBuilder

Transforms data into Chart.js configurations:

// app/Services/Reports/ChartBuilder.php
class ChartBuilder
{
    public function getChartTypes(): array;                    // Available types
    public function buildChart(string $type, array $data, array $options): array;
}

QueryOptimizer (New)

Analyzes and optimizes report queries for performance:

// app/Services/Reports/QueryOptimizer.php
class QueryOptimizer
{
    public function analyze(CustomReport $report): array;      // Analyze query complexity
    public function optimize(Builder $query): Builder;         // Apply optimizations
    public function getCacheKey(CustomReport $report): string; // Generate cache key
    public function cacheResult(string $key, array $data, int $ttl): void;
    public function getCachedResult(string $key): ?array;
}

Query Analysis Features:

  • Estimates execution time based on data source size
  • Recommends async processing for large datasets
  • Suggests index improvements
  • Provides caching recommendations
  • Warns about potentially slow operations

Report Progress Tracking

Large reports are processed asynchronously with real-time progress tracking:

// app/Jobs/GenerateReportJob.php
class GenerateReportJob implements ShouldQueue
{
    public function __construct(
        public readonly CustomReport $report,
        public readonly string $jobId,
        public readonly ?int $userId = null
    ) {}
}

Progress States:

  • queued - Job is waiting in queue
  • running - Job is executing
  • completed - Job finished successfully
  • failed - Job encountered an error

Polling Endpoint:

GET /admin/custom-reports/progress/{jobId}

Returns:

{
    "status": "running",
    "progress": 45,
    "message": "Processing records..."
}

Report Interface

All report types implement this contract:

// app/Services/Reports/Contracts/ReportInterface.php
interface ReportInterface
{
    public static function getType(): string;
    public static function getName(): string;
    public static function getDescription(): string;
    public static function getCategory(): string;
    public static function getParameters(): array;
    public function generate(array $parameters = []): array;
    public function getDefaultChartConfig(): ?array;
}

Base Report Class

Abstract base with common functionality, now implements ExportableInterface:

// app/Services/Reports/BaseReport.php
abstract class BaseReport implements ReportInterface, ExportableInterface
{
    protected array $generatedData = [];
    protected array $generatedSummary = [];

    public function generate(array $parameters = []): array
    {
        $normalized = $this->normalizeParameters($parameters);
        $this->generatedData = $this->fetchData($normalized);
        $this->generatedSummary = $this->calculateSummary($this->generatedData, $normalized);

        return [
            'data' => $this->generatedData,
            'summary' => $this->generatedSummary,
            'metadata' => [...],
        ];
    }

    // ExportableInterface implementation (overridable)
    public function toExportArray(): array { return $this->generatedData; }
    public function getExportHeaders(): array { /* auto-detect from data */ }
    public function getExportFilename(): string { return static::getType() . '-' . now()->format('Y-m-d'); }
    public function getExportMetadata(): array { /* title, description, etc. */ }

    // Helper methods
    protected function getStartDate(array $params): Carbon;
    protected function getEndDate(array $params): Carbon;
    protected function formatCurrency(float $amount): string;
    protected function calculatePercentageChange(float $old, float $new): float;
}

API Reference

Report Types

GET  /admin/reports/types          # List all report types
GET  /admin/reports/chart-types    # List chart types
GET  /admin/reports/type/{type}    # Show report form
POST /admin/reports/preview        # Preview report data
POST /admin/reports/generate       # Generate and store report
GET  /admin/reports/history        # View report history

Custom Reports

GET    /admin/custom-reports              # List custom reports
GET    /admin/custom-reports/create       # Create form
POST   /admin/custom-reports              # Store new report
GET    /admin/custom-reports/{id}         # View/execute report
GET    /admin/custom-reports/{id}/edit    # Edit form
PUT    /admin/custom-reports/{id}         # Update report
DELETE /admin/custom-reports/{id}         # Delete report
POST   /admin/custom-reports/preview      # Preview query results
POST   /admin/custom-reports/{id}/duplicate  # Duplicate report
GET    /admin/custom-reports/fields/{source} # Get data source fields
GET    /admin/custom-reports/{id}/export/{format} # Export results

Report Schedules

GET    /admin/report-schedules             # List schedules
GET    /admin/report-schedules/create      # Create form
POST   /admin/report-schedules             # Store schedule
GET    /admin/report-schedules/{id}        # View schedule
GET    /admin/report-schedules/{id}/edit   # Edit form
PUT    /admin/report-schedules/{id}        # Update schedule
DELETE /admin/report-schedules/{id}        # Delete schedule
POST   /admin/report-schedules/{id}/toggle # Toggle active status
POST   /admin/report-schedules/{id}/run-now  # Run immediately
POST   /admin/report-schedules/{id}/preview  # Preview next run
GET    /admin/report-schedules/due         # Get schedules due to run

Shared Reports

POST /admin/reports/share/generated/{id}   # Share generated report
POST /admin/reports/share/custom/{id}      # Share custom report
POST /admin/reports/share/schedule/{id}    # Share scheduled report
PUT  /admin/shared-reports/{id}            # Update share settings
DELETE /admin/shared-reports/{id}          # Revoke share

# Public access (no auth required)
GET  /r/{token}                            # View shared report
GET  /r/{token}/download                   # Download shared report

Database Schema

Table: report_schedules

ColumnTypeDescription
idbigintPrimary key
namevarcharSchedule name
report_typevarcharReport type key
parametersjsonReport parameters
frequencyvarchardaily/weekly/monthly/quarterly/custom
schedule_timetimeExecution time
schedule_dayintegerDay of week/month
cron_expressionvarcharCustom cron (nullable)
recipientsjsonEmail/user IDs
formatvarcharcsv/pdf/excel
is_activebooleanEnabled status
last_run_attimestampLast execution
next_run_attimestampNext execution
created_bybigintOwner user ID
created_attimestampCreated date
updated_attimestampUpdated date

Table: custom_reports

ColumnTypeDescription
idbigintPrimary key
namevarcharReport name
descriptiontextOptional description
data_sourcevarcharData source key
columnsjsonSelected columns
filtersjsonFilter conditions
group_byvarcharGrouping column
order_byvarcharSort column
order_directionvarcharasc/desc
aggregationsjsonAggregation config
chart_configjsonChart configuration
is_publicbooleanPublic visibility
created_bybigintOwner user ID
created_attimestampCreated date
updated_attimestampUpdated date

Table: shared_reports

ColumnTypeDescription
idbigintPrimary key
reportable_typevarcharPolymorphic type
reportable_idbigintPolymorphic ID
tokenvarchar(64)Unique share token
expires_attimestampExpiration (nullable)
passwordvarcharHashed password (nullable)
max_viewsintegerView limit (nullable)
max_downloadsintegerDownload limit (nullable)
view_countintegerCurrent views
download_countintegerCurrent downloads
permissionsjson['view', 'download', 'edit']
created_bybigintCreator user ID
created_attimestampCreated date
updated_attimestampUpdated date

Table: generated_reports

ColumnTypeDescription
idbigintPrimary key
namevarcharReport name
report_typevarcharReport type key
parametersjsonGeneration parameters
result_datajsonReport results
file_pathvarcharStored file path
formatvarcharExport format
generated_bybigintGenerator user ID
created_attimestampGeneration date
updated_attimestampUpdated date

Dependencies

FeatureRelationship
AuthorizationAdmin access required
Background JobsScheduled generation
NotificationsEmail delivery

Complementary Features

FeatureDescription
AnalyticsDashboard analytics
Search FilteringFilter report data
PDF GenerationPDF exports

Best Practices

For Users

  1. Use date ranges appropriate to report type
  2. Filter large reports to relevant data
  3. Schedule recurring reports instead of manual generation
  4. Use PDF for sharing, CSV for analysis
  5. Set expiration on shared links for security

For Developers

  1. Queue large exports for performance
  2. Cache report data where appropriate
  3. Limit date ranges to prevent timeouts
  4. Index commonly filtered columns
  5. Implement ReportInterface for new report types

Troubleshooting

IssueSolution
Report times outReduce date range or add filters
Export failsCheck disk space and permissions
Scheduled not runningVerify scheduler and queue worker
Empty resultsCheck filter parameters
Chart not renderingVerify data format matches chart type
Share link expiredCreate new share with extended expiry

See Also