2026-09-28 21:45:29 +02:00
|
|
|
# Setting it up
|
|
|
|
|
|
|
|
|
|
## Installing
|
|
|
|
|
|
|
|
|
|
Updates come from the plugin's own release feed, not wordpress.org.
|
|
|
|
|
|
|
|
|
|
1. Download `woocommerce-email-discount-manager.zip` from the latest release at
|
|
|
|
|
`https://gitea.nolimit.dk/kw/nolimit-discounts-dist/releases`.
|
|
|
|
|
2. **Plugins → Add New → Upload Plugin.**
|
|
|
|
|
3. Activate. WooCommerce must already be active — activation stops with an
|
|
|
|
|
error message if it is not, rather than activating into a broken state.
|
|
|
|
|
|
|
|
|
|
After the first install, the plugin offers its own updates in **Dashboard →
|
|
|
|
|
Updates** like any other. Nothing else needs configuring for that to work.
|
|
|
|
|
|
|
|
|
|
### If the update fails with "could not copy file"
|
|
|
|
|
|
|
|
|
|
The plugin directory is not writable by the user PHP runs as. This is a file
|
|
|
|
|
ownership problem on the server, not a fault in the release — WordPress cannot
|
|
|
|
|
overwrite files it does not own. Check it as the web server's user rather than
|
|
|
|
|
as root, because root can write everything and the check will pass for the
|
|
|
|
|
wrong reason:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
docker exec <container> sh -c 'find /var/www/html/wp-content/plugins/woocommerce-email-discount-manager -type f | wc -l'
|
|
|
|
|
docker exec -u 33 <container> sh -c 'find /var/www/html/wp-content/plugins/woocommerce-email-discount-manager -type f -writable | wc -l'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The two numbers must be equal. `33` is `www-data` on the Debian-based images;
|
|
|
|
|
confirm with `ps -o user,args -e | grep apache` before trusting it.
|
|
|
|
|
|
|
|
|
|
## The three screens
|
|
|
|
|
|
|
|
|
|
**WooCommerce → Nolimit Discounts** (also reachable under the shared **Nolimit**
|
|
|
|
|
menu) has three tabs.
|
|
|
|
|
|
|
|
|
|
### Groups
|
|
|
|
|
|
|
|
|
|
A group is a name, a discount percent, and a list of WooCommerce product
|
|
|
|
|
categories. The percent applies to products in those categories and nothing
|
|
|
|
|
else. Categories are ordered by drag and drop; the order is cosmetic.
|
|
|
|
|
|
|
|
|
|
### Emails
|
|
|
|
|
|
|
|
|
|
One row per email pattern. Each row picks **one** of Group, Coupon or Custom —
|
|
|
|
|
they are exclusive, and the form will not let a row carry two.
|
|
|
|
|
|
|
|
|
|
This is the screen where a decision is actually required: **how specific should
|
|
|
|
|
the pattern be?** A domain pattern (`@company.com`) gives the discount to every
|
|
|
|
|
current and future address at that company, including ones nobody has seen yet.
|
|
|
|
|
A fragment pattern (`john`) matches `john@anywhere.com` and also
|
|
|
|
|
`johnson@example.org`. If a discount is worth real money, use the full address.
|
|
|
|
|
|
|
|
|
|
### Shipping
|
|
|
|
|
|
2026-10-02 12:28:45 +02:00
|
|
|
Per group, per shipping method, one of **show**, **only** or **hide**.
|
2026-09-28 21:45:29 +02:00
|
|
|
|
2026-10-02 12:28:45 +02:00
|
|
|
**Show** offers the method to the group (and, once any method is shown, the
|
|
|
|
|
group is offered only the methods marked show or only). Nobody else is
|
|
|
|
|
affected. **Only** does the same and also *reserves* the method: customers
|
|
|
|
|
outside the group stop seeing it everywhere on the shop. That is how "free
|
|
|
|
|
delivery for approved addresses" stays unavailable to everybody else — set the
|
|
|
|
|
free methods to **only** and the ordinary ones (parcel shops, pickup) to
|
|
|
|
|
**show**. Adding one only rule changes what strangers see.
|
2026-09-28 21:45:29 +02:00
|
|
|
|
|
|
|
|
## How to tell it is working
|
|
|
|
|
|
|
|
|
|
Not "no errors". A specific number on a specific screen:
|
|
|
|
|
|
|
|
|
|
1. **WooCommerce → Nolimit Discounts → Emails.** The row you added is listed
|
|
|
|
|
with its type and its value. If the tab is empty after saving, the write
|
|
|
|
|
failed and nothing else below will work.
|
|
|
|
|
|
|
|
|
|
2. **The Nolimit dashboard card.** **Nolimit** in the admin menu shows a card
|
|
|
|
|
for this plugin with two counts — groups and email assignments. They should
|
|
|
|
|
equal what the Groups and Emails tabs show. The card is cached for five
|
|
|
|
|
minutes, so wait that long before reading it as disagreement.
|
|
|
|
|
|
|
|
|
|
3. **The real test, in a cart.** Log in as (or check out with) an address that
|
|
|
|
|
matches a pattern and put a product from a covered category in the cart.
|
|
|
|
|
The cart totals show a **negative fee line** carrying the group's name. No
|
|
|
|
|
line means no match — check the pattern, not the percent.
|
|
|
|
|
|
|
|
|
|
4. **Shipping, if you set any rules.** With rules in place, compare the
|
|
|
|
|
checkout as a matching customer and in a private window as a stranger. The
|
2026-10-02 12:28:45 +02:00
|
|
|
method marked only must be absent for the stranger. Both should show at least
|
2026-09-28 21:45:29 +02:00
|
|
|
one method; if the stranger sees *everything*, the rules emptied the list
|
|
|
|
|
and the never-leave-them-stranded fallback returned all of them.
|
|
|
|
|
|
|
|
|
|
5. **Updates.** **Dashboard → Updates** names this plugin with a version and
|
|
|
|
|
draws its icon. A broken image there means the release is missing its
|
|
|
|
|
`assets/` — report it rather than pressing update.
|
|
|
|
|
|
|
|
|
|
## Settings that need no decision
|
|
|
|
|
|
|
|
|
|
There is no settings page beyond the three tabs. Rate limiting on the REST API
|
|
|
|
|
and the audit log's retention are on by default and adjustable only by filter
|
|
|
|
|
— see CONTRACT.md. A shop that does not want to write code never touches them.
|