magendoo / module-omnibus

magendoo/module-omnibus

EU Omnibus Directive (2019/2161) price tracker for Magento 2. Records price changes with timestamps, computes the lowest prior price in the disclosure window, and displays it on PDP and PLP, with async queue processing for bulk operations.

magento2-module Compatibility: Not yet tested Code Quality: Pending Tests: N/A Security: Pending MIT

Are you the maintainer of magendoo?

Packagento pulls magendoo's Composer packages from the public registry so buyers can find them here.

Claim the namespace to take ownership, publish new releases directly, and start charging for premium versions.

Claim this namespace →

Viewing version 2.0.0. Latest version is 2.0.1. Switch to latest

Magendoo Omnibus Price Tracker

A Magento 2 module that records product price history and computes the lowest price in a configurable window, satisfying the requirements of the EU Omnibus Directive 2019/2161 (Article 6a).

The directive requires that any price reduction must show the lowest price from the preceding 30 days — measured not from today, but from the moment the reduction began. This module implements that anchored-window algorithm correctly.


Requirements

Dependency Version
PHP ≥ 8.1
Magento Open Source / Adobe Commerce 2.4.4 – 2.4.x
MySQL / MariaDB 8.0 / 10.6+

No RabbitMQ required: all queue topics are pinned to Magento's MySQL-backed db queue connection (queue_message table), so the async pipeline works on any standard Magento installation. Consumers run through Magento cron (consumers_runner) or a process manager — see Async processing.


Installation

The module is distributed via its GitHub repository (it is not published on Packagist).

Via Composer (recommended)

Add the repository to your project's composer.json:

"repositories": [
    {
        "type": "vcs",
        "url": "https://github.com/magendooro/module-omnibus"
    }
]

Install and enable:

composer require magendoo/module-omnibus:^2.0
bin/magento module:enable Magendoo_Omnibus
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush

Manual installation

Copy the module directory to app/code/Magendoo/Omnibus/, then run the same setup:upgrade / setup:di:compile / cache:flush sequence.


Quick Start

After installation, navigate to:

Stores → Configuration → Magendoo Extensions → Omnibus Price Tracker

  1. Set Enable Price History to Yes
  2. Set Period in Days to 30 (minimum required by the Directive; increase for a wider safety margin)
  3. Set Display Mode to Discounted Products Only (recommended for compliance)
  4. Set Display Omnibus Prices On to Product Pages Only or Product and Category Pages — the default is None, which records history but renders nothing on the storefront
  5. Click Save Config → the module queues a full catalog recompute on the magendoo.omnibus.recompute queue (make sure consumers are running)
  6. Seed an initial baseline so products have history to compute from:
bin/magento omnibus:history:restore --force

The omnibus_price product attribute is then populated and the label renders on the configured surfaces.


Configuration Reference

