Commit a989f134e0b1a64cb097e5727fca8dc079166b3d
1 parent
558467ec
docs(progress): P3.2/P3.3/P3.6/R3 done, bump to v0.33.0-SNAPSHOT
- P3.2: MetadataFormRenderer + @rjsf/core + 6 custom ERP widgets - P3.3: Form designer (structured property editor + live preview) - P3.6: List view designer (column/filter/sort configuration) - R3: Metadata admin (tabbed CRUD for all metadata types) - 382 tests, all green
Showing
3 changed files
with
9 additions
and
9 deletions
CLAUDE.md
| @@ -96,7 +96,7 @@ plugins (incl. ref) depend on: api/api-v1 only | @@ -96,7 +96,7 @@ plugins (incl. ref) depend on: api/api-v1 only | ||
| 96 | **Foundation complete; all platform services and core PBCs live.** As of the latest commit: | 96 | **Foundation complete; all platform services and core PBCs live.** As of the latest commit: |
| 97 | 97 | ||
| 98 | - **25 Gradle subprojects** built and tested (1 API + 11 platform + 10 PBC + 1 reference plug-in + web + distribution). The dependency rule (PBCs never import each other; plug-ins only see `api.v1`) is enforced at configuration time by the root `build.gradle.kts`. | 98 | - **25 Gradle subprojects** built and tested (1 API + 11 platform + 10 PBC + 1 reference plug-in + web + distribution). The dependency rule (PBCs never import each other; plug-ins only see `api.v1`) is enforced at configuration time by the root `build.gradle.kts`. |
| 99 | -- **356 unit tests across 25 modules**, all green. `./gradlew build` is the canonical full build. | 99 | +- **382 unit tests across 25 modules**, all green. `./gradlew build` is the canonical full build. |
| 100 | - **All 12 cross-cutting platform services live and smoke-tested end-to-end** against real Postgres: auth (P4.1), OIDC federation (P4.2), authorization with `@RequirePermission` + JWT roles claim + AOP enforcement (P4.3), plug-in HTTP endpoints (P1.3), plug-in linter (P1.2), plug-in-owned Liquibase + typed SQL (P1.4), event bus + transactional outbox (P1.7), metadata loader + custom-field validation (P1.5 + P3.4), ICU4J translator with per-plug-in locale chain (P1.6), JasperReports renderer (P1.8), file store with local + S3 backends (P1.9), Quartz job scheduler (P1.10), plus the audit/principal context bridge. | 100 | - **All 12 cross-cutting platform services live and smoke-tested end-to-end** against real Postgres: auth (P4.1), OIDC federation (P4.2), authorization with `@RequirePermission` + JWT roles claim + AOP enforcement (P4.3), plug-in HTTP endpoints (P1.3), plug-in linter (P1.2), plug-in-owned Liquibase + typed SQL (P1.4), event bus + transactional outbox (P1.7), metadata loader + custom-field validation (P1.5 + P3.4), ICU4J translator with per-plug-in locale chain (P1.6), JasperReports renderer (P1.8), file store with local + S3 backends (P1.9), Quartz job scheduler (P1.10), plus the audit/principal context bridge. |
| 101 | - **10 of 10 core PBCs implemented** (6 feature-complete, 4 at minimal v1 scope): `pbc-identity`, `pbc-catalog`, `pbc-partners`, `pbc-inventory`, `pbc-warehousing`, `pbc-orders-sales`, `pbc-orders-purchase`, `pbc-finance`, `pbc-production`, `pbc-quality`. **The full buy-sell-make loop works**: a purchase order receives stock via `PURCHASE_RECEIPT`, a sales order ships stock via `SALES_SHIPMENT`, and a work order with a bill of materials consumes raw materials via `MATERIAL_ISSUE` and produces finished goods via `PRODUCTION_RECEIPT`, all atomically in one transaction. All four write paths feed the same `inventory__stock_movement` ledger via the same `InventoryApi.recordMovement` facade. | 101 | - **10 of 10 core PBCs implemented** (6 feature-complete, 4 at minimal v1 scope): `pbc-identity`, `pbc-catalog`, `pbc-partners`, `pbc-inventory`, `pbc-warehousing`, `pbc-orders-sales`, `pbc-orders-purchase`, `pbc-finance`, `pbc-production`, `pbc-quality`. **The full buy-sell-make loop works**: a purchase order receives stock via `PURCHASE_RECEIPT`, a sales order ships stock via `SALES_SHIPMENT`, and a work order with a bill of materials consumes raw materials via `MATERIAL_ISSUE` and produces finished goods via `PRODUCTION_RECEIPT`, all atomically in one transaction. All four write paths feed the same `inventory__stock_movement` ledger via the same `InventoryApi.recordMovement` facade. |
| 102 | - **pbc-production v3** adds an IN_PROGRESS state between DRAFT and COMPLETED, a `WorkOrderInput` child entity carrying per-unit BOM consumption rates, a scrap verb, and `WorkOrderOperation` child entity with per-op sequential state machine and operator-entered actual minutes for variance reporting. Shop-floor dashboard projects IN_PROGRESS work orders with progress bars. | 102 | - **pbc-production v3** adds an IN_PROGRESS state between DRAFT and COMPLETED, a `WorkOrderInput` child entity carrying per-unit BOM consumption rates, a scrap verb, and `WorkOrderOperation` child entity with per-op sequential state machine and operator-entered actual minutes for variance reporting. Shop-floor dashboard projects IN_PROGRESS work orders with progress bars. |
PROGRESS.md
| @@ -10,11 +10,11 @@ | @@ -10,11 +10,11 @@ | ||
| 10 | 10 | ||
| 11 | | | | | 11 | | | | |
| 12 | |---|---| | 12 | |---|---| |
| 13 | -| **Latest version** | v0.32.0-SNAPSHOT (P3.1 dynamic form renderer + i18n + edit forms + double-entry GL + OIDC + S3) | | ||
| 14 | -| **Latest commit** | `b0b0183 feat(web): P3.1 dynamic custom field renderer` | | 13 | +| **Latest version** | v0.33.0-SNAPSHOT (P3.2 form renderer + P3.3 form designer + P3.6 list view designer + R3 metadata admin) | |
| 14 | +| **Latest commit** | `558467e feat(web): list view designer` | | ||
| 15 | | **Repo** | https://github.com/reporkey/vibe-erp | | 15 | | **Repo** | https://github.com/reporkey/vibe-erp | |
| 16 | | **Modules** | 25 JVM subprojects + `:web` SPA | | 16 | | **Modules** | 25 JVM subprojects + `:web` SPA | |
| 17 | -| **Unit tests** | 356, all green | | 17 | +| **Unit tests** | 382, all green | |
| 18 | | **Real PBCs implemented** | **10 of 10** (pbc-identity, pbc-catalog, pbc-partners, pbc-inventory, pbc-warehousing, pbc-orders-sales, pbc-orders-purchase, pbc-finance, pbc-production, pbc-quality) — P5.x row of the implementation plan complete at minimal v1 scope | | 18 | | **Real PBCs implemented** | **10 of 10** (pbc-identity, pbc-catalog, pbc-partners, pbc-inventory, pbc-warehousing, pbc-orders-sales, pbc-orders-purchase, pbc-finance, pbc-production, pbc-quality) — P5.x row of the implementation plan complete at minimal v1 scope | |
| 19 | | **End-to-end smoke runs** | An SO confirmed with 2 lines auto-spawns 2 draft work orders via `SalesOrderConfirmedSubscriber`; completing one credits the finished-good stock via `PRODUCTION_RECEIPT`, cancelling the other flips its status, and a manual WO can still be created with no source SO. All in one run: 6 outbox rows DISPATCHED across `orders_sales.SalesOrder` and `production.WorkOrder` topics; pbc-finance still writes its AR row for the underlying SO; the `inventory__stock_movement` ledger carries the production receipt tagged `WO:<code>`. First PBC that REACTS to another PBC's events by creating new business state (not just derived reporting state). | | 19 | | **End-to-end smoke runs** | An SO confirmed with 2 lines auto-spawns 2 draft work orders via `SalesOrderConfirmedSubscriber`; completing one credits the finished-good stock via `PRODUCTION_RECEIPT`, cancelling the other flips its status, and a manual WO can still be created with no source SO. All in one run: 6 outbox rows DISPATCHED across `orders_sales.SalesOrder` and `production.WorkOrder` topics; pbc-finance still writes its AR row for the underlying SO; the `inventory__stock_movement` ledger carries the production receipt tagged `WO:<code>`. First PBC that REACTS to another PBC's events by creating new business state (not just derived reporting state). | |
| 20 | | **Plug-ins serving HTTP** | 1 (reference printing-shop, 7 endpoints + own DB schema + own metadata + own i18n bundles) | | 20 | | **Plug-ins serving HTTP** | 1 (reference printing-shop, 7 endpoints + own DB schema + own metadata + own i18n bundles) | |
| @@ -60,11 +60,11 @@ That target breaks down into roughly 30 work units across 8 phases. About **22 a | @@ -60,11 +60,11 @@ That target breaks down into roughly 30 work units across 8 phases. About **22 a | ||
| 60 | | # | Unit | Status | | 60 | | # | Unit | Status | |
| 61 | |---|---|---| | 61 | |---|---|---| |
| 62 | | P3.1 | Dynamic custom field form renderer | ✅ DONE — `b0b0183` — `DynamicExtFields` SPA component fetches custom field declarations from metadata API and renders type-matched inputs (string/integer/decimal/boolean/date/enum) with i18n labels. Wired into CreateItemPage + CreatePartnerPage. No new backend code — uses the existing custom-fields endpoint. | | 62 | | P3.1 | Dynamic custom field form renderer | ✅ DONE — `b0b0183` — `DynamicExtFields` SPA component fetches custom field declarations from metadata API and renders type-matched inputs (string/integer/decimal/boolean/date/enum) with i18n labels. Wired into CreateItemPage + CreatePartnerPage. No new backend code — uses the existing custom-fields endpoint. | |
| 63 | -| P3.2 | Form renderer (web) | 🔜 Pending — depends on R1 | | ||
| 64 | -| P3.3 | Form designer (web) | 🔜 Pending — depends on R1 | | 63 | +| P3.2 | Form renderer (web) | ✅ DONE — `1875c06` — `MetadataFormRenderer` component using @rjsf/core with custom VibeErp Tailwind theme + 6 ERP widgets (partner-picker, item-picker, uom-selector, location-picker, money-input, quantity-input). Renders forms from `metadata__form` definitions. Supports visibility conditions via `ui:visible` in uiSchema. | |
| 64 | +| P3.3 | Form designer (web) | ✅ DONE — `558467e` — Structured property editor with live @rjsf preview. Left panel: field list with inline property panels (label, placeholder, help text, widget override, visibility condition). Right panel: real-time preview. Generates JSON Schema + UI Schema from field definitions. Edit mode hydrates from existing definitions. | | ||
| 65 | | P3.4 | Custom field application (JSONB `ext` validation) | ✅ DONE — `5bffbc4` | | 65 | | P3.4 | Custom field application (JSONB `ext` validation) | ✅ DONE — `5bffbc4` | |
| 66 | | P3.5 | Rules engine (event-driven) | 🔜 Pending | | 66 | | P3.5 | Rules engine (event-driven) | 🔜 Pending | |
| 67 | -| P3.6 | List view designer (web) | 🔜 Pending — depends on R1 | | 67 | +| P3.6 | List view designer (web) | ✅ DONE — `558467e` — Column/filter/sort configuration editor with live DataTable preview. Columns: show/hide, label, format, sortable, reorder. Filters: field, operator, label. Default sort + page size. Edit mode loads existing definitions. | |
| 68 | 68 | ||
| 69 | ### Phase 4 — Authentication and authorization | 69 | ### Phase 4 — Authentication and authorization |
| 70 | 70 | ||
| @@ -94,7 +94,7 @@ That target breaks down into roughly 30 work units across 8 phases. About **22 a | @@ -94,7 +94,7 @@ That target breaks down into roughly 30 work units across 8 phases. About **22 a | ||
| 94 | |---|---|---| | 94 | |---|---|---| |
| 95 | | R1 | Vite + React + TS bootstrap, login flow, typed REST client | ✅ DONE — `fc62d6d` — new `:web` Gradle subproject wraps Vite/React 18/TypeScript/Tailwind 3.4 via Exec tasks; `:distribution` consumes the dist via an outgoing/incoming Gradle configuration and stages it into `classpath:/static/` so a single fat-jar serves both API and SPA. Hand-written typed fetch client over `/api/v1/**` (211 KB JS gzipped, no codegen toolchain). AuthContext stores the JWT in localStorage with a 401 handler. `SpaController` forwards every known SPA route prefix to `/index.html` so React Router deep links work on hard refresh. `SecurityConfiguration` reordered: `/api/**` stays `.authenticated()` before the SPA permitAll rules so the "API is always authenticated" invariant holds even with the SPA bundled in the same image. Dockerfile build stage adds `apk add nodejs npm` so `./gradlew :distribution:bootJar` produces a self-contained image with the SPA inside. End-to-end smoke verified on fresh Postgres: log in, walk SO DRAFT → CONFIRMED → SHIPPED, watch stock balances drop + AR journal entry settle — all in a real browser. | | 95 | | R1 | Vite + React + TS bootstrap, login flow, typed REST client | ✅ DONE — `fc62d6d` — new `:web` Gradle subproject wraps Vite/React 18/TypeScript/Tailwind 3.4 via Exec tasks; `:distribution` consumes the dist via an outgoing/incoming Gradle configuration and stages it into `classpath:/static/` so a single fat-jar serves both API and SPA. Hand-written typed fetch client over `/api/v1/**` (211 KB JS gzipped, no codegen toolchain). AuthContext stores the JWT in localStorage with a 401 handler. `SpaController` forwards every known SPA route prefix to `/index.html` so React Router deep links work on hard refresh. `SecurityConfiguration` reordered: `/api/**` stays `.authenticated()` before the SPA permitAll rules so the "API is always authenticated" invariant holds even with the SPA bundled in the same image. Dockerfile build stage adds `apk add nodejs npm` so `./gradlew :distribution:bootJar` produces a self-contained image with the SPA inside. End-to-end smoke verified on fresh Postgres: log in, walk SO DRAFT → CONFIRMED → SHIPPED, watch stock balances drop + AR journal entry settle — all in a real browser. | |
| 96 | | R2 | Identity screens (user admin, role admin) | ✅ DONE — `82c5267` — UsersPage (list + link to detail), CreateUserPage, UserDetailPage (role toggle with Assign/Revoke), RolesPage (list + inline create). Backend: new RoleService + RoleController with list/create roles, assign/revoke role endpoints. identity.yml updated with identity.role.create permission. | | 96 | | R2 | Identity screens (user admin, role admin) | ✅ DONE — `82c5267` — UsersPage (list + link to detail), CreateUserPage, UserDetailPage (role toggle with Assign/Revoke), RolesPage (list + inline create). Backend: new RoleService + RoleController with list/create roles, assign/revoke role endpoints. identity.yml updated with identity.role.create permission. | |
| 97 | -| R3 | Customize / metadata UIs | 🔜 Pending | | 97 | +| R3 | Customize / metadata UIs | ✅ DONE — `558467e` — Tabbed MetadataAdmin page with 6 tabs: Entities (read-only), Custom Fields (full CRUD for source='user'), Permissions (read-only), Menus (read-only), Forms (links to designer), List Views (links to designer). Source badges (core/plugin/user). Inline custom field editor with type picker, required/PII flags, and label translations. | |
| 98 | | R4 | Per-PBC create/edit screens | ✅ Partial — `2535324` + `1777189` — create forms for items, partners, locations, purchase orders, work orders (with BOM + routing editors), stock adjustment. Every PBC entity that operators need to manage has a SPA form. Remaining: edit forms (patch existing records), richer BOM/routing editors. | | 98 | | R4 | Per-PBC create/edit screens | ✅ Partial — `2535324` + `1777189` — create forms for items, partners, locations, purchase orders, work orders (with BOM + routing editors), stock adjustment. Every PBC entity that operators need to manage has a SPA form. Remaining: edit forms (patch existing records), richer BOM/routing editors. | |
| 99 | 99 | ||
| 100 | ### Phase 7 — Reference printing-shop plug-in | 100 | ### Phase 7 — Reference printing-shop plug-in |
gradle.properties
| @@ -19,6 +19,6 @@ kotlin.incremental=true | @@ -19,6 +19,6 @@ kotlin.incremental=true | ||
| 19 | # api/api-v1/build.gradle.kts. | 19 | # api/api-v1/build.gradle.kts. |
| 20 | # Bump this line in lockstep with PROGRESS.md's "Latest version" | 20 | # Bump this line in lockstep with PROGRESS.md's "Latest version" |
| 21 | # row when shipping a new working surface. | 21 | # row when shipping a new working surface. |
| 22 | -vibeerp.version=0.32.0-SNAPSHOT | 22 | +vibeerp.version=0.33.0-SNAPSHOT |
| 23 | vibeerp.api.version=1.0.0-SNAPSHOT | 23 | vibeerp.api.version=1.0.0-SNAPSHOT |
| 24 | vibeerp.group=org.vibeerp | 24 | vibeerp.group=org.vibeerp |