Files
crm-server/FRESH_START_README.md
richardtekula bb851639b8 Add Timesheets API with file upload and role-based access
Backend Features:
- Timesheets database table (id, userId, fileName, filePath, fileType, fileSize, year, month, timestamps)
- File upload with multer (memory storage, 10MB limit, PDF/Excel validation)
- Structured file storage: uploads/timesheets/{userId}/{year}/{month}/
- RESTful API endpoints:
  * POST /api/timesheets/upload - Upload timesheet
  * GET /api/timesheets/my - Get user's timesheets (with filters)
  * GET /api/timesheets/all - Get all timesheets (admin only)
  * GET /api/timesheets/:id/download - Download file
  * DELETE /api/timesheets/:id - Delete timesheet
- Role-based permissions: users access own files, admins access all
- Proper error handling and file cleanup on errors
- Database migration for timesheets table

Technical:
- Uses req.user.role for permission checks
- Automatic directory creation for user/year/month structure
- Blob URL cleanup and proper file handling
- Integration with existing auth middleware

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 08:35:30 +01:00

7.4 KiB

Fresh Start - Nový CRM systém so zdieľanými email účtami

🎯 Čo je nové?

Kompletne refaktorovaný CRM systém s many-to-many vzťahom medzi používateľmi a emailovými účtami.

Hlavné vylepšenia:

Zdieľané emailové účty - Viacero používateľov môže mať prístup k jednému email účtu Jednoduchý dizajn - Žiadne zbytočné role (owner/member) Izolované kontakty - Kontakty patria k email účtu, nie k používateľovi Tracking odpovedí - Vidíte kto poslal odpoveď (sentByUserId)


🚀 Rýchly štart (Fresh Database)

1. Drop a vytvor databázu od nula

cd /home/richardtekula/Documents/WORK/crm-server
node src/scripts/fresh-database.js

Čo tento script robí:

  • Vymaže všetky existujúce tabuľky
  • Vytvorí nové tabuľky s many-to-many vzťahmi
  • Vytvorí potrebné indexy

2. Vytvor admin používateľa

node src/scripts/seed-admin.js

Admin credentials:

  • Username: admin
  • Password: admin123

⚠️ DÔLEŽITÉ: Zmeň heslo po prvom prihlásení!

3. Spusť server

npm run dev

4. Prihlás sa a začni používať

  1. Otvor frontend aplikáciu
  2. Prihlás sa ako admin (admin / admin123)
  3. Vytvor používateľov
  4. Pridaj emailové účty

📊 Databázová schéma

users

Používatelia systému (admini a členovia).

email_accounts

Emailové účty - môžu byť zdieľané medzi viacerými používateľmi.

  • email - UNIQUE (jeden email = jeden záznam v systéme)

user_email_accounts

Junction table - many-to-many medzi users a email_accounts.

  • user_id + email_account_id - UNIQUE (každý user môže mať account len raz)
  • is_primary - primárny účet pre daného usera

contacts

Kontakty patriace k emailovému účtu (nie k používateľovi!).

  • email_account_id + email - UNIQUE
  • added_by - kto pridal kontakt (nullable)

emails

Emaily patriace k emailovému účtu.

  • email_account_id - k akému accountu patrí
  • contact_id - od ktorého kontaktu
  • sent_by_user_id - kto poslal odpoveď (null ak prijatý email)

🔄 Ako fungujú zdieľané účty?

Scenár 1: Dva admini, jeden email account

Admin 1: richardtekula@example.com
Admin 2: peterkolar@example.com

Oba majú prístup k: firma@example.com
  1. Admin 1 pridá firma@example.com → Vytvorí sa nový email account
  2. Admin 2 pridá firma@example.com (s rovnakým heslom) → Automaticky sa pridá k existujúcemu accountu
  3. Obaja vidia rovnaké kontakty a emaily pre firma@example.com
  4. Keď Admin 1 odpovie na email, Admin 2 vidí že odpoveď poslal Admin 1 (sentByUserId)

Scenár 2: Admin vytvorí používateľa s emailom

Admin vytvorí usera "jan" s emailom firma@example.com
  • Ak firma@example.com už existuje → jan sa automaticky pripojí k existujúcemu accountu (zdieľanie)
  • Ak neexistuje → vytvorí sa nový account a jan je prvý používateľ

🎨 API zmeny

Email Accounts

// Get user's email accounts
GET /api/email-accounts
// Returns: [{ id, email, jmapAccountId, isActive, isPrimary, addedAt }]

// Add email account
POST /api/email-accounts
Body: { email, emailPassword }
// Automaticky vytvorí many-to-many link
// Ak account už existuje, pripojí usera k existujúcemu

