Flexible variant pricing with percentage calculations and fixed surcharges for Shopware 6.6/6.7.
Live Demo: Try all OXID eShop and Shopware plugins by Markus Michalski live β no installation, no risk. demo.markus-michalski.net
Ideal for products with size-dependent or option-based pricing:
| Feature | Description |
|---|---|
| Percentage Calculation | Variant price = Parent product x Percentage |
| Fixed Surcharges | Add absolute EUR amounts (positive or negative) |
| Combined Mode | Use both percentage AND surcharge together |
| Per-Variant Activation | Controlled individually via Custom Fields |
| Field-Specific Inheritance | Variant inherits custom field values from parent when not explicitly set |
| Storefront-Optimized | Only active in frontend, no admin overhead |
| Cart Integration | Correct prices in shopping cart and checkout |
| Configurable Rounding | Decimal places and rounding mode adjustable |
| NaN/INF Protection | Robust validation against invalid values |
| Shopware 6.6 + 6.7 | Compatible with both versions |
Variant Price = (Parent Price + Fixed Surcharge) x (Percentage / 100)
Parent Product Price: 100.00 EUR
| Variant | Percentage | Surcharge | Calculation | Result |
|---|---|---|---|---|
| Standard | 100% | 0 EUR | (100 + 0) x 1.00 | 100.00 EUR |
| Discount | 50% | 0 EUR | (100 + 0) x 0.50 | 50.00 EUR |
| With Zipper | 100% | +8 EUR | (100 + 8) x 1.00 | 108.00 EUR |
| Premium XL | 120% | +10 EUR | (100 + 10) x 1.20 | 132.00 EUR |
| Sale Item | 100% | -15 EUR | (100 - 15) x 1.00 | 85.00 EUR |
Safety: The calculated price never goes negative. If the formula results in a value below 0, it is automatically set to 0.00 EUR.
| Requirement | Version | Note |
|---|---|---|
| Shopware | 6.6.x or 6.7.x | Both major versions supported |
| PHP | 8.2+ | Tested with 8.2, 8.3 and 8.4 |
| License | Single installation | Incl. dev/staging, all sales channels |
1. Add Private Repository
Add the private Composer repository to your shop's composer.json:
{
"repositories": [
{
"type": "composer",
"url": "https://packeton.markus-michalski.net"
}
]
}
Note: Repository credentials will be provided upon license purchase. Private repositories are managed via Packeton.
2. Install Plugin
composer require mmd/sw6-variant-price-surcharge
When prompted for authentication, enter the credentials provided with your license.
3. Activate Plugin
bin/console plugin:refresh
bin/console plugin:install --activate MmdVariantPriceSurcharge
bin/console cache:clear
Recommendation: Prefer Shopware Store or Composer installation for easy updates and dependency management.
Update to the latest version:
composer update mmd/sw6-variant-price-surcharge
bin/console cache:clear
In Shopware Admin under Extensions > My Extensions > Variant Price Surcharge > Configuration:
| Setting | Default | Description |
|---|---|---|
| Decimal Places | 2 | Number of decimal places for rounded prices |
| Rounding Mode | HALF_UP | Rounding method (see below) |
Available Rounding Modes:
| Mode | Description | Example (2.545) |
|---|---|---|
| HALF_UP | Commercial (default) | 2.55 |
| HALF_DOWN | Round down at .5 | 2.54 |
| HALF_EVEN | Banker's Rounding | 2.54 |
| HALF_ODD | Round to odd | 2.55 |
The plugin automatically creates three custom fields at product level during installation:
| Technical Name | Type | Range | Description |
|---|---|---|---|
mmd_surcharge_enabled |
Boolean | - | Enable surcharge pricing |
mmd_surcharge_percentage |
Float | 0 - 1000 | Percentage (e.g., 50 for 50%) |
mmd_surcharge_fixed |
Float | -100,000 to +100,000 | Fixed surcharge in EUR |
Field-Specific Inheritance: When a custom field is NOT set on the variant, the parent product's value is automatically used. This allows you to set a fixed surcharge only on the parent and have it apply to all variants.
100 for 100%)8.00 for +8 EUR or -5.00 for -5 EUR discount)Important: The variant's own price is ignored. Only the parent product price with surcharge and percentage matters.
Parent Product "CRM Software": 49.00 EUR (1-User License)
| Variant | Percentage | Surcharge | Result |
|---|---|---|---|
| 1 User | 100% | 0 EUR | 49.00 EUR |
| 5 Users | 200% | 0 EUR | 98.00 EUR |
| 10 Users | 350% | 0 EUR | 171.50 EUR |
| Enterprise (unlimited) | 800% | +50 EUR | 442.00 EUR |
Parent Product "Pillow Cover": 12.00 EUR (Standard size 40x40)
| Variant | Percentage | Surcharge | Calculation | Result |
|---|---|---|---|---|
| 40x40 Standard | 100% | 0 EUR | (12 + 0) x 1.0 | 12.00 EUR |
| 40x40 + Zipper | 100% | +3 EUR | (12 + 3) x 1.0 | 15.00 EUR |
| 50x50 | 130% | 0 EUR | (12 + 0) x 1.3 | 15.60 EUR |
| 50x50 + Zipper | 130% | +3 EUR | (12 + 3) x 1.3 | 19.50 EUR |
Parent Product "T-Shirt": 25.00 EUR
| Variant | Percentage | Surcharge | Result |
|---|---|---|---|
| Single | 100% | 0 EUR | 25.00 EUR |
| 3-Pack | 100% | -5 EUR | 20.00 EUR |
| 5-Pack | 100% | -8 EUR | 17.00 EUR |
src/
βββ Core/Checkout/Cart/
β βββ VariantPriceProcessor.php # Cart Processor (Priority 1000)
βββ Exception/
β βββ ParentProductNotFoundException.php # HTTP 404 Exception
βββ Migration/
β βββ Migration1705200000CreateCustomFields.php
βββ Resources/config/
β βββ config.xml # Rounding settings
β βββ services.xml # Service container
βββ Service/
β βββ ParentPriceResolver.php # Parent lookup with request cache
β βββ SurchargeConfig.php # Readonly value object
β βββ SurchargeConfigReader.php # Custom field reader + validation
β βββ VariantPriceCalculator.php # Core calculation logic
βββ Subscriber/
β βββ ProductSubscriber.php # Storefront event listener
βββ MmdVariantPriceSurcharge.php # Main plugin class
| Component | Event / Interface | Task |
|---|---|---|
| ProductSubscriber | sales_channel.product.loaded |
Storefront price calculation |
| VariantPriceProcessor | CartProcessorInterface (Priority 1000) |
Cart price calculation |
| ParentPriceResolver | ResetInterface |
Request-level caching, N+1 prevention |
The ParentPriceResolver supports multi-currency:
Symptom: Despite configured custom fields, the variant shows the original price.
Check:
mmd_surcharge_enabled set to true?Solution:
bin/console cache:clear
Ensure all three custom fields are correctly filled. Check whether the value is set on the variant or the parent (inheritance).
Symptom: Product page shows correct price, but the cart shows a different one.
Check:
Solution:
The VariantPriceProcessor runs at Priority 1000 (late) to execute after most other processors. For conflicts with other pricing plugins, contact support.
Symptom: The custom fields mmd_surcharge_* do not appear on the product.
Check:
Solution:
bin/console plugin:refresh
bin/console plugin:install --activate MmdVariantPriceSurcharge
bin/console cache:clear
Caution: If custom fields were manually deleted, uninstall and reinstall the plugin.
Symptom: Prices deviate slightly from the expected calculation.
Check: Which rounding mode is configured?
Solution: Under Extensions > Variant Price Surcharge > Configuration, check the rounding mode and decimal places. Default: HALF_UP with 2 decimal places (commercial rounding).
Why do I see the original price in Admin?
This is intentional. The plugin is only active in the Storefront to not impact Admin performance. The correct price is displayed in the frontend and cart.
What happens if the calculated price is negative?
The plugin ensures prices never go below 0.00 EUR.
Can I use only percentage without surcharge?
Yes, simply set mmd_surcharge_fixed to 0 or leave it empty. The calculation becomes: Parent Price x Percentage.
Can I use only surcharge without percentage?
Yes, simply set mmd_surcharge_percentage to 100 or leave it empty. The calculation becomes: Parent Price + Surcharge.
Can surcharges be negative?
Yes, negative surcharges act as discounts. Example: -10 EUR reduces the base price by 10 EUR before percentage calculation.
What does Field-Specific Inheritance mean?
When a custom field is not explicitly set on the variant, the parent product's value is automatically used. This allows you to define a fixed surcharge centrally on the parent product.
What is the maximum percentage?
The plugin allows up to 1000% (10x the parent product price).
What is the maximum surcharge?
The plugin allows surcharges from -100,000 EUR to +100,000 EUR.
Does the plugin work with multi-currency?
Yes, the parent price is loaded currency-specifically. If no price is available in the current currency, the default currency is used.
Commercial License - Single installation license including:
See LICENSE file for full terms.
For questions and support:
Markus Michalski
Email: support@markus-michalski.net
See CHANGELOG.md in the repository for the full version history.