PHP code example of risetechapps / fusion-report-client

1. Go to this page and download the library: Download risetechapps/fusion-report-client library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

risetechapps / fusion-report-client example snippets


// config/fusion-report.php
return [
    'api_key' => env('FUSION_REPORT_API_KEY'),

    // Persiste cada geração na tabela fusion_report_generations
    'log_generations' => env('FUSION_REPORT_LOG_GENERATIONS', true),

    'webhook' => [
        'url'    => env('FUSION_REPORT_WEBHOOK_URL'),
        'secret' => env('FUSION_REPORT_WEBHOOK_SECRET'),

        // Exige assinatura HMAC valida. Com true (padrao) e 'secret' vazio,
        // a rota recusa a requisicao em vez de aceitar payload nao assinado.
        // So desligue em desenvolvimento local.
        '        'path'       => env('FUSION_REPORT_WEBHOOK_PATH', '/fusion/webhook'),
        'middleware' => ['api'],
    ],

    'defaults' => [
        // Tema padrão aplicado quando a geração não define um via ->theme().
        // Ignorado nas gerações por ID de template.
        'theme' => env('FUSION_REPORT_THEME', 'default'),

        // Locale padrão aplicado quando a geração não define um via ->locale().
        'locale' => env('FUSION_REPORT_LOCALE', 'pt_BR'),

        // Formato(s) usados quando a geracao nao define nenhum via ->format().
        // O servidor exige 'format': sem este default, geracao sem ->format()
        // volta 422. Aceita 'pdf', 'pdf,xlsx' ou ['pdf', 'xlsx'].
        'format' => env('FUSION_REPORT_FORMAT', 'pdf'),

        'params' => [
            // Parâmetros enviados em toda geração automaticamente
            // 'TENANT_ID' => '123',
        ],
    ],

    'reports' => [
        // Definições de relatórios pré-registradas
        // 'client_all' => \App\Reports\ClientesAllReport::class,
    ],
];

$templates = FusionReport::templates()->list();

foreach ($templates as $template) {
    $template->id();
    $template->name();
    $template->theme();
    $template->description();
    $template->hasResources();
    $template->originalFilename();
    $template->createdAt();
    $template->updatedAt();
}

return response()->json($templates);

$template = FusionReport::templates()->find('uuid-do-template');

$template = FusionReport::templates()->upload(
    filePath:         resource_path('reports/client_all.jrxml'),
    name:             'client_all',
    theme:            'default',
    description:      'Relatório de clientes',
    resourcesZipPath: resource_path('reports/resources.zip'), // opcional
);

$template->id();
$template->hasResources();

$template = FusionReport::templates()->update(
    id:               'uuid-do-template',
    filePath:         resource_path('reports/client_all_v2.jrxml'),
    name:             'client_all',     // opcional
    theme:            'blue',           // opcional
    description:      'Nova descrição', // opcional
    resourcesZipPath: resource_path('reports/resources.zip'), // opcional
);

$template = FusionReport::templates()->updateByName(
    name:             'client_all',
    filePath:         resource_path('reports/client_all_v2.jrxml'),
    theme:            'blue',           // opcional
    description:      'Nova descrição', // opcional
    resourcesZipPath: resource_path('reports/resources.zip'), // opcional
);

$response = FusionReport::templates()->downloadJrxml('uuid-do-template');

$xml = $response->body();

// Comparar com o arquivo local antes de sincronizar
$local = file_get_contents(resource_path('reports/client_all/default.jrxml'));

if (trim($xml) !== trim($local)) {
    $this->info('Template divergente do servidor.');
}

FusionReport::templates()->delete('uuid-do-template');

FusionReport::templates()->deleteByName('client_all');
FusionReport::templates()->deleteByName('client_all', 'blue'); // tema específico

// Por ID do template
$generations = FusionReport::templates()->generations('uuid-do-template');

// Por nome do template
$generations = FusionReport::templates()->generationsByName('client_all');

