Add EOI automation system with email processing and document management

- Implement automated EOI processing from sales emails
- Add EOI document upload and management capabilities
- Enhance email thread handling with better parsing and grouping
- Add retry logic and error handling for file operations
- Introduce Documeso integration for document processing
- Create server tasks and plugins infrastructure
- Update email composer with improved attachment handling
This commit is contained in:
2025-06-10 13:59:09 +02:00
parent 5c30411c2b
commit 218705da52
25 changed files with 2351 additions and 71 deletions

View File

@@ -12,6 +12,14 @@ export default defineEventHandler(async (event) => {
});
}
// Protect EOIs folder from deletion
if (fileName === 'EOIs/' || fileName === 'EOIs') {
throw createError({
statusCode: 403,
statusMessage: 'The EOIs folder is protected and cannot be deleted',
});
}
// Delete folder or file based on type
if (isFolder) {
await deleteFolder(fileName);

View File

@@ -12,16 +12,44 @@ export default defineEventHandler(async (event) => {
});
}
// Get the download URL from MinIO
const url = await getDownloadUrl(fileName);
// Retry logic for getting download URL and fetching file
let response: Response | null = null;
let lastError: any = null;
// Fetch the file from MinIO
const response = await fetch(url);
for (let attempt = 0; attempt < 3; attempt++) {
try {
console.log(`[proxy-download] Attempting to download ${fileName} (attempt ${attempt + 1}/3)`);
// Get the download URL from MinIO
const url = await getDownloadUrl(fileName);
// Fetch the file from MinIO with timeout
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 30000); // 30 second timeout
response = await fetch(url, { signal: controller.signal });
clearTimeout(timeout);
if (response.ok) {
break; // Success, exit retry loop
}
lastError = new Error(`HTTP ${response.status}: ${response.statusText}`);
} catch (error: any) {
lastError = error;
console.error(`[proxy-download] Attempt ${attempt + 1} failed:`, error.message);
// Wait before retry with exponential backoff
if (attempt < 2) {
await new Promise(resolve => setTimeout(resolve, (attempt + 1) * 1000));
}
}
}
if (!response.ok) {
if (!response || !response.ok) {
throw createError({
statusCode: response.status,
statusMessage: 'Failed to fetch file from storage',
statusCode: response?.status || 500,
statusMessage: lastError?.message || 'Failed to fetch file from storage after 3 attempts',
});
}

View File

@@ -8,7 +8,15 @@ export default defineEventHandler(async (event) => {
if (!oldName || !newName) {
throw createError({
statusCode: 400,
statusMessage: 'Old name and new name are required',
statusMessage: 'Both old and new names are required',
});
}
// Protect EOIs folder from renaming
if (oldName === 'EOIs/' || oldName === 'EOIs') {
throw createError({
statusCode: 403,
statusMessage: 'The EOIs folder is protected and cannot be renamed',
});
}