ISP network management tools for blocking/unblocking internet access based on AbraFlexi invoice status.
abraflexi-reminder (3rd reminder sent)
│
│ emits: invoice.reminder.sent
▼
multiflexi-event-processor
│ rule: invoice.reminder.sent → mark-defaulters runtemplate
▼
abraflexi-mark-defaulters
- finds customers with UPOMINKA3 + active internet contract (typSmlouvy.INTERNET)
- sets ODPOJENO label in AbraFlexi
│
│ AbraFlexi webhook: adresar updated
▼
multiflexi-event-processor
│ rule: adresar update → blocknet runtemplate
▼
blocknet
- disconnects all customers with ODPOJENO label
Payment clears → abraflexi-reminder-clean-labels removes UPOMINKA* →
multiflexi-event-processor triggers unblocknet → internet restored.
AbraFlexi: new record in banka or pokladna evidence
│
│ webhook via abraflexi-webhook-acceptor → changes_cache
▼
multiflexi-event-processor
│ rule: banka/pokladna create → match-received-payment runtemplate
│ env_mapping: {"DOCUMENTID": "recordid"}
▼
isp-match-received-payment
exit 0: payment matched to invoice
│
│ AbraFlexi: faktura-vydana updated (linked to payment)
│ webhook: faktura-vydana, update
▼
multiflexi-event-processor
│ rule: faktura-vydana update → potvrzeni-prijeti-uhrady runtemplate
│ env_mapping: {"DOCID": "recordid"}
▼
isp-potvrzeni-prijeti-uhrady
- sends tax document confirmation to customer
exit 2: payment found but not matched (unknown varsym / under/overpayment)
│
│ rule: payment.unmatched → potvrzeni-prijeti-bankovni-platby runtemplate
│ env_mapping: {"DOCID": "recordid"}
▼
isp-potvrzeni-prijeti-bankovni-platby
- notifies customer their payment was received but awaits manual matching
Note on Pipeline B stage 2: rules 4–6 below work today — the
multiflexi-event-processorreacts to AbraFlexi webhook changes and the matched invoice update (rule 6) is itself afaktura-vydanawebhook change. Rule 7 (payment.unmatched) requires the event processor to react to job exit codes /job.completed, which it does not support yet; until then runisp-potvrzeni-prijeti-bankovni-platbymanually or from a wrapper that inspects the matcher's exit code.
This project provides six MultiFlexi applications:
Identifies customers with the UPOMINKA3 label (3rd reminder sent) who also
have an active internet service contract and marks them for disconnection by
adding the ODPOJENO label. Triggered by the invoice.reminder.sent event.
Customers with only VoIP, IpTV, Hosting or Housing contracts are not marked
for internet disconnection even if their invoices are overdue. Set INET_CONTRACT_TYPE
to the AbraFlexi typSmlouvyK code of internet contracts to enable precise filtering.
Blocks internet access for all clients with the ODPOJENO (DISCONNECTED) label in AbraFlexi.
Customers labelled VIP or NEODPOJOVAT are skipped. Customer IP addresses are
resolved through the configured network backend and each IP is blocked by setting
its speed to 0.
Restores internet access for disconnected customers who no longer owe:
- Finds customers with the
ODPOJENOlabel. - Checks AbraFlexi for unpaid overdue issued invoices per customer.
- Customers without debt get all their IPs unblocked (the backend restores the
original speed recorded at block time;
DEFAULT_SPEEDis the fallback). - After a successful unblock the
ODPOJENOlabel is removed from the customer.
Matches a received bank/cash payment to an unpaid issued invoice by variable
symbol and links it via AbraFlexi payment pairing (sparovani).
- Env:
DOCUMENTID(record code or numeric id, required),PAYMENT_EVIDENCE(banka|pokladna|auto, defaultauto),MATCH_OVERPAY_MODE(settle|manual, defaultsettle),LABEL_OVERPAY,LABEL_INVOICE_MISSING,LABEL_UNIDENTIFIED. - Exit codes:
0= matched and linked,2= received but cannot be auto-matched (unknown variable symbol, ambiguity, or overpayment inmanualmode) — emitspayment.unmatched,1= error. - Underpayment is linked as a partial payment (
castecnaUhrada).
Sends the customer a payment-received confirmation email with the tax document
(invoice PDF) attached. Skips invoices that are not (at least partially) paid,
so it is safe to trigger from a generic faktura-vydana update rule.
- Env:
DOCID(faktura-vydana code, required),EASE_FROM,MUTE(true= dry run). - Exit codes:
0= sent (or dry run / not paid),1= error (unknown document, no email, send failure).
Notifies the customer that their bank payment was received but awaits manual matching by accounting.
- Env:
DOCID(bank record code or numeric id, required),PAYMENT_EVIDENCE,EASE_FROM,MUTE. - Exit codes:
0= notified (unknown payer is a warning, not an error),1= error.
composer installCopy .env.example to .env and configure your connections:
cp .env.example .envABRAFLEXI_URL- Your AbraFlexi server URL (e.g.,https://your-server.com:5434)ABRAFLEXI_LOGIN- AbraFlexi usernameABRAFLEXI_PASSWORD- AbraFlexi passwordABRAFLEXI_COMPANY- Company code in AbraFlexi
EASE_LOGGER- Logging configuration (default:console|syslog)RESULT_FILE- Output file for results (default:isp_tools_result.json)APP_DEBUG- Debug mode (default:false)
LABEL_DISCONNECTED- Label for disconnected customers (default:ODPOJENO)LABEL_NODISCONNECT- Label for customers not to disconnect (default:NEODPOJOVAT)LABEL_VIP- VIP customer label (default:VIP)LABEL_THIRD_REMINDER- Label set by abraflexi-reminder after the 3rd reminder (default:UPOMINKA3)
MATCH_OVERPAY_MODE- Overpayment handling:settleormanual(default:settle)PAYMENT_EVIDENCE- Evidence to load payments from:banka,pokladnaorauto(default:auto)LABEL_OVERPAY- Label for overpaid documents (default:PREPLATEK)LABEL_INVOICE_MISSING- Label for payments without a matching invoice (default:CHYBIFAKTURA)LABEL_UNIDENTIFIED- Label for unidentified payments (default:NEIDENTIFIKOVANO)EASE_FROM- Sender address for confirmation emailsMUTE-true= dry run, confirmation emails are not actually sent
DEFAULT_SPEED- Fallback speed used when the backend has no stored original speed (default:0)
SVNUSER- Subversion repository usernameSVNPASS- Subversion repository passwordSVNURL- Subversion repository URLSVNBIN- Path to subversion binary (default:/usr/bin/svn)LOGFILE- Path to log file for operations
Blocking rewrites the hosts-file comment of the customer's IP line to
# speed=0 orig=<previous speed>; unblocking restores the speed recorded in
the orig= token (falling back to DEFAULT_SPEED when the line never carried
a speed= value). Customer IPs are resolved preferably by the machine-readable
{code:XXXXX} comment token.
NETBOXURL- NetBox server URL (e.g.,https://netbox.yourdomain.com)NETBOXTOKEN- NetBox API token for authentication
bin/abraflexi-mark-defaultersbin/blocknetbin/unblocknetThese applications are designed to work with MultiFlexi for automated scheduling and execution.
The MultiFlexi application definitions are located in the multiflexi/ directory:
mark_defaulters.multiflexi.app.json- MarkDefaulters application definitionblocknet.multiflexi.app.json- BlockNet application definitionunblocknet.multiflexi.app.json- UnblockNet application definitionmatch_received_payment.multiflexi.app.json- MatchReceivedPayment application definitionpotvrzeni_prijeti_uhrady.multiflexi.app.json- PotvrzeniPrijetiUhrady application definitionpotvrzeni_prijeti_bankovni_platby.multiflexi.app.json- PotvrzeniPrijetiBankovniPlatby application definition
After registering all apps in MultiFlexi and creating their runtemplates,
configure the event processor rules via multiflexi-cli:
# ── Pipeline A: Reminder → Disconnection ──────────────────────────────────
# Rule 1: after 3rd reminder → mark customers for disconnection
multiflexi-cli eventrule create \
--event_source_id 1 \
--evidence "invoice.reminder.sent" \
--operation "any" \
--runtemplate_id <MARK_DEFAULTERS_RUNTEMPLATE_ID> \
--priority 10 \
--enabled 1
# Rule 2: after ODPOJENO is set (adresar webhook) → block internet
multiflexi-cli eventrule create \
--event_source_id 1 \
--evidence "adresar" \
--operation "update" \
--runtemplate_id <BLOCKNET_RUNTEMPLATE_ID> \
--priority 5 \
--enabled 1
# Rule 3: after UPOMINKA* labels removed (adresar webhook) → unblock internet
multiflexi-cli eventrule create \
--event_source_id 1 \
--evidence "adresar" \
--operation "update" \
--runtemplate_id <UNBLOCKNET_RUNTEMPLATE_ID> \
--priority 5 \
--enabled 1
# ── Pipeline B: Bank Payment → Matching → Confirmation ────────────────────
# Rule 4: new bank record → run payment matcher
multiflexi-cli eventrule create \
--event_source_id 1 \
--evidence "banka" \
--operation "create" \
--runtemplate_id <MATCHER_RUNTEMPLATE_ID> \
--priority 20 \
--enabled 1 \
--env_mapping '{"DOCUMENTID":"recordid"}'
# Rule 5: new cash record → run payment matcher
multiflexi-cli eventrule create \
--event_source_id 1 \
--evidence "pokladna" \
--operation "create" \
--runtemplate_id <MATCHER_RUNTEMPLATE_ID> \
--priority 20 \
--enabled 1 \
--env_mapping '{"DOCUMENTID":"recordid"}'
# Rule 6: invoice updated (= matched payment) → send tax document confirmation
multiflexi-cli eventrule create \
--event_source_id 1 \
--evidence "faktura-vydana" \
--operation "update" \
--runtemplate_id <POTVRZENI_PRIJETI_UHRADY_RUNTEMPLATE_ID> \
--priority 10 \
--enabled 1 \
--env_mapping '{"DOCID":"recordid"}'
# Rule 7: unmatched payment (exit 2 from matcher) → notify customer
multiflexi-cli eventrule create \
--event_source_id 1 \
--evidence "payment.unmatched" \
--operation "any" \
--runtemplate_id <POTVRZENI_PRIJETI_BANKOVNI_PLATBY_RUNTEMPLATE_ID> \
--priority 10 \
--enabled 1 \
--env_mapping '{"DOCID":"recordid"}'Set to typSmlouvy.INTERNET for Spoje.net deployment to restrict disconnection
to customers with active internet contracts only (typSmlouvy code INTERNET).
Leave empty to match all contract types.
| Label | Set by | Meaning |
|---|---|---|
UPOMINKA3 |
abraflexi-reminder | 3rd payment reminder sent |
ODPOJENO |
abraflexi-mark-defaulters | Customer marked for disconnection |
NEODPOJOVAT |
Manual | Never disconnect this customer |
VIP |
Manual | Skip disconnection for VIP customers |
For modern infrastructure management, the system supports NetBox as an alternative backend to Subversion.
Add NetBox settings to your .env file:
# NetBox API Configuration
NETBOXURL=https://your-netbox-instance.com
NETBOXTOKEN=your-api-token-here- IP Address Management: Ensure your customer IP addresses are registered in NetBox IPAM
- Custom Fields: Add a custom field named
speedto IP addresses:- Type: Integer
- Label: Speed
- Description: Internet connection speed in Mbps
To switch from Subversion-based management to NetBox:
-
Pass a
NetBoxerinstance to theDeBlockerconstructor (it defaults toSubVersioner):$deblocker = new \SpojeNet\DeBlocker(new \SpojeNet\NetBoxer());
-
Ensure all customer IPs are properly configured in NetBox with speed custom fields
-
Test blocking/unblocking operations
Note: the NetBox backend currently implements only customer IP lookup; its
blockIp()/unblockIp()operations are not implemented yet.
- NetBox API access with token authentication
- IP addresses must have custom field
speedfor speed management - Blocking sets speed to 0, unblocking restores the configured speed
The project includes comprehensive unit tests for all components.
composer install
vendor/bin/phpunitFor testing the Subversion backend, a test repository is included in tests/svn/ containing:
- Subversion repository with sample hosts file
- Working copy for testing operations
- Documentation in
tests/svn/README.md
The test repository allows testing blocking/unblocking operations without affecting production systems.
- PHP >= 8.1
- AbraFlexi account
- vitexsoftware/abraflexi-bricks library
- NetBox (optional, for modern infrastructure management)
MIT