7.9 KiB
Service Factory — ERPNext Custom App Project
Current Version: V0.1.0017 — Each completed prompt/step increments the patch number by 1 (V0.1.0000 → V0.1.0001 → V0.1.0002…). The agent automatically commits and pushes after every step.
Project Overview
Service Factory is a custom Frappe/ERPNext application that productizes professional services by treating human teams as structured "Resource Centers" and engagements as "Production Orders." Built for Frappe v16/ERPNext.
Architecture
ERPNext Deployment (Production)
| Attribute | Value |
|---|---|
| Location | /opt/erpnext/frappe-bench/ |
| System user | erpnext |
| Frappe version | v16 (via bench) |
| Database | MariaDB |
| Domain | erp.lohmar.co.uk |
| Port | 8080 (web via nginx proxy, proxies web + SocketIO) |
| Direct port | 8000 (gunicorn direct — SocketIO won't work) |
| Reverse proxy | Nginx on ports 8000+8080 → gunicorn:8001 (web) + node:9000 (SocketIO) |
| Zoraxy config | WebSocket passthrough: enabled — Virtual directory: /socket.io → http://172.16.8.20:9000/socket.io |
| Static assets | /assets/ served directly by nginx (bypasses gunicorn) — essential for correct MIME handling behind Zoraxy |
| Process manager | systemd (5 services managed via frappe-bench.target) |
| Reverse proxy | Zoraxy (unifies web + SocketIO on port 8080) |
Sites
| Site | URL | Purpose |
|---|---|---|
erp.lohmar.co.uk |
http://erp.lohmar.co.uk:8000 | Production — ERPNext with all default apps + service_factory |
test_sf.lohmar.co.uk |
(site created) | Testing — isolated site for Service Factory development |
Installed Apps (on production site)
frappe, erpnext, service_factory
Default ERPNext apps active: Framework, Organization, Accounting, Assets, Buying, Manufacturing, Projects, Quality, Selling, Stock, Subcontracting, ERPNext Settings.
Bench Services (systemd)
| Service | Description |
|---|---|
frappe-bench-web.service |
Gunicorn web server (port 8001, behind nginx on ports 8000+8080) |
frappe-bench-worker.service |
Background async worker |
frappe-bench-schedule.service |
Scheduled job runner |
frappe-bench-socketio.service |
Realtime WebSocket (port 9000) |
frappe-bench-watch.service |
File watcher for dev/assets |
All services managed via frappe-bench.target (start/stop/status as a unit).
Credentials
Location: /root/erpnext-admin-credentials.txt
Site: http://erp.lohmar.co.uk:8080
Username: Administrator
Development Repository Structure
~/development/
├── erp-next/ # Git repository (Forgejo: cclohmar/erp-next.git)
│ ├── service_factory/ # Frappe app source (DEV COPY — may be behind bench)
│ ├── pyproject.toml
│ ├── README.md
│ └── .pre-commit-config.yaml
└── sow.md # Statement of Work — the authoritative blueprint
The actual live app lives at:
/opt/erpnext/frappe-bench/apps/service_factory/
IMPORTANT: The bench app and the dev repo are two separate git clones. The bench app contains the latest development work (all milestones complete). The dev repo at ~/development/erp-next/ may be behind and needs syncing after changes are made in the bench.
Milestone Status (ALL COMPLETE in bench)
| # | Milestone | Status |
|---|---|---|
| M1 | Custom App Scaffold & DB Schema (5 DocTypes) | ✅ Done |
| M2 | Backend Python Controllers (cost rollup, card generation, capacity warnings) | ✅ Done |
| M3+4 | Frontend JS Components + Role-Based Workspaces | ✅ Done |
| M5 | Test Suite (4 integration tests) | ✅ Done |
| — | Deployment config with systemd, nginx, Zoraxy proxy | ✅ Done |
| — | App icon + fixtures (seed data) | ✅ Done |
DocTypes Created
Setup (Master)
Engagement Task Type— Task categories (Demo, POC, Deployment, RFP/RFI, Other)Team Template— Pre-defined teams by department- Child:
Team Template Member— Employee assignment with role
- Child:
Transaction
Engagement Card— Universal work card (TEC)- Child:
Engagement Card Assignment— Multi-person team allocation - Child:
Engagement Card Activity— Activity log with milestones - Child:
Engagement Card Time Log— Per-employee hours tracking - Child:
Engagement Card Subtask— Delegatable breakdown items
- Child:
Business Logic (server-side)
EngagementOrder.validate()— Recipe step auto-population, capacity warnings, cost totalsEngagementOrder.on_submit()— Auto-generates Execution Cards for assigned stepsExecutionCard.on_update()— Rollup of actual hours → parent order costs/billing
Dashboards (3 role-based workspaces)
- Engineer Workspace — My Execution Cards, Timer, Hours chart, Quick actions
- Manager Workspace — Schedule Gantt, Capacity Alerts, Active/Stalled KPIs
- Director Workspace — Margin Ledger, Delivery Efficiency, Resource Burn-Down
Tests (bench app)
test_engagement_order.py — 4 integration tests:
1. Execution Cards generated on Order submit
2. Cost/billing rollup from Card hours
3. Recipe steps auto-populate from template
4. Capacity warning fires on overallocation
Git Operations
Git server: git.lohmar.co.uk (self-hosted Forgejo)
Two .gitenv files exist:
/root/.gitenv— template (placeholder, ignore)/root/bin/.gitenv— actual credentials
source /root/bin/.gitenv
| Setting | Value |
|---|---|
| Remote | https://cclohmar:${TOKEN}@git.lohmar.co.uk/cclohmar/erp-next.git |
| Default branch | main |
| Commit prefix | chore: |
| Auto-stash | enabled |
Two Git Repos — Keep in Sync
DEV REPO: ~/development/erp-next/ (1 commit — scaffold only)
BENCH APP: /opt/erpnext/frappe-bench/apps/service_factory/ (10 commits — all milestones)
The bench app has all the development work. When making changes:
- Develop in the bench's app directory (or sync bench → dev repo first)
- Commit from the bench app OR the dev repo
- Push to Forgejo
Auto-Push Workflow
After every completed prompt/step, the agent MUST:
- Stage all changes (
git add -A) - Commit with prefix
chore:and a concise description - Increment the version in this file's header (V0.1.xxxx → V0.1.xxxx+1)
- Push to
origin/main - If the dev repo is behind the bench app, sync first before committing
This ensures every interaction is checkpointed and version-tracked.
Development Environment
| Tool | Location |
|---|---|
| OpenAgentsControl | /root/.opencode/ |
| Context files | /root/.opencode/context/ |
| Tmux manager | /root/bin/workspace (tmux-project new|return|list|kill) |
| Linting | ruff (Python), eslint (JS), prettier |
| Python | ≥3.14 |
| Runtime | Node.js/Bun, @opencode-ai/plugin |
Agent Modes (Toggle)
OpenAgent operates in two explicit modes during conversation:
| Mode | Trigger | Behaviour |
|---|---|---|
| 🗣️ Discuss | Default — every interaction starts here | Ideas, trade-offs, architecture sketches (text-only), questions, exploration. Not a single file is touched, no bash executed. |
| 🔧 Build | Only when you say "build it" or equivalent |
Execute the agreed plan — write files, edit code, run benchmarks, deploy, commit & push. All standard approval gates still apply. |
The toggle is conversational: I stay in 🗣️ Discuss until you explicitly switch to 🔧 Build. This ensures we align on direction before any work begins.
Agent Rules
- OpenAgent — General purpose, workflow orchestration (toggle mode: discuss / build)
- OpenCoder — Production development
- Load context via ContextScout before any code/doc/test work
- Approval gates required before file writes and bash execution
- STOP on test failure — never auto-fix