Collect and validate EU VAT numbers from clients directly inside the Perfex client portal. A modal prompts clients without a VAT number to enter one. Numbers are validated in real time against the EU VIES database. Admins get a full dashboard with filtering, manual verification, CSV export, and a complete audit log of every change.
What you get
- Client portal modal — appears automatically for clients without a VAT number
- Real-time VIES validation against the EU VIES SOAP service
- Admin dashboard — filter by with/without VAT, VIES verified, VIES invalid
- Manual VIES re-verify and clear per client from admin
- Full audit log — every set, change, clear and verify action recorded
- CSV export of all clients with VAT status
- Configurable modal — custom message text, skip allowed or mandatory
- Client group filter — show modal only to selected groups
- Settings tab integrated in Perfex Settings panel
- Fully bilingual — DE / EN included
Setup
- Install and activate — modal is immediately active for clients without VAT
- Go to Settings → VAT Manager to configure groups and modal behaviour
- Set Show modal for client groups to limit which clients see the modal
- Enable or disable VIES validation under Settings
- Toggle Allow skip or Require VAT (mandatory) as needed
- Admin dashboard: VAT Manager → Dashboard in the sidebar
- Export CSV from the dashboard header button
Client Portal Modal
How the modal works
- Injected via
app_customers_footerhook on every client portal page - Only shown if the client has no VAT number in the Perfex
clientstable - Group filter: if groups are configured, only clients belonging to those groups see the modal
- On submit: VAT is sanitised (uppercased, whitespace stripped) and saved to
clients.vat - VIES check runs immediately on save if enabled — result shown inline before the modal closes
- If skip is allowed, a skip link dismisses the modal for the session
- If mandatory, skip link is hidden — client cannot proceed without entering a number
VIES Validation logic
- VAT must start with a 2-letter EU country code (AT, BE, DE, FR, etc.) to be checked via VIES
- Non-EU format (no country prefix) — saved without VIES check, status: not checked
- Non-EU country prefix (e.g. CH, GB) — saved without VIES check, status: not checked
- EU format — checked via VIES SOAP (
checkVatService.wsdl) - VIES unavailable — number saved, status stays null, error logged
- Admin can manually re-verify any client from the dashboard at any time
Admin Dashboard
Dashboard stats
- Total clients
- Clients with VAT number
- Clients without VAT number
- VIES verified (valid)
- Not yet verified
- VIES invalid
Dashboard filters
- All — full client list
- With VAT — clients who have entered a number
- Without VAT — clients missing a number
- VIES OK — numbers confirmed valid
- VIES Invalid — numbers that failed VIES check
- Per-row actions: Verify VIES, Clear VAT number
- CSV export of current filtered view
Audit Log
What is logged
- Every VAT set, change, clear, VIES verify and VIES fail action
- Old value and new value stored per entry
- VIES result (valid / invalid / null) stored per entry
- Actor recorded — client (portal) or admin (staff ID)
- Timestamp recorded for every action
- Log visible in the admin dashboard — last 20 entries by default
All settings live under Perfex Settings → VAT Manager tab. They are stored in the Perfex options table and readable anywhere via get_option().
Available options
client_vat_manager_active— module active flag (1/0), set on activationclient_vat_manager_client_groups— comma-separated group IDs; empty = show modal to all clientsclient_vat_manager_modal_content— custom HTML/text shown inside the modal above the input fieldclient_vat_manager_vies_enabled— 1 = run VIES check on save, 0 = save without checkingclient_vat_manager_allow_skip— 1 = show skip link, 0 = hide skip linkclient_vat_manager_require— 1 = skip link hidden, VAT entry mandatory; overrides allow_skip
Client group multi-select: The settings filter hook
cvm_filter_settings converts the multi-select array into a comma-separated string before saving. The raw option value is always a comma-separated string — use explode(',', get_option('client_vat_manager_client_groups')) to get an array.
Registered hooks
admin_init→cvm_init_menu()— registers sidebar menu item and childrenadmin_init→cvm_add_settings_tab()— injects VAT Manager tab into Perfex Settingsapp_customers_footer→cvm_portal_footer()— injects modal + JS into client portal if conditions metbefore_settings_updated→cvm_filter_settings()— converts client group multi-select to CSV string before save
Admin controller routes
GET admin/client_vat_manager— dashboard with stats, client list, audit logGET admin/client_vat_manager/verify_ajax?id={client_id}— trigger VIES re-verify for a clientGET admin/client_vat_manager/verify_ajax?vat={vat_string}— ad-hoc VIES check without savingPOST admin/client_vat_manager/clear_ajax— clear VAT number for a client (admin)GET admin/client_vat_manager/export_csv— download CSV of all clients with VAT statusPOST admin/client_vat_manager/get_client_tax— JSON: returns VAT + tax terms string for a client ID
Client portal routes
POST clients/cvm_client/update_vat— submit VAT from modal, runs VIES if enabled, redirects back
Non-destructive: All schema changes are additive. Deactivating the module does not drop tables or columns. Reactivating is safe.
New table — {db_prefix}cvm_log
idINT AUTO_INCREMENT PRIMARY KEYclient_idINT — references clients.useridactionVARCHAR(50) — set / changed / cleared / verified / failedold_valueVARCHAR(100) — previous VAT numbernew_valueVARCHAR(100) — new VAT numbervies_validTINYINT(1) — 1 valid / 0 invalid / NULL not checkedby_typeVARCHAR(20) — client or adminby_idINT — staff ID (admin) or client ID (portal)created_atDATETIME
Columns added to {db_prefix}clients
cvm_vies_validTINYINT(1) DEFAULT NULL — 1 valid / 0 invalid / NULL not checkedcvm_verified_atDATETIME DEFAULT NULL — timestamp of last successful VIES checkcvm_updated_atDATETIME DEFAULT NULL — timestamp of last VAT number save
Perfex options table entries
client_vat_manager_activeclient_vat_manager_client_groupsclient_vat_manager_modal_contentclient_vat_manager_vies_enabledclient_vat_manager_allow_skipclient_vat_manager_require
Server requirements
- Perfex CRM 3.0 or higher
- PHP 8.0 or higher
- PHP SOAP extension enabled (required for VIES validation)
- MySQL 5.7+ / MariaDB 10.3+
- Outgoing HTTPS to
ec.europa.eu(VIES SOAP service)
If something does not work
- Modal not showing? → Check client group settings — client may not be in configured group
- VIES always fails? → Check PHP SOAP extension is enabled and outgoing HTTPS is not blocked
- Settings tab missing? → Deactivate and reactivate the module
- Columns missing? → Deactivate and reactivate — install.php runs again on activation
- Still stuck? → Email support with your domain and module version