FEAT: Implement debug and test endpoints for fetching and analyzing berth interested parties
This commit is contained in:
parent
d0632b2839
commit
d9f359d874
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { requireAuth } from '~/server/utils/auth';
|
||||||
|
import { getBerthById } from '~/server/utils/nocodb';
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
console.log('[debug-berth-interested-parties] Request received');
|
||||||
|
|
||||||
|
// Check authentication
|
||||||
|
await requireAuth(event);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get a berth ID from query params
|
||||||
|
const query = getQuery(event);
|
||||||
|
const berthId = query.id as string;
|
||||||
|
|
||||||
|
if (!berthId) {
|
||||||
|
throw createError({
|
||||||
|
statusCode: 400,
|
||||||
|
statusMessage: 'Berth ID is required'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[debug-berth-interested-parties] Fetching berth:', berthId);
|
||||||
|
|
||||||
|
// First, get the raw berth data without population
|
||||||
|
const config = useRuntimeConfig().nocodb;
|
||||||
|
const rawBerthResponse = await $fetch(`${config.url}/api/v2/tables/mczgos9hr3oa9qc/records/${berthId}`, {
|
||||||
|
headers: {
|
||||||
|
"xc-token": config.token,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
fields: '*'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('[debug-berth-interested-parties] Raw berth data:', JSON.stringify(rawBerthResponse, null, 2));
|
||||||
|
|
||||||
|
// Check the structure of Interested Parties
|
||||||
|
const interestedParties = (rawBerthResponse as any)['Interested Parties'];
|
||||||
|
console.log('[debug-berth-interested-parties] Raw Interested Parties structure:', JSON.stringify(interestedParties, null, 2));
|
||||||
|
console.log('[debug-berth-interested-parties] Interested Parties type:', typeof interestedParties);
|
||||||
|
console.log('[debug-berth-interested-parties] Is Array:', Array.isArray(interestedParties));
|
||||||
|
|
||||||
|
if (Array.isArray(interestedParties) && interestedParties.length > 0) {
|
||||||
|
console.log('[debug-berth-interested-parties] First party:', JSON.stringify(interestedParties[0], null, 2));
|
||||||
|
console.log('[debug-berth-interested-parties] First party type:', typeof interestedParties[0]);
|
||||||
|
console.log('[debug-berth-interested-parties] First party keys:', Object.keys(interestedParties[0] || {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now try the populated version
|
||||||
|
const populatedBerth = await getBerthById(berthId);
|
||||||
|
console.log('[debug-berth-interested-parties] Populated Interested Parties:', JSON.stringify(populatedBerth['Interested Parties'], null, 2));
|
||||||
|
|
||||||
|
return {
|
||||||
|
berthId,
|
||||||
|
raw: {
|
||||||
|
interestedParties: interestedParties,
|
||||||
|
type: typeof interestedParties,
|
||||||
|
isArray: Array.isArray(interestedParties),
|
||||||
|
length: Array.isArray(interestedParties) ? interestedParties.length : 0,
|
||||||
|
firstItem: Array.isArray(interestedParties) && interestedParties.length > 0 ? interestedParties[0] : null,
|
||||||
|
firstItemKeys: Array.isArray(interestedParties) && interestedParties.length > 0 && interestedParties[0] ? Object.keys(interestedParties[0]) : []
|
||||||
|
},
|
||||||
|
populated: {
|
||||||
|
interestedParties: populatedBerth['Interested Parties'],
|
||||||
|
success: !!populatedBerth['Interested Parties']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('[debug-berth-interested-parties] Error:', error);
|
||||||
|
throw createError({
|
||||||
|
statusCode: 500,
|
||||||
|
statusMessage: error.message || 'Failed to debug berth interested parties'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
import { getNocoDbConfiguration } from "../utils/nocodb";
|
||||||
|
import { requireAuth } from "../utils/auth";
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
console.log('[get-berth-interested-parties] Request received');
|
||||||
|
|
||||||
|
// Check authentication
|
||||||
|
await requireAuth(event);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const query = getQuery(event);
|
||||||
|
const { berthId } = query;
|
||||||
|
console.log('[get-berth-interested-parties] Request params:', { berthId });
|
||||||
|
|
||||||
|
if (!berthId) {
|
||||||
|
throw createError({
|
||||||
|
statusCode: 400,
|
||||||
|
statusMessage: "berthId is required"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = getNocoDbConfiguration();
|
||||||
|
const berthsTableId = "mczgos9hr3oa9qc"; // Berth table ID
|
||||||
|
|
||||||
|
// The "Interested Parties" field ID needs to be determined
|
||||||
|
// For now, let's try to fetch the berth first and see what we get
|
||||||
|
const berthUrl = `${config.url}/api/v2/tables/${berthsTableId}/records/${berthId}`;
|
||||||
|
console.log('[get-berth-interested-parties] Fetching berth:', berthUrl);
|
||||||
|
|
||||||
|
const berth = await $fetch(berthUrl, {
|
||||||
|
headers: {
|
||||||
|
"xc-token": config.token,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('[get-berth-interested-parties] Berth data:', JSON.stringify(berth, null, 2));
|
||||||
|
|
||||||
|
// Check if we have Interested Parties field
|
||||||
|
const interestedPartiesField = (berth as any)['Interested Parties'];
|
||||||
|
console.log('[get-berth-interested-parties] Interested Parties field:', JSON.stringify(interestedPartiesField, null, 2));
|
||||||
|
|
||||||
|
// If we have interested parties, fetch their details
|
||||||
|
if (interestedPartiesField && Array.isArray(interestedPartiesField)) {
|
||||||
|
// Extract IDs from the interested parties
|
||||||
|
const partyIds = interestedPartiesField.map((party: any) => {
|
||||||
|
// Handle different possible formats
|
||||||
|
if (typeof party === 'number') return party;
|
||||||
|
if (typeof party === 'string') return parseInt(party);
|
||||||
|
if (party && typeof party === 'object' && party.Id) return party.Id;
|
||||||
|
if (party && typeof party === 'object' && party.id) return party.id;
|
||||||
|
return null;
|
||||||
|
}).filter(id => id !== null);
|
||||||
|
|
||||||
|
console.log('[get-berth-interested-parties] Party IDs to fetch:', partyIds);
|
||||||
|
|
||||||
|
// Fetch full interest records
|
||||||
|
if (partyIds.length > 0) {
|
||||||
|
const interestsTableId = "mbs9hjauug4eseo";
|
||||||
|
const interestPromises = partyIds.map(id =>
|
||||||
|
$fetch(`${config.url}/api/v2/tables/${interestsTableId}/records/${id}`, {
|
||||||
|
headers: {
|
||||||
|
"xc-token": config.token,
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
console.error(`[get-berth-interested-parties] Failed to fetch interest ${id}:`, error);
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const interests = await Promise.all(interestPromises);
|
||||||
|
const validInterests = interests.filter(i => i !== null);
|
||||||
|
|
||||||
|
console.log('[get-berth-interested-parties] Fetched interests:', validInterests.length);
|
||||||
|
|
||||||
|
return {
|
||||||
|
list: validInterests,
|
||||||
|
pageInfo: {
|
||||||
|
totalRows: validInterests.length,
|
||||||
|
page: 1,
|
||||||
|
pageSize: validInterests.length,
|
||||||
|
isFirstPage: true,
|
||||||
|
isLastPage: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return empty list if no interested parties
|
||||||
|
return {
|
||||||
|
list: [],
|
||||||
|
pageInfo: {
|
||||||
|
totalRows: 0,
|
||||||
|
page: 1,
|
||||||
|
pageSize: 0,
|
||||||
|
isFirstPage: true,
|
||||||
|
isLastPage: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('[get-berth-interested-parties] Error occurred:', error);
|
||||||
|
console.error('[get-berth-interested-parties] Error details:', error instanceof Error ? error.message : 'Unknown error');
|
||||||
|
|
||||||
|
// Check if it's a 404 error
|
||||||
|
if (error.statusCode === 404 || error.status === 404) {
|
||||||
|
// Return empty list instead of throwing error
|
||||||
|
return {
|
||||||
|
list: [],
|
||||||
|
pageInfo: {
|
||||||
|
totalRows: 0,
|
||||||
|
page: 1,
|
||||||
|
pageSize: 0,
|
||||||
|
isFirstPage: true,
|
||||||
|
isLastPage: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,147 @@
|
||||||
|
import { requireAuth } from '~/server/utils/auth';
|
||||||
|
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
console.log('[test-berth-interested-parties] Testing berth interested parties...');
|
||||||
|
|
||||||
|
// Check authentication
|
||||||
|
await requireAuth(event);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const config = useRuntimeConfig().nocodb;
|
||||||
|
|
||||||
|
// First, let's get all berths and see which ones have interested parties
|
||||||
|
const berthsResponse = await $fetch(`${config.url}/api/v2/tables/mczgos9hr3oa9qc/records`, {
|
||||||
|
headers: {
|
||||||
|
"xc-token": config.token,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
limit: 100,
|
||||||
|
fields: '*'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const berths = (berthsResponse as any).list || [];
|
||||||
|
console.log('[test-berth-interested-parties] Total berths:', berths.length);
|
||||||
|
|
||||||
|
// Find berths with interested parties
|
||||||
|
const berthsWithParties = berths.filter((b: any) =>
|
||||||
|
b['Interested Parties'] && Array.isArray(b['Interested Parties']) && b['Interested Parties'].length > 0
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('[test-berth-interested-parties] Berths with interested parties:', berthsWithParties.length);
|
||||||
|
|
||||||
|
if (berthsWithParties.length === 0) {
|
||||||
|
return {
|
||||||
|
message: "No berths found with interested parties",
|
||||||
|
totalBerths: berths.length,
|
||||||
|
berthsWithParties: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take the first berth with interested parties for testing
|
||||||
|
const testBerth = berthsWithParties[0];
|
||||||
|
console.log('[test-berth-interested-parties] Test berth:', {
|
||||||
|
id: testBerth.Id,
|
||||||
|
mooringNumber: testBerth['Mooring Number'],
|
||||||
|
interestedPartiesCount: testBerth['Interested Parties'].length
|
||||||
|
});
|
||||||
|
|
||||||
|
// Log the raw interested parties data
|
||||||
|
console.log('[test-berth-interested-parties] Raw Interested Parties data:',
|
||||||
|
JSON.stringify(testBerth['Interested Parties'], null, 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Analyze the structure
|
||||||
|
const firstParty = testBerth['Interested Parties'][0];
|
||||||
|
const partyAnalysis = {
|
||||||
|
type: typeof firstParty,
|
||||||
|
isArray: Array.isArray(firstParty),
|
||||||
|
isObject: firstParty && typeof firstParty === 'object',
|
||||||
|
value: firstParty,
|
||||||
|
keys: firstParty && typeof firstParty === 'object' && !Array.isArray(firstParty)
|
||||||
|
? Object.keys(firstParty)
|
||||||
|
: []
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('[test-berth-interested-parties] First party analysis:', partyAnalysis);
|
||||||
|
|
||||||
|
// Try to extract IDs
|
||||||
|
const extractedIds = testBerth['Interested Parties'].map((party: any) => {
|
||||||
|
if (typeof party === 'number') return { id: party, type: 'number' };
|
||||||
|
if (typeof party === 'string') return { id: party, type: 'string' };
|
||||||
|
if (party && typeof party === 'object') {
|
||||||
|
return {
|
||||||
|
id: party.Id || party.id || party.ID || party._id || null,
|
||||||
|
type: 'object',
|
||||||
|
keys: Object.keys(party)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return { id: null, type: 'unknown' };
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('[test-berth-interested-parties] Extracted IDs:', extractedIds);
|
||||||
|
|
||||||
|
// Try to fetch one interest if we have an ID
|
||||||
|
let fetchedInterest = null;
|
||||||
|
const validId = extractedIds.find((item: any) => item.id !== null);
|
||||||
|
|
||||||
|
if (validId && validId.id) {
|
||||||
|
try {
|
||||||
|
const interestId = typeof validId.id === 'string' ? validId.id : validId.id.toString();
|
||||||
|
fetchedInterest = await $fetch(`${config.url}/api/v2/tables/mbs9hjauug4eseo/records/${interestId}`, {
|
||||||
|
headers: {
|
||||||
|
"xc-token": config.token,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log('[test-berth-interested-parties] Successfully fetched interest:', interestId);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[test-berth-interested-parties] Failed to fetch interest:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
testBerth: {
|
||||||
|
id: testBerth.Id,
|
||||||
|
mooringNumber: testBerth['Mooring Number'],
|
||||||
|
interestedPartiesCount: testBerth['Interested Parties'].length
|
||||||
|
},
|
||||||
|
rawInterestedParties: testBerth['Interested Parties'],
|
||||||
|
firstPartyAnalysis: partyAnalysis,
|
||||||
|
extractedIds: extractedIds,
|
||||||
|
fetchedInterest: fetchedInterest,
|
||||||
|
recommendation: determineRecommendation(testBerth['Interested Parties'])
|
||||||
|
};
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('[test-berth-interested-parties] Error:', error);
|
||||||
|
return {
|
||||||
|
error: error.message || 'Unknown error',
|
||||||
|
details: error
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function determineRecommendation(interestedParties: any[]): string {
|
||||||
|
if (!interestedParties || interestedParties.length === 0) {
|
||||||
|
return "No interested parties found";
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstParty = interestedParties[0];
|
||||||
|
|
||||||
|
if (typeof firstParty === 'number') {
|
||||||
|
return "Interested parties are stored as number IDs. Population logic should handle this format.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof firstParty === 'string') {
|
||||||
|
return "Interested parties are stored as string IDs. Population logic should parse these.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstParty && typeof firstParty === 'object') {
|
||||||
|
const keys = Object.keys(firstParty);
|
||||||
|
if (keys.includes('Id') || keys.includes('id')) {
|
||||||
|
return "Interested parties are objects with ID fields. Population logic looks correct.";
|
||||||
|
}
|
||||||
|
return `Interested parties are objects but with unexpected keys: ${keys.join(', ')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Unknown format for interested parties data";
|
||||||
|
}
|
||||||
|
|
@ -523,30 +523,47 @@ export const getBerthById = async (id: string) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('[nocodb.getBerthById] Successfully fetched berth:', result.Id);
|
console.log('[nocodb.getBerthById] Successfully fetched berth:', result.Id);
|
||||||
|
console.log('[nocodb.getBerthById] Raw Interested Parties:', JSON.stringify(result['Interested Parties'], null, 2));
|
||||||
|
|
||||||
// Now fetch and populate the interested parties details
|
// Now fetch and populate the interested parties details
|
||||||
if (result['Interested Parties'] && Array.isArray(result['Interested Parties'])) {
|
if (result['Interested Parties'] && Array.isArray(result['Interested Parties'])) {
|
||||||
console.log('[nocodb.getBerthById] Fetching details for interested parties:', result['Interested Parties'].length);
|
console.log('[nocodb.getBerthById] Fetching details for interested parties:', result['Interested Parties'].length);
|
||||||
|
|
||||||
const interestedPartiesDetails = await Promise.all(
|
// Extract IDs from various possible formats
|
||||||
result['Interested Parties'].map(async (party: any) => {
|
const partyIds = result['Interested Parties'].map((party: any) => {
|
||||||
if (party && (party.Id || party.id)) {
|
// Handle different possible formats from NocoDB
|
||||||
const interestId = party.Id || party.id;
|
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 {
|
try {
|
||||||
console.log('[nocodb.getBerthById] Fetching interest details for ID:', interestId);
|
console.log('[nocodb.getBerthById] Fetching interest details for ID:', partyId);
|
||||||
const interestDetails = await getInterestById(interestId.toString());
|
const interestDetails = await getInterestById(partyId.toString());
|
||||||
return interestDetails;
|
return interestDetails;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[nocodb.getBerthById] Failed to fetch interest details for ID:', interestId, error);
|
console.error('[nocodb.getBerthById] Failed to fetch interest details for ID:', partyId, error);
|
||||||
return party; // Return original party if fetch fails
|
// Return a placeholder object if fetch fails
|
||||||
|
return { Id: partyId, 'Full Name': `Interest #${partyId}` } as any;
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
return party;
|
);
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
result['Interested Parties'] = interestedPartiesDetails;
|
result['Interested Parties'] = interestedPartiesDetails;
|
||||||
console.log('[nocodb.getBerthById] Populated interested parties details');
|
console.log('[nocodb.getBerthById] Populated interested parties details:', interestedPartiesDetails.length);
|
||||||
|
} else {
|
||||||
|
console.log('[nocodb.getBerthById] No valid party IDs found to populate');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue