Skip to content

Commit

Permalink
feat: subscriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
tassyla committed Aug 23, 2024
1 parent 519beea commit 8572756
Show file tree
Hide file tree
Showing 33 changed files with 1,638 additions and 1,023 deletions.
2 changes: 2 additions & 0 deletions src/modules/groups/dtos/ICreateGroupDTO.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
interface ICreateGroupDTO {
name: string;
description: string;
super_adm_id: string;
subscription_id: string;
}

export default ICreateGroupDTO;
1 change: 1 addition & 0 deletions src/modules/groups/dtos/IUpdateGroupDTO.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
interface IUpdateGroupDTO {
name: string;
description: string;
}

export default IUpdateGroupDTO;
10 changes: 8 additions & 2 deletions src/modules/groups/infra/http/controller/GroupsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,19 @@ export default class GroupController {
public async create(req: Request, res: Response): Promise<Response> {
const {
name,
super_adm_id,
description,
subscription_id,
} = req.body;

const { id } = req.token;

const createGroup = container.resolve(CreateGroupService);

const group = await createGroup.execute({
name,
super_adm_id,
subscription_id,
description,
super_adm_id: id,
});

return res.status(201).json(group);
Expand Down Expand Up @@ -49,6 +54,7 @@ export default class GroupController {

const {
name,
description,

Check failure on line 57 in src/modules/groups/infra/http/controller/GroupsController.ts

View workflow job for this annotation

GitHub Actions / Check linting (20.11.1)

'description' is assigned a value but never used
} = req.body;

const updateGroup = container.resolve(UpdateGroupService);
Expand Down
12 changes: 6 additions & 6 deletions src/modules/groups/infra/http/routes/groups.routes.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Router } from 'express';

import ensureAuthenticated from '@shared/infra/http/middlewares/EnsureAuthenticated';
import GroupsController from '../controller/GroupsController';

const groupsRoutes = Router();

const groupsController = new GroupsController();

groupsRoutes.post('/register', groupsController.create);
groupsRoutes.get('/read', groupsController.readAll);
groupsRoutes.get('/read/:id', groupsController.readById);
groupsRoutes.patch('/update/:id', groupsController.update);
groupsRoutes.delete('/delete/:id', groupsController.delete);
groupsRoutes.post('/register', ensureAuthenticated, groupsController.create);
groupsRoutes.get('/read', ensureAuthenticated, groupsController.readAll);
groupsRoutes.get('/read/:id', ensureAuthenticated, groupsController.readById);
groupsRoutes.patch('/update/:id', ensureAuthenticated, groupsController.update);
groupsRoutes.delete('/delete/:id', ensureAuthenticated, groupsController.delete);

export default groupsRoutes;
1 change: 1 addition & 0 deletions src/modules/groups/infra/prisma/entities/groups.prisma
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
model Groups {
id String @id @default(uuid())
name String
description String
created_at DateTime @default(now())
updated_at DateTime @default(now())
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ export default class GroupsRepository implements IGroupsRepository {

public async create(data: ICreateGroupDTO & { include: { invited_users: { select: { email: true; name: true; }; }; }; }): Promise<Groups> {
const group = await this.ormRepository.create({
data,
data: {
name: data.name,
super_adm_id: data.super_adm_id,
subscription: {
connect: { id: data.subscription_id }

Check failure on line 21 in src/modules/groups/infra/prisma/repositories/GroupsRepository.ts

View workflow job for this annotation

GitHub Actions / Check linting (20.11.1)

Missing trailing comma
},
description: data.description,
},
include: {
invited_users: {
select: {
Expand Down
2 changes: 0 additions & 2 deletions src/modules/groups/repositories/IGroupsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import ICreateGroupDTO from '../dtos/ICreateGroupDTO';
import IUpdateGroupDTO from '../dtos/IUpdateGroupDTO';

interface IGroupsRepository {
// findByEmailWithRelations(email: string): Promise<Groups | null>;
// findByEmailPhoneOrCpf(email: string, phone: string, cpf: string): Promise<Groups | null>;
create(data: ICreateGroupDTO): Promise<Groups>;
findAll(): Promise<Groups[]>;
findById(id: string): Promise<Groups | null>;
Expand Down
28 changes: 25 additions & 3 deletions src/modules/groups/services/CreateGroupService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ import { Groups } from '@prisma/client';
import AppError from '@shared/errors/AppError';
import IUsersRepository from '@modules/users/repositories/IUsersRepository';
import IGroupsRepository from '../repositories/IGroupsRepository';

Check failure on line 5 in src/modules/groups/services/CreateGroupService.ts

View workflow job for this annotation

GitHub Actions / Check linting (20.11.1)

`../repositories/IGroupsRepository` import should occur after import of `@modules/invites/repositories/IInvitesRepository`
import ISubscriptionsRepository from '@modules/subscriptions/repositories/ISubscriptionsRepository';
import IInvitesRepository from '@modules/invites/repositories/IInvitesRepository';

interface IRequest {
name: string;
description: string;
super_adm_id: string;
subscription_id: string;
}

@injectable()
Expand All @@ -17,19 +21,37 @@ export default class CreateGroupService {

@inject('UsersRepository')
private usersRepository: IUsersRepository,

@inject('SubscriptionsRepository')
private subscriptionsRepository: ISubscriptionsRepository,

@inject('InvitesRepository')
private invitesRepository: IInvitesRepository,
) { }

public async execute({
name, super_adm_id,
name, description, super_adm_id, subscription_id

Check failure on line 33 in src/modules/groups/services/CreateGroupService.ts

View workflow job for this annotation

GitHub Actions / Check linting (20.11.1)

Missing trailing comma
}: IRequest): Promise<Groups> {
const userAlreadyExists = await this.usersRepository.findById(super_adm_id);
if (!userAlreadyExists) throw new AppError('User with this super_adm_id does not exist');

const group = this.groupsRepository.create({
const subscriptionAlreadyExists = await this.subscriptionsRepository.findById(subscription_id);
if (!subscriptionAlreadyExists) throw new AppError('Subscription with this id does not exist');

const groupAlreadyExists = await this.subscriptionsRepository.groupIsVinculated(subscription_id);
if (groupAlreadyExists) throw new AppError('This subscription is already vinculated to a group');

const group = await this.groupsRepository.create({
name,
description,
super_adm_id,
subscription_id,
});

return group;
const updatedGroup = await this.invitesRepository.defaultAdm(group.id, super_adm_id);

const subscription = await this.subscriptionsRepository.vinculateGroup(subscription_id, group.id);

Check failure on line 53 in src/modules/groups/services/CreateGroupService.ts

View workflow job for this annotation

GitHub Actions / Check linting (20.11.1)

'subscription' is assigned a value but never used

return updatedGroup;
}
}
43 changes: 41 additions & 2 deletions src/modules/invites/infra/http/controller/InvitesController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import CreateInviteService from '@modules/invites/services/CreateInviteService';
import ReadInvitesByGroupIdService from '@modules/invites/services/ReadInvitesByGroupIdService';
import DeleteInviteService from '@modules/invites/services/DeleteInviteService';
import AcceptInviteService from '@modules/invites/services/AcceptInviteService';
import RejectInviteService from '@modules/invites/services/RejectInviteService';
import TurnIntoAdmService from '@modules/invites/services/TurnIntoAdmService';

export default class InvitesController {
public async create(req: Request, res: Response): Promise<Response> {
Expand All @@ -13,9 +15,12 @@ export default class InvitesController {
email,
} = req.body;

const { id } = req.token;

const createInvite = container.resolve(CreateInviteService);

const group = await createInvite.execute({
id,
group_id,
email,
});
Expand All @@ -25,10 +30,12 @@ export default class InvitesController {

public async readAllInvitesByGroup(req: Request, res: Response): Promise<Response> {
const { group_id } = req.params;
const { id } = req.token;

const readUser = container.resolve(ReadInvitesByGroupIdService);

const user = await readUser.execute({
id,
group_id,
});

Expand All @@ -38,10 +45,12 @@ export default class InvitesController {
public async delete(req: Request, res: Response): Promise<Response> {
const { group_id } = req.params;
const { email } = req.body;
const { id } = req.token;

const deleteUser = container.resolve(DeleteInviteService);

const user = await deleteUser.execute({
id,
group_id,
email,
});
Expand All @@ -50,16 +59,46 @@ export default class InvitesController {
}

public async accept(req: Request, res: Response): Promise<Response> {
const { user_id } = req.params;
const { id } = req.token;
const { group_id } = req.body;

const acceptInvite = container.resolve(AcceptInviteService);

const group = await acceptInvite.execute({
user_id,
user_id: id,
group_id,
});

return res.status(201).json(group);
}

public async reject(req: Request, res: Response): Promise<Response> {
const { id } = req.token;
const { group_id } = req.body;

const rejectInvite = container.resolve(RejectInviteService);

const group = await rejectInvite.execute({
user_id: id,
group_id,
});

return res.status(201).json(group);
}

public async turnIntoAdm(req: Request, res: Response): Promise<Response> {
const { group_id } = req.body;
const { user_id } = req.params;
const { id } = req.token;

const turnIntoAdm = container.resolve(TurnIntoAdmService);

const group = await turnIntoAdm.execute({
id,
group_id,
user_id,
});

return res.status(201).json(group);
}
}
12 changes: 7 additions & 5 deletions src/modules/invites/infra/http/routes/invites.routes.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { Router } from 'express';

import ensureAuthenticated from '@shared/infra/http/middlewares/EnsureAuthenticated';
import InvitesController from '../controller/InvitesController';

const invitesRoutes = Router();

const invitesController = new InvitesController();

invitesRoutes.post('/register', invitesController.create);
invitesRoutes.get('/read/:group_id', invitesController.readAllInvitesByGroup);
invitesRoutes.delete('/delete/:group_id', invitesController.delete);
invitesRoutes.post('/accept/:user_id', invitesController.accept);
invitesRoutes.post('/register', ensureAuthenticated, invitesController.create);
invitesRoutes.get('/read/:group_id', ensureAuthenticated, invitesController.readAllInvitesByGroup);
invitesRoutes.delete('/delete/:group_id', ensureAuthenticated, invitesController.delete);
invitesRoutes.post('/accept', ensureAuthenticated, invitesController.accept);
invitesRoutes.post('/reject', ensureAuthenticated, invitesController.reject);
invitesRoutes.post('/registerAdm/:user_id', ensureAuthenticated, invitesController.turnIntoAdm);

export default invitesRoutes;
85 changes: 85 additions & 0 deletions src/modules/invites/infra/prisma/repositories/InvitesRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,4 +255,89 @@ export default class InvitesRepository implements IInvitesRepository {
},
});
}

async isAlreadyUser(group_id: string, user_id: string): Promise<Groups | null> {
return await prisma.groups.findUnique({
where: {
id: group_id,
users: {
some: { id: user_id },
},
},
});
}

async isAlreadyAdm(group_id: string, id: string): Promise<Groups | null> {
return await prisma.groups.findUnique({
where: {
id: group_id,
adms: {
some: { id },
},
},
});
}

async turnIntoAdm(group_id: string, user_id: string): Promise<Groups> {
return await prisma.groups.update({
where: {
id: group_id,
},
data: {
users: {
disconnect: {
id: user_id,
},
},
adms: {
connect: {
id: user_id,
},
},
},
include: {
users: {
select: {
email: true,
name: true,
},
},
adms: {
select: {
email: true,
name: true,
},
},
},
});
}

async defaultAdm(group_id: string, user_id: string): Promise<Groups> {
return await prisma.groups.update({
where: {
id: group_id,
},
data: {
adms: {
connect: {
id: user_id,
},
},
},
include: {
users: {
select: {
email: true,
name: true,
},
},
adms: {
select: {
email: true,
name: true,
},
},
},
});
}
}
4 changes: 4 additions & 0 deletions src/modules/invites/repositories/IInvitesRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ interface IInvitesRepository {
delete(group_id: string, email: string): Promise<Groups>;
updateInvites(email: string): Promise<Groups[]>;
acceptInvite(group_id: string, user_id: string): Promise<Groups>;
isAlreadyUser(group_id: string, user_id: string): Promise<Groups | null>;
isAlreadyAdm(group_id: string, id: string): Promise<Groups | null>;
turnIntoAdm(group_id: string, user_id: string): Promise<Groups>;
defaultAdm(group_id: string, user_id: string): Promise<Groups>;
}

export default IInvitesRepository;
Loading

0 comments on commit 8572756

Please sign in to comment.