This commit is contained in:
zramsay 2025-03-11 18:38:05 -04:00
parent 29c6f9389b
commit 7239fd45f4

View File

@ -134,22 +134,23 @@ export async function awardPointsForImage(
};
}
// If userId is an email, use it for consistent storage
if (userId.includes('@')) {
console.log('userId is an email, using it as the email field');
// But keep the userId as is for consistent UUID generation
// Log what email and userId we're starting with
console.log('Award points starting values:', { userId, email });
// Make sure we have a valid email - NOT a generated one
if (email === 'unknown@example.com' || email.endsWith('@user.wildlife.app')) {
console.log('WARNING: Using a synthetic email address:', email);
}
// If email is missing but userId looks like an email, use that
if (!email && userId.includes('@')) {
email = userId;
console.log('Using userId as email since it contains @:', email);
}
// Ensure we have a valid email
// Always prefer the email parameter directly from the authentication system
if (!email || email === 'unknown@example.com') {
email = userId.includes('@') ? userId : `${userId}@user.wildlife.app`;
console.log('Generated proper email for points system:', email);
if (userId.includes('@')) {
email = userId;
console.log('Using userId as email since it looks like an email:', email);
} else {
// This should be very rare - only if both auth email and userId are invalid
console.log('WARNING: Both userId and email are invalid or missing');
}
}
// Convert userId to UUID format
@ -201,38 +202,87 @@ export async function awardPointsForImage(
console.log('Creating point transaction for user:', userIdUUID);
// Try to create transaction using RPC first with admin client
const { data: transactionData, error: rpcError } = await supabaseAdmin
.rpc('create_point_transaction', {
user_id_param: userIdUUID,
points_param: POINTS.IMAGE_UPLOAD,
transaction_type_param: 'image_upload',
image_hash_param: imageHash,
image_url_param: imageUrl,
description_param: description,
animal_type_param: animalType
});
if (rpcError) {
console.log('Info: Could not create transaction via RPC, trying direct insert:', rpcError.message);
// Fallback to direct insert with admin client
console.log('Attempting direct insert for transaction...');
const { error: transactionError } = await supabaseAdmin
.from('point_transactions')
.insert({
user_id: userIdUUID,
points: POINTS.IMAGE_UPLOAD,
transaction_type: 'image_upload',
image_hash: imageHash,
image_url: imageUrl,
description,
animal_type: animalType,
created_at: new Date().toISOString()
// We'll try these approaches in sequence, with detailed logging
let transactionCreated = false;
// 1. Try to create transaction using RPC first with admin client
try {
console.log('Attempting to create transaction via RPC...');
const { data: transactionData, error: rpcError } = await supabaseAdmin
.rpc('create_point_transaction', {
user_id_param: userIdUUID,
points_param: POINTS.IMAGE_UPLOAD,
transaction_type_param: 'image_upload',
image_hash_param: imageHash,
image_url_param: imageUrl,
description_param: description,
animal_type_param: animalType
});
if (transactionError) {
console.warn('Direct transaction insert also failed:', transactionError.message);
if (!rpcError) {
console.log('Successfully created transaction via RPC:', transactionData);
transactionCreated = true;
} else {
console.log('Could not create transaction via RPC:', rpcError.message);
}
} catch (error) {
console.error('Exception in RPC transaction creation:', error);
}
// 2. Fallback to direct insert with admin client
if (!transactionCreated) {
try {
console.log('Attempting direct insert for transaction...');
const { data: insertData, error: transactionError } = await supabaseAdmin
.from('point_transactions')
.insert({
user_id: userIdUUID,
points: POINTS.IMAGE_UPLOAD,
transaction_type: 'image_upload',
image_hash: imageHash,
image_url: imageUrl,
description,
animal_type: animalType
})
.select()
.single();
if (transactionError) {
console.warn('Direct transaction insert failed:', transactionError.message);
} else {
console.log('Successfully created transaction via direct insert:', insertData);
transactionCreated = true;
}
} catch (error) {
console.error('Exception in direct transaction insert:', error);
}
}
// 3. Last resort insert with minimal fields
if (!transactionCreated) {
try {
console.log('Attempting minimal transaction insert as last resort...');
const { error: minimalError } = await supabaseAdmin
.from('point_transactions')
.insert({
user_id: userIdUUID,
points: POINTS.IMAGE_UPLOAD,
transaction_type: 'image_upload',
image_hash: imageHash
});
if (minimalError) {
console.warn('Even minimal transaction insert failed:', minimalError.message);
return {
success: false,
message: 'Failed to record points transaction after multiple attempts'
};
} else {
console.log('Successfully created minimal transaction');
transactionCreated = true;
}
} catch (error) {
console.error('Exception in minimal transaction insert:', error);
return {
success: false,
message: 'Failed to record points transaction'
@ -245,44 +295,89 @@ export async function awardPointsForImage(
let pointsUpdated = false;
// Try RPC method first with admin client
const { error: updateError } = await supabaseAdmin.rpc('increment_user_points', {
user_id_param: userIdUUID,
points_param: POINTS.IMAGE_UPLOAD
});
if (!updateError) {
pointsUpdated = true;
} else {
console.log('Info: Could not update points via RPC, trying direct update:', updateError.message);
// Fallback: Direct update with admin client
// 1. Try RPC method first with admin client
try {
console.log('Attempting to update points via RPC...');
const { data: rpcData, error: updateError } = await supabaseAdmin.rpc('increment_user_points', {
user_id_param: userIdUUID,
points_param: POINTS.IMAGE_UPLOAD
});
if (!updateError) {
console.log('Successfully updated points via RPC:', rpcData);
pointsUpdated = true;
} else {
console.log('Could not update points via RPC:', updateError.message);
}
} catch (error) {
console.error('Exception in RPC points update:', error);
}
// 2. Fallback: Direct update with admin client
if (!pointsUpdated) {
try {
console.log('Attempting direct update for points...');
// Get current points first with admin client
const { data: currentPointsData } = await supabaseAdmin
const { data: currentPointsData, error: selectError } = await supabaseAdmin
.from('user_points')
.select('total_points')
.eq('user_id', userIdUUID)
.maybeSingle();
const currentPoints = currentPointsData?.total_points || 0;
// Then update with new total with admin client
const { error: fallbackError } = await supabaseAdmin
if (selectError) {
console.warn('Could not get current points:', selectError.message);
} else {
console.log('Current points data:', currentPointsData);
const currentPoints = currentPointsData?.total_points || 0;
const newPoints = currentPoints + POINTS.IMAGE_UPLOAD;
console.log(`Updating points from ${currentPoints} to ${newPoints}`);
// Then update with new total with admin client
const { data: updateData, error: fallbackError } = await supabaseAdmin
.from('user_points')
.update({
total_points: newPoints,
updated_at: new Date().toISOString()
})
.eq('user_id', userIdUUID)
.select()
.single();
if (!fallbackError) {
console.log('Successfully updated points via direct update:', updateData);
pointsUpdated = true;
} else {
console.warn('Direct points update failed:', fallbackError.message);
}
}
} catch (err) {
console.error('Exception in direct points update:', err);
}
}
// 3. Last resort: Force an update to 1 point if this is their first transaction
if (!pointsUpdated) {
try {
console.log('Attempting force update as last resort...');
const { error: forceError } = await supabaseAdmin
.from('user_points')
.update({
total_points: currentPoints + POINTS.IMAGE_UPLOAD,
total_points: 1, // Force to at least 1 point
updated_at: new Date().toISOString()
})
.eq('user_id', userIdUUID);
if (!fallbackError) {
if (!forceError) {
console.log('Successfully forced points update to 1');
pointsUpdated = true;
} else {
console.warn('Direct points update also failed:', fallbackError.message);
console.warn('Even forced points update failed:', forceError.message);
}
} catch (err) {
console.warn('Error in points update fallback:', err);
console.error('Exception in forced points update:', err);
}
}
@ -345,19 +440,15 @@ export async function getUserPoints(userId: string) {
.eq('user_id', userIdUUID)
.maybeSingle();
// If we got an empty result or a not found error, try to initialize the user
// If we got an empty result or a not found error, the user doesn't exist yet
if (!userExists || (checkError && checkError.code === 'PGRST116')) {
// Check if the userId is an email
let email;
if (userId.includes('@')) {
email = userId; // Use the userId as email if it is one
console.log('Using email from userId for initialization:', email);
} else {
// Use a real email format if possible - but don't use example.com
email = userId.includes('@') ? userId : `${userId}@user.wildlife.app`;
console.log('Using generated email for initialization:', email);
}
console.log('User does not exist yet in user_points table, need to initialize');
// At this point, the user should already be authenticated, so we should have their real email
// But if we don't, we need to handle that case
const email = userId.includes('@') ? userId : `${userId}@user.wildlife.app`;
console.log('Initializing user with:', { userId, email });
await initializeUser(userId, email);
}
} catch (initError) {