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>
297 lines
7.4 KiB
Markdown
297 lines
7.4 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
node src/scripts/seed-admin.js
|
|
```
|
|
|
|
**Admin credentials:**
|
|
- Username: `admin`
|
|
- Password: `admin123`
|
|
|
|
⚠️ **DÔLEŽITÉ:** Zmeň heslo po prvom prihlásení!
|
|
|
|
### 3. Spusť server
|
|
|
|
```bash
|
|
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
|
|
|
|
```javascript
|
|
// 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
|
|
|
|
```javascript
|
|
// 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)
|
|
|
|
```javascript
|
|
// 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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:**
|
|
```sql
|
|
-- 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)
|