diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..37047a5 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "Bash(python3 -c \":*)" + ] + } +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..c1af0a0 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,143 @@ +# AGENTS.md — Statistics App (Appsmith) + +## Project Overview + +Internal statistics dashboard built on **Appsmith** (file-based git sync mode). Displays filtered data from a **PostgreSQL / xTuple ERP** database (`xTuple_GoLive` datasource). The app is a collection of JSON widget definitions, SQL query files, and Appsmith configuration — there is no traditional application code. + +**Live URL**: `https://appsmith.mpeapp.com/applications/6947cc068872ae1d129983a0/pages/6947cc068872ae1d129983a3` + +## Tech Stack + +| Layer | Technology | +|-------|-----------| +| Platform | Appsmith (file format v5, 64-column grid layout) | +| Database | PostgreSQL via xTuple ERP (`mpe` and `public` schemas) | +| Datasource | `xTuple_GoLive` (production) / `xTuple_Sandbox` (development) | +| Version control | Git (Bitbucket), Appsmith git sync | + +## Repository Structure + +``` +statistics-app/ +├── AGENTS.md # This file — keep up to date after every change +├── application.json # Page registry, app metadata +├── metadata.json # Appsmith schema versions +├── theme.json # UI theme (colors, fonts, borders) +├── datasources/ +│ └── xTuple_GoLive.json # PostgreSQL connection config (credentials managed by Appsmith server, not stored here) +├── pages/ # One directory per page +│ └── / +│ ├── .json # Page definition (gitSyncId required) +│ ├── widgets/ # Widget JSON files +│ │ ├── Heading.json +│ │ ├── Container1/ # Navigation sidebar widgets +│ │ └── Tabs1/ # Tabbed content (if applicable) +│ └── queries/ # SQL queries +│ └── / +│ ├── .txt # Raw SQL (source of truth) +│ └── metadata.json # Appsmith action config +└── .cursor/skills/ # AI agent workflows (Cursor-specific) +``` + +## Pages + +| Section | Page | Key Data | +|---------|------|----------| +| Sales | Capacity Planning (default) | `mpe.poormancapacity` | +| Sales | Units Shipped | Orders shipped by series / power input, date-filtered | +| Sales | Units Ordered | Orders placed by series / power input, date-filtered | +| Engineering | Pending POs | Purchase orders via `mpe.get_prototype_po_dashboard_data()` | +| Engineering | Pending Revisions | Revisions via `mpe.get_prototype_dashboard_data()` | +| Engineering | xGen | 8 tabs: build info, compatibility, firmware, test measurements | +| Operations | Engineering Holds | Work orders with active engineering holds | +| Operations | Job Drawing Status | CAD drawing builds from `mpe.inventortools` | +| Operations | Unused Items | Items with no inventory transactions for X days (default 365), filterable via input widget | + +## Critical Conventions + +### gitSyncId (REQUIRED) + +Every page JSON and query `metadata.json` **must** have a `gitSyncId` as the first field. Format: `"<24-char-hex>_"`. Without it, Appsmith silently deletes the entity on next sync. + +Generate: +```bash +python3 -c "import uuid; print(uuid.uuid4().hex[:24] + '_' + str(uuid.uuid4()))" +``` + +### Widget IDs + +Every `widgetId` across all pages must be globally unique. Use short descriptive strings with a 2-3 character page prefix (e.g., `ui1btn3jds`, `eh1heading1`). + +### Navigation + +- Every page has identical nav sidebar (`Container1/`) with buttons for all pages. +- Active page button: `buttonColor` = `{{appsmith.theme.colors.backgroundColor}}` (dynamic binding). +- Inactive buttons: `buttonColor` = `#ffffff` (static, no dynamic binding). +- `parentId` for nav widgets = the Canvas `widgetId` inside that page's `Container1.json` (varies per page — always read it). +- Current nav sections: **Sales** (rows 0–16), **Engineering** (rows 18–34), **Operations** (rows 36–52). + +### Canvas Widget IDs (for parentId in Container1 children) + +| Page | Canvas widgetId | +|------|----------------| +| Sales - Capacity Planning | `x3pc17vp6q` | +| Sales - Units Shipped | `wj6fxg5wpg` | +| Sales - Units Ordered | `wj6fxg5wpg` | +| Pending POs | `pa1canvas01` | +| Pending Revisions | `pr1canvas01` | +| xGen | `xg1canvas01` | +| Operations - Job Drawing Status | `jd1canvas01` | +| Operations - Engineering Holds | `eh1canvas01` | +| Operations - Unused Items | `ui1canvas01` | + +### Grid Layout + +- 64 columns wide, 10px per row. +- Nav container: rows 0–7. Content starts at row 8. +- Nav buttons: 4 rows each, 2-row gap between sections. + +### Queries + +- SQL source of truth: `.txt` (readable, real newlines). +- `metadata.json` `body` field: same SQL but JSON-escaped (`\n`, `\"`). +- Table binding: `{{query_name.data}}`. +- Optional date filter pattern: `NULLIF('{{Widget.selectedDate}}','') IS NULL OR ... BETWEEN ...::date AND ...::date`. +- All production queries use `xTuple_GoLive` datasource. +- **Database credentials are managed by Appsmith server-side** — they are not stored in this repository. The datasource JSON only contains the name and plugin reference. When developing/testing SQL queries locally, use separate read-only credentials provided by the user — never embed them in committed files. + +## Common Tasks + +### Add a new page + +Provide: page name (`
-