import { getNocoDbConfiguration } from '~/server/utils/nocodb'; import { createSessionManager } from '~/server/utils/session'; export default defineEventHandler(async (event) => { console.log('[api/admin/membership-status-fix] POST /api/admin/membership-status-fix'); try { // Validate session and require admin privileges const sessionManager = createSessionManager(); const cookieHeader = getCookie(event, 'monacousa-session') ? getHeader(event, 'cookie') : undefined; const session = sessionManager.getSession(cookieHeader); if (!session?.user) { throw createError({ statusCode: 401, statusMessage: 'Authentication required' }); } if (session.user.tier !== 'admin') { throw createError({ statusCode: 403, statusMessage: 'Admin privileges required' }); } console.log('[api/admin/membership-status-fix] Authorized admin:', session.user.email); const body = await readBody(event); const { action, tableId } = body; const config = getNocoDbConfiguration(); if (action === 'check') { return await checkMembershipStatusField(config, tableId); } else if (action === 'fix') { return await fixMembershipStatusField(config, tableId); } else { throw createError({ statusCode: 400, statusMessage: 'Invalid action. Use "check" or "fix"' }); } } catch (error: any) { console.error('[api/admin/membership-status-fix] Error:', error); throw error; } }); async function checkMembershipStatusField(config: any, tableId: string) { console.log('[checkMembershipStatusField] Checking membership status field configuration'); try { // Get table schema to check the membership_status field configuration const tableSchema = await $fetch(`${config.url}/api/v2/tables/${tableId}`, { headers: { "xc-token": config.token, } }); console.log('[checkMembershipStatusField] Table schema fetched'); // Find the membership_status field const membershipStatusField = tableSchema.columns?.find((col: any) => col.column_name === 'membership_status' || col.title === 'Membership Status' ); if (!membershipStatusField) { return { success: false, error: 'Membership Status field not found in table schema', tableSchema: tableSchema.columns?.map((col: any) => ({ name: col.column_name, title: col.title, uidt: col.uidt })) || [] }; } console.log('[checkMembershipStatusField] Membership Status field found:', { column_name: membershipStatusField.column_name, title: membershipStatusField.title, uidt: membershipStatusField.uidt, dtxp: membershipStatusField.dtxp }); // Check if it's a Single Select field and what options are available if (membershipStatusField.uidt === 'SingleSelect') { const options = membershipStatusField.colOptions?.options || []; const allowedValues = options.map((opt: any) => opt.title); const requiredValues = ['Active', 'Inactive', 'Pending', 'Expired']; const missingValues = requiredValues.filter(val => !allowedValues.includes(val)); return { success: true, fieldType: 'SingleSelect', currentOptions: allowedValues, requiredOptions: requiredValues, missingOptions: missingValues, needsFix: missingValues.length > 0, fieldId: membershipStatusField.id, message: missingValues.length > 0 ? `Missing options: ${missingValues.join(', ')}` : 'All required options are present' }; } else { return { success: true, fieldType: membershipStatusField.uidt, needsFix: false, message: `Field type is ${membershipStatusField.uidt}, not SingleSelect. This should work fine.` }; } } catch (error: any) { console.error('[checkMembershipStatusField] Error:', error); return { success: false, error: error.message || 'Failed to check field configuration' }; } } async function fixMembershipStatusField(config: any, tableId: string) { console.log('[fixMembershipStatusField] Fixing membership status field configuration'); try { // First check the current state const checkResult = await checkMembershipStatusField(config, tableId); if (!checkResult.success) { throw new Error(checkResult.error || 'Failed to check field configuration'); } if (!checkResult.needsFix) { return { success: true, message: 'No fix needed - all options are already present', currentOptions: checkResult.currentOptions }; } if (checkResult.fieldType !== 'SingleSelect') { return { success: false, error: `Cannot fix field type ${checkResult.fieldType}. Only SingleSelect fields can be updated.` }; } // Update the field to include all required options const fieldId = checkResult.fieldId; const currentOptions = checkResult.currentOptions || []; const requiredOptions = ['Active', 'Inactive', 'Pending', 'Expired']; // Create options array with all required values const optionsToSet = requiredOptions.map((option, index) => ({ title: option, color: getStatusColor(option), order: index + 1 })); console.log('[fixMembershipStatusField] Updating field with options:', optionsToSet); // Update the field via NocoDB API const updateResult = await $fetch(`${config.url}/api/v2/tables/${tableId}/columns/${fieldId}`, { method: 'PATCH', headers: { "xc-token": config.token, "Content-Type": "application/json" }, body: { colOptions: { options: optionsToSet } } }); console.log('[fixMembershipStatusField] Field updated successfully'); return { success: true, message: 'Membership Status field updated successfully', addedOptions: checkResult.missingOptions, allOptions: requiredOptions }; } catch (error: any) { console.error('[fixMembershipStatusField] Error:', error); return { success: false, error: error.message || 'Failed to fix field configuration' }; } } function getStatusColor(status: string): string { const colors = { 'Active': '#22c55e', // Green 'Inactive': '#6b7280', // Gray 'Pending': '#f59e0b', // Yellow 'Expired': '#ef4444' // Red }; return colors[status as keyof typeof colors] || '#6b7280'; }