namespace App\Reports;

use RiseTechApps\FusionReport\Datasources\Contracts\Datasource;
use RiseTechApps\FusionReport\Datasources\InlineJsonDatasource;
use RiseTechApps\FusionReport\Definitions\ReportDefinition;
use RiseTechApps\FusionReport\Definitions\ReportProtection;
use RiseTechApps\FusionReport\Definitions\ThemeFusion;
use RiseTechApps\FusionReport\Resources\GenerationResource;
use RiseTechApps\FusionReport\Webhook\WebhookPayload;

class ClientesAllReport extends ReportDefinition
{
    public function name(): string
    {
        return 'client_all';
    }

    // ── Usado pelo comando fusion-report:sync (registro de templates) ──
    //
    // No servidor a identidade de um template é o par (name + theme), então
    // cada ThemeFusion é um template distinto, com seu próprio .jrxml e resources.

    public function themes(): array
    {
        return [
            ThemeFusion::make('default')
                ->from(resource_path('reports/client_all/default.jrxml'))
                ->withResources(resource_path('reports/client_all/default.zip'))
                ->describedAs('Relatório consolidado de clientes'),

            // Cada tema tem seu próprio arquivo; resources/description são opcionais.
            ThemeFusion::make('blue')
                ->from(resource_path('reports/client_all/blue.jrxml')),
        ];
    }

    public function datasource(array $params = []): Datasource
    {
        return InlineJsonDatasource::from(
            Cliente::query()
                ->when($params['ANO'] ?? null, fn($q, $v) => $q->where('ano', $v))
                ->get()
                ->toArray()
        );
    }

    public function defaultParams(): array
    {
        return ['ANO' => date('Y')];
    }

    public function protection(): ?ReportProtection
    {
        return ReportProtection::password('secreta123'); // opcional
    }

    public function webhookParams(array $params = []): array
    {
        // Parâmetros anexados à URL base do webhook (query string).
        // Útil para carregar contexto que o callback precisa restabelecer.
        // Ex.: em apps multi-tenant, identificar o tenant na volta.
        return ['tenant_id' => tenancy()->getKey()];
    }

    public function onGenerated(GenerationResource $generation, array $context = []): void
    {
        // Só no modo SÍNCRONO (generate()). generateAsync() não chama este hook:
        // ali o servidor apenas enfileirou o job e files() viria vazio.
        // O equivalente assíncrono é onWebhookReceived(), logo abaixo.
        if ($context['send_email'] ?? false) {
            Mail::to($context['email'])->send(new ReportReadyMail($generation));
        }

        dispatch(new ProcessReportJob($generation->id()));
    }

    public function onWebhookReceived(WebhookPayload $payload, array $context = []): void
    {
        // Executado automaticamente quando o callback da geração assíncrona
        // chega — desde que o template_name do payload bata com name().
        // O $context é o mesmo informado no disparo (->context([...])).
        if (! $payload->isSuccess()) {
            return;
        }

        if ($context['send_email'] ?? false) {
            Mail::to($context['email'])->send(new ReportReadyMail($payload));
        }

        dispatch(new ProcessReportJob($payload->uuid()));
    }
}

'reports' => [
    'client_all' => \App\Reports\ClientesAllReport::class,
],

$generation = FusionReport::make('client_all')->format('pdf')->generate();

// Com params e context
$generation = FusionReport::make('client_all', ['ANO' => '2025'])
    ->format(['pdf', 'xlsx'])
    ->context(['send_email' => true, 'email' => '[email protected]'])
    ->generate();

// Acessar arquivos
$generation->id();
$generation->mode();            // 'sync'
$generation->currentStatus();  // 'completed'
$generation->frpId();          // ID do arquivo .frp para re-exportar depois
$generation->files();          // Collection<FileResource>
$generation->expiresAt();

