PHPackages                             lobbster/module-discount-filter - 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. [Search &amp; Filtering](/categories/search)
4. /
5. lobbster/module-discount-filter

ActiveMagento2-module[Search &amp; Filtering](/categories/search)

lobbster/module-discount-filter
===============================

Indexed is\_discounted flag for layered navigation and Elastic/OpenSearch facets

1.0.0(1mo ago)01↑2900%proprietaryPHPPHP &gt;=8.2

Since Apr 22Pushed 1mo agoCompare

[ Source](https://github.com/lobbster-doo/discount-filter)[ Packagist](https://packagist.org/packages/lobbster/module-discount-filter)[ RSS](/packages/lobbster-module-discount-filter/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (11)Versions (2)Used By (0)

Lobbster Discount Filter
========================

[](#lobbster-discount-filter)

Adds an indexed boolean product attribute — **`is_discounted`** — derived from `catalog_product_index_price` (`final_price < price`, tier prices included). The module powers a Sale-style layered-navigation facet and an Elastic/OpenSearch-ready attribute without relying on ad-hoc SQL at render time.

A staging table, **`lobbster_discountfilter_flag`**, stores the authoritative **per website × customer group** truth. The EAV attribute is a **website-level roll-up** of that staging data, scoped for layered navigation and search facets.

Installation
------------

[](#installation)

Install via Composer:

```
composer require lobbster/module-discount-filter
```

Enable the module, run setup, and reindex the affected indexers:

```
bin/magento module:enable Lobbster_DiscountFilter
bin/magento setup:upgrade
bin/magento indexer:reindex catalog_product_price lobbster_discountfilter catalog_product_flat catalogsearch_fulltext
```

Commands
--------

[](#commands)

Full rebuild — staging + EAV rollup + downstream flat/fulltext chunking:

```
bin/magento lobbster:discountfilter:rebuild
```

Kill switch — truncate staging and zero `is_discounted` for every `catalog_product_website` row:

```
bin/magento lobbster:discountfilter:reset
```

Attribute
---------

[](#attribute)

PropertyValueCode`is_discounted`ScopeWebsiteLayered navigationYes — Sale-style facet. Only the **“Yes”** option renders; if nothing in the result set is discounted the whole filter block is hidden. The **“Yes”** label is configurable (see **Configuration**).Indexers
--------

[](#indexers)

IDRole`lobbster_discountfilter`Rebuilds staging + EAV roll-up. Depends on `catalog_product_price` and `catalogrule_product`.`catalog_product_flat`Declared to depend on `lobbster_discountfilter`, so flat tables rebuild after `is_discounted` changes.Materialized-view subscriptions (`etc/mview.xml`): `catalog_product_index_price`, `catalog_product_super_link`, `catalog_product_website`, `cataloginventory_stock_status`, `catalogrule_product_price`, `customer_group`.

Configuration
-------------

[](#configuration)

**Stores → Configuration → Lobbster → Discount Filter**

FieldDefaultNotes**Enable Indexer**YesWhen disabled, indexer `execute*` methods no-op. Use `lobbster:discountfilter:reset` to zero existing values.**EAV Roll-up Strategy**`any_group``any_group` marks the attribute true if **any** customer group is discounted on the website. `not_logged_in_only` only considers guest / group 0.**Discount facet option label**`Yes``Yes` matches the native Sale filter style; `On Sale` gives explicit wording. Store-scope supported.**Indexer Batch Size**`5000`Products per batch during a full rebuild.**Downstream Reindex Chunk Size**—Chunk size for `catalog_product_flat` / `catalogsearch_fulltext` `reindexList` calls.### Facet block title vs option label

[](#facet-block-title-vs-option-label)

Layered navigation shows **two different labels**, edited in different places:

What you seeWhere to change it**Facet block heading** (e.g. “Is Discounted”)**Admin → Stores → Attributes → Product → `is_discounted` → Labels** (default + store view labels). This module does **not** hardcode the group title. Flush Blocks HTML / Full Page cache after changes.**Single facet option** (“Yes” vs “On Sale”)**Stores → Configuration → Lobbster → Discount Filter → Layered navigation → Discount facet option label**. Kept separate from the attribute’s boolean option source so the storefront can match Sale-style wording without touching EAV options.API for non-search code paths
-----------------------------

[](#api-for-non-search-code-paths)

The EAV roll-up is intentionally lossy at the customer-group level. For accurate group-scoped checks (cart rules, promo blocks, bespoke reports), inject the staging-backed interface:

```
use Lobbster\DiscountFilter\Api\DiscountFlagLookupInterface;

public function __construct(private readonly DiscountFlagLookupInterface $lookup) {}

$this->lookup->isDiscounted($productId, $websiteId, $customerGroupId);
$this->lookup->filterDiscounted($productIds, $websiteId, $customerGroupId);
```

Supported product types
-----------------------

[](#supported-product-types)

The indexer computes `is_discounted` for **simple, virtual, downloadable, and configurable** products. **Configurable** parents only consider **saleable** children (`inventory_stock_*` when MSI is enabled, otherwise `cataloginventory_stock_status`). **Bundle** and **grouped** products remain `0` until phase-2 logic is added.

Operational notes
-----------------

[](#operational-notes)

1. Keep **`catalog_product_price`** up to date; `is_discounted` is derived from its `final_price` / `price`.
2. Tier pricing counts as discounted when it lowers `final_price` below `price`.
3. With **flat catalog product** enabled, the pipeline triggers `catalog_product_flat` for affected IDs after flag changes.
4. **Elastic/OpenSearch** facets can’t natively facet `is_discounted` per customer group — use the staging-backed API above for group-accurate logic.

Testing
-------

[](#testing)

```
./vendor/bin/phpunit --configuration dev/tests/unit/phpunit.xml.dist app/code/Lobbster/DiscountFilter/Test/Unit
```

Coding standard
---------------

[](#coding-standard)

Run from the **Magento project root**:

```
vendor/bin/phpcs --standard=app/code/Lobbster/DiscountFilter/phpcs.xml app/code/Lobbster/DiscountFilter
# or:
composer cs:discountfilter
```

The module ships `phpcs.xml` referencing **Magento2** + **Magento2Framework** from `magento/magento-coding-standard`. **Adobe copyright sniffs** are disabled for this path (see `rule severity="0"` in the module `phpcs.xml` and the matching `exclude-pattern` in the project-root `phpcs.xml`) so Lobbster file headers aren’t compared to Adobe’s copyright. All other rules — including PHPDoc sniffs — apply in full.

License
-------

[](#license)

Use, copy, modify, and distribute this software **free of charge for non-commercial purposes only**. Commercial use — including selling, sublicensing for a fee, or using the software primarily to operate a business for profit — is **not permitted** without separate written permission from the copyright holder.

```
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

```

Canonical text: [`LICENSE`](LICENSE).

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance90

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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

Unknown

Total

1

Last Release

49d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9170a971f75c31822e5bb80c2bc12453e0e4cb3f26cc3c97e0f3030efdb05b36?d=identicon)[sinisa.colic](/maintainers/sinisa.colic)

---

Top Contributors

[![sinisa-colic](https://avatars.githubusercontent.com/u/4529208?v=4)](https://github.com/sinisa-colic "sinisa-colic (9 commits)")

### Embed Badge

![Health badge](/badges/lobbster-module-discount-filter/health.svg)

```
[![Health](https://phpackages.com/badges/lobbster-module-discount-filter/health.svg)](https://phpackages.com/packages/lobbster-module-discount-filter)
```

###  Alternatives

[dotdigital/dotdigital-magento2-extension

Dotdigital for Magento 2

50390.4k20](/packages/dotdigital-dotdigital-magento2-extension)[mollie/magento2

Mollie Payment Module for Magento 2

1131.8M12](/packages/mollie-magento2)[run-as-root/magento2-prometheus-exporter

Magento2 Prometheus Exporter

68353.9k](/packages/run-as-root-magento2-prometheus-exporter)[swissup/module-search-mysql-legacy

Legacy mysql search for magento 2.4

10486.4k](/packages/swissup-module-search-mysql-legacy)[buckaroo/magento2

Buckaroo Magento 2 extension

32414.8k7](/packages/buckaroo-magento2)[amzn/amazon-pay-magento-2-module

Official Magento2 Plugin to integrate with Amazon Pay

108521.2k1](/packages/amzn-amazon-pay-magento-2-module)

PHPackages © 2026

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