From 18762e42cb24db3eb9d8b124f230892d2908bcef Mon Sep 17 00:00:00 2001 From: Xavier Karma Date: Sun, 4 Oct 2026 22:09:03 +0530 Subject: [PATCH] Verify the ERPNext integration live and fix the defects it found (Phase F4) Ran the push flow against ERPNext 15.121.6 on a plain site and on a site with India Compliance 15.32.0 (podman, scripts/erpnext-e2e). 15 ignored live tests pass on both. Fixes, each covered by a mock-based test: - load_options no longer fails on a plain site: the India Compliance-only gstin field is dropped on a 417 and retried. - Code-less rows with fractional hours or minutes send stock_uom, since ERPNext defaults it to Nos. - A created document whose total differs from Voiced's (ERPNext's default Banker's Rounding on half-paise ties) is recorded as a conflict, kept as a draft, not submitted and not given a PDF. The message names Commercial Rounding as the fix. - An existing customer address is reused instead of creating a duplicate on every first push. A bare creation order-by is not used with a Dynamic Link filter. - A re-adopted document no longer gets a second copy of the PDF. - Reverse charge: India Compliance rejects is_reverse_charge unless tax rows are negative RCM amounts, so the flag is sent as 0 with a warning that the invoice lands as a normal taxed invoice. - The 16-character name rule is checked locally in mirror mode under India Compliance, and a TDS-only payment is refused locally with the reason. Payment Entry mapping verified: bank_account is the Account name (paid_to), paid and received amounts equal the cash received, allocated_amount is cash plus TDS, and TDS is one positive deductions row. The integration user needs the Accounts User and Sales User roles. Not verified: ERPNext v14 and v16, other India Compliance versions, the Tauri commands and UI against a live site, SEZ and overseas customers, UTGST supplier states, TLS sites, e-invoicing. --- scripts/erpnext-e2e/Containerfile.ic | 5 + scripts/erpnext-e2e/README.md | 148 ++++ scripts/erpnext-e2e/compose.yml | 66 ++ scripts/erpnext-e2e/setup.sh | 42 + scripts/erpnext-e2e/setup_site.py | 197 +++++ .../src/integrations/erpnext/discovery.rs | 49 +- .../src/integrations/erpnext/live_tests.rs | 755 ++++++++++++++++++ src-tauri/src/integrations/erpnext/mapping.rs | 41 +- src-tauri/src/integrations/erpnext/mod.rs | 3 + src-tauri/src/integrations/erpnext/push.rs | 138 +++- .../src/integrations/erpnext/push/tests.rs | 149 +++- 11 files changed, 1554 insertions(+), 39 deletions(-) create mode 100644 scripts/erpnext-e2e/Containerfile.ic create mode 100644 scripts/erpnext-e2e/README.md create mode 100644 scripts/erpnext-e2e/compose.yml create mode 100755 scripts/erpnext-e2e/setup.sh create mode 100644 scripts/erpnext-e2e/setup_site.py create mode 100644 src-tauri/src/integrations/erpnext/live_tests.rs diff --git a/scripts/erpnext-e2e/Containerfile.ic b/scripts/erpnext-e2e/Containerfile.ic new file mode 100644 index 0000000..65184c6 --- /dev/null +++ b/scripts/erpnext-e2e/Containerfile.ic @@ -0,0 +1,5 @@ +# frappe/erpnext v15 plus the india_compliance app (installed per site, not globally) +FROM docker.io/frappe/erpnext:v15.121.6 +USER frappe +RUN bench get-app --skip-assets --branch version-15 https://github.com/resilient-tech/india-compliance.git \ + && ls -1 apps > sites/apps.txt || true diff --git a/scripts/erpnext-e2e/README.md b/scripts/erpnext-e2e/README.md new file mode 100644 index 0000000..e1c9796 --- /dev/null +++ b/scripts/erpnext-e2e/README.md @@ -0,0 +1,148 @@ +# ERPNext live end-to-end (podman) + +Runs Voiced's ERPNext integration against real ERPNext v15 sites: one plain site and one with India Compliance. +Everything is rootless podman (`podman` and `podman-compose`, never docker). All names are prefixed `voiced-erp`. + +| File | Purpose | +|---|---| +| `compose.yml` | Lean stack: MariaDB, one Redis, backend (gunicorn on `127.0.0.1:8088`), one worker. Project name `voiced-erp`. | +| `Containerfile.ic` | `frappe/erpnext:v15.121.6` plus the `india_compliance` app files (`version-15` branch). | +| `setup.sh` | Builds the image, starts the stack, creates both sites, prepares them, writes `.env.a` and `.env.b`. | +| `setup_site.py` | Runs inside the container: company, accounts, address, items, integration user and keys. | +| `../../src-tauri/src/integrations/erpnext/live_tests.rs` | The `#[ignore]` Rust tests. | + +## Reproduce + +```bash +cd scripts/erpnext-e2e +./setup.sh # first run pulls ~2 GB of images and takes about 10 minutes +``` + +`setup.sh` creates two sites that one backend serves by Host header: + +| Site | URL | Contents | Env file | +|---|---|---|---| +| `127.0.0.1` | `http://127.0.0.1:8088` | ERPNext only | `.env.a` | +| `localhost` | `http://localhost:8088` | ERPNext + India Compliance | `.env.b` | + +Both get the company "Voiced Test Co" (abbreviation `VTC`, INR, India, fiscal year 2026-27), the output tax accounts +`Output Tax CGST|SGST|UTGST|IGST - VTC` (India Compliance creates its own with the same names), `TDS Receivable - VTC`, +the bank account `HDFC - VTC`, a company address, the UOMs Hour/Minute/Second, the items `VOICED-SERVICE` (stock UOM Nos) +and `VOICED-HOURLY` (stock UOM Hour), and an integration user with a fresh API key and secret. +`.env.*` files hold those keys; they are git-ignored (`.env.*` in the root `.gitignore`) and must never be committed. + +Run the Rust tests (they only touch the site named by the sourced env file): + +```bash +set -a; . scripts/erpnext-e2e/.env.a; set +a # or .env.b for the India Compliance site +cargo test --manifest-path src-tauri/Cargo.toml live_ -- --ignored --test-threads=1 +``` + +Environment variables the tests read: + +| Variable | Meaning | +|---|---| +| `ERPNEXT_URL`, `ERPNEXT_KEY`, `ERPNEXT_SECRET` | Site address and the integration user's API key and secret. | +| `ERPNEXT_COMPANY` (`Voiced Test Co`), `ERPNEXT_ABBR` (`VTC`) | Company; account names derive from the abbreviation. | +| `ERPNEXT_IC` | `1` on the India Compliance site; the `live_ic_*` tests skip themselves otherwise. | +| `ERPNEXT_ROUNDING` | `banker` (ERPNext default) or `commercial`; decides what the half-paise test expects. | +| `ERPNEXT_BANK_ACCOUNT` (`HDFC - VTC`) | Account that receives payments. | + +Each test builds its own in-memory Voiced database and a fresh invoice series (`L