refractoring & add timesheet service

This commit is contained in:
richardtekula
2025-11-25 07:52:31 +01:00
parent 125e30338a
commit 31297ee9a9
13 changed files with 277 additions and 463 deletions

View File

@@ -626,57 +626,33 @@ logUserCreation(adminId, newUserId, username, role, ip, userAgent)
---
### 13. timesheet.controller.js
**Účel:** File upload a správa timesheetov (PDF/Excel)
**Účel:** HTTP vrstva pre timesheet upload/list/download/delete (PDF/Excel)
**Databáza:** `timesheets`, `users`
**Deleguje na:** `services/timesheet.service.js`
**Metódy:**
**Toky handlerov:**
```javascript
uploadTimesheet(req, res)
Validácia file type (PDF, Excel)
Max 10MB limit
Save to: uploads/timesheets/{userId}/{year}/{month}/
INSERT INTO timesheets
File stored on disk (not in DB)
timesheetService.uploadTimesheet({ userId, year, month, file })
Vráti sanitized meta (bez filePath)
getMyTimesheets(userId, filters)
Filter: year, month (optional)
SELECT * FROM timesheets WHERE userId
ORDER BY uploadedAt DESC
getMyTimesheets(req, res)
timesheetService.getTimesheetsForUser(userId, { year?, month? })
getAllTimesheets(filters)
Admin only!
Filter: userId, year, month (all optional)
LEFT JOIN users (get username, name)
Vráti timesheets všetkých userov
getAllTimesheets(req, res)
timesheetService.getAllTimesheets({ userId?, year?, month? })
downloadTimesheet(timesheetId, userId, userRole)
Check permissions: owner alebo admin
Validate file exists on disk
downloadTimesheet(req, res)
timesheetService.getDownloadInfo(timesheetId, { userId, role })
res.download(filePath, fileName)
deleteTimesheet(timesheetId, userId, userRole)
Check permissions: owner alebo admin
Delete file from filesystem (fs.unlink)
DELETE FROM timesheets
Continue even if file deletion fails
deleteTimesheet(req, res)
timesheetService.deleteTimesheet(timesheetId, { userId, role })
```
**Volá:**
- Databázu (timesheets, users)
- File system operations (fs/promises)
- `utils/errors.NotFoundError, ForbiddenError, BadRequestError`
**File Storage Pattern:**
```
uploads/timesheets/
└── {userId}/
└── {year}/
└── {month}/
└── filename-timestamp-random.pdf
```
**POZNÁMKA:** Timesheet service NEEXISTUJE - všetka logika je priamo v controlleri!
**Poznámky:**
- Service vrstva rieši validáciu MIME typu (PDF/XLSX), tvorbu adresárovej štruktúry `uploads/timesheets/{userId}/{year}/{month}`, permission check (owner/admin) a bezpečné mazanie súboru.
- Response payloady obsahujú len meta údaje: `id, fileName, fileType, fileSize, year, month, isGenerated, uploadedAt`.
---
@@ -696,7 +672,7 @@ setPasswordSchema
confirmPassword: musí sa zhodovať
.refine() custom validation pre password match
linkEmailSchema
linkEmailSchema (momentálne neexponované; route je vypnutá)
email: valid email format, max 255 chars
emailPassword: min 1 char
@@ -715,7 +691,8 @@ changeRoleSchema
```
**Použitie:**
- Všetky `/api/auth/*` routes
- Aktívne: `/api/auth/login`, `/api/auth/set-password`, `/api/auth/logout`, `/api/auth/session`
- Neaktivované: `/api/auth/link-email`, `/api/auth/skip-email` (ponechané schema pre prípadné obnovenie)
- Admin user management routes
---
@@ -896,16 +873,16 @@ export const methodName = async (req, res) => {
### Zoznam Route Files:
1. **admin.routes.js** - User management (Auth + Admin role)
2. **auth.routes.js** - Login, set password, link email (Mixed public/protected)
2. **auth.routes.js** - Login, set password (Mixed public/protected)
3. **company.routes.js** - Firmy + nested notes (Auth only)
4. **contact.routes.js** - Kontakty (Auth only)
5. **crm-email.routes.js** - Emaily (Auth only)
6. **email-account.routes.js** - JMAP účty (Auth only)
7. **note.routes.js** - Standalone poznámky (Auth only, nevyužité)
8. **project.routes.js** - Projekty + notes + team (Auth only)
9. **todo.routes.js** - Úlohy (Auth only)
10. **time-tracking.routes.js** - Time tracking (Auth only)
11. **timesheet.routes.js** - Timesheets upload/download (Auth, admin for /all)
7. **project.routes.js** - Projekty + notes + team (Auth only)
8. **todo.routes.js** - Úlohy (Auth only)
9. **time-tracking.routes.js** - Time tracking (Auth only)
10. **timesheet.routes.js** - Timesheets upload/download (Auth, admin for /all)
11. **note.routes.js** - Standalone poznámky (odpojené z app.js, ponechané len ako archív)
### Štruktúra route file:
```javascript
@@ -1100,20 +1077,6 @@ Auth: Áno
Rate Limit: Áno
```
#### POST /api/auth/link-email
```
Účel: Pripojenie email účtu
Body: { email, emailPassword }
Auth: Áno
Volá: email.service, emailAccountService
```
#### POST /api/auth/skip-email
```
Účel: Preskočiť email setup
Auth: Áno
```
#### POST /api/auth/logout
```
Účel: Odhlásenie (clear cookies)
@@ -1128,12 +1091,7 @@ Auth: Áno
Response: { user, authenticated: true }
```
#### GET /api/auth/me
```
Účel: Profil aktuálneho usera
Auth: Áno
Response: { user with emailAccounts }
```
**Removed/disabled:** `/api/auth/link-email`, `/api/auth/skip-email`, `/api/auth/me` (nepoužíva ich FE).
---
@@ -1195,13 +1153,7 @@ Auth: Áno
Response: Company object
```
#### GET /api/companies/:companyId/details
```
Účel: Firma s všetkými reláciami
Auth: Áno
Response: { ...company, projects: [], todos: [], notes: [] }
Poznámka: NEVYUŽÍVA SA vo frontende (robí sa 3 samostatné cally)
```
> Poznámka: Endpoint `/api/companies/:companyId/details` bol odstránený (frontend používa samostatné volania).
#### POST /api/companies
```
@@ -1270,13 +1222,7 @@ Auth: Áno
Auth: Áno
```
#### GET /api/projects/:projectId/details
```
Účel: Projekt s reláciami
Auth: Áno
Response: { ...project, company, todos, notes, timesheets, assignedUsers }
Poznámka: NEVYUŽÍVA SA vo frontende
```
> Poznámka: Endpoint `/api/projects/:projectId/details` bol odstránený (nepoužíva ho FE).
#### POST /api/projects
```
@@ -1389,26 +1335,13 @@ Query: všetky parametre optional
Auth: Áno
```
#### GET /api/todos/my?status=
```
Účel: Moje úlohy (assigned to current user)
Auth: Áno
Poznámka: NEVYUŽÍVA SA vo frontende
```
#### GET /api/todos/:todoId
```
Účel: Detail todo
Auth: Áno
```
#### GET /api/todos/:todoId/details
```
Účel: Todo s reláciami
Auth: Áno
Response: { ...todo, project, company, assignedUser, notes }
Poznámka: NEVYUŽÍVA SA vo frontende
```
> Poznámka: Endpoints `/api/todos/my` a `/api/todos/:todoId/details` boli odstránené (nepoužíva ich FE).
#### POST /api/todos
```
@@ -1445,8 +1378,8 @@ Response: Updated todo
### 📝 NOTES (Standalone)
**POZNÁMKA:** Všetky standalone note routes sú **NEVYUŽITÉ** vo frontende.
Notes sa používajú iba cez nested routes (companies/:id/notes, projects/:id/notes).
**POZNÁMKA:** Standalone note routes sú odpojené z app.js a frontend ich nepoužíva.
Poznámky sa riešia iba cez nested routes (companies/:id/notes, projects/:id/notes).
#### GET /api/notes?search=&companyId=&projectId=&todoId=&contactId=
```
@@ -1534,26 +1467,7 @@ Auth: Áno
Efekt: CASCADE delete emails
```
#### POST /api/contacts/:contactId/link-company?accountId=uuid
```
Účel: Linknúť firmu k kontaktu
Body: { companyId* }
Poznámka: NEVYUŽÍVA SA vo frontende
```
#### POST /api/contacts/:contactId/unlink-company?accountId=uuid
```
Účel: Odlinkovať firmu od kontaktu
Poznámka: NEVYUŽÍVA SA vo frontende
```
#### POST /api/contacts/:contactId/create-company?accountId=uuid
```
Účel: Vytvoriť firmu z kontaktu
Body: (optional) { name, email, phone, ... }
Poznámka: NEVYUŽÍVA SA vo frontende
Efekt: Vytvorí company, nastaví contact.companyId
```
> Poznámka: Link/unlink company a create-company routes boli odstránené (FE ich nevolá).
---
@@ -1566,12 +1480,7 @@ Auth: Áno
Response: Array of accounts (bez passwords!)
```
#### GET /api/email-accounts/:id
```
Účel: Detail email accountu
Auth: Áno
Poznámka: NEVYUŽÍVA SA vo frontende
```
> Poznámka: Endpoints `/api/email-accounts/:id`, `/:id/password`, `/:id/status` boli odstránené (nepoužíva ich FE).
#### POST /api/email-accounts
```
@@ -1588,22 +1497,6 @@ Efekt:
Volá: email.service, password.encryptPassword()
```
#### PATCH /api/email-accounts/:id/password
```
Účel: Zmeniť heslo k emailu
Body: { emailPassword* }
Auth: Áno
Poznámka: NEVYUŽÍVA SA vo frontende
```
#### PATCH /api/email-accounts/:id/status
```
Účel: Aktivovať/deaktivovať email account
Body: { isActive* }
Auth: Áno
Poznámka: NEVYUŽÍVA SA vo frontende
```
#### POST /api/email-accounts/:id/set-primary
```
Účel: Nastaviť ako primárny email
@@ -1681,25 +1574,13 @@ Auth: Áno
Efekt: UPDATE emails SET isRead = true + sync JMAP
```
#### GET /api/emails/contact/:contactId?accountId=uuid
```
Účel: Emaily od konkrétneho kontaktu
Poznámka: NEVYUŽÍVA SA vo frontende
```
#### POST /api/emails/contact/:contactId/read?accountId=uuid
```
Účel: Označiť všetky emaily kontaktu ako prečítané
Auth: Áno
```
#### PATCH /api/emails/:jmapId/read?accountId=uuid
```
Účel: Označiť jeden email ako read/unread
Body: { isRead* }
Auth: Áno
Poznámka: NEVYUŽÍVA SA vo frontende
```
> Poznámka: Endpoints `/api/emails/contact/:contactId` a `/api/emails/:jmapId/read` boli odstránené (FE ich nevolá).
#### POST /api/emails/reply
```
@@ -2294,13 +2175,18 @@ console.log('[DEBUG] JMAP validation:', valid);
---
**Vytvorené:** 2025-11-21
**Posledná aktualizácia:** 2025-11-24
**Posledná aktualizácia:** 2025-11-25
**Autor:** CRM Server Team
---
## CHANGELOG
### 2025-11-25 - Cleanup + Timesheet Service
- Presunutá biznis logika timesheetov do `services/timesheet.service.js`, controller ostáva tenký.
- Odstránené nevyužité routes (FE): auth link-email/skip-email/me, company/project/todo details, contacts link/unlink/create-company, email-account detail/password/status, emails contact listing + PATCH read, standalone notes odpojené z app.js.
- Dokumentácia zosúladená s aktuálnymi endpointmi.
### 2025-11-24 - Additions
**Pridané sekcie:**
1. **VALIDATORS** - Kompletná dokumentácia všetkých Zod schemas