Lalabase
Tickets, Doku, Zeiterfassung und Kundengespräche an einem Ort, durchsuchbar per KI. Für Softwarefirmen mit Kundenprojekten. Open Source: auf deinem eigenen Server oder in unserer Cloud in Deutschland.
翻譯準備中
請購、批准、採購、授標、交付、檢驗、三方匹配、付款與結案——一個案件、一條時間線、一條審計追蹤。建於肯尼亞。
AI 翻譯
Requisition, approval, sourcing, award, delivery, inspection, three-way match, payment and close-out — one case, one timeline, one audit trail. Built in Kenya.
商業TypeScript · PLpgSQLGitHub @edoscentre-coder上線中營運者未確認
試用過了嗎? 點一下就好,不需要登入。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Enterprise Procurement, Workflow, Queue and Service Delivery Management
Platform — multi-tenant SaaS. See PRD.md and
ARCHITECTURE.md for the full product and technical
blueprint; this file only covers running what's built so far.
Phase 1 — Platform Foundation: implemented.檢視完整 README ↗Enterprise Procurement, Workflow, Queue and Service Delivery Management Platform — multi-tenant SaaS. See PRD.md and ARCHITECTURE.md for the full product and technical blueprint; this file only covers running what's built so far.
Phase 1 — Platform Foundation: implemented.
edospmis_provision_tenant, one transaction: tenant row, membership,
a starter set of 10 tenant-scoped roles seeded from the PRD's persona
list, Tenant Administrator assignment).legal.contract.*,
seeded ahead of the module itself — see below), tenant-scoped custom
roles, a Roles admin screen (create a role, toggle its permissions by
category, delete an unused custom role — system roles are read-only)./update-password is where they land after
accepting), change their role, suspend/reactivate.edospmis_audit_logs) — every invite, role change, role
permission change, suspension and tenant-provisioning event is written
here; nothing updates or deletes an existing row.Phase 2 — Case + PR + Workflow + Queue + Approval + SLA (MVP): implemented.
PR-{year}-{seq} — default as of
migration 0031_pr_numbering_format, tenant-configurable in Settings >
Organization, atomically sequenced), and is submitted for approval from
the Case detail page. The Case entity and case_id FK are unchanged —
only the displayed/stored number string moved from CASE- to PR-, to
match the "PR No." label used everywhere in the UI.draft → approval → approved workflow is
seeded per tenant, versioned and stored as data (edospmis_workflow_versions.definition)
so the Case detail chevron (WorkflowStepper) reads real stage labels —
see ARCHITECTURE.md §1.2/§4.2 for the scope cut (procedural, not a fully
generic interpreter yet).edospmis_submit_pr and
edospmis_decide_approval run the chain as single atomic transactions.0004_admin_holds_dept_manager.sql.Phase 3 — Procurement + Legal/Contract Provisioning: implemented (v1 cuts).
procurement.rfq.create), which opens an RFQ seeded
from the PR's own items. From the Case detail page's Procurement panel:
invite suppliers, record what they quoted, and award — issuing a PO
(PO-2026-000001, derived from the case number) and moving the case to
Awarded. Suppliers get their own admin screen, same pattern as Clients.Phase 4 — Fulfilment: implemented (v1 cuts).
GRN-2026-000001
off the case number (-01, -02, ... for partial/repeat receipts). The
case moves to Receiving on the first GRN.receiving.grn.approve records one pass/fail/
conditional outcome per GRN, with comments and a free-text evidence
reference — no file upload yet (see the migration header), so a report
number or photo filename stands in for an attached document.procurement.case.close and the case not already being in a terminal
state — deliberately not hard-blocked on "delivery confirmed", since a
case can legitimately end without one (a services-only PR, a client
collecting in person). The Case detail screen nudges toward closing after
delivery confirms; it never refuses the button.Draft › Approval › Approved › Procurement › Awarded › Receiving › Delivery › Completed — Finance is Phase 5, not in this chevron yet).
Existing tenants' default workflow was also given this fuller stage list
via a new workflow version, so this applies to their next case too, not
only brand-new tenants.Phase 5 — Finance + Advanced Controls: implemented (v1 cuts).
edospmis_decide_approval now honours an active
delegation the same way it honours directly holding the role, drawing
the permission from the delegated role itself so the delegate doesn't
need to separately hold it. Delegating and revoking are both audited.finance stage. One
real design bug was caught and fixed during this pass: delegation was
only granted routing authority, not the underlying permission check, so
a delegate with no independent grant on the delegated permission could
never actually act — fixed by drawing the permission from the delegated
role rather than the acting user's own role set.Flow Alignment — implemented. A real client's own turnaround-time export (SAP Business One PR/PO/GRPO day-counts) and their target 12-stage procure-to-pay diagram were audited against the build above; this closed the gaps that came out of it, fitted additively rather than as a rework:
edospmis_case_stage_history): a database trigger
on edospmis_cases — not a call threaded through every RPC — opens a
stage row on creation and closes/reopens one on every status change,
automatically, for every past and future write path. This is the exact
"days from X to Y" metric the client's Excel report computes by hand,
now live per case. The Case detail page shows it as "Time in each
stage", and the current stage's SLA (if the tenant has configured one
for it — edospmis_sla_policies was always generic per stage, only
approval ever had a row) shows a live breach/warning status the same
way approval SLA already did.requires_po_approval,
off by default) between Procurement and Awarded — the client's data
proved this is a real, distinct step (PO Created ≠ PO Approved dates)
that most tenants don't need. Reuses a procurement.po.approve
permission that had existed in the catalogue, unused, since Phase 1.cancelled status has existed since Phase 2 with
no path to reach it; closed with one RPC + button, reusing the
procurement.pr.cancel permission (also unused since Phase 1).Phase 6 — Reporting/Analytics: implemented (v1 cuts).
reports.view, already granted to several roles
since Phase 1 and never used until now): open requests by age, time
spent in each stage plus how many cases are sitting in each one right
now (a live bottleneck view), approval SLA compliance, supplier
performance (spend, GRN acceptance rate, average lead time from award to
first receipt), and spend by category.case_stage_history from Flow Alignment, workflow_tasks, GRNs/
GRN items, POs, PRs/categories). Nothing is scheduled or pre-computed;
each report runs live.department_id exists on cases/PRs but nothing sets it yet, while
category_id is populated on every PR and, since the flow-alignment
audit, reflects each tenant's real vocabulary instead of a generic
placeholder.edos.ai — implemented. The same assistant every EDOS Centre sibling app (edos-poa, edoshatch360) ships, brought to EDOSPMIS:
src/lib/ai/llm.ts)
— the model never touches the database. Each tool (src/lib/ai/tools.ts)
is a query already scoped to the signed-in tenant: open-request aging,
stage cycle times/bottlenecks, SLA compliance, supplier performance,
spend by category, "what's waiting on me", case lookup and full case
detail, supplier lookup, and a contracts overview. The model decides
which to call and phrases the answer, but can't quote a figure this
tenant's own data doesn't hold, because no tool returns one that isn't
there.ANTHROPIC_API_KEY; without one, edos.ai says so
plainly and points at the Reports screen instead of guessing. This
deliberately does not replicate the sibling apps' deterministic
natural-language fallback ("answers of last resort" without a model
configured) — real, separate work; matching its full breadth wasn't
needed to bring the same assistant to this product.user_id = auth.uid(), like everything else in this app) rather than
copying edos-poa's differing "RLS on, no policies, service-role only"
arrangement — consistency within this codebase over matching a
sibling's internal choice.Phase 7 — Integrations: implemented (v1 cuts).
edospmis_audit_logs (one event pipeline, two consumers, per
ARCHITECTURE.md §14 — the same log every RPC since Phase 1 already
writes to, not a new parallel events table) dispatches a signed POST via
pg_net for every matching action, tenant-wide, automatically, with no
changes needed to any existing RPC. Each payload carries an
X-EDOSPMIS-Signature: sha256=<hex> HMAC over the raw body, and a
Settings screen shows recent deliveries with an on-demand status check
(reads net._http_response). A misconfigured endpoint can never break
the transaction that produced the event — the trigger swallows its own
dispatch errors per webhook.httpbin.org, which echoes back exactly what it received): a genuine
HTTPS POST left Supabase's infrastructure via pg_net, and the HMAC
signature independently recomputed from the raw bytes that endpoint
actually received matched exactly — the one subtlety worth flagging for
anyone verifying a delivery themselves: hash the raw request body, never
a reparsed-and-reserialized copy of it, the same rule Stripe/GitHub
document for their own webhook signatures. Also verified: non-https://
endpoints rejected, a paused webhook receiving no further deliveries,
and deletion.finance stage
no longer sits empty in the demo's own stage-timing report.Not yet built (later phases, see ARCHITECTURE.md §18): the rest of Phase 8's AI scope (PR classification, spec extraction, duplicate detection, SLA-breach prediction — PRD FR-39). Also not yet built: the Platform Super Admin role (cross-tenant oversight for EDOS Centre as the SaaS operator) — every account today is scoped to one tenant only, by design, with no back door across tenants.
A persistent, read-only demo tenant for onboarders to explore without signing up or risking real tenant data:
[email protected] / AmaniDemo2026!procurement.pr.view, legal.contract.view, reports.view,
admin.audit.view — no create/edit/approve/close permissions anywhere),
so every write action across the app is correctly refused if attempted;
nothing an onboarder does can corrupt the shared demo data. It was
seeded by first provisioning the tenant normally (temporarily Tenant
Administrator, so every seeded record was created through the same real
RPCs a genuine user would call — not hand-crafted rows) and only
stripping the account down to Demo Viewer once seeding finished.src/lib/nav-items.ts) — the demo account sees "My Work" and
"Requests" (its own 9 seeded cases) and "Contracts"; the admin/config
screens (Users, Roles, Suppliers, Clients, Approval Rules) require a
.manage permission the demo role deliberately doesn't hold, so they're
hidden rather than shown-but-broken.Next.js (App Router) + TypeScript + Tailwind v4, Supabase (Postgres + Auth + Storage), deployed to Vercel — see ARCHITECTURE.md §13 for why.
This app's tables all live in the same shared Supabase project as EDOS
Centre's other products (edospoa_, edoshatch360_ prefixes), under the
edospmis_ prefix — see ARCHITECTURE.md §2.
npm install
cp .env.example .env.local # fill in the Supabase project's URL/keys
npm run dev
Required env vars are documented in .env.example. The service-role key
is only needed for tenant sign-up's admin-invite path and inbound
webhooks (see src/lib/supabase/admin.ts) — never used from a page or
component.
Migrations live in supabase/migrations/, applied directly against the
shared project (no local Supabase stack is run for this app currently —
see MULTI_TENANCY.md, a Phase 1 documentation deliverable, for the
full reasoning once written).
0001_platform_foundation.sql — Phase 1: org structure, users,
memberships, RBAC, audit log, edospmis_provision_tenant().0002_legal_contract_rbac.sql — forward-seeds the Phase 3 Lawyer/Advocate
role and legal.contract.* permissions (module itself not built yet).0003_phase2_case_pr_workflow.sql — Phase 2: cases, PRs, workflow/queue/
approval/SLA tables, edospmis_submit_pr(), edospmis_decide_approval().0004_admin_holds_dept_manager.sql — fixes a gap the pre-commit smoke
test caught: the founding admin now also holds Department Manager so
the seeded default approval rule is immediately actionable solo.0005_phase3_procurement.sql — Phase 3a: suppliers, RFQs, quotations,
evaluations, purchase orders, edospmis_start_procurement(),
edospmis_award_po(); extends the case lifecycle past "approved".0006_phase3_contracts_v1.sql — Phase 3b: contracts + signing parties
(v1 cut — see the migration header), edospmis_send_contract(),
edospmis_record_contract_signature(), edospmis_void_contract().npx tsc --noEmit, npx eslint ., npm run build — all three gate
every change; npm run build specifically catches the "server-only
imported from a client component" class of bug that tsc alone misses.
A dedicated tenant-isolation test suite (ARCHITECTURE.md §17) is a
near-term follow-up, not yet written.
src/
app/ Next.js App Router — auth pages, /app (the product), /auth/callback
components/
ui/ shared design-system primitives (Button, Card, Field, Badge, Spinner)
app/ app-shell components (sidebar/mobile nav)
lib/
data/ server-only data-access modules (session, rbac)
supabase/ client/server/admin Supabase client factories
audit.ts logAudit() — the one place anything writes to edospmis_audit_logs
supabase/migrations/
cancelled