All general/* and label/* settings are scoped per website; cleanup/* and cron/* are global.

Path Default Description
general/enabled No Master toggle. Disabling stops capture and display but does not delete existing history.
general/period_in_days 30 Window length in days. Hard minimum: 30 (enforced at save time and again at read time).
general/display_mode discounted_only discounted_only — show only during active reductions. all_products — show for all products (rolling window).
general/display_on none Where to render the label: none, pdp_only, or pdp_and_plp. Must be changed from the default for any storefront output.
general/hide_if_matches Yes Suppress the label when the Omnibus price equals the current price.
general/show_history_on_product No Adds a notice on the admin product edit page pointing to the price history grid.
general/hide_for_customer_groups (none) Suppress the label for specific customer groups (history is still recorded).
label/template The lowest price from the last {days} days: {omnibus_price} Label text. Variables: {days}, {omnibus_price}, {percentage}. Allowed HTML tags: span i u b strong em.
label/display_format text text (inline) or tooltip.
label/percentage_difference disabled Show % change between current price and Omnibus price via {percentage}.
cleanup/enabled Yes Automatic deletion of old history records by the cleanup cron.
cleanup/period_in_days 400 Delete records older than this many days. Must be ≥ period_in_days + 30. The newest pre-cutoff record per product/website/group is always kept (carry-in).
cron/sync_schedule 0 2 * * * Drift-sync cron: queues captures for products whose current effective price (rule / active special / regular) drifted from the last history entry.
cron/cleanup_schedule 0 3 * * * Cleanup cron: deletes records older than the retention window.

All recorded_at timestamps are stored in UTC.


CLI Commands

All three commands refuse to run (exit non-zero) while magendoo_omnibus/general/enabled is 0.

# Recompute omnibus_price for all products on all websites
bin/magento omnibus:prices:recompute

# Recompute for a single product (all websites)
bin/magento omnibus:prices:recompute --product-id=42

# Recompute for a single product on a specific website
bin/magento omnibus:prices:recompute --product-id=42 --website-id=2

# Delete history older than the configured retention period, or a given date.
# The newest pre-cutoff record per product/website/group is always preserved.
bin/magento omnibus:history:clean
bin/magento omnibus:history:clean --before=2025-01-01
bin/magento omnibus:history:clean --before="2025-01-01 12:00:00"

# Wipe and rebuild history (fresh snapshot + full recompute).
# Prints the actual inserted row count, per-product coverage, and how many
# products ended up with a stored omnibus_price value.
# Requires confirmation unless --force is passed.
bin/magento omnibus:history:restore
bin/magento omnibus:history:restore --force
bin/magento omnibus:history:restore --force --website-id=1

Admin Interface

Marketing → Omnibus → Price Change History

The price history grid displays every recorded price change across your catalog. Columns: ID, SKU, Website, Customer Group, Price Type, Price (excl. tax), Price (incl. tax), Source, Recorded At, Actions.

Filterable columns include SKU (text), Website, Customer Group, Price Type, Source, and Recorded At (date range).

  • Row action: Delete — POST with confirmation dialog.
  • Mass action: Delete selected — POST.
  • Toolbar button: Restore History — wipes the history table and rebuilds it from a full catalog snapshot (POST with confirmation; only visible to admins holding the manage ACL resource). Refuses to run while the module is disabled globally or for any website: the capture/recompute services no-op when disabled, so the wipe would never be re-seeded.

All destructive endpoints accept POST only; GET requests are rejected.

ACL resources

Resource Grants
Magendoo_Omnibus::view_history View the price history grid
Magendoo_Omnibus::delete_history Delete single records / mass delete
Magendoo_Omnibus::manage Restore History (wipe + rebuild)
Magendoo_Omnibus::configuration Stores → Configuration section

Product attributes

Attribute Where Purpose
omnibus_price Product edit → Prices group (read-only value, website scope) The computed lowest prior price.
omnibus_hide Product edit → General group (Yes/No) Set to Yes to suppress the storefront label for this product.

Async processing

Bulk capture and recompute work runs through two message queue topics on the MySQL (db) queue connection:

  • magendoo.omnibus.capture — price capture for single products (catalog rule changes, imports, drift sync)
  • magendoo.omnibus.recomputeomnibus_price recompute batches (config changes)

Magento's cron consumers_runner starts the consumers automatically. To run them under a process manager instead:

bin/magento queue:consumers:start magendoo.omnibus.capture
bin/magento queue:consumers:start magendoo.omnibus.recompute

A single product save in admin/API is captured synchronously (so the product page is correct immediately); everything else is queued.


How It Works

See docs/how-it-works.md for a full explanation of the anchored-window algorithm (including the carry-in rule), the price resolution chain, and the complete event capture pipeline.

Architecture

See docs/architecture.md for the module structure, database schema, DI wiring, queue topology, and cron schedule.

Testing

See docs/testing.md for the PHPUnit suite inventory and manual verification checklist.


Roadmap

Reserved for future versions (constants exist in Api/Data/PriceHistoryInterface, but no code writes them yet):

  • Per-customer-group price tracking (tier / group price types)
  • REST API write sources (api, api_override source labels)
  • Cart price rule (checkout promotion) disclosure — the v1.x salesrule.is_omnibus column was removed in v2.0.0 and may return as a separate feature

Changelog

v2.0.0 — 2026-07-18

Major refactor. Breaking changes — review before upgrading from v1.x:

Removed

  • Config field general/display_child_products (never implemented), constant OmnibusConfigInterface::XML_PATH_DISPLAY_CHILD_PRODUCTS, method Config::isDisplayChildProducts()
  • Methods Config::getSyncCronSchedule() / Config::getCleanupCronSchedule() (schedules are read by etc/crontab.xml directly)
  • DB column salesrule.is_omnibusdropped on setup:upgrade; any data in that column is lost — and the sales_rule_form.xml checkbox that wrote it
  • Redundant index MGDOO_OMNIBUS_HIST_PROD_WEB_TIME_IDX (the unique key covers the same prefix)
  • The magendoo.omnibus.cleanup queue topic and its consumer (cleanup deletes directly, no queue round-trip)
  • Admin grid filter options that were never written: sources API / API Override, price types Tier / Group (interface constants remain reserved)

Fixed / changed

  • Window query now applies the carry-in rule: the price in force before the window opened is part of the minimum, so a product with a long-stable price gets a correct reference price
  • History retention (omnibus:history:clean and the cleanup cron) always keeps the newest pre-cutoff row per product/website/customer group — the future carry-in
  • Catalog rule changes, imports, config changes, and drift sync now publish to the message queue instead of doing bulk work inline; product save stays synchronous
  • Drift-sync cron pre-filters with a single SQL query per website and queues only genuinely drifted products
  • Config-change recompute is gated on the changed paths (enabled, period_in_days, display_mode)
  • PLP label implemented (pricing render plugin, pdp_and_plp mode); previously advertised but missing
  • Special price date handling: a special_from_date of today is active from the start of the day
  • All timestamps generated in UTC via the framework date library
  • Admin: ACL split into view/delete/manage/configuration; destructive endpoints POST-only; Restore button hidden without the manage resource
  • CLI commands exit with an error when the module is disabled; restore prints real inserted/coverage counts
  • Data patches are re-runnable (skip attribute creation when the attribute exists)

Notes

  • Product deletion also deletes that product's price history (ON DELETE CASCADE on the history table). If you need audit history to survive product deletion, export before deleting products.
  • composer.json version 2.0.0; module description updated to match actual behavior.

v1.0.0 — 2026-04-16

Initial release:

  • Price capture from admin save, catalog rules, Magento Import, config change, nightly cron
  • Anchored 30-day window algorithm
  • Async queue processing (MySQL-backed)
  • Admin price history grid with filters, mass-delete, and restore
  • CLI commands, omnibus_price and omnibus_hide EAV product attributes
  • PHPUnit unit test suite

License

MIT — see the license header in each source file.
Copyright © Magendoo (https://magendoo.com)

No changelog yet

The vendor hasn't published a changelog. Tagged releases appear in the Versions tab.

Versions
Version Stability QA Status Compatibility Released
2.0.1 stable Fail Magento 2.4.7-2.4.9 Details 2026-07-20 07:14:09
2.0.0 stable Not tested Not yet tested Details 2026-07-18 20:41:56
1.0.0 stable Not tested Not yet tested Details 2026-04-16 12:07:42

Requires 10

Package Constraint
magento/framework >=103.0.0
magento/module-backend >=102.0.0
magento/module-catalog >=104.0.0
magento/module-catalog-rule >=101.2.0
magento/module-eav >=102.1.0
magento/module-sales-rule >=101.2.0
magento/module-store >=101.0.0
magento/module-tax >=100.4.0
magento/module-ui >=101.2.0
php >=8.1

Requires-dev 2

Package Constraint
phpstan/phpstan ^1.10 || ^2.0
phpunit/phpunit ^10.5

No QA results yet

QA pipelines haven't run for this version. Compatibility and quality results appear here once the vendor publishes a tagged release that gets ingested.

License
MIT
Authors
  • Magendoo

More from magendoo

View vendor
Make it pay

Turn an existing module into recurring revenue.

If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.