diff --git a/server/api/test-berth-with-parties.ts b/server/api/test-berth-with-parties.ts new file mode 100644 index 0000000..854dd7b --- /dev/null +++ b/server/api/test-berth-with-parties.ts @@ -0,0 +1,62 @@ +import { getBerthById } from '~/server/utils/nocodb'; +import { requireAuth } from '~/server/utils/auth'; + +export default defineEventHandler(async (event) => { + console.log('[test-berth-with-parties] Testing berth with interested parties...'); + + // Check authentication + await requireAuth(event); + + try { + // Get a berth ID from query params or use a default + const query = getQuery(event); + const berthId = query.id as string || '1'; // Default to berth ID 1 (A1) + + console.log('[test-berth-with-parties] Fetching berth:', berthId); + const berth = await getBerthById(berthId); + + // Extract interested parties info + const interestedParties = berth['Interested Parties']; + let partiesInfo = null; + + if (interestedParties) { + if (Array.isArray(interestedParties)) { + partiesInfo = { + type: 'array', + count: interestedParties.length, + parties: interestedParties.map(party => ({ + id: party.Id, + name: party['Full Name'], + email: party['Email Address'], + salesLevel: party['Sales Process Level'], + eoiStatus: party['EOI Status'] + })) + }; + } else if (typeof interestedParties === 'number') { + partiesInfo = { + type: 'number', + count: interestedParties, + note: 'This is just a count - should have been replaced with actual data' + }; + } else { + partiesInfo = { + type: typeof interestedParties, + value: interestedParties + }; + } + } + + return { + berthId: berth.Id, + mooringNumber: berth['Mooring Number'], + interestedPartiesField: partiesInfo, + success: Array.isArray(interestedParties) && interestedParties.length > 0 + }; + } catch (error: any) { + console.error('[test-berth-with-parties] Error:', error); + return { + error: error.message || 'Unknown error', + details: error + }; + } +}); diff --git a/server/utils/nocodb.ts b/server/utils/nocodb.ts index 006405d..3955f10 100644 --- a/server/utils/nocodb.ts +++ b/server/utils/nocodb.ts @@ -446,9 +446,9 @@ export const getBerths = async () => { if (result.list && Array.isArray(result.list)) { console.log('[nocodb.getBerths] Processing berths to populate interested parties...'); - // Count berths with interested parties + // Count berths with interested parties (NocoDB returns count as number) const berthsWithParties = result.list.filter(b => - b['Interested Parties'] && Array.isArray(b['Interested Parties']) && b['Interested Parties'].length > 0 + b['Interested Parties'] && (typeof b['Interested Parties'] === 'number' && b['Interested Parties'] > 0) ); console.log('[nocodb.getBerths] Berths with interested parties:', berthsWithParties.length); @@ -467,7 +467,61 @@ export const getBerths = async () => { await Promise.all( result.list.map(async (berth) => { - if (berth['Interested Parties'] && Array.isArray(berth['Interested Parties']) && berth['Interested Parties'].length > 0) { + // Check if berth has interested parties (as a number count) + if (berth['Interested Parties'] && typeof berth['Interested Parties'] === 'number' && berth['Interested Parties'] > 0) { + const partyCount = berth['Interested Parties'] as number; + console.log(`[nocodb.getBerths] Berth ${berth['Mooring Number']} has ${partyCount} interested parties (as count)`); + + // When we have a count, fetch the linked records using the links API + try { + const config = getNocoDbConfiguration(); + const berthsTableId = "mczgos9hr3oa9qc"; + const interestedPartiesFieldId = "c7q2z2rb27c1cb5"; + + const linkUrl = `${config.url}/api/v2/tables/${berthsTableId}/links/${interestedPartiesFieldId}/records/${berth.Id}`; + console.log(`[nocodb.getBerths] Fetching linked parties from: ${linkUrl}`); + + const linkedResponse = await $fetch(linkUrl, { + headers: { + "xc-token": config.token, + }, + params: { + limit: 100 + } + }); + + console.log(`[nocodb.getBerths] Linked response for berth ${berth['Mooring Number']}:`, linkedResponse); + + if (linkedResponse && linkedResponse.list && Array.isArray(linkedResponse.list)) { + // The linked records should be full interest records + berth['Interested Parties'] = linkedResponse.list; + console.log(`[nocodb.getBerths] Successfully fetched ${linkedResponse.list.length} interested parties for berth ${berth['Mooring Number']}`); + } else { + // Fallback to placeholders if API call doesn't return expected format + const placeholderParties = Array.from({ length: partyCount }, (_, index) => ({ + Id: index + 1, + 'Full Name': `Party ${index + 1}`, + 'Sales Process Level': null, + 'EOI Status': null, + 'Contract Status': null + })); + berth['Interested Parties'] = placeholderParties as any; + console.log(`[nocodb.getBerths] Using placeholders for berth ${berth['Mooring Number']}`); + } + } catch (linkError) { + console.error(`[nocodb.getBerths] Failed to fetch linked parties for berth ${berth['Mooring Number']}:`, linkError); + // Fallback to placeholders on error + const placeholderParties = Array.from({ length: partyCount }, (_, index) => ({ + Id: index + 1, + 'Full Name': `Party ${index + 1}`, + 'Sales Process Level': null, + 'EOI Status': null, + 'Contract Status': null + })); + berth['Interested Parties'] = placeholderParties as any; + } + } else if (berth['Interested Parties'] && Array.isArray(berth['Interested Parties']) && berth['Interested Parties'].length > 0) { + // Handle case where we get an array (this might happen in some cases) console.log(`[nocodb.getBerths] Processing ${berth['Interested Parties'].length} parties for berth ${berth['Mooring Number']}`); // Extract IDs from various possible formats @@ -563,43 +617,99 @@ export const getBerthById = async (id: string) => { console.log('[nocodb.getBerthById] Raw Interested Parties:', JSON.stringify(result['Interested Parties'], null, 2)); // Now fetch and populate the interested parties details - if (result['Interested Parties'] && Array.isArray(result['Interested Parties'])) { - console.log('[nocodb.getBerthById] Fetching details for interested parties:', result['Interested Parties'].length); - - // Extract IDs from various possible formats - const partyIds = result['Interested Parties'].map((party: any) => { - // Handle different possible formats from NocoDB - if (typeof party === 'number') return party; - if (typeof party === 'string') return parseInt(party); - if (party && typeof party === 'object') { - // Check various possible ID field names - return party.Id || party.id || party.ID || party._id || null; - } - return null; - }).filter(id => id !== null && !isNaN(id)); - - console.log('[nocodb.getBerthById] Extracted party IDs:', partyIds); - - // Fetch full interest records - if (partyIds.length > 0) { - const interestedPartiesDetails = await Promise.all( - partyIds.map(async (partyId: number) => { - try { - console.log('[nocodb.getBerthById] Fetching interest details for ID:', partyId); - const interestDetails = await getInterestById(partyId.toString()); - return interestDetails; - } catch (error) { - console.error('[nocodb.getBerthById] Failed to fetch interest details for ID:', partyId, error); - // Return a placeholder object if fetch fails - return { Id: partyId, 'Full Name': `Interest #${partyId}` } as any; - } - }) - ); + if (result['Interested Parties']) { + // Handle case where interested parties is a count (number) + if (typeof result['Interested Parties'] === 'number' && result['Interested Parties'] > 0) { + const partyCount = result['Interested Parties'] as number; + console.log(`[nocodb.getBerthById] Berth has ${partyCount} interested parties (as count)`); - result['Interested Parties'] = interestedPartiesDetails; - console.log('[nocodb.getBerthById] Populated interested parties details:', interestedPartiesDetails.length); - } else { - console.log('[nocodb.getBerthById] No valid party IDs found to populate'); + // Fetch the linked records using the links API + try { + const config = getNocoDbConfiguration(); + const berthsTableId = "mczgos9hr3oa9qc"; + const interestedPartiesFieldId = "c7q2z2rb27c1cb5"; + + const linkUrl = `${config.url}/api/v2/tables/${berthsTableId}/links/${interestedPartiesFieldId}/records/${result.Id}`; + console.log(`[nocodb.getBerthById] Fetching linked parties from: ${linkUrl}`); + + const linkedResponse = await $fetch(linkUrl, { + headers: { + "xc-token": config.token, + }, + params: { + limit: 100 + } + }); + + console.log(`[nocodb.getBerthById] Linked response:`, linkedResponse); + + if (linkedResponse && linkedResponse.list && Array.isArray(linkedResponse.list)) { + // The linked records should be full interest records + result['Interested Parties'] = linkedResponse.list; + console.log(`[nocodb.getBerthById] Successfully fetched ${linkedResponse.list.length} interested parties`); + } else { + // Fallback to placeholders if API call doesn't return expected format + const placeholderParties = Array.from({ length: partyCount }, (_, index) => ({ + Id: index + 1, + 'Full Name': `Party ${index + 1}`, + 'Sales Process Level': null, + 'EOI Status': null, + 'Contract Status': null + })); + result['Interested Parties'] = placeholderParties as any; + console.log(`[nocodb.getBerthById] Using placeholders`); + } + } catch (linkError) { + console.error(`[nocodb.getBerthById] Failed to fetch linked parties:`, linkError); + // Fallback to placeholders on error + const placeholderParties = Array.from({ length: partyCount }, (_, index) => ({ + Id: index + 1, + 'Full Name': `Party ${index + 1}`, + 'Sales Process Level': null, + 'EOI Status': null, + 'Contract Status': null + })); + result['Interested Parties'] = placeholderParties as any; + } + } else if (Array.isArray(result['Interested Parties'])) { + // Handle case where we get an array (might happen in some cases) + console.log('[nocodb.getBerthById] Fetching details for interested parties:', result['Interested Parties'].length); + + // Extract IDs from various possible formats + const partyIds = result['Interested Parties'].map((party: any) => { + // Handle different possible formats from NocoDB + if (typeof party === 'number') return party; + if (typeof party === 'string') return parseInt(party); + if (party && typeof party === 'object') { + // Check various possible ID field names + return party.Id || party.id || party.ID || party._id || null; + } + return null; + }).filter(id => id !== null && !isNaN(id)); + + console.log('[nocodb.getBerthById] Extracted party IDs:', partyIds); + + // Fetch full interest records + if (partyIds.length > 0) { + const interestedPartiesDetails = await Promise.all( + partyIds.map(async (partyId: number) => { + try { + console.log('[nocodb.getBerthById] Fetching interest details for ID:', partyId); + const interestDetails = await getInterestById(partyId.toString()); + return interestDetails; + } catch (error) { + console.error('[nocodb.getBerthById] Failed to fetch interest details for ID:', partyId, error); + // Return a placeholder object if fetch fails + return { Id: partyId, 'Full Name': `Interest #${partyId}` } as any; + } + }) + ); + + result['Interested Parties'] = interestedPartiesDetails; + console.log('[nocodb.getBerthById] Populated interested parties details:', interestedPartiesDetails.length); + } else { + console.log('[nocodb.getBerthById] No valid party IDs found to populate'); + } } }