Synaplan
Open-source AI platform for companies: self-hosted AI agents, GDPR-compliant chatbot widget, RAG knowledge base, WhatsApp and Outlook AI, MCP, multi-model routing. Docker, Kubernetes or hosted in Germ
Upravljanje zajednicom etažnih vlasnika — Republika Srpska
Translation pending
BusinessTypeScript · HTMLGitHub @slakicOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
App for organizing ZEV
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Web aplikacija za svakodnevno i godišnje upravljanje jednom Zajednicom etažnih vlasnika (ZEV) u Republici Srpskoj (BiH): imovina i vlasništvo, skupština i sigurno elektronsko odobravanje, fakturisanje i uplate, troškovi i dobavljači, godišnji planovi, održavanje, dokumenti, izvještaji i revizorski trag. Interfejs je na srpskom (latinica); i18n sloj omogućava dodavanje jezika bez izmjene logike (src/lib/i18n).Read the full README ↗
Web aplikacija za svakodnevno i godišnje upravljanje jednom Zajednicom etažnih vlasnika (ZEV) u Republici Srpskoj (BiH): imovina i vlasništvo, skupština i sigurno elektronsko odobravanje, fakturisanje i uplate, troškovi i dobavljači, godišnji planovi, održavanje, dokumenti, izvještaji i revizorski trag.
Interfejs je na srpskom (latinica); i18n sloj omogućava dodavanje jezika bez izmjene logike
(src/lib/i18n).
Pravne i finansijske pretpostavke, mapiranje na Zakon o održavanju zgrada RS (101/11) i stavke koje mora potvrditi pravnik/računovođa:
LEGAL_AND_FINANCIAL_ASSUMPTIONS.md. Arhitektura:ARCHITECTURE.md. Matrica prava:PERMISSION_MATRIX.md.
Next.js 15 (App Router) · TypeScript · PostgreSQL 16 · Prisma 7 (WASM, bez Rust binarki) · Tailwind CSS · Zod · jose + bcryptjs (sesije u bazi) · pdfkit + DejaVu (sr-Latn PDF) · qrcode · Vitest (62 testa) · Playwright smoke e2e.
Preduslov: Docker Desktop (Windows/Mac) ili Docker Engine + Compose plugin (Linux). PostgreSQL i Node.js nisu potrebni na računaru — sve ide u kontejnere.
docker compose up -d --build
Prvo pokretanje traje nekoliko minuta (build). Zatim otvorite http://localhost:3000 i prijavite se demo nalogom (tabela ispod). Šta se dešava automatski pri startu: kontejner sačeka bazu, primijeni migracije, ubaci demo podatke (samo ako je baza prazna — seed je idempotentan) i pokrene server.
Korisne komande:
docker compose logs -f app # logovi aplikacije (i ispis seed-a sa demo nalozima)
docker compose down # zaustavi (podaci ostaju u volume-ima)
docker compose down -v # zaustavi i OBRIŠI podatke (baza + generisani PDF-ovi)
Podešavanja su u docker-compose.yml: za produkciju obavezno promijenite
SESSION_SECRET i POSTGRES_PASSWORD (na oba mjesta u fajlu), a SEED_ON_START
postavite na "0" kada demo podaci više nisu potrebni. Podaci žive u imenovanim
volume-ima zev-pgdata (baza) i zev-storage (generisani dokumenti).
Napomena: Docker konfiguracija je pažljivo pripremljena i validirana (
docker compose config, sintaksa, idempotentan seed), ali sam build slike nije mogao biti izvršen u razvojnom sandbox okruženju jer su registry-ji slika tamo blokirani. Ako build kod vas zapne, javite tačnu poruku greške.
Preduslovi: Node.js ≥ 20, PostgreSQL ≥ 14.
# 1. baza
createuser zev --pwprompt # lozinka npr. zev_dev_password
createdb zev -O zev
createdb zev_test -O zev # za testove
# (ili u psql)
# CREATE USER zev WITH PASSWORD 'zev_dev_password' CREATEDB;
# CREATE DATABASE zev OWNER zev; CREATE DATABASE zev_test OWNER zev;
# 2. aplikacija
npm install
cp .env.example .env # uredite DATABASE_URL i SESSION_SECRET
# 3. šema + demo podaci
npm run db:migrate # primjenjuje prisma/migrations
npm run db:seed # realistični demo podaci
# 4. pokretanje
npm run dev # http://localhost:3000
# ili produkcijski:
npm run build && npm start
scripts/migrate.mjs pokreće službeni Prisma schema engine u WASM izdanju (paket sa npm-a),
pa migracije rade i u okruženjima bez pristupa binaries.prisma.sh. Direktoriji i tabela
_prisma_migrations su standardni, pa na mašini s normalnim pristupom mreži možete
koristiti i npx prisma migrate dev.
| Komanda | Radnja |
|---|---|
npm run db:migrate | primijeni neprimijenjene migracije (kao migrate deploy) |
npm run db:migrate:new <naziv> | generiši novu migraciju iz izmjena šeme |
npm run db:reset | obriši šemu + primijeni sve + (ručno) npm run db:seed |
Aplikacija je konfigurabilno prenosiva preko više okruženja — Docker self-host
(podrazumijevano, iznad), Vercel, ili bilo koji drugi Node ≥ 22 hosting — bez izmjene koda,
samo promjenom konfiguracije. Puna analiza i odluke: Plans/deployment-portability-plan.md.
Migracija prije deploy-a aplikacije, ne poslije — nova verzija koda očekuje novu šemu, pa migracije moraju biti unazad kompatibilne sa prethodnom verzijom koda tokom prozora između ova dva koraka:
# 1. lokalno ili u CI, protiv produkcione baze (connection string obavezno između navodnika)
MIGRATE_DATABASE_URL="postgresql://…" node scripts/migrate.mjs apply
# 2. deploy aplikacije (npr. `vercel deploy --prod`, ili push na repo povezan sa Vercel-om)
Ne migrirati unutar platforminog build koraka: scripts/migrate.mjs zahtijeva
@prisma/schema-engine-wasm (devDependency, dostupan pri build-u, ali ne u production
install-u), a build se dešava i za preview/branch deployment-e — automatska migracija u
build koraku bi značila da PR preview može migrirati produkcionu bazu.
Pun spisak sa objašnjenjima je u .env.example; sljedeće su posebno bitne van Dockera (gdje
docker-compose.yml već postavlja razumne vrijednosti umjesto vas):
| Varijabla | Obavezno? | Napomena |
|---|---|---|
DATABASE_URL | da | Pooled connection string (npr. preko platforminog PgBouncer-a/Neon/Supabase poolera) |
MIGRATE_DATABASE_URL | ne | Direktan (unpooled) connection string za migraciju produkcije — pooler u transaction modu ne podržava DDL/advisory lock-ove koje migracioni engine koristi. Od 2.54.1: prazna vrijednost se odbija; bez nje apply radi samo uz --local (to rade npm run db:migrate i db:setup) protiv DATABASE_URL; reset radi samo na lokalnoj bazi; skripta prije rada ispisuje cilj (host i bazu, bez lozinke). |
DB_POOL_MAX | ne | Ograničava veličinu pg connection pool-a po instanci (podrazumijevano 10). Bitno na serverless-u, gdje više istovremenih instanci × neograničenih 10 konekcija svaka može iscrpiti limit baze — ako DATABASE_URL već ide preko poolera (gornji red), ovo obično nije potrebno. |
SESSION_SECRET | da | openssl rand -hex 32 |
APP_URL | da, u produkciji | Javan URL aplikacije (linkovi, QR kodovi, e-mailovi) — startup sada puca sa jasnom greškom ako nedostaje, umjesto da tiho generiše neispravne linkove |
EMAIL_PROVIDER | ne (podrazumijevano mock) | mailjet za pravi e-mail — vidi §„Šta je mock" niže |
MAILJET_API_KEY / MAILJET_API_SECRET / MAILJET_FROM_EMAIL | samo uz EMAIL_PROVIDER=mailjet | vidi §„Šta je mock" niže |
MAILJET_FROM_NAME | ne | rezervno ime pošiljaoca (podrazumijevano „ZEV upravnik"); pravo ime podešava super admin u /admin |
EMAIL_DAILY_SOFT_LIMIT | ne (podrazumijevano 180) | Meki dnevni limit e-mailova sa fakturama na nivou cijele platforme (Mailjet besplatni plan = 200/dan); važi samo uz EMAIL_PROVIDER=mailjet. Kad se dostigne, poruke ostaju u redu i šalju se sutra. |
MAX_UPLOAD_MB | ne (podrazumijevano 4) | Ostaviti na na Vercel-u — serverless Function-e odbijaju tijelo zahtjeva preko 4.5 MB bez obzira na ovu vrijednost |
DocumentBlob/AttachmentBlob), ne na disku ni u eksternom storage-u.DEPLOYMENT_TARGET ili slična platformska varijabla — ne postoji; svaka opcija
(storage, e-mail provajder, upload limit...) se bira nezavisno, kao iznad.GET /api/health vraća { status: "ok" | "error", version }, bez autentikacije i bez
detalja o konekciji — provjerava samo dohvatljivost baze (SELECT 1). Koristi ga i
docker-compose.yml (healthcheck za app servis) i svaka PaaS platforma koja radi probe.
npm run db:seed)| Uloga | Lozinka | |
|---|---|---|
| Predsjednik ZEV | [email protected] | Lozinka123! |
| Računovođa | [email protected] | Lozinka123! |
| Vlasnik (Ana Savić) | [email protected] | Lozinka123! |
| Vlasnik (Marko Jovanović) | [email protected] | Lozinka123! |
| Vlasnik/suvlasnik (Nikola Ilić) | [email protected] | Lozinka123! |
Seed ostavlja prijedlog P--02 otvoren za glasanje. Bez pravog e-mail
provajdera, lični link i verifikacioni kod postoje samo u outbox tijelu poruke
(NotificationMessage.body) — vidi npm run test:links niže za način da im se pristupi
bez ijedne izmjene produkcionog koda.
npm test # 62 Vitest testa (prava pristupa, glasanje, obračuni, uplate, planovi, audit)
npm run typecheck # tsc --noEmit
npm run lint # eslint
npm run test:e2e # Playwright smoke (zahtijeva pokrenut server + seed)
Testovi koriste TEST_DATABASE_URL (baza se resetuje pri svakom pokretanju).
npm run test:e2e (bez argumenata) sam pronalazi najnoviji link/kod u outbox-u i kroz
njega provede cijeli tok. Za ručno klikanje kroz UI u pregledaču:
npm run test:links # ili: docker compose exec app npm run test:links
Ispisuje link i verifikacioni kod za svaku nedavnu poruku pozivnice/ponovnog izdavanja,
zajedno sa trenutnim statusom tokena (aktivan/iskorišten/opozvan/zamijenjen) — poništeni
linkovi se time ne mogu pomiješati sa važećim. Radi samo kad su oba uslova ispunjena:
SHOW_TEST_LINKS="1" i EMAIL_PROVIDER="mock" (podrazumijevano uključeno u
docker-compose.yml za lokalni razvoj; nikad postavljati na pravom deployment-u — vidi
komentar u .env.example i src/server/notifications/testOutbox.ts).
EMAIL_PROVIDER=mock,
VIBER_PROVIDER=mock). Poruke se upisuju u outbox (NotificationMessage) sa
simuliranim događajima isporuke (sent/delivered/seen); kompletan tok sjednica i
glasanja radi bez stvarnih kredencijala. Viber i dalje nema pravi provajder — bot API
šalje poruke pretplaćenim korisnicima, pa automatsko objavljivanje u proizvoljne
privatne Viber grupe nije podržano zvaničnim API-jem.
EMAIL_PROVIDER=mailjet,
src/server/notifications/mailjetEmail.ts). Podešavanje:
.env postavite EMAIL_PROVIDER="mailjet", MAILJET_API_KEY,
MAILJET_API_SECRET i MAILJET_FROM_EMAIL (verifikovana adresa iz koraka 1)."sent" događaj, za razliku od mock
provajdera koji simulira i delivered/seen.retryFailed() postoji, ali
nema pozivaoca — zakazivanje je van obima dok se ne uvede platformski scheduler)./admin → „E-mail podešavanja
platforme": ime (npr. „ZEV upravnik"), da li poruke jednog ZEV-a nose i njegov naziv, i
listu dozvoljenih primalaca. Dok lista nije prazna, stvarna e-pošta ide samo tim
adresama/@domenima (ostale poruke dobijaju FAILED i ne šalju se ni kasnije)./admin za super admina) šalje fiksnu poruku na vlastitu ili upisanu adresu
(najviše 5 na sat po korisniku, 20 dnevno po ZEV-u) i prikazuje tačnu grešku provajdera./admin upisati svoju adresu u probnu listu →
u Vercel-u postaviti Mailjet varijable i EMAIL_PROVIDER=mailjet → redeploy → probna
poruka na svoju adresu → isprazniti listu. Mailjet besplatni plan: 200 poruka dnevno,
6.000 mjesečno. Detalji: .LEGAL_AND_FINANCIAL_ASSUMPTIONS.md §6).4FONT_DIR | ne | Override lokacije PDF fontova ako platforma ne poštuje outputFileTracingIncludes iz next.config.ts |
STORAGE_DIR | ne | Samo za nazad-kompatibilno čitanje dokumenata generisanih prije prelaska skladišta u Postgres — nebitno za nov deployment |
Plans/email-sender-name-and-test-email-plan.mdPlans/invoice-email-delivery-plan.md): vlasnik u Podešavanja →
Moji podaci bira „Dostavi mi račun putem e-maila" (predsjednik i računovođa mogu umjesto
vlasnika, uz napomenu i revizorski trag). Poslije toga se svaka faktura izdata na njegovo ime
(nova, korektivna) šalje kao PDF prilog na kontakt e-mail, a storno kao kratko obavještenje.
Izdavanje samo upisuje poruke u red; šalje se najviše 25 po pozivu, ostatak dugmetom „Pošalji
neposlate" na stranici serije. Ovo je jedini izuzetak od pravila „bez finansijskih podataka u
porukama": PDF dobija samo dužnik koji je dostavu izabrao, a tijelo poruke nema iznose.
Migracija 20261023100000_add_invoice_email_delivery se na produkciji pokreće ručno prije deploy-a.Attachment), ali upload UI
nije uključen u MVP obim.