Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a749fd4
Merge pull request #126 from WorkUpMaua/test
VictorGasperi Oct 28, 2025
ed00880
docs: adicionando diagramas
VictorGasperi Oct 29, 2025
54c35e8
docs: upload README
VictorGasperi Oct 29, 2025
7bc5964
Merge pull request #127 from WorkUpMaua/docs/images
VictorGasperi Oct 29, 2025
6ff9345
docs: arrumando imagens
VictorGasperi Oct 29, 2025
78de9ac
docs: tentando arrumar a leitura da imagem
VictorGasperi Oct 29, 2025
14f74db
Merge pull request #128 from WorkUpMaua/docs/images
VictorGasperi Oct 29, 2025
7c9d6a8
chore: adicionar arquivo package-lock.json e atualizar dependências p…
LucasKiller Oct 31, 2025
49dafaf
refactor: centralizar lógica de encerramento do servidor em uma função
LucasKiller Oct 31, 2025
7522270
chore: adicionar a propriedade "peer" em várias dependências no packa…
LucasKiller Oct 31, 2025
28b04f0
chore: atualizar a dependência "crypto" para ser direta no pubspec.yaml
LucasKiller Oct 31, 2025
36a7114
feat: adicionar suporte para código de porta nas operações de aluguel
LucasKiller Oct 31, 2025
1e9ca0c
feat: adicionar verificação de código de porta e controlador correspo…
LucasKiller Oct 31, 2025
f0779e2
feat: implementar verificação de código de porta com hash SHA-256 e c…
LucasKiller Oct 31, 2025
75d5e0e
chore: comentar importações e testes no arquivo aluguel_dart_test.dart
LucasKiller Oct 31, 2025
907726e
feat: remover suporte a código de porta nas operações de criação de a…
LucasKiller Oct 31, 2025
2f046a8
feat: remover lógica de verificação e manipulação de doorCode nas ope…
LucasKiller Oct 31, 2025
705996a
feat: implementar consumidor para busca de código de porta e refatora…
LucasKiller Nov 1, 2025
d20c5ed
Merge pull request #129 from WorkUpMaua/aluguel-door-code
LucasKiller Nov 2, 2025
e652593
fix: arrumando as rotas de codigo
VictorGasperi Nov 3, 2025
a698078
feat: refatorar verificação de código de porta e atualizar resposta d…
LucasKiller Nov 3, 2025
2293484
Merge pull request #130 from WorkUpMaua/fix/door_code
LucasKiller Nov 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ Além de seu propósito funcional, o sistema serve como aplicação prática de

---

## 🗺️ Diagramas

<figure>
<img src="docs/fluxo.png" width="800">
<figcaption><strong>Figura 1:</strong> Arquitetura do projeto</figcaption>
</figure>

<figure>
<img src="docs/deploy_to_aws.png" width="800">
<figcaption><strong>Figura 2:</strong> Fluxo de deploy</figcaption>
</figure>

---

## 📚 Documentação da API

A coleção completa de endpoints, exemplos de requisições e esquemas de resposta está disponível no Postman:
Expand Down
55 changes: 28 additions & 27 deletions back/microsservicos/aluguel/bin/aluguel_dart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,27 @@ import 'package:aluguel_dart/application/get_aluguel_usecase.dart';
import 'package:aluguel_dart/application/create_aluguel_usecase.dart';
import 'package:aluguel_dart/application/update_aluguel_usecase.dart';
import 'package:aluguel_dart/application/delete_aluguel_usecase.dart';
import 'package:aluguel_dart/application/verify_door_code_usecase.dart';
import 'package:aluguel_dart/domain/repositories/aluguel_repository.dart';
import 'package:aluguel_dart/presentation/http/controllers/get_aluguel_controller.dart';
import 'package:aluguel_dart/presentation/http/controllers/create_aluguel_controller.dart';
import 'package:aluguel_dart/presentation/http/controllers/update_aluguel_controller.dart';
import 'package:aluguel_dart/presentation/http/controllers/delete_aluguel_controller.dart';
import 'package:aluguel_dart/presentation/http/controllers/get_door_hash_controller.dart';

