Synaplan
기업을 위한 오픈소스 AI 플랫폼
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기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).