# storetown-media/module-surcharge-max

> Magento 2 surcharge module with category- and product-level rules, named reusable rules with per-product binding and bulk-assign from the catalog grid, tier and customer-group pricing, conditional caps (min/max/free-threshold) and country-based shipping restriction.

`composer require storetown-media/module-surcharge-max`

Canonical URL: https://packagento.com/storetown-media/module-surcharge-max

## At a glance

- **Vendor**: Storetown Media (https://packagento.com/storetown-media.md)
- **Latest version**: v2.4.1 — released 2026-08-23
- **Pricing**: $99.00/year, subscription
- **Package type**: Magento 2 module
- **Status**: active, accepting new buyers

## Installation

This is a paid package. The Packagento install flow is licence-gated, so a Composer install needs a licence + project + project credentials in place first.

1. **Sign in or create an account** at https://packagento.com/customer/account/.

2. **Purchase the package.** Open https://packagento.com/storetown-media/module-surcharge-max, add it to your cart, and complete checkout. A licence is minted automatically once payment clears.

3. **Create or pick a project, then activate the licence on it.**
   - Projects represent the Magento installs you deploy to. Manage them at https://packagento.com/projects/.
   - Activate the new licence on the project you'll deploy this package to. Activation is what generates the Composer credentials scoped to that project.

4. **Add the project credentials to your Magento codebase.**

   Grab the project's public + private key from https://packagento.com/projects/ (open the project, then its Credentials tab), and add them to `auth.json`:

   ```json
   {
     "http-basic": {
       "packagento.com": {
         "username": "ppk_live_...",
         "password": "psk_live_..."
       }
     }
   }
   ```

   Add the Packagento Composer repository to `composer.json`:

   ```json
   {
     "repositories": [
       { "type": "composer", "url": "https://packagento.com" }
     ]
   }
   ```

5. **Install and apply.**

   ```bash
   composer require storetown-media/module-surcharge-max:*
   bin/magento setup:upgrade
   bin/magento setup:di:compile
   bin/magento cache:flush
   ```

## What it does

Magento 2 surcharge module with category- and product-level rules, named reusable rules with per-product binding and bulk-assign from the catalog grid, tier and customer-group pricing, conditional caps (min/max/free-threshold) and country-based shipping restriction.

## README

Rule-based surcharges for Adobe Commerce and Magento Open Source. Adds a
configurable surcharge to the cart and order totals — per category, per product,
per customer group or by quantity tier — with caps, free-shipping thresholds and
country restrictions.

Built and maintained by [Storetown Media](https://www.storetown-media.de), an
e-commerce agency from Tornesch near Hamburg, and used in live customer projects.

### Features

- **Named, reusable rules.** Maintain surcharge rules under *Catalog → STM
  Surcharge Rules* (name, cost, calculation mode, active flag, sort order) and
  bind them to products.
- **Bulk assignment from the product grid.** Select products — including
  select-all across pages — and assign a rule in one pass via the
  *Assign STM Surcharge Rule* mass action.
- **Per-product override.** A product-level amount always wins over the rule.
- **Category surcharges.** Apply a surcharge to one or more category IDs.
- **Tier pricing.** Different surcharge amounts by quantity.
- **Customer group pricing.** Different amounts per customer group.
- **Conditions and limits.** Minimum amount, maximum cap, free above a cart
  subtotal, and restriction by shipping country.
- **Storefront notice.** Optional custom notice on the product page.
- **Multi-language.** German and English translations included.

#### Resolution order

For every quote item the surcharge is resolved in this order:

1. `stm_surcharge_amount` — per-product override
2. Rule cost — from the bound rule
3. Customer group price
4. Tier price
5. Section default

Products bound to a rule are eligible even without a category assignment.

### Requirements

- PHP 8.1 or newer
- Magento Open Source / Adobe Commerce 2.4.x (`magento/framework` >= 103.0)

### Installation

```bash
composer require storetown-media/module-surcharge-max
bin/magento module:enable STM_SurchargeMax
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
```

### Configuration

*Stores → Configuration → STM → Category Surcharge*

| Section | What it does |
|---|---|
| General Settings | Switch the module on or off |
| Surcharge Configuration | Category IDs, cost, label, calculation mode |
| Tier Pricing | Amounts by quantity |
| Customer Group Pricing | Amounts per customer group |
| Conditions & Limits | Minimum, cap, free-above threshold, country restriction |

Access is controlled by the ACL resource `STM_SurchargeMax::rules` with the
sub-permissions `rules_save`, `rules_delete` and `rules_assign`.

### Support

- E-mail: [support@storetown-media.de](mailto:support@storetown-media.de)
- Issues: https://github.com/storetown-media/module-surcharge-max/issues
- Website: https://www.storetown-media.de

### License

Proprietary — see [LICENSE.txt](LICENSE.txt). Changes are documented in
[CHANGELOG.md](CHANGELOG.md).

## Changelog

Alle nennenswerten Änderungen an diesem Modul werden in dieser Datei dokumentiert.
Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.1.0/)
und das Projekt folgt [Semantic Versioning](https://semver.org/lang/de/).

### [2.4.0] - 2026-04-26

> Multi-Rule-Engine. Admin kann benannte Surcharge-Regeln pflegen und mehreren
> Produkten per Bulk-Aktion aus dem Produkt-Grid zuordnen. Lean-Scope (Name,
> Kosten, Berechnungsmodus, Aktiv-Flag, Sortierung); Conditions/Date-Range
> sind für eine spätere Minor reserviert.

#### Hinzugefügt

- **Neue DB-Tabelle `stm_surchargemax_rule`** (`rule_id`, `name`, `cost`,
  `calculation_mode`, `is_active`, `sort_order`, `created_at`, `updated_at`).
  Index `(is_active, sort_order)` für die Resolver-Lookups.
- **Neues Produkt-Attribut `stm_surcharge_rule_id`** (int, Scope=Store,
  Attribut-Gruppe `STM Surcharge Max`). Quelle-Klasse
  `STM\SurchargeMax\Model\Config\Source\Rule` listet aktive Regeln nach
  `sort_order` / `name`. Setup-Patch `AddRuleAttribute`.
- **Resolver-Erweiterung in `Model/Total/Quote/Surcharge.php`** und
  `ViewModel/Product/ShippingNotice.php`. Neue Priority-Chain pro Item:
  `stm_surcharge_amount` (per-Produkt-Override) > Rule-Kosten > Customer-Group >
  Staffel > Section-Default. Rule-bound Produkte sind eligible auch ohne
  `stm_surcharge_enabled` und ohne Kategorie-Zuordnung. Per-Request-Memoization
  des Rule-Lookups.
- **Adminhtml-CRUD für Regeln**: Menüpunkt unter `Catalog → STM Surcharge
  Rules`, eigener Route-FrontName `stm_surchargemax`. Listing-Grid mit
  Filter/Sort/Bookmarks und Massenaktionen Delete / Enable / Disable;
  Edit-Formular mit Validation.
- **Mass-Action im Produkt-Grid: "Assign STM Surcharge Rule"**. Selektion
  wird via `Magento\Ui\Component\MassAction\Filter` aufgelöst (Select-All
  über Pages funktioniert), Chooser-Page zeigt Anzahl + Rule-Dropdown,
  `Magento\Catalog\Model\Product\Action::updateAttributes` setzt
  `stm_surcharge_rule_id` indexfreundlich in einem Pass.
- **ACL-Resourcen**: `STM_SurchargeMax::rules` (Sub-Nodes `rules_save`,
  `rules_delete`, `rules_assign`).
- **Übersetzungen**: 60 neue Strings in `i18n/de_DE.csv` und
  `i18n/en_US.csv`.

#### Geändert

- `etc/db_schema_whitelist.json` um die neue Tabelle erweitert.
- `etc/di.xml`: virtualType `STM\SurchargeMax\Model\ResourceModel\Rule\Grid\Collection`
  als SearchResult-Datasource für das Listing-UI-Component, plus Mapping in
  `Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory`.
- `Surcharge::collect`-Constructor: 6. Parameter
  `RuleCollectionFactory $ruleCollectionFactory` (war zuvor 5 nach
  License-Removal).

### [2.3.0] - 2026-04-26

> Erste Adobe-Marketplace-fähige Variante. Lizenzpflichtige Funktionen
> (STM_License) wurden entfernt; alle Settings sind ab dieser Version
> unter dem zentralen STM-Tab erreichbar.

#### Umbenannt

- **Modul umbenannt von `STM_RohreShipping` nach `STM_SurchargeMax`** (finaler
  Marketplace-Name). PHP-Namespace `STM\RohreShipping\` → `STM\SurchargeMax\`,
  Composer-Package `stm/module-rohre-shipping` → `storetown-media/module-surcharge-max`,
  Section-ID `stm_rohreshipping/*` → `stm_surchargemax/*`,
  ACL-Resource `STM_RohreShipping::config` → `STM_SurchargeMax::config`.
- DB-Spalten `stm_rohre_surcharge` / `base_stm_rohre_surcharge` und der
  Total-Code `stm_rohre_surcharge` bleiben **unverändert** (Persistence-Stabilität).
- Setup-Patches `MigrateConfigPaths` und `AddProductAttributes` deklarieren
  über `getAliases()` ihre alten Klassen-Namen, damit bereits angewendete
  Patches nicht erneut laufen.
- Neuer Setup-Patch `RenameSectionPath` migriert Konfigurationswerte aus dem
  Interim-Pfad `stm_rohreshipping/*` (Pre-Rename-Builds) idempotent nach
  `stm_surchargemax/*`.

#### Geändert

_(Changelog truncated for .md surface. Full history on https://packagento.com/storetown-media/module-surcharge-max.)_

## Recent Versions

| Version | Released |
|---|---|
| v2.4.1 | 2026-08-23 |

## Dependencies

### Require

| Package | Constraint |
|---|---|
| magento/framework | >=103.0 |
| php | >=8.1 |

### Require (dev)

| Package | Constraint |
|---|---|
| phpunit/phpunit | >=9.5 |

## Quality

Latest release (v2.4.1) fails the Packagento QA pipeline. Verdicts below are per-cell (Magento line × PHP version) for the matrixed tools, and run-once for the static / security tiers.


### Compatibility

Each Magento line is installed on its supported PHP versions, then the module is built (DI compile + static-content deploy). Cells show passed / failed / untested; staircase gaps render as `–`.

| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | Pass | Pass | – | – |
| 2.4.8 | – | Pass | Pass | – |
| 2.4.9 | – | – | Pass | Pass |


### Code Quality

Advisory checks against the module's source. Never affect the Compatibility verdict — a phpcs finding can't make a module incompatible.

#### Static Analysis

Coding standards (phpcs), mess detection (phpmd), copy-pasted code (cpd), PHP cross-version compatibility, composer.json validity. Each runs once for the whole module.

| Tool | Status | Findings | Summary |
|---|---|---|---|
| PHPCS | Pass | 0 |  |
| PHPMD | Warning | 47 | 47 rule violations (UnusedPrivateField:47) |
| Cpd | Pass | 0 |  |
| Composer validate | Info | 1 | valid; 1 advisory note (composer validate --strict) |

#### PHPStan

Type-checks the module against a real Magento install. Re-runs per Magento + PHP version because resolvable symbols differ between releases.

| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | 14 | 14 | – | – |
| 2.4.8 | – | 14 | 14 | – |
| 2.4.9 | – | – | 13 | 13 |


### Tests

Unit and integration suites run per Magento + PHP cell. Test failures speak to the module's behaviour, not its compatibility with a line, so they're reported here separately.

#### Unit Tests

| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | N/A | N/A | – | – |
| 2.4.8 | – | N/A | N/A | – |
| 2.4.9 | – | – | N/A | N/A |

#### Integration Tests

| Magento | PHP 8.2 | PHP 8.3 | PHP 8.4 | PHP 8.5 |
|---|---|---|---|---|
| 2.4.7 | N/A | N/A | – | – |
| 2.4.8 | – | N/A | N/A | – |
| 2.4.9 | – | – | N/A | N/A |


### Security

Dependency-advisory audit (composer audit) plus a source malware scan. A malware detection fails the version outright.

| Tool | Status | Findings | Summary |
|---|---|---|---|
| Composer audit | Pass | 0 |  |
| Malware scan | Pass | 0 |  |

## Licence and pricing

Subscription — $99.00/year, auto-renews until cancelled. Includes all minor + patch upgrades within the licensed major. One licence per project; cancelling stops auto-renewal but the existing licence keeps working until its end date.

Refundable within 14 days of first purchase via https://packagento.com/account/refunds/.

## Install via Claude Code or any MCP client

The Packagento MCP server can run the licence + project + Composer steps above in one tool call:

```
purchase_and_install_packages(
  composer_names=["storetown-media/module-surcharge-max"],
  project_id="proj_xxx"
)
```

This handles cart, checkout, licence minting, project activation, and writes auth.json credentials. Connect a client with `claude mcp add packagento https://mcp.packagento.com`. Full setup at https://packagento.com/docs/mcp-setup.

## Vendor

Storetown Media is a Magento 2 vendor on Packagento. See https://packagento.com/storetown-media.md for their full catalogue.

