tmonier / sylius-timeline-plugin
Order and customer timeline with internal staff notes for the Sylius 2 admin panel
Package info
github.com/thibmonier/sylius-timeline-plugin
Type:sylius-plugin
pkg:composer/tmonier/sylius-timeline-plugin
Requires
- php: ^8.2
- sylius/sylius: ^2.2
Requires (Dev)
- nyholm/psr7: ^1.8
- phpstan/phpstan: ^2.1
- phpstan/phpstan-doctrine: ^2.0
- phpstan/phpstan-webmozart-assert: ^2.0
- phpunit/phpunit: ^10.5
- sylius-labs/coding-standard: ^4.4
- sylius/test-application: ^2.0.0@alpha
- symfony/browser-kit: ^6.4 || ^7.4 || ^8.0
- symfony/css-selector: ^6.4 || ^7.4 || ^8.0
- symfony/debug-bundle: ^6.4 || ^7.4 || ^8.0
- symfony/dom-crawler: ^6.4 || ^7.4 || ^8.0
- symfony/dotenv: ^6.4 || ^7.4 || ^8.0
- symfony/http-client: ^6.4 || ^7.4 || ^8.0
- symfony/intl: ^6.4 || ^7.4 || ^8.0
- symfony/runtime: ^6.4 || ^7.4 || ^8.0
- symfony/web-profiler-bundle: ^6.4 || ^7.4 || ^8.0
- symfony/webpack-encore-bundle: ^2.2
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-10 20:01:08 UTC
README
An order and customer timeline with internal staff notes for the Sylius 2 back office.
The Sylius 2 order page has no history: the History page only lists address changes, the customer's checkout note is read-only, and staff cannot leave a note on an order or a customer. The Sylius 1 plugins that did it were never ported.
This plugin records what happens to an order (placed, paid, shipped, cancelled, refunded, e-mails sent) and lets the team write internal notes, free and open source.
Features
| Need | What the plugin does |
|---|---|
| Know what happened to an order, and who did it | Timeline card on the admin order page, newest first: order placed, order / payment / shipping state changes, each payment (method + amount) and shipment (method + tracking code), e-mails sent (with recipients). Each entry shows an icon, a label, the author (administrator name, Customer or System) and the date. |
| See the customer's checkout note in context | The checkout note becomes a Customer note entry at the time the order was placed. |
| Share information inside the team | Internal notes on orders and on customers: plain text up to 5,000 characters, line breaks kept, HTML escaped. Never shown in the shop. |
| Keep important information in sight | Pin a note: pinned notes are shown at the top of the order or customer page in a highlighted card. |
| Know the customer | Customer timeline on the admin customer page: customer notes and the key events of their orders (placed with number and total, cancelled, payments completed or refunded), last 50 entries with a link to the full paginated page. |
| Spot orders that need attention | Notes badge with the number of internal notes in the admin orders grid. |
| Install on a running shop | tmonier:timeline:backfill rebuilds a timeline for existing orders. |
Also included: translations in English, French, German, Spanish, Italian, Dutch and Polish; Twig Hooks everywhere; MySQL, MariaDB and PostgreSQL support.
Screenshots
Requirements
| Version | |
|---|---|
| PHP | 8.2+ |
| Sylius | 2.2, 2.3 |
| Symfony | 6.4, 7.4, 8.0 |
The state machine abstraction must use the Symfony Workflow adapter (the Sylius 2 default,
sylius_state_machine_abstraction.default_adapter: symfony_workflow). Graphs mapped to the
Winzou adapter do not dispatch Symfony Workflow events and are not recorded.
Installation
-
Require the package:
composer require tmonier/sylius-timeline-plugin
-
Register the bundle in
config/bundles.php(Symfony Flex does it automatically once a recipe exists):Tmonier\SyliusTimelinePlugin\TmonierSyliusTimelinePlugin::class => ['all' => true],
-
Import the configuration in
config/packages/tmonier_sylius_timeline.yaml:imports: - { resource: "@TmonierSyliusTimelinePlugin/config/config.yaml" }
-
Import the admin routes in
config/routes/tmonier_sylius_timeline.yaml:tmonier_sylius_timeline: resource: "@TmonierSyliusTimelinePlugin/config/routes.yaml"
-
Run the migrations:
bin/console doctrine:migrations:migrate
-
Optionally, give the orders placed before the installation a timeline:
bin/console tmonier:timeline:backfill --dry-run bin/console tmonier:timeline:backfill
Configuration
# config/packages/tmonier_sylius_timeline.yaml tmonier_sylius_timeline: record_emails: true # e-mails sent by the Sylius mailer about an order enabled_workflows: # default value - sylius_order - sylius_order_payment - sylius_order_shipping - sylius_payment - sylius_shipment
enabled_workflows accepts any Symfony workflow whose subject is an order, a payment or a
shipment, so your own workflows can be recorded too (they get a generic label, or your own
tmonier_timeline.event.<workflow>.<transition> translation). The bookkeeping transitions
applied while an order is placed (request_payment, request_shipping, payment create and
process, shipment create) are never recorded, and neither is anything happening to a cart.
The TimelineEntry resource can be extended like any Sylius resource
(tmonier_sylius_timeline.resources.timeline_entry.classes.model).
To hide the notes column of the orders grid:
sylius_grid: grids: sylius_admin_order: fields: tmonier_timeline_notes: enabled: false
Customisation
The admin parts are built with Twig Hooks:
| Hook | Content |
|---|---|
sylius_admin.order.show.content.sections#left → tmonier_timeline_pinned_notes |
Pinned notes (top of the order page) |
sylius_admin.order.show.content.sections#left → tmonier_timeline |
Timeline card (bottom of the order page) |
sylius_admin.order.show.content.sections.tmonier_timeline → note_form, entries |
Note form and entries of the order timeline |
sylius_admin.customer.show.content.sections → tmonier_timeline_pinned_notes |
Pinned notes (top of the customer page) |
sylius_admin.customer.show.content.sections → tmonier_timeline |
Timeline card (bottom of the customer page) |
sylius_admin.customer.show.content.sections.tmonier_timeline → note_form, entries |
Note form and entries (configuration.limit, default 50) |
tmonier_timeline.admin.customer.timeline |
Full customer timeline page |
Templates can be overridden in templates/bundles/TmonierSyliusTimelinePlugin/. To record
your own events, use the services:
public function __construct( private TimelineEntryFactoryInterface $entryFactory, private TimelineEntryWriterInterface $writer, ) {} $entry = $this->entryFactory->createForOrder($order, TimelineEntryInterface::TYPE_TRANSITION, Actor::system()); $entry->setWorkflow('app_fraud_check'); $entry->setTransition('flag'); $this->writer->persist($entry); // flushed with your own changes
How events are recorded
- Workflow transitions: a listener on
workflow.completedrecords the transitions of the configured workflows. The entry is persisted without flushing, so it is saved by the flush that saves the state change itself, in the same transaction (and not at all if that change is rolled back). When the order is not persisted yet (fixtures, imports), the entry waits for the flush that inserts the order. - E-mails: a listener on
sylius.email_send.post_sendrecords e-mails whose data contains anorder(or ashipment/paymentof an order). E-mails are sent after the application flush, so the entry is flushed right away, but only when nothing else is pending in the unit of work; otherwise it waits for the application's next flush. - Authors: the authenticated administrator (name snapshot kept when the account is deleted), Customer for shop users and orders placed by guests, System otherwise (console, message consumers, payment notifications).
- Failures never break a checkout: recording errors are caught and logged on the
tmonier_timelinechannel.
Notes rules
- Notes are plain text (HTML is escaped, line breaks are kept), 5,000 characters maximum.
- Any administrator can add, pin and unpin notes.
- Only the author can delete a note. When the author's admin account has been deleted, any administrator can.
- Notes cannot be edited: delete and write a new one.
- Every action is a CSRF-protected POST.
Limitations
- Changes made outside Symfony Workflow (direct SQL, Winzou-mapped graphs, setters without a transition) are not recorded. Address changes stay in the Sylius History page.
- The backfill can only rebuild what an order still tells: placement (with the customer's
checkout note), completed payments, shipped shipments and cancellation. Dates of payments
and cancellations are approximated from
updatedAt. - Entries record facts with a snapshot (payment method name, amount, tracking code); they are not updated when the order is edited later.
- Sylius Plus RBAC is not integrated: every administrator can see and write notes.
Development
docker compose up -d mysql # or your own MySQL composer install (cd vendor/sylius/test-application && yarn install && yarn build) vendor/bin/console doctrine:database:create vendor/bin/console doctrine:migrations:migrate -n vendor/bin/console sylius:fixtures:load -n vendor/bin/phpunit --testsuite unit APP_ENV=test vendor/bin/phpunit --testsuite non-unit # needs a test database with fixtures vendor/bin/phpstan analyse vendor/bin/ecs check
License
MIT. See LICENSE.

