update 9/20/25
This commit is contained in:
358
functions/migrated_functions.js
Normal file
358
functions/migrated_functions.js
Normal file
@@ -0,0 +1,358 @@
|
||||
// Complete Migration Helper Script for remaining functions
|
||||
// This script contains the migrated versions of key functions
|
||||
|
||||
const { executeQuery, executeTransaction } = require('./database');
|
||||
|
||||
/**
|
||||
* Get User Organizations - Migrated to PostgreSQL
|
||||
*/
|
||||
exports.getUserOrganizations = onRequest({cors: true}, async (req, res) => {
|
||||
const authContext = await validateAuthAndGetContext(req, res);
|
||||
if (!authContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.method !== "GET") {
|
||||
return res.status(405).json({ error: "Method not allowed" });
|
||||
}
|
||||
|
||||
try {
|
||||
// Get user's organizations
|
||||
const userOrgsRows = await executeQuery(
|
||||
`SELECT uo.organization_id as orgId, uo.role, uo.joined_at as joinedAt,
|
||||
uo.onboarding_completed as onboardingCompleted, o.name
|
||||
FROM user_organizations uo
|
||||
JOIN organizations o ON uo.organization_id = o.id
|
||||
WHERE uo.user_id = $1`,
|
||||
[authContext.userId]
|
||||
);
|
||||
|
||||
const organizations = userOrgsRows.map(row => ({
|
||||
orgId: row.orgid,
|
||||
name: row.name,
|
||||
role: row.role,
|
||||
onboardingCompleted: row.onboardingcompleted,
|
||||
joinedAt: row.joinedat
|
||||
}));
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
organizations,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Get user organizations error:", error);
|
||||
res.status(500).json({ error: "Failed to get user organizations" });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get Organization Data - Migrated to PostgreSQL
|
||||
*/
|
||||
exports.getOrgData = onRequest({cors: true}, async (req, res) => {
|
||||
const authContext = await validateAuthAndGetContext(req, res);
|
||||
if (!authContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.method !== "GET") {
|
||||
return res.status(405).json({ error: "Method not allowed" });
|
||||
}
|
||||
|
||||
try {
|
||||
const orgId = authContext.orgId;
|
||||
if (!orgId) {
|
||||
return res.status(400).json({ error: "User has no associated organizations" });
|
||||
}
|
||||
|
||||
// Get organization data
|
||||
const orgRows = await executeQuery(
|
||||
'SELECT * FROM organizations WHERE id = $1',
|
||||
[orgId]
|
||||
);
|
||||
|
||||
if (orgRows.length === 0) {
|
||||
return res.status(404).json({ error: "Organization not found" });
|
||||
}
|
||||
|
||||
const orgData = {
|
||||
id: orgRows[0].id,
|
||||
name: orgRows[0].name,
|
||||
industry: orgRows[0].industry,
|
||||
description: orgRows[0].description,
|
||||
mission: orgRows[0].mission,
|
||||
vision: orgRows[0].vision,
|
||||
values: orgRows[0].values,
|
||||
onboardingCompleted: orgRows[0].onboarding_completed,
|
||||
onboardingData: orgRows[0].onboarding_data,
|
||||
createdAt: orgRows[0].created_at,
|
||||
updatedAt: orgRows[0].updated_at
|
||||
};
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
org: orgData
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Get org data error:", error);
|
||||
res.status(500).json({ error: "Failed to get organization data" });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Update Organization Data - Migrated to PostgreSQL
|
||||
*/
|
||||
exports.updateOrgData = onRequest({cors: true}, async (req, res) => {
|
||||
const authContext = await validateAuthAndGetContext(req, res);
|
||||
if (!authContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.method !== "PUT") {
|
||||
return res.status(405).json({ error: "Method not allowed" });
|
||||
}
|
||||
|
||||
try {
|
||||
const { data } = req.body;
|
||||
|
||||
if (!data) {
|
||||
return res.status(400).json({ error: "Data is required" });
|
||||
}
|
||||
|
||||
const orgId = authContext.orgId;
|
||||
if (!orgId) {
|
||||
return res.status(400).json({ error: "User has no associated organizations" });
|
||||
}
|
||||
|
||||
// Build dynamic update query
|
||||
const updateFields = [];
|
||||
const values = [];
|
||||
let paramCount = 1;
|
||||
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
// Convert camelCase to snake_case for database columns
|
||||
const dbKey = key.replace(/([A-Z])/g, '_$1').toLowerCase();
|
||||
updateFields.push(`${dbKey} = $${paramCount}`);
|
||||
values.push(typeof value === 'object' ? JSON.stringify(value) : value);
|
||||
paramCount++;
|
||||
}
|
||||
|
||||
if (updateFields.length === 0) {
|
||||
return res.status(400).json({ error: "No valid fields to update" });
|
||||
}
|
||||
|
||||
updateFields.push(`updated_at = $${paramCount}`);
|
||||
values.push(Date.now());
|
||||
values.push(orgId); // for WHERE clause
|
||||
|
||||
const query = `UPDATE organizations SET ${updateFields.join(', ')} WHERE id = $${paramCount + 1}`;
|
||||
await executeQuery(query, values);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: "Organization data updated successfully"
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Update org data error:", error);
|
||||
res.status(500).json({ error: "Failed to update organization data" });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get Employees - Migrated to PostgreSQL
|
||||
*/
|
||||
exports.getEmployees = onRequest({cors: true}, async (req, res) => {
|
||||
const authContext = await validateAuthAndGetContext(req, res);
|
||||
if (!authContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.method !== "GET") {
|
||||
return res.status(405).json({ error: "Method not allowed" });
|
||||
}
|
||||
|
||||
try {
|
||||
const orgId = authContext.orgId;
|
||||
if (!orgId) {
|
||||
return res.status(400).json({ error: "User has no associated organizations" });
|
||||
}
|
||||
|
||||
// Get all employees
|
||||
const employeesRows = await executeQuery(
|
||||
'SELECT * FROM employees WHERE organization_id = $1 AND status != $2 ORDER BY name',
|
||||
[orgId, 'deleted']
|
||||
);
|
||||
|
||||
const employees = employeesRows.map(row => ({
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
email: row.email,
|
||||
role: row.role,
|
||||
department: row.department,
|
||||
status: row.status,
|
||||
joinedAt: row.joined_at,
|
||||
createdAt: row.created_at
|
||||
}));
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
employees
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Get employees error:", error);
|
||||
res.status(500).json({ error: "Failed to get employees" });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Create Invitation - Migrated to PostgreSQL
|
||||
*/
|
||||
exports.createInvitation = onRequest({cors: true}, async (req, res) => {
|
||||
const authContext = await validateAuthAndGetContext(req, res);
|
||||
if (!authContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.method !== "POST") {
|
||||
return res.status(405).json({ error: "Method not allowed" });
|
||||
}
|
||||
|
||||
try {
|
||||
const { name, email, role = "employee", department } = req.body;
|
||||
|
||||
if (!email || !name) {
|
||||
return res.status(400).json({ error: "Name and email are required" });
|
||||
}
|
||||
|
||||
const orgId = authContext.orgId;
|
||||
if (!orgId) {
|
||||
return res.status(400).json({ error: "User has no associated organizations" });
|
||||
}
|
||||
|
||||
// Generate invite code
|
||||
const code = Math.random().toString(36).substring(2, 15);
|
||||
|
||||
// Generate employee ID
|
||||
const employeeId = `emp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
||||
const currentTime = Date.now();
|
||||
|
||||
// Create employee data
|
||||
const employeeData = {
|
||||
id: employeeId,
|
||||
name: name.trim(),
|
||||
email: email.trim(),
|
||||
role: role?.trim() || "employee",
|
||||
department: department?.trim() || "General",
|
||||
status: "invited",
|
||||
inviteCode: code
|
||||
};
|
||||
|
||||
await executeTransaction(async (client) => {
|
||||
// Store invitation
|
||||
if (process.env.USE_NEON_SERVERLESS === 'true') {
|
||||
await client(
|
||||
`INSERT INTO invites (code, organization_id, email, employee_data, status, created_at, expires_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)`,
|
||||
[
|
||||
code, orgId, email, JSON.stringify(employeeData), 'pending',
|
||||
currentTime, currentTime + (7 * 24 * 60 * 60 * 1000) // 7 days
|
||||
]
|
||||
);
|
||||
|
||||
// Create employee record
|
||||
await client(
|
||||
`INSERT INTO employees (id, organization_id, name, email, role, department, status, invite_code, created_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
|
||||
[employeeId, orgId, name.trim(), email.trim(), role || 'employee', department || 'General', 'invited', code, currentTime]
|
||||
);
|
||||
} else {
|
||||
await client.query(
|
||||
`INSERT INTO invites (code, organization_id, email, employee_data, status, created_at, expires_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)`,
|
||||
[
|
||||
code, orgId, email, JSON.stringify(employeeData), 'pending',
|
||||
currentTime, currentTime + (7 * 24 * 60 * 60 * 1000) // 7 days
|
||||
]
|
||||
);
|
||||
|
||||
// Create employee record
|
||||
await client.query(
|
||||
`INSERT INTO employees (id, organization_id, name, email, role, department, status, invite_code, created_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
|
||||
[employeeId, orgId, name.trim(), email.trim(), role || 'employee', department || 'General', 'invited', code, currentTime]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Generate invite links
|
||||
const baseUrl = process.env.CLIENT_URL || 'https://auditly-one.vercel.app';
|
||||
const inviteLink = `${baseUrl}/#/employee-form/${code}`;
|
||||
|
||||
console.log(`📧 Invite link: ${inviteLink}`);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
code,
|
||||
employee: employeeData,
|
||||
inviteLink,
|
||||
message: "Invitation sent successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Create invitation error:", error);
|
||||
res.status(500).json({ error: "Failed to create invitation" });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get Invitation Status - Migrated to PostgreSQL
|
||||
*/
|
||||
exports.getInvitationStatus = onRequest({cors: true}, async (req, res) => {
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.status(204).send('');
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.method !== "GET") {
|
||||
return res.status(405).json({ error: "Method not allowed" });
|
||||
}
|
||||
|
||||
const { code } = req.query;
|
||||
|
||||
if (!code) {
|
||||
return res.status(400).json({ error: "Invitation code is required" });
|
||||
}
|
||||
|
||||
try {
|
||||
const inviteRows = await executeQuery(
|
||||
'SELECT * FROM invites WHERE code = $1',
|
||||
[code]
|
||||
);
|
||||
|
||||
if (inviteRows.length === 0) {
|
||||
return res.status(404).json({ error: "Invitation not found" });
|
||||
}
|
||||
|
||||
const invite = inviteRows[0];
|
||||
|
||||
// Check if expired
|
||||
if (Date.now() > invite.expires_at) {
|
||||
return res.status(400).json({ error: "Invitation has expired" });
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
used: invite.status !== 'pending',
|
||||
employee: invite.employee_data,
|
||||
invite: {
|
||||
...invite,
|
||||
employee: invite.employee_data
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Get invitation status error:", error);
|
||||
res.status(500).json({ error: "Failed to get invitation status" });
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
// Export these functions so they can be used to replace the existing ones
|
||||
};
|
||||
Reference in New Issue
Block a user