Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | 1x 1x 4x 4x 4x 1x 1x 3x 1x 2x 2x 1x 1x 1x 5x 5x 5x 1x 1x 4x 3x 1x 1x 2x 2x 2x 2x 2x 2x 1x 2x 1x 1x 6x 6x 6x 6x 1x 1x 5x 5x 5x 4x 3x 3x 3x 2x 2x 1x 2x 1x 4x 1x 1x | import { Request, Response } from "express";
import { signupManualUser } from "@deliverables.org/helpers";
import { getItem, deleteItem, addItem, getByID } from "@deliverables.org/database";
import { v4 as uuidv4 } from "uuid";
import { sendWhatsAppMessage, createNotificationTemplate } from "@deliverables.org/helpers"
const TABLE_NAME = "Deliverables";
export const userController = {
manualSignup: async (req: Request, res: Response) => {
try {
const { name, phone, complexId, unitNumber, email } = req.body;
if (!name || !phone || !complexId) {
res.status(400).json({ message: "Missing required fields: name, phone, complexId" });
return;
}
const user = await signupManualUser(name, phone, complexId, unitNumber, email);
res.status(201).json({ success: true, user });
} catch (error: any) {
console.error("Manual signup error:", error);
if (error.message === "User with this phone number already exists.") {
res.status(409).json({ message: error.message });
return;
}
res.status(500).json({ message: "Internal server error" });
}
},
deleteUser: async (req: Request, res: Response) => {
try {
const { complexId, userId } = req.params;
if (!complexId || !userId) {
res.status(400).json({ message: "Missing complexId or userId" });
return;
}
// 1. Get User to find phone number
const userItem = await getItem({
TableName: TABLE_NAME,
Key: { PK: `COMPLEX#${complexId}`, SK: `USER#${userId}` }
});
if (!userItem.Item) {
res.status(404).json({ message: "User not found" });
return;
}
const phone = userItem.Item.phone;
// 2. Delete User Item
await deleteItem({
TableName: TABLE_NAME,
Key: { PK: `COMPLEX#${complexId}`, SK: `USER#${userId}` }
});
// 3. Delete Phone Lookup
// We now use a unique SK per complex: USER_LOOKUP#{complexId}
Eif (phone) {
// Delete the specific lookup for this complex
await deleteItem({
TableName: TABLE_NAME,
Key: { PK: `PHONE#${phone}`, SK: `USER_LOOKUP#${complexId}` }
});
// Optional: Also try to delete the legacy lookup (SK: "USER_LOOKUP") if it points to this user
// This cleans up old data as we migrate
const legacyLookup = await getItem({
TableName: TABLE_NAME,
Key: { PK: `PHONE#${phone}`, SK: "USER_LOOKUP" }
});
if (legacyLookup.Item && legacyLookup.Item.userId === userId) {
await deleteItem({
TableName: TABLE_NAME,
Key: { PK: `PHONE#${phone}`, SK: "USER_LOOKUP" }
});
}
}
res.status(200).json({ success: true });
} catch (error) {
console.error("Delete user error:", error);
res.status(500).json({ message: "Internal server error" });
}
},
addPackageToUser: async (req: Request, res: Response) => {
try {
const userId = req.params.userId as string;
const { packageData, notify } = req.body;
if (!userId || !packageData) {
res.status(400).json({ message: "Missing userId or packageData" });
return;
}
const packageId = uuidv4();
const newItem = {
PK: `USER#${userId}`,
SK: `PACKAGE#${packageId}`,
type: 'package',
id: packageId,
...packageData,
delivered: false,
timeStamp: new Date().toISOString()
};
await addItem({
TableName: TABLE_NAME,
Item: newItem
});
if (notify) {
// We need to find the user's phone number.
// Since we only have userId, and users are stored under COMPLEX#<complexId>, SK: USER#<userId>
// We might need to query by GSI if we don't have complexId.
// However, let's assume we can find the user via GSI or if we pass complexId.
// Actually, looking at deleteUser, it requires complexId.
// Let's check if we can get user by ID using getByID helper if it exists or GSI.
// dbHelper has getByID!
const userResult = await getByID(userId);
const user = userResult.Items && userResult.Items.length > 0 ? userResult.Items[0] : null;
if (user && user.phone) {
let phone = user.phone;
if (!phone.startsWith("whatsapp:")) {
phone = "whatsapp:" + phone;
}
await sendWhatsAppMessage(phone, "", createNotificationTemplate(user.name));
} else {
console.warn(`User ${userId} not found or no phone number for notification.`);
}
}
res.status(201).json({ success: true, packageId });
} catch (error) {
console.error("Add package error:", error);
res.status(500).json({ message: "Internal server error" });
}
}
};
export default userController;
|