Future<void> _shutdownServer(HttpServer server, String message) async {
stdout.writeln(message);
try {
await closeRabbitMQConnection();
} catch (e) {
stderr.writeln('Erro ao fechar RabbitMQ: $e');
} finally {
try {
await server.close(force: true);
} catch (_) {}
exit(0);
}
}

Future<void> main() async {
final AluguelRepository repo = Environments.getAluguelRepo();
Expand All @@ -29,12 +45,14 @@ Future<void> main() async {
final updateAluguelUsecase = UpdateAluguelUsecase(repository: repo);
final deleteAluguelUsecase = DeleteAluguelUsecase(repository: repo);
final getAllAluguelUsecase = GetAllAluguelUsecase(repository: repo);
final verifyDoorCodeUsecase = VerifyDoorCodeUsecase(repository: repo);

final getController = GetAluguelController(getAluguelUsecase);
final createController = CreateAluguelController(createAluguelUsecase);
final updateController = UpdateAluguelController(updateAluguelUsecase);
final deleteController = DeleteAluguelController(deleteAluguelUsecase);
final getAllAluguelController = GetAllAluguelController(getAllAluguelUsecase);
final getDoorHashController = GetDoorHashController(verifyDoorCodeUsecase);

final router = Router()
..mount(
Expand All @@ -44,7 +62,8 @@ Future<void> main() async {
createController: createController,
updateController: updateController,
deleteController: deleteController,
getAllAluguelController: getAllAluguelController
getAllAluguelController: getAllAluguelController,
getDoorHashController: getDoorHashController,
).call,
);

Expand All @@ -57,30 +76,12 @@ Future<void> main() async {
final server = await io.serve(handler, InternetAddress.anyIPv4, port);
print('Aluguel. Porta: $port');
await startQueue();
ProcessSignal.sigint.watch().listen((_) async {
stdout.writeln('Service aluguel interrupted!');
try {
await closeRabbitMQConnection();
} catch (e) {
stderr.writeln('Erro ao fechar RabbitMQ: $e');
} finally {
try {
await server.close(force: true);
} catch (_) {}
exit(0);
}
});
ProcessSignal.sigterm.watch().listen((_) async {
stdout.writeln('Service aluguel terminated!');
try {
await closeRabbitMQConnection();
} catch (e) {
stderr.writeln('Erro ao fechar RabbitMQ: $e');
} finally {
try {
await server.close(force: true);
} catch (_) {}
exit(0);
}
});
ProcessSignal.sigint.watch().listen(
(_) async => _shutdownServer(server, 'Service aluguel interrupted!'),
);
if (!Platform.isWindows) {
ProcessSignal.sigterm.watch().listen(
(_) async => _shutdownServer(server, 'Service aluguel terminated!'),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,24 @@ class CreateAluguelUsecase {
Future<Aluguel> call({
required String userId,
required String workspaceId,
required int startDate,
required int endDate,
required int startDate,
required int endDate,
required int people,
required num finalPrice,
required num finalPrice
}) async {

if (endDate < startDate) {
throw StateError('endDate não pode ser menor que startDate.');
}
if (people <= 0) {
throw StateError('O número de pessoas para a reserva deve ser diferente de null e maior que.');
throw StateError(
'O número de pessoas para a reserva deve ser diferente de null e maior que zero.',
);
}
if (finalPrice < 0) {
throw StateError('finalPrice não pode ser negativo.');
}

Aluguel createdAluguel = await repository.createAluguel(
final createdAluguel = await repository.createAluguel(
userId: userId,
workspaceId: workspaceId,
startDate: startDate,
Expand All @@ -37,18 +38,18 @@ class CreateAluguelUsecase {
status: 'PENDING',
);

RabbitMQEvent aluguelCreated = RabbitMQEvent(eventType: 'AluguelCreated', payload: createdAluguel.toJson());
final aluguelCreated = RabbitMQEvent(
eventType: 'AluguelCreated',
payload: createdAluguel.toJson(),
);

final published = await publishEvent('aluguel.created', aluguelCreated.toJson());
final published =
await publishEvent('aluguel.created', aluguelCreated.toJson());

if(published){
if (published) {
return createdAluguel;
} else {
throw StateError('Não foi possível criar o aluguel');
}

}
}



Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class GetAluguelUsecase {
final AluguelRepository repository;

GetAluguelUsecase({required this.repository});

Future<Aluguel> call(String id) async {
if (id.isEmpty) {
throw ArgumentError('ID do aluguel não pode ser vazio.');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:math';

import 'package:aluguel_dart/domain/entities/aluguel.dart';
import 'package:aluguel_dart/domain/repositories/aluguel_repository.dart';

Expand All @@ -8,13 +10,12 @@ class UpdateAluguelUsecase {

Future<Aluguel> call(
String id, {
int? startDate,
int? startDate,
int? endDate,
int? people,
double? finalPrice,
String? status,
}) async {

if (startDate != null && endDate != null && endDate < startDate) {
throw StateError('endDate não pode ser menor que startDate.');
}
Expand All @@ -25,13 +26,24 @@ class UpdateAluguelUsecase {
throw StateError('finalPrice não pode ser negativo.');
}

String? desiredDoorCode = Random().nextInt(100000).toString().padLeft(5, '0');

if (status != null &&
status.toUpperCase() == 'CONFIRMED') {
final current = await repository.getAluguel(id);
if (current == null) {
throw StateError('aluguel_not_found');
}
}

return repository.updateAluguel(
id,
startDate: startDate,
endDate: endDate,
people: people,
finalPrice: finalPrice,
status: status,
doorCode: desiredDoorCode,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'package:aluguel_dart/domain/entities/aluguel.dart';
import 'package:aluguel_dart/domain/repositories/aluguel_repository.dart';
import 'package:aluguel_dart/infrastructure/clients/rabbitmq/rabbitmq.dart';

class VerifyDoorCodeUsecase {
final AluguelRepository repository;

VerifyDoorCodeUsecase({required this.repository});

Future<String> call({
required String doorCode,
}) async {
final normalizedDoorCode = doorCode.trim();

if (!RegExp(r'^\d{5}$').hasMatch(normalizedDoorCode)) {
throw StateError('door code invalid');
}

final allAlugueis = await repository.getAllAluguel();

if (allAlugueis == null || allAlugueis.isEmpty) {
throw StateError('door code not found');
}

final nowEpoch = DateTime.now().millisecondsSinceEpoch ~/ 1000;

Aluguel? matchingAluguel;

for (final aluguel in allAlugueis.values) {
final storedDoor = aluguel.doorCode?.trim();
if (storedDoor == null || storedDoor.isEmpty) {
continue;
}
if (storedDoor != normalizedDoorCode) {
continue;
}
if (aluguel.status.toUpperCase() != 'CONFIRMED') {
continue;
}
if (nowEpoch < aluguel.startDate || nowEpoch > aluguel.endDate) {
continue;
}
matchingAluguel = aluguel;
break;
}

if (matchingAluguel == null) {
throw StateError('door code not found');
}

final doorSerial = await fetchDoorCodeFromCatalog(
matchingAluguel.workspaceId,
);

if (doorSerial == null || doorSerial.trim().isEmpty) {
throw StateError('door serial not found');
}

return doorSerial.trim();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class Aluguel {
final int people;
final double finalPrice;
final String status;
final String? doorCode;
final int createdAt;
final int updatedAt;

Expand All @@ -19,6 +20,7 @@ class Aluguel {
required this.people,
required this.finalPrice,
required this.status,
this.doorCode,
required this.createdAt,
required this.updatedAt,
});
Expand All @@ -33,6 +35,7 @@ class Aluguel {
'people': people,
'finalPrice': finalPrice,
'status': status,
'doorCode': doorCode,
'createdAt': createdAt,
'updatedAt': updatedAt,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ abstract class AluguelRepository {
int? people,
double? finalPrice,
String? status,
String? doorCode,
});


Future<void> deleteAluguel(String id);
}

Future<Aluguel?> getDoorAluguel(String doorCode);
}
Loading