// server/api/admin/fix-payment-dates.post.ts export default defineEventHandler(async (event) => { try { const { getMembers, updateMember } = await import('~/server/utils/nocodb'); console.log('[api/admin/fix-payment-dates.post] Starting payment date migration...'); // Get all members const membersResponse = await getMembers(); const members = membersResponse?.list || []; if (members.length === 0) { return { success: true, message: 'No members found to process', stats: { total: 0, fixed: 0, skipped: 0, failed: 0 } }; } const results = { total: members.length, fixed: 0, skipped: 0, failed: 0, errors: [] as any[] }; // Process each member for (const member of members) { try { // Check if member has membership_date_paid but no payment_due_date if (member.membership_date_paid && !member.payment_due_date) { const paymentDate = new Date(member.membership_date_paid); // Calculate payment_due_date as 1 year from payment date const dueDate = new Date(paymentDate); dueDate.setFullYear(dueDate.getFullYear() + 1); const dueDateStr = dueDate.toISOString().split('T')[0]; console.log(`[api/admin/fix-payment-dates.post] Fixing dates for ${member.first_name} ${member.last_name} (ID: ${member.Id})`); console.log(` Payment Date: ${member.membership_date_paid}`); console.log(` New Due Date: ${dueDateStr}`); // Update the member await updateMember(member.Id, { payment_due_date: dueDateStr }); results.fixed++; console.log(`[api/admin/fix-payment-dates.post] ✅ Fixed payment dates for member ${member.Id}`); } else if (member.membership_date_paid && member.payment_due_date) { // Member already has both dates, skip results.skipped++; console.log(`[api/admin/fix-payment-dates.post] Skipped member ${member.Id} - already has payment_due_date`); } else if (!member.membership_date_paid && !member.payment_due_date) { // Member hasn't paid yet, check if they're new (within grace period) if (member.member_since) { const joinDate = new Date(member.member_since); const gracePeriodEnd = new Date(joinDate); gracePeriodEnd.setMonth(gracePeriodEnd.getMonth() + 1); // 1 month grace period const now = new Date(); if (now < gracePeriodEnd) { // Still in grace period, set payment_due_date to end of grace period const dueDateStr = gracePeriodEnd.toISOString().split('T')[0]; await updateMember(member.Id, { payment_due_date: dueDateStr }); results.fixed++; console.log(`[api/admin/fix-payment-dates.post] Set grace period due date for new member ${member.Id}`); } else { // Past grace period, set due date to 1 year from join date const dueDate = new Date(joinDate); dueDate.setFullYear(dueDate.getFullYear() + 1); const dueDateStr = dueDate.toISOString().split('T')[0]; await updateMember(member.Id, { payment_due_date: dueDateStr }); results.fixed++; console.log(`[api/admin/fix-payment-dates.post] Set overdue date for member ${member.Id}`); } } else { results.skipped++; console.log(`[api/admin/fix-payment-dates.post] Skipped member ${member.Id} - no payment or join date`); } } else { results.skipped++; } } catch (error: any) { console.error(`[api/admin/fix-payment-dates.post] ❌ Failed to fix dates for member ${member.Id}:`, error); results.failed++; results.errors.push({ memberId: member.Id, name: `${member.first_name} ${member.last_name}`, error: error.message || 'Unknown error' }); } } const message = `Payment date migration complete!\n` + `Fixed: ${results.fixed} members\n` + `Skipped: ${results.skipped} members\n` + `Failed: ${results.failed} members`; console.log(`[api/admin/fix-payment-dates.post] ${message}`); return { success: results.failed === 0, message, stats: results }; } catch (error: any) { console.error('[api/admin/fix-payment-dates.post] Error:', error); throw createError({ statusCode: error.statusCode || 500, statusMessage: error.message || 'Failed to fix payment dates' }); } });