ERPNext was built for MariaDB; we run it on PostgreSQL because that's
what fit the legacy migration. Frappe's SQL generator is loose on
MariaDB (missing GROUP BY columns OK, double-quoted strings OK,
HAVING without GROUP BY OK) but strict on Postgres, so we end up
hand-patching files in `patches/fix_pg_groupby.py` after every
ERPNext upgrade. The community has packaged a comprehensive fix as
a Frappe app — `frappe_pg` — that covers the same bugs in one
place. The cleaner path long-term is to install that app instead
of growing our own patch set.
Two doc updates:
- docs/architecture/overview.md §6 item 8 — full background:
the 3 SQL patterns that break (GROUP BY, HAVING, double-quoted
string literals), the 12 hotspots we've already patched, the
4 known remaining (bank_clearance, bank_reconciliation_tool,
accounts/utils L1660, gross_profit), and the install
recommendation with trade-offs (pin a commit, validate on
staging, keep our patches as backup for 4-6 weeks).
- docs/SETUP.md §7 — quick-start install commands for whoever
decides to flip the switch, plus the warning about pinning
rather than tracking main. Also notes that custom Server
Scripts with raw SQL (like `customer_balance`) need the same
single-quote vs double-quote vigilance even after installing
frappe_pg, and the export-fixtures hint to version-control
them.
5.3 KiB
Dev setup — gigafibre-fsm
Quick reference for getting the stack running on a new machine.
1. Clone
git clone https://git.targo.ca/louis/gigafibre-fsm.git
cd gigafibre-fsm
2. Env files
The actual .env files are gitignored (they hold secrets). Each component
ships a .env.example with placeholder values + comments. Copy and fill in:
cp apps/ops/.env.example apps/ops/.env
cp services/targo-hub/.env.example services/targo-hub/.env
Ask the team for the real values (or copy from /opt/<service>/.env on the
prod box if you have access). The hub .env is the long one — most fields
correspond to one external integration (Stripe, Twilio, Authentik, etc.).
Anything left blank disables that feature gracefully.
3. Run the apps
apps/ops (Vue 3 + Quasar SPA)
cd apps/ops
npm install
npx quasar dev # dev server at http://localhost:9000
npx quasar build # production bundle in dist/spa/
Notes:
- The SPA expects to find ERPNext at the same origin in production
(
erp.gigafibre.ca/ops/is served from/opt/ops-app/via the ERPNext nginx). In dev, setVITE_HUB_URLto the local hub or the prod hub for backend calls. - Authentik SSO redirects only work behind a real domain — dev mode
uses the API token (
VITE_ERP_TOKEN) for direct ERPNext calls.
services/targo-hub (Node 20+)
cd services/targo-hub
npm install --production
node server.js # listens on :3300
In production this runs in a Docker container under /opt/targo-hub/ with
the host's .env file mounted.
Other services
The services/ and apps/ directories also contain Docker compose stacks
that run on the prod server (ERPNext, Authentik, Traccar proxy, Fonoster,
DocuSeal, …). Reproducing them locally is rarely needed — the hub talks
to ERPNext + Authentik over the network and that's enough for most
front-end work.
4. Common tasks
| Task | Command |
|---|---|
| Build + deploy ops SPA to prod | cd apps/ops && npx quasar build && scp -r dist/spa/* root@96.125.196.67:/opt/ops-app/ |
| Push hub code change | scp services/targo-hub/lib/<file>.js root@96.125.196.67:/opt/targo-hub/lib/ then ssh root@... 'docker restart targo-hub' |
| Tail prod logs | ssh root@96.125.196.67 'docker logs -f targo-hub --tail 50' |
| Re-build after changing daemon.json or compose | docker compose up -d --force-recreate from the relevant /opt/<service>/ |
5. Where things live
apps/ops/ Quasar SPA — main internal tool (dispatch, clients, …)
apps/ops/src/pages/ Top-level pages (DispatchPage, ClientDetailPage, …)
apps/ops/src/composables/ Shared logic (useMap, useResourceFilter, …)
apps/ops/src/components/shared/detail-sections/ Per-doctype detail panels
services/targo-hub/ Node middleware between SPA / ERPNext / 3rd parties
services/targo-hub/lib/ One module per integration (auth, dispatch, ai, …)
services/targo-hub/server.js Top-level HTTP router
docs/ This file + future runbooks
6. Auth quirks (fyi)
- Authentik staff instance =
auth.targo.ca(admin token inAUTHENTIK_TOKEN). ERPNext uses it as an OAuth provider. - Authentik client instance =
id.gigafibre.ca(separate stack, for customer portal — uses/opt/authentik-client/). - Inviting a user via ops Settings → Utilisateurs hits
POST /auth/userson the hub, which (a) creates the Authentik user, (b) sets a temp password, (c) emails it via Mailjet, (d) creates the matching ERPNext System User. - The Authentik recovery email flow isn't configured (no
flow_recoveryon the brand) — the hub sends the credentials itself instead.
7. ERPNext on PostgreSQL — known incompatibilities
ERPNext was built for MariaDB. We run on PostgreSQL because the legacy migration data was easier to handle there. Frappe & ERPNext generate SQL that's lenient under MariaDB but strict under Postgres — symptoms on the UI are "column X does not exist" errors or empty/blank reports on certain accounting screens (Bank Clearance, Payment Reconciliation, Gross Profit, etc.).
Strongly suggested: install the
frappe_pg
community app, which bundles a comprehensive set of PostgreSQL
compatibility patches as a Frappe app. It's the cleaner alternative
to maintaining our own per-file patches in patches/fix_pg_groupby.py,
which we have to re-apply after every ERPNext upgrade.
# On the prod box, inside the erpnext-backend container:
docker exec -it erpnext-backend-1 bench get-app frappe_pg
docker exec -it erpnext-backend-1 bench --site erp.gigafibre.ca install-app frappe_pg
docker exec -it erpnext-backend-1 bench restart
Before installing on prod: pin a known-good commit in apps.txt
rather than tracking main — the app is community-maintained and can
lag behind ERPNext releases. Validate on staging first by running the
smoke test on the 4 known-broken accounting UIs.
Our own custom Server Scripts with raw SQL (e.g. customer_balance)
need the same vigilance regardless: PostgreSQL treats "Customer" as
a column identifier; use 'Customer' (single quotes) for string
literals. Add a bench export-fixtures step to version-control any
Server Script we tweak so the fix isn't lost on re-deployment. See
docs/architecture/overview.md §6 item 8 for the full background.