Synaplan
开源 AI 软件平台,面向企业:自托管 AI 代理,符合 GDPR 的聊天机器人小部件,RAG 知识库,WhatsApp 与 Outlook AI,MCP,多模型路由。支持 Docker、Kubernetes 或在 Germ 托管。
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
A multi-tenant ERP web application for marketplace (Amazon / Noon) sellers.
Full double-entry accounting, perpetual inventory, and the complete sales &
purchase document cycle — with a fully Arabic, right-to-left UI.
The codebase and comments are in English; the product UI is in Arabic. This
README and docs/ are in English so any engineer can onboard quickly.
There is no CRM, scraping, desktop app, or AI layer — this repo is ERP-web only.
Prerequisites: Node 20+, Docker (for Postgres + MinIO).
Default login: admin / password123 (all seeded users share that password).查看完整 README ↗A multi-tenant ERP web application for marketplace (Amazon / Noon) sellers. Full double-entry accounting, perpetual inventory, and the complete sales & purchase document cycle — with a fully Arabic, right-to-left UI.
The codebase and comments are in English; the product UI is in Arabic. This README and
docs/are in English so any engineer can onboard quickly.
| Concern | Choice |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack, output: standalone) · React 19 · TypeScript |
| Styling | TailwindCSS · shadcn/ui (Radix) · Thmanyah (ثمانية) font |
| Database | PostgreSQL · Drizzle ORM + drizzle-kit |
| Auth | Auth.js v5 — credentials (username or email), JWT sessions, role-based |
| Object store | MinIO / any S3-compatible service — item images, attachments, backups |
| Charts | Recharts |
| Tests | Vitest |
There is no CRM, scraping, desktop app, or AI layer — this repo is ERP-web only.
Prerequisites: Node 20+, Docker (for Postgres + MinIO).
# 1. Install deps
npm install
# 2. Configure env — copy the template and set AUTH_SECRET
cp .env.example .env
npx auth secret # writes AUTH_SECRET; DATABASE_URL default points at local Docker
# 3. Start infra (Postgres :5432, MinIO :9000/:9001, Adminer :8080)
docker compose -f docker/docker-compose.yml up -d postgres minio minio-init adminer
# 4. Create the schema + demo data
npm run db:migrate # appuser role + the full migration chain
npm run db:rls # tenant-isolation policies + integrity triggers
npm run db:seed
# 5. Run
npm run dev # http://localhost:3000
Default login: admin / password123 (all seeded users share that password).
next dev cold-compiles routes on demand and is slow on this repo. To profile the
real thing, run the standalone production server:
npm run build
cp -r .next/static .next/standalone/.next/ && cp -r public .next/standalone/ && cp .env .next/standalone/.env
cd .next/standalone && PORT=3011 NODE_ENV=production AUTH_TRUST_HOST=true node server.js
npm run deploy # build → migrate → RLS → rebuild app AND worker → health gate (auto-rollback)
Before a production deploy, rotate the database and MinIO credentials and generate the
application secrets with npm run gen:secrets. npm run deploy now runs a secret
preflight and refuses missing, short, or known-default production credentials. Follow
docs/SECRET-ROTATION.md for the required rotation order.
See docs/ARCHITECTURE.md for the Docker rebuild
flow and the self-hosted deployment model.
app/
(app)/ Authenticated app shell (sidebar + topbar + org switcher)
dashboard/ Landing — ERP module tiles
erp/ The ERP itself, one folder per module:
accounting · inventory · sales · purchases ·
investors · hr · reports · audit · imports · settings
admin/ OS user management
profile/
(auth)/ login (+ admin emergency login)
(print)/ Print-only layouts (invoices, orders, receipts, barcodes)
actions/ Server actions ("use server") — actions/erp/* is the write layer
api/ Route handlers: auth, cron (no-op), CSV/ledger exports, init-accounting
components/
app-shell/ Nav config, sidebar, topbar, org switcher
erp/ ERP UI (forms, tables, managers) — ~70 components
ui/ shadcn/ui primitives
lib/
erp/ ERP domain logic (see below) — the heart of the app
db.ts Drizzle client (pooled pg)
session.ts requireUser / requireCapability (OS auth)
rbac.ts Global role → capability matrix
storage.ts S3/MinIO object storage (public + presigned private bucket)
env.ts Boot-time env validation
db/
schema.ts OS tables (users, attendance) + re-exports erp.ts
erp.ts All ERP tables (Drizzle)
migrations/ Canonical drizzle-kit migration history
seed.ts Demo tenant + chart of accounts + sample docs
scripts/ Manual dev scripts (see scripts/README.md) — not in build/CI
docs/ Architecture + Arabic planning specs
docker/ docker-compose + Dockerfiles
lib/erp/ — the domain core| File | Responsibility |
|---|---|
posting.ts | Double-entry engine — postEntry / reverseEntry (balanced, idempotent) |
inventory.ts | Perpetual stock — postStockMovement (weighted-average cost), currentStock |
financials.ts | Trial balance, income statement, balance sheet |
org.ts | Active-org resolution + requireErpModule page guard |
action-auth.ts | authorizeErp(permission) for server actions |
entitlements.ts | Per-tenant module subscriptions |
sequence.ts | Atomic document numbering (SO-2026-0001 …) |
amazon-import.ts / amazon-settlement.ts | Amazon order + settlement import & accounting |
npm run dev # dev server
npm run build # production build
npm run typecheck # tsc --noEmit
npm run lint # eslint
npm run test # vitest
npm run db:generate # generate a migration from schema changes
npm run db:migrate # appuser role + apply the migration chain
npm run db:rls # (re)apply RLS policies + integrity triggers — after every migrate
npm run db:baseline # once, on a DB built by the old `push` flow (see ARCHITECTURE)
npm run db:studio # drizzle studio
npm run db:seed # reseed demo data
docs/ARCHITECTURE.md)organization_id. The active org
comes from the erp_org cookie; requireErpModule() resolves + guards it. Always
scope Drizzle queries by org — cross-tenant leakage (IDOR) is the main bug class.postEntry, which validates
the entry balances (in integer cents) and is idempotent per (org, sourceType, sourceId).postStockMovement (weighted-average cost).
Negative stock is rejected. GL 1104 == inventory-ledger value is a hard invariant.toLocaleString("ar-EG-u-nu-latn", …) for money and en-GB for dates. Run
node scripts/utils/scan-ar-digits.mjs after touching UI."use server" files must not re-export imported types. export type { X }
from an action file passes tsc and dev, but the Turbopack production build
turns it into a runtime ReferenceError on action invocation. Import the type where needed instead.node_modules/next/dist/docs/ (see AGENTS.md).