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:
richardtekula
2025-11-21 08:35:30 +01:00
parent 05be898259
commit bb851639b8
27 changed files with 2847 additions and 532 deletions

198
FIX_SUMMARY.md Normal file
View File

@@ -0,0 +1,198 @@
# CRM Email System - Bug Fixes Summary
## Problems Identified
### 1. **Emails Scattered and Showing Under Wrong Contacts**
- **Root Cause**: Email syncing was changed from bidirectional (both FROM and TO contact) to unidirectional (only FROM contact)
- **Impact**: When you sent emails from foxerdxd@gmail.com, they weren't being synced into your CRM database
- **Symptom**: Emails appeared under the wrong contacts because conversations were incomplete
### 2. **Sent Emails from CRM Not Appearing**
- **Root Cause**: Sent emails were saved with `contactId: null` and never linked to contacts
- **Impact**: All emails sent from the CRM weren't showing up in the conversation view
- **Symptom**: You could see received emails but not your replies
### 3. **Inbox-Only Syncing**
- **Root Cause**: Sync was restricted to only Inbox mailbox
- **Impact**: Sent emails in the Sent folder weren't being synced
- **Symptom**: Incomplete conversation history
## Fixes Applied
### src/services/jmap.service.js
#### 1. Fixed `syncEmailsFromSender()` (lines 344-477)
**Before:**
```javascript
filter: {
operator: 'AND',
conditions: [
{ inMailbox: inboxMailbox.id }, // ONLY from Inbox
{ from: senderEmail }, // ONLY from this sender
],
}
```
**After:**
```javascript
filter: {
operator: 'OR',
conditions: [
{ from: senderEmail }, // Emails FROM contact
{ to: senderEmail }, // Emails TO contact (our sent emails)
],
}
```
**Changes:**
- ✅ Removed inbox-only filter (now syncs from ALL mailboxes)
- ✅ Changed from unidirectional to bidirectional sync
- ✅ Now captures complete conversation history
#### 2. Fixed `sendEmail()` (lines 557-681)
**Added:**
```javascript
// Find contact by recipient email address to properly link the sent email
const [recipientContact] = await db
.select()
.from(contacts)
.where(
and(
eq(contacts.emailAccountId, emailAccountId),
eq(contacts.email, to)
)
)
.limit(1);
await db.insert(emails).values({
...
contactId: recipientContact?.id || null, // Link to contact if recipient is in contacts
...
});
```
**Changes:**
- ✅ Now looks up the recipient in contacts before saving
- ✅ Links sent emails to the correct contact
- ✅ Sent emails now appear in conversation view
## Database Cleanup Scripts Created
### 1. `src/scripts/fix-sent-emails-contactid.js`
**Purpose**: Links existing orphaned sent emails to their contacts
**What it does:**
- Finds all emails with `contactId: null`
- For sent emails (where `sentByUserId` is not null), matches by the `to` field
- For received emails, matches by the `from` field
- Updates the `contactId` to link them properly
**Run with:**
```bash
node src/scripts/fix-sent-emails-contactid.js
```
### 2. `src/scripts/resync-all-contacts.js`
**Purpose**: Re-syncs all contacts with bidirectional sync to fetch missing emails
**What it does:**
- Fetches all contacts from the database
- Re-syncs each contact using the new bidirectional sync logic
- Pulls in any missing sent emails that weren't synced before
**Run with:**
```bash
node src/scripts/resync-all-contacts.js
```
## About the Database Schema
### The `sentByUserId` Column
- **Location**: `emails` table, line 93 in `src/db/schema.js`
- **Purpose**: Tracks which user sent the email from the CRM
- **Status**: ✅ This column EXISTS and IS being used correctly
- **Note**: It's NOT `set_by_user_id` (that was a typo in your question)
### Current Architecture (Refactor Branch)
- Email accounts can be **shared** between multiple users via `userEmailAccounts` table
- Contacts belong to email accounts (not individual users)
- Multiple users can manage the same email account
- This design supports your requirement: "chcem mat jeden email account linknuty kludne aj na dvoch crm uctoch"
## How Email Filtering Works Now
### Backend (src/services/crm-email.service.js:9-38)
```javascript
// INNER JOIN with contacts table
.innerJoin(contacts, eq(emails.contactId, contacts.id))
```
- ✅ Only shows emails from added contacts (as requested)
- ✅ No spam or unwanted emails
### Frontend (src/pages/Emails/EmailsPage.jsx:72-113)
```javascript
// Group by contact email
const contactEmail = email.contact.email;
```
- ✅ Groups emails by contact
- ✅ Shows complete conversation threads
## Testing Recommendations
1. **Test New Email Sync:**
```bash
# Add a new contact via Inbox
# Check that both received AND sent emails appear
```
2. **Test Sending Emails:**
```bash
# Send an email to a contact from CRM
# Verify it appears in the conversation immediately
```
3. **Run Cleanup Scripts:**
```bash
# Fix existing data
node src/scripts/fix-sent-emails-contactid.js
# Re-sync all contacts to get complete history
node src/scripts/resync-all-contacts.js
```
4. **Verify Shared Email Accounts:**
```bash
# Add same email account to two different users
# Verify both users see the same contacts and emails
```
## What's Fixed
✅ Emails now sync bidirectionally (FROM and TO contact)
✅ Sent emails from CRM are properly linked to contacts
✅ Complete conversation history is preserved
✅ All emails from all mailboxes are synced (not just Inbox)
✅ Email grouping works correctly by contact
✅ Only emails from added contacts are shown
✅ Shared email accounts work correctly
## Migration Path
1. **Apply the code changes** (already done in `src/services/jmap.service.js`)
2. **Run fix script** to link existing orphaned emails:
```bash
node src/scripts/fix-sent-emails-contactid.js
```
3. **Run resync script** to fetch missing emails:
```bash
node src/scripts/resync-all-contacts.js
```
4. **Test thoroughly** with your email accounts
5. **Delete old migration files** from `MIGRATION_GUIDE.md` if no longer needed
## Notes
- No frontend changes were needed (FE code was already correct)
- No database schema changes needed
- The `sentByUserId` column is working as designed
- The refactor branch architecture supports shared email accounts as intended