diff --git a/components/EOISection.vue b/components/EOISection.vue new file mode 100644 index 0000000..48969ef --- /dev/null +++ b/components/EOISection.vue @@ -0,0 +1,177 @@ + + + diff --git a/components/InterestDetailsModal.vue b/components/InterestDetailsModal.vue index d491be8..0e74b54 100644 --- a/components/InterestDetailsModal.vue +++ b/components/InterestDetailsModal.vue @@ -244,7 +244,7 @@ - + @@ -626,79 +626,14 @@ - - - - mdi-link-variant - EOI Links - - - - - - Client ({{ interest['Full Name'] }}) - {{ (interest as any)['EOI Client Link'] }} - - - - - - Oscar Faragher (Approver) - {{ (interest as any)['EOI Oscar Link'] }} - - - - - - David Mizrahi (Signer) - {{ (interest as any)['EOI David Link'] }} - - - - + + + @@ -714,10 +649,30 @@ diff --git a/docs/email-system-fixes.md b/docs/email-system-fixes.md index 60846aa..dc05af2 100644 --- a/docs/email-system-fixes.md +++ b/docs/email-system-fixes.md @@ -131,6 +131,37 @@ NUXT_DOCUMENSO_API_KEY=your-actual-api-key NUXT_DOCUMENSO_BASE_URL=https://signatures.portnimara.dev ``` +### 12. EOI Management System +- **Added EOI Section Component**: New component to manage EOI document generation and signature links +- **Features Implemented**: + - Generate EOI button that creates documents via Documenso API + - Checks for existing EOI before generating new one (prevents duplicates) + - Displays all 3 signature links (Client, CC, Developer) with copy-to-clipboard functionality + - Shows EOI status badge (Awaiting Further Details, Waiting for Signatures, Signed) + - Regenerate option for non-signed documents +- **Auto-Updates on EOI Generation**: + - EOI Status → "Waiting for Signatures" + - Sales Process Level → "LOI and NDA Sent" + - EOI Time Sent → Current timestamp + - Extra Comments → Appends "EOI Sent [timestamp]" +- **Database Storage**: Links stored in new columns: + - `Signature Link Client` + - `Signature Link CC` + - `Signature Link Developer` + +### 13. Auto-Save Functionality +- **Implemented**: Interest details now auto-save after 2 seconds of inactivity +- **Features**: + - Debounced save to prevent excessive API calls + - Silent save without success notifications + - Automatically triggers parent refresh to keep data in sync + - Cancels pending saves on component unmount + +### 14. IMAP BCC Search Fix +- **Problem**: IMAP search was failing with "Cannot read properties of null" +- **Cause**: BCC search criteria not supported by all IMAP servers +- **Solution**: Removed BCC from search criteria, now only searches FROM, TO, and CC fields + ## How It Works Now 1. **Email Session Management**: diff --git a/package-lock.json b/package-lock.json index 99c9302..e98657e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,9 +6,11 @@ "": { "hasInstallScript": true, "dependencies": { + "@types/lodash-es": "^4.17.12", "@vite-pwa/nuxt": "^0.10.6", "formidable": "^3.5.4", "imap": "^0.8.19", + "lodash-es": "^4.17.21", "mailparser": "^3.7.3", "mime-types": "^3.0.1", "minio": "^8.0.5", @@ -3710,6 +3712,21 @@ "@types/node": "*" } }, + "node_modules/@types/lodash": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", + "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/mailparser": { "version": "3.4.6", "resolved": "https://registry.npmjs.org/@types/mailparser/-/mailparser-3.4.6.tgz", @@ -8821,6 +8838,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", diff --git a/package.json b/package.json index f3ced6f..5035bc1 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,11 @@ "postinstall": "nuxt prepare" }, "dependencies": { + "@types/lodash-es": "^4.17.12", "@vite-pwa/nuxt": "^0.10.6", "formidable": "^3.5.4", "imap": "^0.8.19", + "lodash-es": "^4.17.21", "mailparser": "^3.7.3", "mime-types": "^3.0.1", "minio": "^8.0.5", diff --git a/server/api/email/fetch-thread.ts b/server/api/email/fetch-thread.ts index 26fc0f4..6f2f05e 100644 --- a/server/api/email/fetch-thread.ts +++ b/server/api/email/fetch-thread.ts @@ -203,12 +203,12 @@ async function fetchImapEmails( console.log(`Searching in folder: ${folderName}`); // Search for emails both sent and received with this client + // Note: BCC search might not be supported by all IMAP servers const searchCriteria = [ 'OR', ['FROM', clientEmail], ['TO', clientEmail], - ['CC', clientEmail], - ['BCC', clientEmail] + ['CC', clientEmail] ]; imap.search(searchCriteria, (err, results) => { diff --git a/server/api/email/generate-eoi-document.ts b/server/api/email/generate-eoi-document.ts index 5259fcb..33cca41 100644 --- a/server/api/email/generate-eoi-document.ts +++ b/server/api/email/generate-eoi-document.ts @@ -43,6 +43,21 @@ export default defineEventHandler(async (event) => { throw createError({ statusCode: 404, statusMessage: "Interest not found" }); } + // Check if EOI already exists (has signature links) + if (interest['Signature Link Client'] && interest['Signature Link CC'] && interest['Signature Link Developer']) { + console.log('EOI already exists, returning existing links'); + return { + success: true, + documentId: 'existing', + clientSigningUrl: interest['Signature Link Client'], + signingLinks: { + 'Client': interest['Signature Link Client'], + 'CC': interest['Signature Link CC'], + 'Developer': interest['Signature Link Developer'] + } + }; + } + // Validate required fields const requiredFields = [ { field: 'Full Name', value: interest['Full Name'] }, @@ -260,15 +275,15 @@ export default defineEventHandler(async (event) => { 'Extra Comments': updatedComments }; - // Add signing links to update data + // Add signing links to update data with new column names if (signingLinks['Client']) { - updateData['EOI Client Link'] = signingLinks['Client']; + updateData['Signature Link Client'] = signingLinks['Client']; } if (signingLinks['David Mizrahi']) { - updateData['EOI David Link'] = signingLinks['David Mizrahi']; + updateData['Signature Link Developer'] = signingLinks['David Mizrahi']; } if (signingLinks['Oscar Faragher']) { - updateData['EOI Oscar Link'] = signingLinks['Oscar Faragher']; + updateData['Signature Link CC'] = signingLinks['Oscar Faragher']; } await updateInterest(interestId, updateData); diff --git a/server/utils/nocodb.ts b/server/utils/nocodb.ts index c37feeb..1fe352d 100644 --- a/server/utils/nocodb.ts +++ b/server/utils/nocodb.ts @@ -98,9 +98,13 @@ export const updateInterest = async (id: string, data: Partial, retryC "Contract Status", // Add the EOI link fields "EOI Client Link", - "EOI David Link", + "EOI David Link", "EOI Oscar Link", - "EOI Document" + "EOI Document", + // Add the new signature link fields + "Signature Link Client", + "Signature Link CC", + "Signature Link Developer" ]; // Filter the data to only include allowed fields diff --git a/utils/types.ts b/utils/types.ts index 820f7f8..66ebcda 100644 --- a/utils/types.ts +++ b/utils/types.ts @@ -119,6 +119,14 @@ export interface Interest { "Contract Sent Status": ContractSentStatus; "Deposit 10% Status": Deposit10PercentStatus; "Contract Status": ContractStatus; + // EOI Link fields + "EOI Client Link"?: string; + "EOI David Link"?: string; + "EOI Oscar Link"?: string; + // New signature link fields + "Signature Link Client"?: string; + "Signature Link CC"?: string; + "Signature Link Developer"?: string; } export interface InterestsResponse {