feat: Migrate Street and Task models from MongoDB to CouchDB

- Replace Street model with CouchDB-based implementation
- Replace Task model with CouchDB-based implementation
- Update routes to use new model interfaces
- Handle geospatial queries with CouchDB design documents
- Maintain adoption functionality and middleware
- Use denormalized document structure with embedded data
- Update test files to work with new models
- Ensure API compatibility while using CouchDB underneath

🤖 Generated with [AI Assistant]

Co-Authored-By: AI Assistant <noreply@ai-assistant.com>
This commit is contained in:
William Valentin
2025-11-01 13:12:34 -07:00
parent 2961107136
commit 7c7bc954ef
14 changed files with 1943 additions and 928 deletions

View File

@@ -20,17 +20,10 @@ async function createTestUser(overrides = {}) {
const userData = { ...defaultUser, ...overrides };
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(userData.password, salt);
const user = await User.create({
name: userData.name,
email: userData.email,
password: hashedPassword,
});
const user = await User.create(userData);
const token = jwt.sign(
{ user: { id: user.id } },
{ user: { id: user._id } },
process.env.JWT_SECRET,
{ expiresIn: 3600 }
);
@@ -65,9 +58,21 @@ async function createTestStreet(userId, overrides = {}) {
},
city: 'Test City',
state: 'TS',
adoptedBy: userId,
};
// Add adoptedBy if userId is provided
if (userId) {
const user = await User.findById(userId);
if (user) {
defaultStreet.adoptedBy = {
userId: user._id,
name: user.name,
profilePicture: user.profilePicture || ''
};
defaultStreet.status = 'adopted';
}
}
const street = await Street.create({ ...defaultStreet, ...overrides });
return street;
}
@@ -76,14 +81,34 @@ async function createTestStreet(userId, overrides = {}) {
* Create a test task
*/
async function createTestTask(userId, streetId, overrides = {}) {
// Get street details for embedding
const street = await Street.findById(streetId);
const streetData = {
streetId: street._id,
name: street.name,
location: street.location
};
const defaultTask = {
street: streetId,
street: streetData,
description: 'Test task description',
type: 'cleaning',
createdBy: userId,
status: 'pending',
};
// Add completedBy if userId is provided
if (userId) {
const user = await User.findById(userId);
if (user) {
defaultTask.completedBy = {
userId: user._id,
name: user.name,
profilePicture: user.profilePicture || ''
};
defaultTask.status = 'completed';
}
}
const task = await Task.create({ ...defaultTask, ...overrides });
return task;
}
@@ -152,13 +177,22 @@ async function createTestReport(userId, streetId, overrides = {}) {
* Clean up all test data
*/
async function cleanupDatabase() {
await User.deleteMany({});
await Street.deleteMany({});
await Task.deleteMany({});
await Post.deleteMany({});
await Event.deleteMany({});
await Reward.deleteMany({});
await Report.deleteMany({});
const couchdbService = require('../../services/couchdbService');
await couchdbService.initialize();
// Delete all documents by type
const types = ['user', 'street', 'task', 'post', 'event', 'reward', 'report', 'badge', 'user_badge', 'point_transaction'];
for (const type of types) {
try {
const docs = await couchdbService.findByType(type);
for (const doc of docs) {
await couchdbService.deleteDocument(doc._id, doc._rev);
}
} catch (error) {
console.error(`Error cleaning up ${type}s:`, error.message);
}
}
}
module.exports = {