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>
This commit is contained in:
296
FRESH_START_README.md
Normal file
296
FRESH_START_README.md
Normal file
@@ -0,0 +1,296 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user