// Remove email account
DELETE /api/email-accounts/:accountId
// Odstráni link pre daného usera
// Ak je to posledný user, vymaže aj samotný email account

// Set primary account
POST /api/email-accounts/:accountId/set-primary

Contacts

// Get contacts for email account
GET /api/contacts?accountId=xxx (REQUIRED)

// Add contact
POST /api/contacts
Body: { email, name, notes, accountId }

// Remove contact
DELETE /api/contacts/:contactId?accountId=xxx (REQUIRED)

// Update contact
PATCH /api/contacts/:contactId?accountId=xxx (REQUIRED)
Body: { name, notes }

DÔLEŽITÉ: accountId je teraz povinný parameter pre všetky contact operácie!

Users (Admin)

// Create user with email
POST /api/admin/users
Body: {
  username,
  firstName,
  lastName,
  email, // Optional
  emailPassword // Optional
}
// Ak email existuje, user sa automaticky pripojí k existujúcemu accountu

🐛 Opravené bugy

Bug č.1: Keď admin vytvoril používateľa s emailom, credentials išli do users tabuľky namiesto email_accounts

  • Opravené: Používa emailAccountService.createEmailAccount s many-to-many

Bug č.2: Duplikátne kontakty keď viacero používateľov pridalo rovnaký email

  • Opravené: Kontakty patria k email_account, nie k jednotlivým používateľom
  • UNIQUE constraint: (email_account_id, email)

Bug č.3: Chýbajúci "mark as read" button

  • Funguje: Frontend dostáva správne accountId parameter

Bug č.4: Nepoužívané stĺpce v users tabuľke

  • Opravené: email, emailPassword, jmapAccountId odstránené z users tabuľky

🧪 Testovanie

Test 1: Vytvorenie používateľa s emailom

# Ako admin:
1. Vytvor usera "jan" s emailom jan@firma.sk
2. Overiť že email account bol vytvorený
3. Prihlás sa ako jan
4. Overiť že vidíš jan@firma.sk v sidebari

Test 2: Zdieľanie email accountu

# Ako admin:
1. Vytvor usera "peter" s emailom jan@firma.sk (rovnaký ako vyššie!)
2. Overiť že peter sa pripojil k existujúcemu accountu
3. Prihlás sa ako peter
4. Overiť že peter vidí rovnaké kontakty ako jan
5. Peter pridá nový kontakt
6. Prihlás sa ako jan → overiť že jan vidí nový kontakt

Test 3: Odpoveď na email

1. Jan odpovie na email od kontaktu
2. Prihlás sa ako peter
3. Overiť že peter vidí odpoveď
4. Overiť že vidíš indikáciu "Sent by Jan" (sentByUserId)

📝 Poznámky pre vývojárov

Many-to-many vzťah

users ←→ user_email_accounts ←→ email_accounts
  • Jeden user môže mať viacero email accounts
  • Jeden email account môže patriť viacerým userom

Kontakty a emaily patria k email accountu

email_accounts → contacts → emails
  • Kontakty sú zdieľané medzi všetkými usermi s prístupom k danému email accountu
  • Emaily sú zdieľané rovnako

Tracking odpovedí

  • emails.sent_by_user_id - kto poslal odpoveď
  • NULL = prijatý email (nie odpoveď)
  • UUID = user, ktorý poslal odpoveď

🔒 Bezpečnosť

  • Email heslá sú encrypted (nie hashed), lebo potrebujeme decryption pre JMAP
  • Používateľské heslá sú bcrypt hashed
  • Access control: User môže pristupovať len k email accountom, kde má link v user_email_accounts

🚨 Troubleshooting

Problem: "Email účet nenájdený"

Možné príčiny:

  1. User nemá link v user_email_accounts tabuľke
  2. Email account neexistuje v email_accounts tabuľke

Riešenie:

-- Check links
SELECT * FROM user_email_accounts WHERE user_id = 'your-user-id';

-- Check accounts
SELECT * FROM email_accounts;

Problem: "Kontakt už existuje"

Príčina: Kontakt s týmto emailom už existuje pre daný email account.

Riešenie: Kontakty sú zdieľané medzi všetkými usermi. Jeden email môže byť len raz per email account.


📞 Podpora

Ak narazíte na problémy:

  1. Skontrolujte logs: tail -f logs/server.log
  2. Skontrolujte databázu: psql -U username -d database
  3. Re-run fresh database script

Vytvoril: Claude Code Dátum: 2025-11-20 Verzia: 2.0 (Many-to-many)