// URLs dos arquivos
$urls = $generation->files()->mapWithKeys(
    fn($f) => [$f->format() => $f->url()]
);
// ['pdf' => 'https://...', 'xlsx' => 'https://...']

// Download direto
$response = $generation->download('pdf');

return response($response->body(), 200, [
    'Content-Type'        => 'application/pdf',
    'Content-Disposition' => 'attachment; filename="relatorio.pdf"',
]);

// webhook_url vai automaticamente do config
$generation = FusionReport::make('client_all')
    ->format('pdf')
    ->generateAsync();

$id = $generation->id(); // salve para consultar depois

// Com webhook diferente do padrão
$generation = FusionReport::make('client_all')
    ->format('pdf')
    ->generateAsync(webhook: 'https://outro-endpoint.com/webhook');

// Usa defaults.format
FusionReport::make('client_all')->generate();

// Sobrescreve o default — não acumula com ele
FusionReport::make('client_all')->format('xlsx')->generate();

// Múltiplos formatos, nas três formas aceitas
->format(['pdf', 'xlsx'])
->format('pdf,xlsx')
->format('pdf')->format('xlsx')

->params([
    'ANO'     => 2026,
    'ATIVO'   => true,               // ATIVO=true
    'PERIODO' => new DateTimeImmutable('2026-01-01'),
    'TAGS'    => ['a', 'b'],         // TAGS=["a","b"]
])

use RiseTechApps\FusionReport\Datasources\InlineJsonDatasource;

FusionReport::report('client_all')
    ->theme('blue')
    ->format(['pdf', 'xlsx'])
    ->params(['ANO' => '2026', 'EMPRESA' => 'Acme'])
    ->datasource(InlineJsonDatasource::from($data))
    ->locale('pt_BR')
    ->protection(ReportProtection::password('senha123'))
    ->generate();

FusionReport::reportById('uuid-do-template')
    ->format('pdf')
    ->generate();

FusionReport::reportById('uuid-do-template')
    ->format('pdf')
    ->generateAsync();

FusionReport::report('template')->format('pdf')->generate();

use RiseTechApps\FusionReport\Datasources\InlineJsonDatasource;

->datasource(InlineJsonDatasource::from($array))
->datasource(InlineJsonDatasource::fromJson('{"key":"value"}'))

use RiseTechApps\FusionReport\Datasources\InlineCsvDatasource;

->datasource(InlineCsvDatasource::from($csvString))
->datasource(InlineCsvDatasource::from($csvString, firstRow: true, delimiter: ';'))
->datasource(InlineCsvDatasource::fromRows($arrayOfRows))

use RiseTechApps\FusionReport\Datasources\JsonUrlDatasource;

->datasource(JsonUrlDatasource::get('https://api.exemplo.com/dados'))
->datasource(JsonUrlDatasource::get('https://api.exemplo.com/dados', [
    'Authorization' => 'Bearer token123',
]))
->datasource(JsonUrlDatasource::post('https://api.exemplo.com/dados'))

use RiseTechApps\FusionReport\Datasources\ProfileDatasource;

->datasource(ProfileDatasource::use('nome_do_perfil'))

use RiseTechApps\FusionReport\Definitions\ReportProtection;

// Senha de abertura
->protection(ReportProtection::password('senha123'))

// Senha de abertura + senha do owner
->protection(ReportProtection::withOwner('senha_user', 'senha_owner'))

$file = $generation->files()->first(fn($f) => $f->format() === 'pdf');

$file->id();
$file->format();    // 'pdf', 'xlsx', 'frp', etc.
$file->filename();
$file->url();       // URL de download (requer autenticação)
$file->expiresAt();

// Download do arquivo
$response = $file->download();

// Re-exportar .frp para outro formato → retorna nova GenerationResource
$novaGeracao = $file->export('xlsx');
$novaGeracao = FusionReport::file($frpId)->export('pdf');

$nova = FusionReport::generation($generationId)->export('xlsx');

$nova->id();       // geração nova; a original continua intacta
$nova->files();

