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.

Maintainers

Package info

github.com/magendooro/module-base-price

Type:magento2-module

pkg:composer/magendoo/module-base-price

Fund package maintenance!

magendoo.ro

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-04-13 13:29 UTC

This package is auto-updated.

Last update: 2026-04-13 13:29:49 UTC


README

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

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

Dependency Version
Magento Open Source / Adobe Commerce 2.4.x
PHP 8.1 or higher

Installation

Via Composer (recommended)

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

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

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

General

Field Default Description
Enable Base Price Yes Master switch. Disabling this hides base prices everywhere.

Product Page

Field Default Description
Enable on Product Pages Yes Show 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 <div>.

Category & Search

Field Default Description
Enable on Category Pages Yes Show base price on category listing pages.
Category Display Template ({{unit_price}} / {{reference_amount}} {{reference_unit}}) Output format for listing cards.
Enable on Search Results Yes Show base price on catalogsearch result pages.

Cart

Field Default Description
Enable on Cart Page Yes Show 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-Cart Yes Reserved for future Knockout.js integration.

Template variables

All display templates accept the following placeholders:

Variable Description Example output
{{unit_price}} Formatted price per reference unit €16.63
{{reference_amount}} Reference quantity 1
{{reference_unit}} Reference unit label kilogram
{{product_amount}} Numeric amount in the product 300
{{measure_unit}} Name of the product's measurement unit gram
{{product_price}} Selling price formatted via store currency €4.99

Unknown placeholders are left intact, so you can safely mix in static text.

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:

Product Price Amount Unit Calculation Base price
Shampoo €4.99 300 g gram (4.99 ÷ 300) × (1 × 1 000) €16.63 / kg
Wine €9.99 0.75 l litre (9.99 ÷ 0.75) × (1 × 1) €13.32 / litre
Ribbon €5.00 200 cm centimetre (5.00 ÷ 200) × (1 × 100) €2.50 / metre
6-pack €5.94 6 piece (5.94 ÷ 6) × (1 × 1) €0.99 / piece

The result is rounded to 4 decimal places before formatting.

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

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

Nine SI units are pre-installed:

ID Unit Reference unit Rate
1 gram kilogram 1 000
2 milligram kilogram 1 000 000
3 kilogram kilogram 1
4 millilitre litre 1 000
5 centilitre litre 100
6 litre litre 1
7 centimetre metre 100
8 metre metre 1
9 piece piece 1

Adding a custom unit

Click Add New Unit and fill in:

Field Description Example
Name Display name of the product unit fluid ounce
Reference Unit Label The reference unit shown in the output litre
Rate Multiplier to convert to the reference unit 33.814
Reference Amount Default quantity shown in the output 1
Position Sort order in the admin grid 100
Status Active / Inactive Active

Configuring products

Admin UI

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

Field Description
Enable Base Price Override the module-level enable/disable for this specific product.
Product Amount Numeric quantity contained in the package (e.g. 300 for 300 g).
Unit Select from the unit list (gram, millilitre, etc.).
Reference Amount Leave 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

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

Units (admin token required)

Method Endpoint Description
GET /V1/baseprice/units List units (supports searchCriteria)
GET /V1/baseprice/units/:unitId Get unit by ID
POST /V1/baseprice/units Create a unit
PUT /V1/baseprice/units/:unitId Update a unit
DELETE /V1/baseprice/units/:unitId Delete a unit

Create 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)

Method Endpoint Description
GET /V1/baseprice/products/:sku Get base price config for a product
PUT /V1/baseprice/products/:sku Set base price config
DELETE /V1/baseprice/products/:sku Remove base price config

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

  • 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 renderingModel/TemplateRenderer does a plain str_replace over {{variable}} placeholders. HTML escaping is the caller's responsibility; priceCurrency->format() handles currency formatting.

Releases and Packagist

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. Update CHANGELOG.md and composer.json ("version") before tagging.

Publishing to Packagist

  1. Go to 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

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):

Secret Description
MAGENTO_MARKETPLACE_PUBLIC_KEY Public key from marketplace.magento.com/customer/accessKeys
MAGENTO_MARKETPLACE_PRIVATE_KEY Corresponding private key

Without these secrets the CI runs will fail at the composer install step.

Running tests

PHPUnit (unit tests)

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

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

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

MIT — see LICENSE for details.