Skip to content

Commit 8204e2d

Browse files
committed
feat(database): implement MembersService and TablesService classes for group management and database setup
- Add `MembersService`: - Implement `update` method to update group members while validating input. - Implement `add` method to add new members to a group with input validation and error handling. - Utilize `DatabaseService` and `GroupService` for modular design and efficient group member updates. - Add `TablesService`: - Implement `initialTables` method to set up initial database tables using an external SQL file. - Implement `seedTables` method to seed the database with initial data, including checks to prevent duplicate seeding. - Leverage a `ConnectionPool` for database connections. - Decorate methods with a `Catch` decorator for error handling and improved debugging. These enhancements provide comprehensive group management, database setup, and seeding functionalities, ensuring maintainability and scalability of the system.
1 parent 00bd82b commit 8204e2d

2 files changed

Lines changed: 104 additions & 0 deletions

File tree

src/database/service/Members.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { PoolClient } from 'pg';
2+
import { Group } from '../../types/database/TablesTypes'; // Adjust this import based on your actual types
3+
import { GroupService } from '../models/Group';
4+
import { DatabaseService } from './Databas';
5+
6+
export class MembersService {
7+
private group_by_id: Function;
8+
private _db: DatabaseService;
9+
constructor(private _client: PoolClient) {
10+
const groupService = new GroupService(_client);
11+
this.group_by_id = groupService.getByGroupId;
12+
this._db = new DatabaseService(_client);
13+
}
14+
async update(groupId: number, newMember: number | string): Promise<Group> {
15+
const group = await this.group_by_id(groupId);
16+
if (!group) {
17+
throw new Error(`Group with ID ${groupId} not found`);
18+
}
19+
20+
// Convert newMember to a number and ensure it's a valid member
21+
const memberId = Number(newMember);
22+
if (isNaN(memberId)) {
23+
throw new Error('Invalid member ID');
24+
}
25+
26+
const members = group.members.map(Number);
27+
if (!members.includes(memberId)) {
28+
members.push(memberId);
29+
}
30+
const updatedGroup = await this._db.update<Group>('Group', { members: members }, { group_id: groupId });
31+
return updatedGroup;
32+
}
33+
34+
// Add a new member to the group
35+
async add(groupId: number, newMember: number | string): Promise<Group> {
36+
const group = await this.group_by_id(groupId);
37+
if (!group) {
38+
throw new Error(`Group with ID ${groupId} not found`);
39+
}
40+
41+
// Ensure the new member ID is valid
42+
const memberId = Number(newMember);
43+
if (isNaN(memberId)) {
44+
throw new Error('Invalid member ID');
45+
}
46+
47+
// Check if the member is already in the group
48+
if (group.members.includes(memberId)) {
49+
throw new Error('Member already exists in the group');
50+
}
51+
52+
// Add the new member
53+
const updatedMembers = [...group.members, memberId];
54+
55+
const query = `
56+
UPDATE "Group"
57+
SET members = $1, updated_at = NOW()
58+
WHERE group_id = $2
59+
RETURNING *;
60+
`;
61+
const values = [updatedMembers, groupId];
62+
const result = await this._client.query(query, values);
63+
64+
// Return the updated group
65+
return result.rows[0];
66+
}
67+
}

src/database/service/Tables.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Catch } from '../../decorators/Catch';
2+
import { ConnectionPool } from '../ConnectionPool';
3+
import * as path from 'path';
4+
import * as fs from 'fs/promises';
5+
export class TablesService {
6+
constructor(private _connectionPool: ConnectionPool) {}
7+
@Catch({
8+
category: 'Database',
9+
message: 'Failed to set up initial tables.',
10+
statusCode: 500,
11+
})
12+
async initialTables() {
13+
const client = await this._connectionPool.getClient();
14+
const sqlFilePath = path.join(__dirname, '..', './sql/Tables.sql');
15+
const sql = await fs.readFile(sqlFilePath, 'utf-8');
16+
await client.query(sql);
17+
console.log('Initial tables have been set up successfully.');
18+
}
19+
@Catch({
20+
category: 'Database',
21+
message: 'Failed to seed tables.',
22+
statusCode: 500,
23+
})
24+
async seedTables() {
25+
const client = await this._connectionPool.getClient();
26+
const result = await client.query(`SELECT COUNT(*) FROM "User";`);
27+
const userCount = parseInt(result.rows[0].count, 10);
28+
if (userCount > 0) {
29+
console.log('The tables have already been seeded. Skipping seeding process.');
30+
return; // Skip seeding if there's already data in the User table
31+
}
32+
const sqlFilePath = path.join(__dirname, '..', './sql/seed/SeedDataTables.sql');
33+
const sql = await fs.readFile(sqlFilePath, 'utf-8');
34+
await client.query(sql);
35+
console.log('All tables have been seeded successfully.');
36+
}
37+
}

0 commit comments

Comments
 (0)