PHPackages                             magendoo/module-base-price - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. magendoo/module-base-price

ActiveMagento2-module[Utility &amp; Helpers](/categories/utility)

magendoo/module-base-price
==========================

EU Base Price (Grundpreis) display for Magento 2. Shows price per reference unit (kg, litre, m) on product pages, category listings, search results and cart. Compliant with EU Price Indication Directive 98/6/EC and German PAngV.

1.0.0(1mo ago)401MITPHPPHP &gt;=8.1CI failing

Since Apr 13Pushed 1mo agoCompare

[ Source](https://github.com/magendooro/module-base-price)[ Packagist](https://packagist.org/packages/magendoo/module-base-price)[ Fund](https://magendoo.ro)[ RSS](/packages/magendoo-module-base-price/feed)WikiDiscussions master Synced 1w ago

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

Magendoo Base Price — Magento 2 Module
======================================

[](#magendoo-base-price--magento-2-module)

Displays a per-unit reference price (**Grundpreis**) next to every product's selling price across product pages, category listings, search results, and the shopping cart.

A customer buying a 300 g shampoo at €4.99 also sees **"Base price: €16.63 / 1 kilogram"**, enabling direct price comparison across different pack sizes and brands.

---

Legal background
----------------

[](#legal-background)

Displaying a unit reference price is **legally required** in several jurisdictions:

- **Germany** — Preisangabenverordnung (PAngV §4)
- **EU member states** — Price Indication Directive 98/6/EC, updated by Directive 2019/2161 (Omnibus)

The obligation applies to products sold by weight, volume, length, area, or piece count that are offered in different pack sizes. Consult your legal adviser to determine your specific requirements.

---

Requirements
------------

[](#requirements)

DependencyVersionMagento Open Source / Adobe Commerce2.4.xPHP8.1 or higher---

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

[](#installation)

### Via Composer (recommended)

[](#via-composer-recommended)

```
composer require magendoo/module-base-price
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
```

### Manual

[](#manual)

```
mkdir -p app/code/Magendoo/BasePrice
# Copy all module files into that directory
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
```

`setup:upgrade` creates the `magendoo_baseprice_unit` table, adds four EAV product attributes, and seeds nine SI measurement units.

---

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

[](#configuration)

Navigate to **Stores → Configuration → Magendoo Extensions → Base Price**.

### General

[](#general)

FieldDefaultDescriptionEnable Base PriceYesMaster switch. Disabling this hides base prices everywhere.### Product Page

[](#product-page)

FieldDefaultDescriptionEnable on Product PagesYesShow base price on individual product pages.Display Template`Base price: {{unit_price}} / {{reference_amount}} {{reference_unit}}`Output format. Supports all template variables.CSS Class`base-price`Class applied to the wrapping ``.### Category &amp; Search

[](#category--search)

FieldDefaultDescriptionEnable on Category PagesYesShow base price on category listing pages.Category Display Template`({{unit_price}} / {{reference_amount}} {{reference_unit}})`Output format for listing cards.Enable on Search ResultsYesShow base price on catalogsearch result pages.### Cart

[](#cart)

FieldDefaultDescriptionEnable on Cart PageYesShow base price in the shopping cart item rows.Cart Display Template`Base price: {{unit_price}} / {{reference_amount}} {{reference_unit}}`Output format for cart rows.Enable on Mini-CartYesReserved for future Knockout.js integration.---

Template variables
------------------

[](#template-variables)

All display templates accept the following placeholders:

VariableDescriptionExample output`{{unit_price}}`Formatted price per reference unit€16.63`{{reference_amount}}`Reference quantity1`{{reference_unit}}`Reference unit labelkilogram`{{product_amount}}`Numeric amount in the product300`{{measure_unit}}`Name of the product's measurement unitgram`{{product_price}}`Selling price formatted via store currency€4.99Unknown placeholders are left intact, so you can safely mix in static text.

---

Formula
-------

[](#formula)

```
base_price = (selling_price ÷ product_amount) × (reference_amount × rate)

```

Where **rate** is the conversion factor from the product unit to the reference unit (e.g. 1 000 for gram → kilogram).

**Examples:**

ProductPriceAmountUnitCalculationBase priceShampoo€4.99300 ggram(4.99 ÷ 300) × (1 × 1 000)€16.63 / kgWine€9.990.75 llitre(9.99 ÷ 0.75) × (1 × 1)€13.32 / litreRibbon€5.00200 cmcentimetre(5.00 ÷ 200) × (1 × 100)€2.50 / metre6-pack€5.946piece(5.94 ÷ 6) × (1 × 1)€0.99 / pieceThe result is rounded to 4 decimal places before formatting.

### Reference amount override

[](#reference-amount-override)

A product can override the unit's default reference amount. Set **Reference Amount** to `0.1` on a gram-unit product to show the price per 100 g instead of per kilogram:

```
(4.99 ÷ 300) × (0.1 × 1 000) = €1.66 / 100 g

```

---

Unit management
---------------

[](#unit-management)

Navigate to **Catalog → Base Price Units** in the admin panel.

Nine SI units are pre-installed:

IDUnitReference unitRate1gramkilogram1 0002milligramkilogram1 000 0003kilogramkilogram14millilitrelitre1 0005centilitrelitre1006litrelitre17centimetremetre1008metremetre19piecepiece1### Adding a custom unit

[](#adding-a-custom-unit)

Click **Add New Unit** and fill in:

FieldDescriptionExampleNameDisplay name of the product unitfluid ounceReference Unit LabelThe reference unit shown in the outputlitreRateMultiplier to convert to the reference unit33.814Reference AmountDefault quantity shown in the output1PositionSort order in the admin grid100StatusActive / InactiveActive---

Configuring products
--------------------

[](#configuring-products)

### Admin UI

[](#admin-ui)

Open any product in the admin and locate the **Base Price** panel (below the standard price fields):

FieldDescriptionEnable Base PriceOverride the module-level enable/disable for this specific product.Product AmountNumeric quantity contained in the package (e.g. `300` for 300 g).UnitSelect from the unit list (gram, millilitre, etc.).Reference AmountLeave blank to use the unit's default. Set a value to show a custom reference (e.g. `0.1` for "per 100 g").### REST API — set a product's base price

[](#rest-api--set-a-products-base-price)

```
TOKEN=$(curl -s -X POST https://your-store.com/rest/V1/integration/admin/token \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"your-password"}' | tr -d '"')

# Set base price (300 g, gram unit = ID 1)
curl -X PUT https://your-store.com/rest/V1/baseprice/products/24-MB01 \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "productBasePrice": {
      "sku": "24-MB01",
      "product_amount": 300,
      "unit_id": 1
    }
  }'

# Enable it on the product
curl -X PUT https://your-store.com/rest/V1/products/24-MB01 \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "product": {
      "sku": "24-MB01",
      "custom_attributes": [
        {"attribute_code": "baseprice_is_enabled", "value": "1"}
      ]
    }
  }'
```

---

REST API reference
------------------

[](#rest-api-reference)

### Units (admin token required)

[](#units-admin-token-required)

MethodEndpointDescriptionGET`/V1/baseprice/units`List units (supports `searchCriteria`)GET`/V1/baseprice/units/:unitId`Get unit by IDPOST`/V1/baseprice/units`Create a unitPUT`/V1/baseprice/units/:unitId`Update a unitDELETE`/V1/baseprice/units/:unitId`Delete a unitCreate a unit:

```
curl -X POST https://your-store.com/rest/V1/baseprice/units \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "unit": {
      "name": "fluid ounce",
      "reference_unit_label": "litre",
      "rate": 33.814,
      "reference_amount": 1,
      "position": 100,
      "active": true
    }
  }'
```

> **Note:** The active flag is sent as `active`, not `is_active`. Magento's serialiser strips the `is` prefix from getter method names when building the response body.

### Product base price (admin token required)

[](#product-base-price-admin-token-required)

MethodEndpointDescriptionGET`/V1/baseprice/products/:sku`Get base price config for a productPUT`/V1/baseprice/products/:sku`Set base price configDELETE`/V1/baseprice/products/:sku`Remove base price config### Calculator (anonymous)

[](#calculator-anonymous)

```
GET /V1/baseprice/calculate?price=4.99&productAmount=300&unitId=1

```

Returns the raw base price as a float. Optional parameter: `referenceAmountOverride`.

```
curl 'https://your-store.com/rest/V1/baseprice/calculate?price=4.99&productAmount=300&unitId=1'
# → 16.6333
```

---

Architecture notes
------------------

[](#architecture-notes)

- **EAV attributes** — Four product attributes (`baseprice_is_enabled`, `baseprice_product_amount`, `baseprice_unit_id`, `baseprice_reference_amount`) are registered with `used_in_product_listing = true` so they load in category and search collections.
- **Listing injection** — A plugin on `Magento\Catalog\Block\Product\AbstractProduct::getProductDetailsHtml()` appends the base price HTML to every product card, covering all product types without type-specific renderer registration.
- **Cart injection** — The cart block is a child of Magento's `additional.product.info` block. The cart item template iterates through its children and calls `setItem()` + `toHtml()` on each.
- **Product page** — A standard `Template` block is added via `catalog_product_view.xml` and the product block is retrieved directly from layout.
- **Template rendering** — `Model/TemplateRenderer` does a plain `str_replace` over `{{variable}}` placeholders. HTML escaping is the caller's responsibility; `priceCurrency->format()` handles currency formatting.

---

Releases and Packagist
----------------------

[](#releases-and-packagist)

### Creating a release

[](#creating-a-release)

Tag a version and push — the Release workflow runs tests then creates a GitHub release automatically:

```
git tag v1.2.0
git push origin v1.2.0
```

Version numbers follow [Semantic Versioning](https://semver.org). Update `CHANGELOG.md` and `composer.json` (`"version"`) before tagging.

### Publishing to Packagist

[](#publishing-to-packagist)

1. Go to [packagist.org/packages/submit](https://packagist.org/packages/submit) and enter:

    ```
    https://github.com/magendooro/module-base-price

    ```
2. After submission, enable **auto-update** so Packagist picks up new tags automatically:

    - In the Packagist package settings, copy the **webhook URL**
    - In the GitHub repository: Settings → Webhooks → Add webhook → paste the URL
    - Content type: `application/json`, events: Just the push event

    Alternatively, connect your GitHub account to Packagist (Settings → Profile → GitHub) which handles webhooks automatically.

### GitHub Secrets required for CI

[](#github-secrets-required-for-ci)

The workflows install Magento packages from `repo.magento.com`, which requires Marketplace credentials. Add these to the repository as **Actions secrets** (Settings → Secrets and variables → Actions):

SecretDescription`MAGENTO_MARKETPLACE_PUBLIC_KEY`Public key from [marketplace.magento.com/customer/accessKeys](https://marketplace.magento.com/customer/accessKeys/)`MAGENTO_MARKETPLACE_PRIVATE_KEY`Corresponding private keyWithout these secrets the CI runs will fail at the `composer install` step.

---

Running tests
-------------

[](#running-tests)

### PHPUnit (unit tests)

[](#phpunit-unit-tests)

```
# From the Magento root
vendor/bin/phpunit --filter Magendoo\\BasePrice app/code/Magendoo/BasePrice/Test/Unit
```

### Playwright (functional tests)

[](#playwright-functional-tests)

The functional test suite lives in `dev/tests/functional/playwright/tests/baseprice/` and covers:

- `baseprice-calculate-combinations.spec.js` — All nine seed units, `referenceAmountOverride`, edge cases, formula consistency (45 tests, no products or admin setup needed — hits the anonymous `/V1/baseprice/calculate` endpoint directly)
- `baseprice-product-display.spec.js` — Product detail page, category listing, cart page, disabled state (22 tests, sets up three sample products in `beforeAll` and restores them in `afterAll`)

```
cd dev/tests/functional/playwright
npx playwright test tests/baseprice/
```

---

Uninstall
---------

[](#uninstall)

```
bin/magento module:uninstall Magendoo_BasePrice
bin/magento setup:upgrade
bin/magento cache:flush
```

This removes the `magendoo_baseprice_unit` table and the four EAV product attributes.

---

License
-------

[](#license)

MIT — see [LICENSE](LICENSE) for details.

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance89

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community4

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

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

57d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/6ef4a3a58fa09cd06825953bc91392aa224ca399f491b77df13ac932cfcddeea?d=identicon)[florinel-chis](/maintainers/florinel-chis)

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/magendoo-module-base-price/health.svg)

```
[![Health](https://phpackages.com/badges/magendoo-module-base-price/health.svg)](https://phpackages.com/packages/magendoo-module-base-price)
```

###  Alternatives

[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)[baldwin/magento2-module-url-data-integrity-checker

Magento 2 module which can find potential url related problems in your catalog data

282806.2k](/packages/baldwin-magento2-module-url-data-integrity-checker)[loki/magento2-components

Core module for defining Alpine.js components with advanced AJAX features

1010.0k22](/packages/loki-magento2-components)[opengento/module-category-import-export

This module add the capability to import and export the categories from the back-office.

1310.2k1](/packages/opengento-module-category-import-export)[loki/magento2-admin-components

Admin Panel grids and forms created via Loki Components

173.7k7](/packages/loki-magento2-admin-components)

PHPackages © 2026

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