use RiseTechApps\FusionReport\Contracts\WebhookHandler;

$this->app->bind(WebhookHandler::class, \App\Handlers\MeuWebhookHandler::class);

// app/Http/Middleware/InitializeFusionTenant.php
public function handle(Request $request, Closure $next)
{
    if ($tenantId = $request->query('tenant_id')) {
        tenancy()->initialize($tenantId);
    }

    return $next($request);
}

// config/fusion-report.php
'webhook' => [
    // ...
    'middleware' => ['api', \App\Http\Middleware\InitializeFusionTenant::class],
],

$payload->uuid();          // ID da geração
$payload->status();        // 'completed' | 'failed' | ...
$payload->isSuccess();     // status === 'completed'
$payload->isFailed();      // status === 'failed'
$payload->templateName();  // nome do template
$payload->frpId();         // ID do .frp (re-exportar depois)
$payload->error();         // mensagem de erro (quando falhou)
$payload->downloads();     // Collection<WebhookDownload>

foreach ($payload->downloads() as $download) {
    $download->format();     // 'pdf'
    $download->filename();   // 'relatorio.pdf'
    $download->url();        // URL de download (chave download_url)
    $download->expiresAt();  // expiração da URL (ou null)
}

use RiseTechApps\FusionReport\Webhook\WebhookPayload;
use RiseTechApps\FusionReport\Exceptions\WebhookSignatureException;

try {
    $webhook = WebhookPayload::fromRequest($request, secret: config('fusion-report.webhook.secret'));
} catch (WebhookSignatureException $e) {
    return response()->json(['error' => 'Unauthorized'], 401);
}

FusionReport::jasper()->formats();      // Formatos suportados
FusionReport::jasper()->status();       // Status geral
FusionReport::jasper()->jobs();         // Jobs assíncronos em andamento
FusionReport::jasper()->fontsStatus();  // Status das fontes instaladas
FusionReport::jasper()->fontsSync();    // Sincronizar fontes no servidor Java

use RiseTechApps\FusionReport\Exceptions\AuthenticationException;
use RiseTechApps\FusionReport\Exceptions\AuthorizationException;
use RiseTechApps\FusionReport\Exceptions\FusionReportException;
use RiseTechApps\FusionReport\Exceptions\RateLimitException;
use RiseTechApps\FusionReport\Exceptions\ReportNotFoundException;

try {
    $generation = FusionReport::make('client_all')->format('pdf')->generate();
} catch (RateLimitException $e) {
    // Cota do plano esgotada — reenfileire para depois
    $wait = $e->retryAfter() ?? 60;   // segundos, quando o servidor informa
} catch (AuthenticationException $e) {
    // api_key não configurada (lançada antes da requisição sair),
    // api_key inválida, ou rota restrita ao dashboard
} catch (AuthorizationException $e) {
    // Recurso de outra conta
} catch (ReportNotFoundException $e) {
    // Template não encontrado (404 ou 410)
} catch (FusionReportException $e) {
    // Validação (422) ou erro interno do servidor
}

> use Illuminate\Http\Client\ConnectionException;
>
> } catch (ConnectionException $e) {
>     // O servidor pode ter concluído a geração mesmo assim — ver
>     // "Limitações conhecidas".
> }
> 

use RiseTechApps\FusionReport\Events\ReportGenerationStarted;
use RiseTechApps\FusionReport\Events\ReportGenerationCompleted;
use RiseTechApps\FusionReport\Events\ReportGenerationFailed;

class MyListener
{
    public function handle(ReportGenerationCompleted $event): void
    {
        $event->generation;   // GenerationResource
        $event->context;      // array passado via ->context()
        $event->owner;        // ?Model — de ->for() / ReportDefinition::owner()

        foreach ($event->generation->files() as $file) {
            Storage::put("relatorios/{$file->filename()}", $file->download()->body());
        }
    }
}
bash
php artisan vendor:publish --tag=fusion-report