# etechflow/module-order-email-editor

> Edit the customer email on a placed order, optionally sync to the linked customer account, keep an audit trail of every change. Admin-only, Hyvä-safe. Magento Open Source + Adobe Commerce compatible.

`composer require etechflow/module-order-email-editor`

Canonical URL: https://packagento.com/etechflow/module-order-email-editor

## At a glance

- **Vendor**: etechflow (https://packagento.com/etechflow.md)
- **Latest version**: 1.2.4 — released 2026-06-22
- **Pricing**: Free
- **Package type**: Magento 2 module
- **Status**: active, accepting new buyers

## Installation

Packagento is licence-gated, so even free packages need a licence on a project before Composer can resolve them.

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

2. **Add the package to your account.** Open https://packagento.com/etechflow/module-order-email-editor and complete the free checkout. A licence is minted automatically.

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 etechflow/module-order-email-editor:*
   bin/magento setup:upgrade
   bin/magento setup:di:compile
   bin/magento cache:flush
   ```

## What it does

Edit the customer email on a placed order, optionally sync to the linked customer account, keep an audit trail of every change. Admin-only, Hyvä-safe. Magento Open Source + Adobe Commerce compatible.

## README

Edit the customer email address on a placed Magento order. Fix typos, handle customer-service requests, keep a complete audit trail of every change. Admin-only. Hyvä-safe by design.

Commercial eTechFlow module. Per-domain HMAC license or eTechFlow bundle key activates the module on your production host. Dev / staging / `*.magento.cloud` / `localhost` etc. auto-detect and bypass licensing.

### What it adds

- **Edit Email button** on every admin order detail page (Order & Account Information panel)
- A modal: current email shown, new email input, "also update the linked customer account" checkbox
- **Email Change History grid** at *Sales → Operations → Order Email Change History* — every change with admin user, IP, timestamp
- Atomic DB update of every place Magento stores the email (order, addresses, all 4 grid tables, optional customer record, defensive quote sync)

### Features

| | |
|---|---|
| Edit misspelled email on a placed order | ✓ |
| Update billing + shipping address rows on the order | ✓ |
| Auto-reindex Magento's order/invoice/shipment/creditmemo grid tables | ✓ |
| Optionally update the linked `customer_entity.email` | ✓ (disabled for guest orders) |
| Defensive quote-table sync if the original quote still exists | ✓ |
| Full audit log with admin user, IP, timestamp | ✓ |
| Standard Magento ACL — granular per-role permissions | ✓ |
| Per-domain HMAC licensing + bundle key support | ✓ |
| Tideways span instrumentation (`ETechFlow_OEE_UpdateOrderEmail`) | ✓ |
| Verify CLI (`etechflow:oee:verify`) | ✓ |
| No frontend dependencies (admin-only module) | ✓ |

### Compatibility

| Platform | Status |
|---|---|
| Magento Open Source 2.4.4 – 2.4.8 | ✓ |
| Adobe Commerce 2.4.4 – 2.4.8 | ✓ |
| Hyvä themes (any version) | ✓ (admin-only — Hyvä re-skins the storefront only) |
| PHP 8.1 / 8.2 / 8.3 / 8.4 | ✓ |
| MySQL 8 / MariaDB 10.6+ | ✓ |

### Installation

```bash
## Option A — Composer
composer require etechflow/module-order-email-editor:^1.0
bin/magento module:enable ETechFlow_OrderEmailEditor
bin/magento setup:upgrade
bin/magento setup:di:compile      # production mode only
bin/magento setup:static-content:deploy -f en_GB  # production mode only
bin/magento cache:flush

## Option B — Manual drop-in
cp -r ETechFlow/OrderEmailEditor app/code/ETechFlow/OrderEmailEditor
bin/magento module:enable ETechFlow_OrderEmailEditor
bin/magento setup:upgrade
bin/magento setup:di:compile      # production mode only
bin/magento cache:flush
```

The `setup:upgrade` step creates one new database table: `etechflow_email_change_history`.

### Licensing

**Admin → Stores → Configuration → eTechFlow → Order Email Editor → License**

| Field | Default | What it does |
|---|---|---|
| **Production Environment** | Yes | Yes = check the license key against the current domain. No = run at full features without a key (use on dev/staging on non-standard domains). |
| **License Key** | (empty) | Paste the per-domain key from your purchase email. |

If you bought the eTechFlow bundle, enter the bundle key under any module's *License* section — it activates all eTechFlow modules at once.

### Permissions (ACL)

Three new resources appear under **System → Permissions → User Roles → Role Resources**:

- `ETechFlow_OrderEmailEditor::edit_email` — required to use the modal & POST to the update endpoint
- `ETechFlow_OrderEmailEditor::view_history` — required to view the history grid
- `ETechFlow_OrderEmailEditor::config` — required to view the admin config section

By default all three are granted to *Administrators*. Assign granularly to limited roles as needed.

### Usage

1. **Admin → Sales → Orders → pick any order**
2. In the **Order & Account Information** panel you'll see an **Edit Email** button under the existing email
3. Click it. A modal opens with:
   - Current email shown for confirmation
   - New email input
   - "Also update the linked customer account" checkbox (hidden for guest orders)
4. Submit. The modal returns a success message, the email on the page updates inline, and a new row is written to `etechflow_email_change_history`

#### Viewing change history

**Admin → Sales → Operations → Order Email Change History** (or the URL `/admin/order_email_editor/history/index`)

Standard Magento UI Component grid with filterable columns: increment ID, old email, new email, admin who changed it, customer-record-updated flag, IP, timestamp.

### Smoke test

After installing, confirm the module is healthy:

```bash
bin/magento etechflow:oee:verify
```

Should print `✅ ALL CHECKS PASSED. v1.0.0 verified.`

### What this module touches in the database

When the **Change Email** button is clicked, the module updates these tables in a single transaction:

| Table | Column | How |
|---|---|---|
| `sales_order` | `customer_email` | via `OrderRepository::save()` |
| `sales_order_address` | `email` (both billing + shipping rows) | via `OrderRepository::save()` |
| `sales_order_grid` | `customer_email` | **auto** (Magento's `sales_order_save_after` observer reindexes) |
| `sales_invoice_grid` | `customer_email` | auto, same observer |
| `sales_creditmemo_grid` | `customer_email` | auto, same observer |
| `sales_shipment_grid` | `customer_email` | auto, same observer |
| `customer_entity` | `email` | **only if** checkbox is on AND `sales_order.customer_id` is set |
| `quote` + `quote_address` | `customer_email` / `email` | defensive — only if the original quote row still exists |
| `etechflow_email_change_history` | new row | inserted with old/new email, admin info, IP |

### Uninstall

_(README truncated for .md surface. Full README on https://packagento.com/etechflow/module-order-email-editor.)_

## Changelog

All notable changes to this module. Adheres to [Semantic Versioning](https://semver.org/).

---

### [1.1.0] — 2026-06-04 — Portal licensing, server-IP binding & billing-period plans

Adds the eTechFlow Store Portal licensing layer to the module (the HMAC per-module
and shared bundle keys keep working for offline / suite activation).

#### Added

- **Hybrid `Model/LicenseValidator.php`** — SP-XXXX subscription keys validate live
  against the eTechFlow portal with a **domain + server-IP** two-factor binding
  (strict: no offline grace, no stale issued-key fallback). HMAC per-module and
  shared bundle keys unchanged. Dev hosts + `Production Environment = No` bypass.
- **In-admin Stripe checkout + license gate** — `Controller/Adminhtml/License/`
  (`Gate`, `Checkout`, `Activated`) + dark plan-card gate page and success page.
  Billing-period plans: **Weekly $5 / Monthly $15 / Yearly $150** (one full-feature
  module, billed by period), matching the portal subscription model.
- **License + Stripe admin config** — license key, issued-key, portal URL, bundle
  key, and Stripe keys under *Stores → Config → eTechFlow → Order Email Editor*.
- **`etc/db_schema_whitelist.json`** — fixes the missing whitelist so the
  `etechflow_email_change_history` table is created on `setup:upgrade` (the 1.0.x
  package shipped without it).

#### Changed

- **License-gated entry points** — the Edit History grid redirects to the gate when
  unlicensed; the Update endpoint already returns 403 via `Config::isEnabled()`.
- **Customer-account sync** is now a licensed feature (`Config::isCustomerSyncAllowed()`,
  plan flag `customer_sync`; included on all billing-period plans).

---

### [1.0.2] — 2026-05-22 — Move admin menu under eTechFlow top-level sidebar

#### Changed

- **OEE admin pages relocated to a dedicated "eTechFlow" sidebar entry.** Previously the Edit History list lived under `Sales → Sales Operation`. Now it sits as an `Order Email Editor` column inside a new top-level `eTechFlow` sidebar entry (clusters with other paid-extension vendors above Magento's Stores). Matches the pattern Amasty / Magefan / MageWorx use.
- Each eTechFlow module declares the same `eTechFlow::root` + `eTechFlow::settings` + `eTechFlow::configuration` entries — Magento merges by id, so installing N modules still produces exactly one `eTechFlow` sidebar group.

#### Migration

```
composer update etechflow/module-order-email-editor
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f
bin/magento cache:flush
```

Admin URL routes unchanged (`order_email_editor/history/index` still works). No schema or behaviour changes — pure menu-layout adjustment.

---

### [1.0.0] — 2026-05-19

#### Initial commercial release

Edit the customer email on a placed order. Fix typos, handle customer requests, keep an audit trail. Admin-only. Hyvä-safe by design.

##### Added

_(Changelog truncated for .md surface. Full history on https://packagento.com/etechflow/module-order-email-editor.)_

## Recent Versions

| Version | Released |
|---|---|
| 1.2.4 | 2026-06-22 |
| 1.2.0 | 2026-06-06 |
| 1.1.0 | 2026-06-04 |
| 1.0.2 | 2026-05-22 |
| 1.0.1 | 2026-05-21 |

## Dependencies

### Require

| Package | Constraint |
|---|---|
| magento/framework | ^103.0\|\|^104.0 |
| magento/module-backend | ^102.0\|\|^103.0 |
| magento/module-config | ^101.2\|\|^102.0 |
| magento/module-customer | ^103.0\|\|^104.0 |
| magento/module-quote | ^101.2\|\|^102.0 |
| magento/module-sales | ^103.0\|\|^104.0 |
| magento/module-store | ^101.1\|\|^102.0 |
| magento/module-ui | ^101.2\|\|^102.0 |
| php | ~8.1.0\|\|~8.2.0\|\|~8.3.0\|\|~8.4.0 |

### Suggest

| Package | Constraint |
|---|---|
| etechflow/module-next-day-eligibility | Part of the eTechFlow module bundle — one bundle key activates every eTechFlow module. |

## Quality

Latest release (1.2.4) 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 | not tested |


### 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 | Fail | 139 | 8 errors, 131 warnings (ruleset: Magento2) — 52 auto-fixable with phpcbf |
| PHPMD | Warning | 25 | 25 rule violations (MissingImport:7, UnusedFormalParameter:5, EmptyCatchBlock:4, CyclomaticComplexity:3, NPathComplexity:3) |
| Cpd | Warning | 1 | 1 duplicated chunk spanning 29 total lines (min-lines=5, min-tokens=70) |
| 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 | – | – | 14 | N/A |


### 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

Free. A licence is still minted on checkout and bound to your project for Composer access — no payment step.

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=["etechflow/module-order-email-editor"],
  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

etechflow is a Magento 2 vendor on Packagento. See https://packagento.com/etechflow.md for their full catalogue.

