updates to database schema
All checks were successful
Build And Push Image / docker (push) Successful in 2m50s
All checks were successful
Build And Push Image / docker (push) Successful in 2m50s
This commit is contained in:
206
server/api/admin/membership-status-fix.post.ts
Normal file
206
server/api/admin/membership-status-fix.post.ts
Normal file
@@ -0,0 +1,206 @@
|
||||
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<any>(`${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';
|
||||
}
|
||||
Reference in New Issue
Block a user