Title: AMS Studio ERP — Invoicing &amp; Accounting
Author: anthonysgro
Published: <strong>September 17, 2026</strong>
Last modified: September 17, 2026

---

Search plugins

![](https://ps.w.org/ams-studio-erp-invoicing-accounting/assets/banner-772x250.png?
rev=3700131)

![](https://ps.w.org/ams-studio-erp-invoicing-accounting/assets/icon-256x256.png?
rev=3700131)

# AMS Studio ERP — Invoicing & Accounting

 By [anthonysgro](https://profiles.wordpress.org/anthonysgro/)

[Download](https://downloads.wordpress.org/plugin/ams-studio-erp-invoicing-accounting.0.5.25.zip)

 * [Details](https://wordpress.org/plugins/ams-studio-erp-invoicing-accounting/#description)
 * [Reviews](https://wordpress.org/plugins/ams-studio-erp-invoicing-accounting/#reviews)
 *  [Installation](https://wordpress.org/plugins/ams-studio-erp-invoicing-accounting/#installation)
 * [Development](https://wordpress.org/plugins/ams-studio-erp-invoicing-accounting/#developers)

 [Support](https://wordpress.org/support/plugin/ams-studio-erp-invoicing-accounting/)

## Description

AMS Studio ERP turns WordPress into the back office of a small company. Quotes, 
invoices,
 purchase orders, stock, deals, documents, treasury and accounting all
live in your own database, on your own server. There is no service to subscribe 
to and no second password to remember.

**The document chain**

Nothing is retyped from one step to the next. A quote becomes an invoice, the invoice

calls for its payment, the payment produces its ledger entry, and every document
keeps the link back to the one it came from.

 * Quotes sent by email with their PDF, then signed online by the customer
 * Invoices numbered in a continuous, chronological series
 * Payments entered by hand or matched to an imported bank statement
 * Ledger entries posted to the right journal and financial year

**What holds up under audit**

These rules live in the engine, and the plugin refuses whatever breaks them.

 * Numbering stays continuous: a prefix already in use cannot change, and a reopened
   
   document keeps its number
 * An approved document is sealed by a fingerprint over its amounts, its party and
   its
    number; a mistake is corrected by a credit note, never by editing
 * VAT is broken down by rate, as the law requires on the document itself
 * Factur-X (PDF/A-3) and Peppol BIS Billing 3.0; a non-compliant invoice refuses
   to go
    out, in print, by email and on the public page
 * Attachments are encrypted with AES-256-GCM, outside the public media library
 * Exact decimal arithmetic throughout, never floating point

**What this plugin does**

 * Customers: records, addresses, contacts, categories
 * Catalogue: products and services, purchase and sale prices, margins, VAT rates
 * Quotes: drafted, sent by email with their PDF, signed online by the customer
 * Customer invoices and credit notes: continuous numbering, deposits, payment terms,
   
   what is paid and what remains due
 * Factur-X (PDF/A-3) and Peppol BIS Billing 3.0 on every invoice
 * Encrypted attachments, exact decimal arithmetic, an audit trail on every document

**What it does not do**

Purchasing, stock, deals, treasury, accounting, the document library and the
 WooCommerce
bridge are **not part of this plugin**. They come with AMS Studio Pro, a separate
add-on installed alongside it and distributed from https://www.ams-studio.lu/

Nothing here is capped, time-limited or waiting for a key: what you install is
 
complete. The modules above are simply not in this package — the menu shows them
so you know they exist, and says where to get them.

**Languages**

French and English. The plugin follows your site’s language, or its own if you ask
it to —
 an English site can run a French ERP.

### Third-party libraries

Producing an invoice as a PDF needs an HTML-to-PDF engine, and WordPress core
 has
none. Four libraries are bundled, unmodified except where noted, each with its own
licence file in its directory — all GPL-compatible:

 * dompdf/dompdf 3.1.6 — LGPL-2.1 — https://github.com/dompdf/dompdf
 * masterminds/html5 — MIT — https://github.com/Masterminds/html5-php
 * sabberworm/php-css-parser — MIT — https://github.com/MyIntervals/PHP-CSS-Parser
 * php-font-lib — LGPL-2.1 — https://github.com/dompdf/php-font-lib

They are bundled rather than pulled by Composer because the plugin must install

from the WordPress admin, on shared hosting, with no command line. Their namespaces
are prefixed under `AMSBM\Vendor\` with PHP-Scoper, so that two plugins bundling
dompdf in different versions cannot break each other; the prefixing is reproducible
with `bin/scoper.sh`. Every other deviation from the upstream code is marked in 
place and listed in `lib/pdf/ECARTS.md`: a direct-access guard on the two files 
that carry code outside a class, embedding a Factur-X XML attachment into a PDF/
A-3 file which dompdf does not support upstream, heredoc blocks rewritten as concatenation,
and the removal of SVG rendering.

dompdf’s fifth dependency, php-svg-lib, is deliberately **not** bundled. It
 exists
only to draw SVG images inside a PDF, and drawing one means parsing XML that a site
user supplied. The plugin does not need it — logos are PNG, JPEG, GIF or WebP, and
an SVG is refused at upload — so the smaller attack surface is worth more than the
feature. The three places where dompdf reached for it are neutralised in place, 
and an SVG is simply not a recognised image type any more.

One more deviation is replayed automatically rather than by hand: in
 php-font-lib,`
glyf::toHTML()` — a font-debugging method that builds an HTML page with inline scripts—
is emptied. Neither dompdf nor the plugin calls it. bin/pdf-patches.php applies 
that change after every copy of the libraries (`bin/vendor-pdf.sh`) and again after
prefixing (`bin/scoper.sh`), and the package build (`build-zip.sh`) refuses to proceed
if it is missing.

### Compiled admin interface

The admin interface is a React/TypeScript application, compiled with Vite. The
 
compiled, minified bundle is in `app/build/`; its **unminified sources ship with
the plugin, in `app/src/`, along with everything needed to rebuild it: app/package.
json, `app/package-lock.json`, `app/tsconfig.json`, app/tsconfig.node.json, `app/
vite.config.ts`, `app/tailwind.config.js` and app/postcss.config.js.

The same sources are publicly available at https://github.com/SanMat11/wp-erpx

To rebuild the bundle — Node.js 18 or 20 and later, verified with Node.js 22:

    ```
    cd app && npm ci && npm run build

    npm ci installs the exact dependency versions recorded in
    app/package-lock.json. `npm run build` type-checks the sources with TypeScript
    ```

5.9, then builds them with Vite 5.4 into `app/build/`. The file
 app/build/morceaux/
vendor-[hash].js is the npm dependencies listed in app/package.json — React, Ant
Design and the others — bundled together by Vite; each package’s name and exact 
version are in `app/package-lock.json`.

Vite writes the entry point as `amsbm-app-[hash].js` and `amsbm-app-[hash].css`,

with the code split into chunks under `app/build/morceaux/`. The hash in the filename
is the version: a new build produces a new name, so a cached file is never a stale
one. `app/build/manifeste.json` records the current pair, and the plugin reads it
rather than guessing.

Nothing about the plugin requires npm at runtime. The bundle is committed and
 shipped
because the target audience installs from the WordPress admin, on shared hosting,
with no command line.

### External services

**VIES — EU VAT number validation** (European Commission)

Used only when you click “check” beside an EU VAT number, to confirm that the number

exists. What is sent: the country code and the VAT number, in the request URL. Nothing
else — no company name, no site address, no identifier. Service: https://ec.europa.
eu/taxation_customs/vies/ Terms and privacy: https://ec.europa.eu/taxation_customs/
vies/#/help

**Stripe — card payment of your invoices** (Stripe, Inc.)

Used only if you enter your own Stripe API keys in the settings. It lets a customer
of
 yours pay a shared invoice by card. What is sent, when your customer clicks “
pay”: the amount, the currency, the invoice reference and the return address. The
plugin never sends your customer list or your documents. Service: https://stripe.
com/ Terms: https://stripe.com/legal/ssa Privacy: https://stripe.com/privacy

**AMS Studio licence server** (AMS Studio, Luxembourg)

Only reached if you click “Upgrade to Pro” in the application header. That button
is a
 link: your browser opens it, the plugin itself opens no connection and sends
nothing on its own. What travels in that link: an installation identifier drawn 
at random on your site, a one-way hash of a secret drawn with it, your site address
and your admin email address — so that the licence you buy is tied to this site 
and fills itself in when you install the paid package, with nothing to copy by hand.
The hash cannot be reversed, and the secret itself never appears in the link. Nothing
is sent if you never click the button, and nothing is sent on a schedule. Service:
https://licences.ams-studio.lu/ Terms and privacy: https://www.ams-studio.lu/

The plugin contacts nothing else. No telemetry, no update server, no licence check.

## Screenshots

[⌊Dashboard: monthly revenue, pending invoices and active customers.⌉⌊Dashboard:
monthly revenue, pending invoices and active customers.⌉[

Dashboard: monthly revenue, pending invoices and active customers.

[⌊Quotes, from draft to online signature.⌉⌊Quotes, from draft to online signature
.⌉[

Quotes, from draft to online signature.

[⌊Customer invoices, with what is paid and what remains due.⌉⌊Customer invoices,
with what is paid and what remains due.⌉[

Customer invoices, with what is paid and what remains due.

[⌊Customers, with their addresses and contacts.⌉⌊Customers, with their addresses
and contacts.⌉[

Customers, with their addresses and contacts.

[⌊The catalogue: products and services, prices and margins.⌉⌊The catalogue: products
and services, prices and margins.⌉[

The catalogue: products and services, prices and margins.

[⌊Settings: company details, numbering, VAT and appearance.⌉⌊Settings: company details,
numbering, VAT and appearance.⌉[

Settings: company details, numbering, VAT and appearance.

## Installation

 1. Install and activate the plugin as usual.
 2. Open AMS ERP in the admin menu and fill in your company details.
 3. Optionally install the demo data set to look around before entering your own.

No command line is required, and no account anywhere: the plugin ships its own autoloader
and its own PDF engine. Two optional features do contact an outside service when
you use them — see “External services” below.

## FAQ

### Is my data sent anywhere?

Your business data stays put. Documents, customers, articles and ledger entries 
live
 in your own database and are never sent anywhere.

Two features do reach outside, and only when you ask them to:

 * **VAT number validation.** When you click “check” next to an EU VAT number, that
   
   number and its country code are sent to VIES, the European Commission’s service.
   Nothing else. If you never click, nothing is ever sent.
 * **Card payment of an invoice.** If — and only if — you enter your own Stripe 
   keys,
    your customer can pay a shared invoice by card. Stripe then receives the
   amount, the currency and the invoice reference, at the moment your customer clicks“
   pay”.

Both are documented in full under “External services” below.

### Is my data deleted when I uninstall?

No. Dropping the tables requires adding `define( 'AMSBM_REMOVE_ALL_DATA', true );`
to
 your `wp-config.php`. Accounting retention obligations — six years in France,
up to ten elsewhere in Europe — outlast the lifetime of any plugin.

### Does it need InnoDB?

Yes. Without a transactional engine, operations cannot be made atomic. The built-
in
 health check reports it.

### Are any features locked or limited?

No. Every feature in this package works, with no cap on the number of customers,

quotes, invoices or articles, and no trial period.

Some modules — purchasing, stock, deals, treasury, accounting, the document library

and the WooCommerce bridge — are not in this package at all. They ship with a separate
add-on. The menu lists them so you know they exist; they are not disabled code waiting
for a key.

### Do I need Composer or npm to install this?

No. The plugin ships its own autoloader, its own PDF engine and its compiled
 admin
interface. `composer.json` and the JavaScript sources are included so that the build
is reproducible and the dependencies are auditable, not because anything has to 
be run.

### What happens to my data if I deactivate the plugin?

Nothing. Deactivating stops the code from running; the tables, the documents and

the ledger stay exactly as they are, and reactivating picks up where you left off.

### Which chart of accounts is supported?

The French plan comptable général and the Luxembourg plan comptable normalisé 2020.

Accounts, journals and financial years are all editable.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“AMS Studio ERP — Invoicing & Accounting” is open source software. The following
people have contributed to this plugin.

Contributors

 *   [ anthonysgro ](https://profiles.wordpress.org/anthonysgro/)

[Translate “AMS Studio ERP — Invoicing & Accounting” into your language.](https://translate.wordpress.org/projects/wp-plugins/ams-studio-erp-invoicing-accounting)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/ams-studio-erp-invoicing-accounting/),
check out the [SVN repository](https://plugins.svn.wordpress.org/ams-studio-erp-invoicing-accounting/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/ams-studio-erp-invoicing-accounting/)
by [RSS](https://plugins.trac.wordpress.org/log/ams-studio-erp-invoicing-accounting/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 0.5.25

 * On a site without the stock, WooCommerce or accounting modules, the admin
    interface
   no longer requests routes that do not exist there: the dashboard only asks for
   stock alerts when stock is installed, the VAT settings only list accounting accounts
   when accounting is, and the Warehouses and Store settings tabs only appear when
   their module does.
 * Demo data no longer writes purchase orders and supplier invoices on a site
    that
   has no purchasing module.

#### 0.5.24

 * Plugin Check reports nothing left in the plugin’s own code. The hook fired when
   
   the installation fingerprint is renewed is now fired by its literal, prefixed
   name. The one call it discourages, `load_plugin_textdomain()`, says why it stays:
   the plugin ships its own English catalogue, which WordPress only finds through
   that call.

#### 0.5.23

 * The print page of a document is no longer echoed as one string. Its template
   
   is included directly in the response, and escapes every value at the exact place
   where it is output.
 * No inline JavaScript left: the print button, the confirmation before a status
   
   change, the setup fields to copy and the “copy backup codes” button now use a
   script enqueued with `wp_enqueue_script()`, or printed with wp_print_inline_script_tag()
   on the standalone print page. The “copy backup codes” button, which copied nothing,
   now copies.
 * PDF downloads, accounting exports and stored attachments are sent with
    X-Content-
   Type-Options: nosniff.
 * Bundled php-font-lib: a font-debugging method that built HTML with inline
    scripts,
   and that nothing calls, is emptied — see “Third-party libraries”.

#### 0.5.22

 * The sources of the admin interface shipped in `app/src/` can be rebuilt from
   
   the plugin package alone again. A screen that is not part of this package was
   imported unconditionally, so `npm run build` stopped on a missing file; it is
   now loaded only where its file exists.
 * The same sources are published at https://github.com/SanMat11/wp-erpx, and the
   
   readme gives the Node.js version, the exact command and where the output goes.

#### 0.5.21

 * **English is translated again.** The English catalogue was deleted during the
   
   0.5.7 rename and never rebuilt: since then every string written by the server—
   API refusals shown on screen, e-mails, PDFs, meta boxes — came out in French 
   on English sites, while the interface itself switched. All 971 strings the code
   asks for are now translated and shipped as languages/ams-studio-erp-invoicing-
   accounting-en_US.mo.
 * **A quote could not be accepted in English.** The wording a customer copies
    
   out to accept a quote was compared against the French `bon pour accord`, while
   the refusal message told English customers to type “Agreed and accepted”. They
   typed exactly what was asked and were turned away. The expected wording now follows
   the language of the site, and French stays accepted so agreements given before
   a language change remain valid.
 * Four screen strings still quoted the French wording inside English sentences,
   
   and two were left in French outright. The screen, the refusal message and the
   check now say the same thing.

#### 0.5.20

 * The text domain is now `ams-studio-erp-invoicing-accounting`, matching the
    slug
   registered on WordPress.org. It was `ams-studio-business-management` on 1155 
   i18n calls, which prevented the plugin from being translated through translate.
   wordpress.org. The PHP prefix `amsbm_`, the option, table, post type and REST
   namespace names are unchanged, as is the main file name.
 * Internal: the translation catalogue built by `bin/i18n/` was named
    amsbm-.po,
   which matched no text domain — WordPress would never have loaded it. It now carries
   the domain, as the format requires.

#### 0.5.19

 * Internal: the Peppol reader no longer emits a PHP warning when an incoming
    invoice
   omits optional elements — payment terms, legal entity, trading name or tax scheme.
   Absent elements read back as an empty string, as intended.
 * Internal: the test asserting that every document type is reachable by a role
   
   performed no assertion at all: it returned on the first role covering everything.
   It now checks the business roles, and was seen to fail when a document type is
   unwired from them.

#### 0.5.18

 * Internal: the bundled PDF libraries — dompdf, php-font-lib, masterminds/html5
   
   and sabberworm/php-css-parser — now live under the `AMSBM\Vendor\` namespace,
   prefixed with PHP-Scoper. Two plugins bundling dompdf in different versions can
   no longer break each other. A document renders byte-for-byte as before.

#### 0.5.17

 * Internal: the document editor’s article catalogue no longer writes its
    tag by
   hand. It goes through `wp_print_inline_script_tag()`, which carries the page’s
   Content-Security-Policy nonce where there is one. It stays a JSON data block,
   not executable code. Nothing changes on screen.

#### 0.5.16

 * Security: SVG rendering has been removed from the PDF engine, and the
    php-svg-
   lib library with it. Drawing an SVG meant parsing user-supplied XML inside the
   printing chain, for a format the plugin never needed: logos are PNG, JPEG, GIF
   or WebP. An SVG is now refused when the logo is uploaded, and refused again before
   it reaches the PDF. Documents without an SVG render byte-for-byte as before.

#### 0.5.15

 * Internal: every SQL query now goes through `wpdb::prepare()`, with no exception.
   
   Table and column names are bound with the `%i` placeholder instead of being interpolated
   into the query string, and the plugin’s own table names are checked against a
   hard-coded list before any query is built. Nothing changes on screen: the 132
   read routes return byte-for-byte identical answers.

#### 0.5.14

 * Internal: the public quote and invoice page no longer writes its script tags 
   by hand.
    They go through the WordPress loader, which now also carries the page’s
   Content-Security-Policy nonce. Nothing changes on screen.

#### 0.5.13

 * Internal: four blocks in the bundled PDF libraries were rewritten from heredoc
   to
    string concatenation, so that the whole package passes the directory’s automated
   check. The generated PDFs are byte-for-byte identical. Every deviation from the
   upstream libraries is now listed in `lib/pdf/ECARTS.md`.

#### 0.5.12

 * The “Upgrade to Pro” link in the header now offers to subscribe, in so many words:
   
   the dialog it opens says “Subscribe” instead of “Learn more” and states the price—
   the same one the website quotes. It no longer names an empty module when it was
   not opened from a particular screen.

#### 0.5.11

 * Internal: this package now refuses any update whose archive does not come from
   where
    it says it does. Nothing changes for you here — the free edition is updated
   by WordPress.org as it should be.

#### 0.5.10

 * Removing the demo dataset and installing it again left you with no customers 
   and no
    products at all — while reporting it had created twenty. Removing deleted
   the WordPress posts but not the plugin’s own rows, and the next install reused
   a post id that pointed at nothing.
 * A company named “Roussel & Fils” read “Roussel & Fils” in the demo dataset.
 * An IBAN broke into six stacked pieces in the treasury list, and an IBAN entered
   with
    spaces was regrouped wrongly. A cash account shows a dash instead of an
   empty box.

#### 0.5.9

 * This installation now has an identity of its own — an identifier drawn at random
   on
    your site, and a secret drawn with it. Nothing is sent anywhere: they exist
   so that a licence bought later belongs to this site and fills itself in, instead
   of being copied by hand. See “External services” for the one moment anything 
   leaves, and what it is.
 * The activate button no longer sits flush against the licence field.

#### 0.5.8

 * Screens that spoke French on an English site. The public invoice page a customer
   
   opens to pay, the goods receipt screen and the online payment settings carried
   their wording inside the code instead of in the catalogues: 87 sentences that
   no translation could reach. They are now in both catalogues, English included.
 * The subscription screen showed its translation keys instead of its labels — its
   
   whole set of 80 keys was in neither catalogue. It also named the four licence
   states it had never been given a word for, starting with a site that simply has
   no key.

#### 0.5.7

 * This package now contains exactly what it runs. Purchasing, stock, deals, treasury,
   
   accounting, the document library and the WooCommerce bridge moved to a separate
   add-on — their code is no longer shipped here. Nothing is capped or locked: what
   is present works, in full.
 * New name. The plugin was called ERP-X; it is now AMS Studio ERP.
    Everything 
   it declares was renamed with it — options, tables, custom post types, capabilities,
   hooks and the REST namespace. Nothing carries over from the old names, so this
   version is an installation, not an upgrade.
 * Nothing in this package is capped, time-limited or tied to a key. What is here
   
   is installed and open; what is not here is not shipped at all.
 * Electronic invoicing follows. Factur-X (PDF/A-3) and Peppol BIS Billing 3.0
    
   used to be conditional; they now apply to every invoice, which is what a legal
   obligation ought to be.
 * The plugin no longer looks anywhere but here for its updates.

#### 0.5.6

 * A document the WooCommerce bridge found wrong now says so before you click. The
   
   bridge marks it, approval refuses it — but nothing showed the reason, so the 
   refusal arrived out of nowhere.
 * The supplier invoice screens stop offering what the server will refuse: five 
   write
    actions in the list, and approving a credit note, are now hidden from 
   roles that do not have the right — and the reason is stated, with who to ask.
 * A supplier credit note table headed two different columns “Amount excl. VAT”.
 * The credit note route names the capability it needs instead of relying on the
   global
    write right.

#### 0.5.5

 * The plugin’s own header is translated at last. Its name and description were 
   in no
    catalogue, so an English site read the description in French on its plugins
   screen — the one place never reread. The extractor now covers the header, as 
   xgettext does.
 * One header dropped: the plugin address and the author address may not be the 
   same,
    and the site at ams-studio.lu presents the plugin.

#### 0.5.4

 * Every PHP file the plugin ships now refuses a direct HTTP call. On shared hosting
   
   wp-content is often served without going through WordPress, and a file reached
   that way ran outside it — printing the server’s absolute path in the fatal error
   that followed. A test counts them all and fails on the next file shipped without
   a guard.
 * The two-factor QR script goes through the WordPress script queue.
 * Repository compliance: exemptions declared for the directory’s own database sniff,
   
   which is stricter than the WordPress coding standard, and one core function dropped
   in favour of a plain expression.

#### 0.5.3

 * The plugin is named ERP-X throughout, with a new mark drawn in one place and 
   used on
    the admin menu, the sidebar and the sign-in screen.

#### 0.5.2

 * fail2ban on the API, installation blocking, and an allow list on the administration.

#### 0.5.1

 * Sealing: an invoice or credit note the WooCommerce bridge found wrong can no 
   longer be
    approved by any path.
 * Electronic invoicing: a non-compliant invoice no longer goes out by email or 
   on the
    public page either.
 * Purchasing: only what has been received is invoiced; invoicing ahead must be 
   asked for.

#### 0.5.0

 * Two-factor authentication and the per-module permission matrix.

#### 0.2.0

 * The sales cycle end to end: items, parties, quotes, invoices.
 * Multi-rate VAT rounded per rate at the foot of the document.
 * Quote to invoice transformation, with a line-by-line trace.

#### 0.1.0

 * Exact decimal arithmetic, with no silent overflow.
 * Numbering by atomic UPDATE, refusing documents backdated below the last period
   used.
 * Migration lock through a MySQL GET_LOCK, genuinely atomic.

## Meta

 *  Version **0.5.25**
 *  Last updated **10 hours ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.4 or higher **
 *  Tested up to **7.1**
 *  PHP version ** 8.1 or higher **
 * Tags
 * [crm](https://wordpress.org/plugins/tags/crm/)[ERP](https://wordpress.org/plugins/tags/erp/)
   [factur-x](https://wordpress.org/plugins/tags/factur-x/)[invoicing](https://wordpress.org/plugins/tags/invoicing/)
   [quotes](https://wordpress.org/plugins/tags/quotes/)
 *  [Advanced View](https://wordpress.org/plugins/ams-studio-erp-invoicing-accounting/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/ams-studio-erp-invoicing-accounting/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/ams-studio-erp-invoicing-accounting/reviews/)

## Contributors

 *   [ anthonysgro ](https://profiles.wordpress.org/anthonysgro/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/ams-studio-erp-invoicing-accounting/)