PHPackages                             codewow/filament-exact - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Admin Panels](/categories/admin)
4. /
5. codewow/filament-exact

ActiveLibrary[Admin Panels](/categories/admin)

codewow/filament-exact
======================

ExactOnline Panel for FilamentPHP

2.0.9(1mo ago)0307MITPHPPHP ^8.4|^8.5CI passing

Since Mar 11Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/codewownl/filament-exact)[ Packagist](https://packagist.org/packages/codewow/filament-exact)[ Docs](https://github.com/codewownl/filament-exact)[ RSS](/packages/codewow-filament-exact/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (55)Versions (37)Used By (0)

Filament Exact - ExactOnline Integration for FilamentPHP
========================================================

[](#filament-exact---exactonline-integration-for-filamentphp)

---

About the package
-----------------

[](#about-the-package)

`Filament Exact` is a **FilamentPHP plugin** that makes it easy to integrate **ExactOnline API calls** into your Laravel application. The package provides a **queue system** to process API calls efficiently and displays job statuses and errors inside the Filament admin panel.

### Features

[](#features)

- ✅ **ExactOnline API authentication &amp; token management** automatically.
- ✅ **Rate-limiting** to ensure compliance with ExactOnline's API restrictions.
- ✅ **Job processing &amp; error handling**, allowing developers to focus on business logic.
- ✅ **Error Handling** to ensure that errors are logged and displayed in the panel. You can also rec
- ✅ **Job Progress** to see the progress of the jobs right from your Filament panel.
- ✅ **Priority Queue** to prioritize jobs based on their importance.
- ✅ **Webhook support** to handle ExactOnline webhooks in a structured way.
- ✅ **Permission-based access control** (optional) with [Filament Shield](https://filamentphp.com/plugins/bezhansalleh-shield) integration.
-

### Upcoming features

[](#upcoming-features)

- 🔄 **Retry-policy** to automatically retry failed jobs.
- 🚀 **Realtime overview** of the queue status.

[![Filament Exact](https://raw.githubusercontent.com/codewownl/filament-exact/master/docs/filament-exact.png)](https://raw.githubusercontent.com/codewownl/filament-exact/master/docs/filament-exact.png)

---

📥 Installation
--------------

[](#-installation)

### 1. Install the Package via composer

[](#1-install-the-package-via-composer)

```
composer require codewow/filament-exact
```

### 2. Publish the assets and run the installer

[](#2-publish-the-assets-and-run-the-installer)

```
php artisan filament-exact:install
```

### 3. Configure Environment Variables

[](#3-configure-environment-variables)

Edit your `.env` file and add the following environment variables:

```
EXACT_ONLINE_CLIENT_ID=""
EXACT_ONLINE_CLIENT_SECRET=""
EXACT_ONLINE_CLIENT_WEBHOOK_SECRET=""
EXACT_ONLINE_REDIRECT_URI=""
EXACT_ONLINE_WEBHOOK_URI=""
EXACT_ONLINE_DIVISIONS="" # Comma-separated list of divisions (123456,654321)
```

### 4. Add the plugin to your `PanelProvider`

[](#4-add-the-plugin-to-your-panelprovider)

```
use CodeWOW\FilamentExact\FilamentExactPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            FilamentExactPlugin::make()
        ]);
}
```

### 5. Scheduler configuration

[](#5-scheduler-configuration)

Specify the scheduler in your `bootstrap/app.php` file:

```
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        //
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })
    ->withSchedule(function (Schedule $schedule) {
        if (app()->environment('production')) {
            $schedule->command('exact:process-queue production')->everyMinute();
        }
    })
    ->create();
```

### 6. Authorize the application

[](#6-authorize-the-application)

Navigate to the Filament panel and click on the "Authorize" button in the ExactOnline Resource. You will be redirected to the ExactOnline login page to authorize the application. [![Authorize Exact](https://raw.githubusercontent.com/codewownl/filament-exact/master/docs/filament-exact-authorize-button.png)](https://raw.githubusercontent.com/codewownl/filament-exact/master/docs/filament-exact-authorize-button.png)

---

⚙️ Configuration
----------------

[](#️-configuration)

The package provides a configuration file that allows you to customize the behavior of the package. You can publish the configuration file using:

```
php artisan vendor:publish --tag="filament-exact-config"
```

After publishing the configuration file, you can find it in `config/filament-exact.php`.

### Default configuration

[](#default-configuration)

```
return [
    'model' => ExactQueue::class,
    'resource' => ExactQueueResource::class,

    'database' => [
        'tables' => [
            'queue' => 'exact_queue',
            'tokens' => 'exact_tokens',
        ],
        'pruning' => [
            'after' => 30, // days
        ],
    ],

    'notifications' => [
        'mail' => [
            'to' => [],
        ],
    ],

    'exact' => [
        'redirect_uri' => env('EXACT_ONLINE_REDIRECT_URI'),
        'client_id' => env('EXACT_ONLINE_CLIENT_ID'),
        'client_secret' => env('EXACT_ONLINE_CLIENT_SECRET'),
        'webhook_secret' => env('EXACT_ONLINE_WEBHOOK_SECRET'),
        'webhook_uri' => env('EXACT_ONLINE_WEBHOOK_URI'),
        'divisions' => array_filter(
            array_map('trim', explode(',', env('EXACT_ONLINE_DIVISIONS', '')))
        ),
    ],

    'navigation' => [
        'group' => null,
        'sort' => -1,
    ],

    'shield' => [
        'enabled' => false,
        'permissions' => [
            'view_any_exact_queue',
            'view_exact_queue',
            'authorize_exact_queue',
            'duplicate_exact_queue',
            'cancel_exact_queue',
            'prioritize_exact_queue',
        ],
    ],
];
```

### Explanation

[](#explanation)

- **model**: The model used to store the queue items.
- **resource**: The resource used to display the queue items in the Filament panel.
- **database.tables**: The database tables used to store the queue items and tokens.
- **database.pruning**: Configuration for pruning old queue items.
- **notifications.mail.to**: The email addresses to send notifications to. (e.g \["", ""\])
- **exact**: Configuration for the ExactOnline API.
- **navigation.group**: The group to add the ExactOnline plugin to in the Filament panel.
- **navigation.sort**: The sort order of the ExactOnline plugin in the Filament panel.
- **shield.enabled**: Whether to enable the permission-based access control (optional).
- **shield.permissions**: The permissions used for the ExactOnline plugin when using Filament Shield.

---

🔐 Permissions (Optional)
------------------------

[](#-permissions-optional)

The FilamentExact plugin includes **optional** permission-based access control. This feature integrates seamlessly with [Filament Shield](https://github.com/bezhanSalleh/filament-shield).

> **Note:** Permissions are completely optional. The plugin works perfectly without any permission system - all features will be accessible to all users by default.

### How to enable permissions?

[](#how-to-enable-permissions)

1. Make sure you have the required `filament-shield` package installed:

```
composer require bezhanSalleh/filament-shield

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
```

2. Add the `HasRoles` trait to your auth provider model:

```
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles;
}
```

3. Setup Filament Shield by running the following command:

```
php artisan shield:setup
```

4. Register Filament Shield in your `PanelProvider`:

```
->plugins([
    \BezhanSalleh\FilamentShield\FilamentShieldPlugin::make(),
])
```

5. Enable `custom_permissions` in the `config/filament-shield.php` configuration file:

```
'entities' => [
    ...
    'custom_permissions' => true,
],
```

6. Enable the permissions in the `config/filament-exact.php` configuration file:

```
'shield' => [
    'enabled' => true,
    ...
]
```

That's it! The plugin will now use the permissions defined in the `shield.permissions` array to control access to the ExactOnline plugin features.

### Available Permissions

[](#available-permissions)

Permission NameDescription`view_any_exact_queue`View the ExactQueue resource in navigation and access the list`view_exact_queue`View individual queue items and their details`authorize_exact_queue`Access the "Authorize ExactOnline" button and manage API connection`duplicate_exact_queue`Duplicate existing queue items`cancel_exact_queue`Cancel pending or processing queue items`prioritize_exact_queue`Change priority of queue items to urgent### Managing Permissions

[](#managing-permissions)

You can manage permissions using the Filament Shield interface. Navigate to the "Shield" section in your Filament panel, and you will find the ExactOnline permissions listed there. You can assign these permissions to roles or users as needed.

If needed, you can also grant permissions programmatically using the `givePermissionTo` method:

**Assign Permissions to Users**

```
use App\Models\User;

$user = User::find(1);

// Give specific permissions
$user->givePermissionTo('view_exact_queue');
$user->givePermissionTo('authorize_exact_queue');

// Give all permissions
$user->givePermissionTo([
    'view_any_exact_queue',
    'view_exact_queue',
    'authorize_exact_queue',
    'duplicate_exact_queue',
    'cancel_exact_queue',
    'prioritize_exact_queue',
]);
```

**Assign permissions to Roles**

```
use Spatie\Permission\Models\Role;

// Create roles
$adminRole = Role::create(['name' => 'exact-admin']);
$userRole = Role::create(['name' => 'exact-user']);

// Give permissions to roles
$adminRole->givePermissionTo([
    'view_any_exact_queue',
    'view_exact_queue',
    'authorize_exact_queue',
    'duplicate_exact_queue',
    'cancel_exact_queue',
    'prioritize_exact_queue',
]);

$userRole->givePermissionTo([
    'view_any_exact_queue',
    'view_exact_queue',
]);

// Assign roles to users
$user->assignRole('exact-admin');
```

**Helper Trait (Optional)**For convenience, you can use the included `HasExactPermissions` trait in your user model to check permissions easily:

```
use CodeWOW\FilamentExact\Traits\HasExactQueuePermissions;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasRoles, HasExactQueuePermissions;
}

---

## 🚀 Usage

### Adding a Job to the Exact Queue
```php
use App\Jobs\ImportProductsJob;
use CodeWOW\FilamentExact\Models\ExactQueue;
use CodeWOW\FilamentExact\Enums\QueuePriorityEnum;

ExactQueue::create([
    "job" => ImportProductsJob::class,
    "parameters" => [
        "invoice_id" => $invoice->id,
    ],
    "priority" => QueuePriorityEnum::NORMAL,
    "environment" => 'production' // Optional (Default: production)
]);
```

### Available priorities

[](#available-priorities)

The `priority` field in the `ExactQueue` model can be set to one of the following values:

Enum constantValueDescription`QueuePriorityEnum::VERY_LOW``0`Background tasks`QueuePriorityEnum::LOW``1`Low-importance tasks`QueuePriorityEnum::NORMAL``2`Default priority`QueuePriorityEnum::HIGH``3`Time-sensitive`QueuePriorityEnum::URGENT``4`Immediate execution### Create a Custom Job

[](#create-a-custom-job)

```
use CodeWOW\FilamentExact\Jobs\ExactQueueJob;
use Exception;
use Log;
use CodeWOW\FilamentExact\Services\ExactService;
use CodeWOW\FilamentExact\Endpoints\Item;
use App\Models\Product;

class ImportProductsJob extends ExactQueueJob
{

    public $id;

    public function __construct(string $id)
    {
        $this->id = $id;
    }

    public function handle(ExactService $service): void
    {
        $connection = $service->getConnection();

        $itemWrapper = new Item($connection);
        $item = $itemWrapper->find($this->id);
        if (! $item) {
            throw new Exception('Product not found in Exact: '.$this->id);
        }

        // Create a new product in the database
        Product::create([
            'name' => $item->Description,
            'price' => $item->SalesPrice,
            ...
        ]);
    }
}
```

### XML Endpoints

[](#xml-endpoints)

Some Exact Online features are only available via the XML API (`docs/XMLUpload.aspx` and `docs/XMLDownload.aspx`). The package uses the same developer experience as REST endpoints: instantiate the endpoint with a connection and call `save()`, `download()`, or `get()`.

XML endpoints live in `CodeWOW\FilamentExact\Endpoints\XML` and extend `XmlModel`. Each endpoint defines a `$topic`, implements `toXml()` for uploads, and optionally overrides `fromXml()` for hydrated downloads.

```
use CodeWOW\FilamentExact\Endpoints\XML\MatchSets;
use CodeWOW\FilamentExact\Services\ExactService;

$connection = app(ExactService::class)->connect();

$matchSet = new MatchSets($connection, [
    'GLAccountCode' => '1300',
    'AccountCode' => '16001092',
    'MatchLines' => [
        [
            'finyear' => '2026',
            'finperiod' => '7',
            'journal' => '20',
            'entry' => '14200003',
            'amountdc' => '-12.10',
        ],
        [
            'finyear' => '2026',
            'finperiod' => '7',
            'journal' => '50',
            'entry' => '14500026',
            'amountdc' => '12.10',
        ],
    ],
]);

$messages = $matchSet->save();

$xml = (new MatchSets($connection))->download();
$records = (new MatchSets($connection))->get();
```

- `save()` / `upload()` POST XML to `XMLUpload.aspx` and return Exact response messages (array).
- `download()` returns a raw `SimpleXMLElement`.
- `get()` returns hydrated model instances when `fromXml()` is implemented on the endpoint.

To add a new XML endpoint, create a class extending `XmlModel`, set `$topic`, use the `Uploadable` and/or `Downloadable` traits, and implement `toXml()` (and `fromXml()` when needed).

#### Items (GET + POST)

[](#items-get--post)

```
use CodeWOW\FilamentExact\Endpoints\XML\Items;

$item = new Items($connection, [
    'Code' => 'ITEM001',
    'Description' => 'Example product',
    'ItemCategoryCode' => '10',
    'GLRevenueCode' => '8000',
    'IsSalesItem' => true,
    'IsPurchaseItem' => false,
    'IsStockItem' => true,
]);

$messages = $item->save();

$xml = (new Items($connection))->download();
$items = (new Items($connection))->get();
```

For bulk uploads, pass an `Items` array with multiple item payloads. XML downloads are limited to 100 records per request; use the `ts_d` attribute on the response topic for pagination when needed.

---

📌 Webhooks
----------

[](#-webhooks)

This package allows you to **register and handle Exact Online webhooks** in a simple and structured way.

### 1. Create a Webhook Handler

[](#1-create-a-webhook-handler)

Create a class that extends `ExactWebhook` and implement the `handle` method to process the webhook.

```
namespace App\Webhooks;

use CodeWOW\FilamentExact\Webhooks\ExactWebhook;

class ItemsWebhook extends ExactWebhook
{

    // Something to identify the webhook
    public string $topic = 'Items';

    // The slug of the webhook
    public string $slug = 'items';

    public function handle($body): void
    {
        // Handle the webhook here
    }

}
```

### 2. Register the Webhook

[](#2-register-the-webhook)

To register webhooks, call the `webhooks()` method in your `PanelProvider`.

```
use CodeWOW\FilamentExact\FilamentExactPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            FilamentExactPlugin::make()
                ->webhooks([
                    new ItemsWebhook()
                ])
        ]);
}
```

### 3. Run the Webhook Registration Command

[](#3-run-the-webhook-registration-command)

After registering the webhooks, you need to run the following command to subscribe to the webhooks with ExactOnline.

```
php artisan exact:register-webhooks
```

### 4. Receiving Webhooks

[](#4-receiving-webhooks)

Once registered, Exact Online will send webhooks to your application at the url specified in the `EXACT_ONLINE_WEBHOOK_URI` environment variable. Make sure the route has a parameter `{slug}` to identify the webhook handler.

For example:

```
EXACT_ONLINE_WEBHOOK_URI="https://mydomain.com/exact/webhook/{slug}"
```

### 5. Authorization

[](#5-authorization)

To authorize the webhook, you need to provide the `EXACT_ONLINE_WEBHOOK_SECRET` environment variable.

---

🌍 Translations
--------------

[](#-translations)

This package supports multiple languages. You can publish the translation files using:

```
php artisan vendor:publish --tag="filament-exact-translations"
```

By default, the package provides translations for:

- 🇬🇧 English
- 🇳🇱 Dutch

To customize the translations, modify the language files inside `resources/lang/vendor/filament-exact/`. If you would like to contribute translations for other languages, feel free to submit a pull request!

---

🚀 Screenshots
-------------

[](#-screenshots)

### Queue Overview

[](#queue-overview)

The queue overview provides a list of all jobs in the queue, including their status, priority, and progress. You can filter the queue by status quickly find the job you are looking for. If you want to see more details about a job, you can click on the job to view the details. [![Queue Overview](https://raw.githubusercontent.com/codewownl/filament-exact/master/docs/filament-exact-overview.png)](https://raw.githubusercontent.com/codewownl/filament-exact/master/docs/filament-exact-overview.png)

### Queue Job Details

[](#queue-job-details)

From within this view you can see the progress of the job, the status, and any errors that occurred. You can also retry the job or delete it from the queue. If you wish to put the job on top of the queue, you can raise the priority of the job.

[![Queue Job Details](https://raw.githubusercontent.com/codewownl/filament-exact/master/docs/filament-exact-detail.png)](https://raw.githubusercontent.com/codewownl/filament-exact/master/docs/filament-exact-detail.png)

---

🛠 Debugging &amp; Troubleshooting
---------------------------------

[](#-debugging--troubleshooting)

### 1. Job Stuck in Queue

[](#1-job-stuck-in-queue)

You can manually process the queue by running the following command:

```
php artisan exact:process-queue {environment}
```

### 2. View Logs for Errors

[](#2-view-logs-for-errors)

```
tail -f storage/logs/laravel.log
```

### 3. Getting 401 Unauthorized Errors?

[](#3-getting-401-unauthorized-errors)

You may need to authorize the application again. You can do this from the Filament panel by clicking on the "Authorize" button in the ExactOnline Resource.

[![Authorize Exact](https://raw.githubusercontent.com/codewownl/filament-exact/master/docs/filament-exact-authorize-button.png)](https://raw.githubusercontent.com/codewownl/filament-exact/master/docs/filament-exact-authorize-button.png)

---

🧪 Testing
---------

[](#-testing)

```
composer test
```

🔄 Changelog
-----------

[](#-changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

🤝 Contributing
--------------

[](#-contributing)

Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.

🔒 Security Vulnerabilities
--------------------------

[](#-security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

👏 Credits
---------

[](#-credits)

- [Jessedev1](https://github.com/Jessedev1)
- [All Contributors](../../contributors)

📜 License
---------

[](#-license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

50

—

FairBetter than 95% of packages

Maintenance93

Actively maintained with recent releases

Popularity17

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity67

Established project with proven stability

 Bus Factor1

Top contributor holds 87.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~15 days

Total

30

Last Release

36d ago

Major Versions

1.1.9 → 2.0.02026-01-20

PHP version history (3 changes)1.0.0PHP ^8.1

2.0.1PHP ^8.4

2.0.7PHP ^8.4|^8.5

### Community

Maintainers

![](https://www.gravatar.com/avatar/c88b234d76284cb0bf6687a56a9f61806b557d6bd04e495a3b5e1c40aeaaa131?d=identicon)[Jessedev1](/maintainers/Jessedev1)

---

Top Contributors

[![Jessedev1](https://avatars.githubusercontent.com/u/60600868?v=4)](https://github.com/Jessedev1 "Jessedev1 (86 commits)")[![JordyPorte](https://avatars.githubusercontent.com/u/144008951?v=4)](https://github.com/JordyPorte "JordyPorte (7 commits)")[![hilbertknl](https://avatars.githubusercontent.com/u/9106339?v=4)](https://github.com/hilbertknl "hilbertknl (2 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")[![keesrijpstra](https://avatars.githubusercontent.com/u/90974087?v=4)](https://github.com/keesrijpstra "keesrijpstra (1 commits)")

---

Tags

laravelcreativeworkfilament-exactcodewowcodewownl

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/codewow-filament-exact/health.svg)

```
[![Health](https://phpackages.com/badges/codewow-filament-exact/health.svg)](https://phpackages.com/packages/codewow-filament-exact)
```

###  Alternatives

[rawilk/profile-filament-plugin

Profile &amp; MFA starter kit for filament.

3914.6k](/packages/rawilk-profile-filament-plugin)[backstage/mails

View logged mails and events in a beautiful Filament UI.

16120.0k](/packages/backstage-mails)[mradder/filament-logger

Audit logging, activity tracking, exports, alerts, and dashboards for Filament admin panels.

2317.4k](/packages/mradder-filament-logger)[waguilar33/filament-guardian

Role and permission management for Filament

162.3k](/packages/waguilar33-filament-guardian)[a2insights/filament-saas

Filament Saas for A2Insights

171.7k](/packages/a2insights-filament-saas)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
