erp-next/AGENTS.md

209 lines
7.9 KiB
Markdown

# Service Factory — ERPNext Custom App Project
> **Current Version: V0.1.0014** — 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
**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
### Business Logic (server-side)
- `EngagementOrder.validate()` — Recipe step auto-population, capacity warnings, cost totals
- `EngagementOrder.on_submit()` — Auto-generates Execution Cards for assigned steps
- `ExecutionCard.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**
```bash
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:
1. Develop in the bench's app directory (or sync bench → dev repo first)
2. Commit from the bench app OR the dev repo
3. Push to Forgejo
### Auto-Push Workflow
After **every completed prompt/step**, the agent MUST:
1. Stage all changes (`git add -A`)
2. Commit with prefix `chore:` and a concise description
3. Increment the version in this file's header (V0.1.xxxx → V0.1.xxxx+1)
4. Push to `origin/main`
5. 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