-
Notifications
You must be signed in to change notification settings - Fork 0
Feature - GET /questionnaires #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| db/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # Project Summary | ||
|
|
||
| ## Overview | ||
| This project is developed using Kotlin as the primary programming language, and it leverages various frameworks and libraries commonly used in modern software development. The project appears to be a backend service that likely manages products, with functionalities for creating, retrieving, and managing product data. It also includes configurations for Docker and Helm, indicating a focus on containerization and deployment in cloud environments. | ||
|
|
||
| ### Languages, Frameworks, and Main Libraries Used | ||
| - **Language**: Kotlin | ||
| - **Build Tool**: Maven (indicated by `pom.xml`) | ||
| - **Containerization**: Docker (indicated by multiple Dockerfiles) | ||
| - **Documentation**: Markdown files for CI/CD and other related documentation | ||
| - **Testing Framework**: Presumably JUnit or similar, as indicated by the test files | ||
|
|
||
| ## Purpose of the Project | ||
| The purpose of the project is to provide a robust backend service that manages product-related operations, including creating and retrieving product information. It likely supports RESTful API endpoints for interaction with clients. The use of Docker and Helm suggests that the project is intended for deployment in cloud environments, facilitating scalability and maintainability. | ||
|
|
||
| ## Configuration and Build Files | ||
| Here are the relevant files for configuration and building the project: | ||
|
|
||
| 1. `/pom.xml` | ||
| 2. `/mvnw` | ||
| 3. `/mvnw.cmd` | ||
| 4. `/Dockerfile` | ||
| 5. `/Dockerfile.dev` | ||
| 6. `/sonar-project.properties` | ||
| 7. `/helm/Chart.yaml` | ||
| 8. `/helm/values-dev.yaml` | ||
| 9. `/helm/values-prod.yaml` | ||
| 10. `/helm/values.yaml` | ||
|
|
||
| ## Source Files Location | ||
| The source files can be found in the following directory: | ||
| - `/src/main/kotlin` | ||
|
|
||
| ## Documentation Files Location | ||
| Documentation files are located in the following directory: | ||
| - `/docs` | ||
| - Additionally, there are README files located at: | ||
| - `/README.md` | ||
| - `/helm/README.md` | ||
|
|
||
| This project structure indicates a well-organized codebase with clear separation of concerns, making it easier to maintain and extend in the future. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,6 +57,10 @@ | |
| <groupId>io.quarkus</groupId> | ||
| <artifactId>quarkus-micrometer-registry-prometheus</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>io.quarkus</groupId> | ||
| <artifactId>quarkus-jdbc-postgresql</artifactId> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>io.quarkus</groupId> | ||
| <artifactId>quarkus-junit5</artifactId> | ||
|
|
@@ -238,8 +242,8 @@ | |
| <include>.gitignore</include> | ||
| </includes> | ||
| <!-- define the steps to apply to those files --> | ||
| <trimTrailingWhitespace/> | ||
| <endWithNewline/> | ||
| <trimTrailingWhitespace /> | ||
| <endWithNewline /> | ||
|
Comment on lines
+245
to
+246
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove extra space here |
||
| <indent> | ||
| <tabs>true</tabs> | ||
| <spacesPerTab>4</spacesPerTab> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package org.ptss.support.api.controllers | ||
|
|
||
| import jakarta.enterprise.context.ApplicationScoped | ||
| import jakarta.ws.rs.GET | ||
| import jakarta.ws.rs.Path | ||
| import jakarta.ws.rs.Produces | ||
| import jakarta.ws.rs.core.MediaType | ||
| import org.ptss.support.api.dtos.responses.QuestionnaireResponse | ||
| import org.ptss.support.core.facades.QuestionnaireFacade | ||
| import org.ptss.support.domain.interfaces.controllers.IQuestionnaireController | ||
|
|
||
| @Path("/questionnaires") | ||
| @ApplicationScoped | ||
| @Produces(MediaType.APPLICATION_JSON) | ||
| class QuestionnaireController( | ||
| private val questionnaireFacade: QuestionnaireFacade, | ||
| ) : IQuestionnaireController { | ||
|
|
||
| @GET | ||
| override suspend fun getAllQuestionnaires(): List<QuestionnaireResponse> = | ||
| questionnaireFacade.getAllQuestionnaires() | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package org.ptss.support.api.dtos.responses | ||
|
|
||
| data class QuestionnaireResponse( | ||
| val id: String, | ||
| val title: String, | ||
| val description: String, | ||
| val estimatedTimeOfCompletion: String, | ||
| val assignedAt: String, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is assigned at a string? Should be date time no?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the swagger it is annotated this way so the response should give back a string right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One question, PS: Something seems off in Swagger, always double check. |
||
| val isFinished: Boolean, | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package org.ptss.support.core.facades | ||
|
|
||
| import jakarta.enterprise.context.ApplicationScoped | ||
| import jakarta.inject.Inject | ||
| import org.ptss.support.api.dtos.responses.QuestionnaireResponse | ||
| import org.ptss.support.core.mappers.QuestionnaireMapper | ||
| import org.ptss.support.core.services.QuestionnaireService | ||
|
|
||
| @ApplicationScoped | ||
| class QuestionnaireFacade @Inject constructor( | ||
| private val questionnaireService: QuestionnaireService, | ||
| ) { | ||
| suspend fun getAllQuestionnaires(): List<QuestionnaireResponse> = | ||
| questionnaireService.getAllQuestionnairesAsync() | ||
| .map(QuestionnaireMapper::toResponse) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package org.ptss.support.core.mappers | ||
|
|
||
| import org.ptss.support.api.dtos.responses.QuestionnaireResponse | ||
| import org.ptss.support.domain.models.Questionnaire | ||
|
|
||
| object QuestionnaireMapper { | ||
| fun toResponse(questionnaire: Questionnaire): QuestionnaireResponse { | ||
| return QuestionnaireResponse( | ||
| id = questionnaire.id, | ||
| title = questionnaire.title, | ||
| description = questionnaire.description, | ||
| estimatedTimeOfCompletion = questionnaire.estimatedTimeOfCompletion, | ||
| assignedAt = questionnaire.assignedAt, | ||
| isFinished = questionnaire.isFinished, | ||
| ) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package org.ptss.support.core.services | ||
|
|
||
| import jakarta.enterprise.context.ApplicationScoped | ||
| import org.ptss.support.domain.models.Questionnaire | ||
| import org.ptss.support.domain.queries.GetAllQuestionnairesQuery | ||
| import org.ptss.support.infrastructure.handlers.queries.questionnaire.GetAllQuestionnairesQueryHandler | ||
| import org.ptss.support.infrastructure.util.executeWithExceptionLoggingAsync | ||
| import org.slf4j.LoggerFactory | ||
|
|
||
| @ApplicationScoped | ||
| class QuestionnaireService( | ||
| private val getAllQuestionnairesQueryHandler: GetAllQuestionnairesQueryHandler, | ||
| ) { | ||
| private val logger = LoggerFactory.getLogger(QuestionnaireService::class.java) | ||
|
|
||
| suspend fun getAllQuestionnairesAsync(): List<Questionnaire> { | ||
| return logger.executeWithExceptionLoggingAsync( | ||
| operation = { getAllQuestionnairesQueryHandler.handleAsync(GetAllQuestionnairesQuery()) }, | ||
| logMessage = "Failed to get all questionnaires" | ||
| ) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| package org.ptss.support.domain.interfaces.controllers | ||
|
|
||
| import jakarta.ws.rs.GET | ||
| import org.eclipse.microprofile.openapi.annotations.Operation | ||
| import org.eclipse.microprofile.openapi.annotations.media.Content | ||
| import org.eclipse.microprofile.openapi.annotations.media.Schema | ||
| import org.eclipse.microprofile.openapi.annotations.responses.APIResponse | ||
| import org.eclipse.microprofile.openapi.annotations.responses.APIResponses | ||
| import org.ptss.support.api.dtos.responses.QuestionnaireResponse | ||
| import org.ptss.support.common.exceptions.ServiceError | ||
|
|
||
| // error 201, 400, 401, 403 and 500 | ||
| interface IQuestionnaireController { | ||
| @GET | ||
| @Operation(summary = "Get all questionnaires", description = "Retrieves a list of all questionnaires") | ||
| @APIResponses( | ||
| APIResponse( | ||
| responseCode = "201", | ||
| description = "List of questionnaires successfully retrieved", | ||
| content = [Content(schema = Schema(implementation = Array<QuestionnaireResponse>::class))], | ||
| ), | ||
| APIResponse( | ||
| responseCode = "400", | ||
| description = "Bad request", | ||
| content = [Content(schema = Schema(implementation = ServiceError::class))], | ||
| ), | ||
| APIResponse( | ||
| responseCode = "401", | ||
| description = "Unauthorized", | ||
| content = [Content(schema = Schema(implementation = ServiceError::class))], | ||
| ), | ||
| APIResponse( | ||
| responseCode = "403", | ||
| description = "Forbidden", | ||
| content = [Content(schema = Schema(implementation = ServiceError::class))], | ||
| ), | ||
| APIResponse( | ||
| responseCode = "500", | ||
| description = "Internal server error", | ||
| content = [Content(schema = Schema(implementation = ServiceError::class))], | ||
| ), | ||
| ) | ||
| suspend fun getAllQuestionnaires(): List<QuestionnaireResponse> | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| package org.ptss.support.domain.interfaces.queries | ||
|
|
||
| class GetAllQuestionnairesQuery() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package org.ptss.support.domain.interfaces.repositories | ||
|
|
||
| import org.ptss.support.domain.models.Questionnaire | ||
|
|
||
| interface IQuestionnaireRepository { | ||
| fun getAll(): List<Questionnaire> | ||
| } |
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do you need this to be vars btw? can't you just make this a data class?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. true, changed it |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package org.ptss.support.domain.models | ||
|
|
||
| class Questionnaire() { | ||
| var id: String = "" | ||
| var title: String = "" | ||
| var description: String = "" | ||
| var estimatedTimeOfCompletion: String = "" | ||
| var assignedAt: String = "" | ||
|
Comment on lines
+4
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. these default values are redundant, as it automatically becomes an empty string |
||
| var isFinished: Boolean = false | ||
|
CyberAve2100 marked this conversation as resolved.
|
||
|
|
||
| constructor( | ||
| id: String, | ||
| title: String, | ||
| description: String, | ||
| estimatedTimeOfCompletion: String, | ||
| assignedAt: String, | ||
| isFinished: Boolean | ||
| ) : this() { | ||
| this.id = id | ||
| this.title = title | ||
| this.description = description | ||
| this.estimatedTimeOfCompletion = estimatedTimeOfCompletion | ||
| this.assignedAt = assignedAt | ||
| this.isFinished = isFinished | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| package org.ptss.support.domain.queries | ||
|
|
||
| class GetAllQuestionnairesQuery() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package org.ptss.support.infrastructure.config | ||
|
|
||
| import io.smallrye.config.ConfigMapping | ||
| import io.smallrye.config.WithName | ||
|
|
||
| @ConfigMapping(prefix = "quarkus.datasource") | ||
| interface PostgreSQLConfig { | ||
| @WithName("jdbc.url") | ||
| fun url(): String | ||
|
|
||
| @WithName("username") | ||
| fun username(): String | ||
|
|
||
| @WithName("password") | ||
| fun password(): String | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package org.ptss.support.infrastructure.handlers.queries.questionnaire | ||
|
|
||
| import jakarta.enterprise.context.ApplicationScoped | ||
| import org.ptss.support.domain.interfaces.queries.IQueryHandler | ||
| import org.ptss.support.domain.interfaces.repositories.IQuestionnaireRepository | ||
| import org.ptss.support.domain.models.Questionnaire | ||
| import org.ptss.support.domain.queries.GetAllQuestionnairesQuery | ||
|
|
||
| @ApplicationScoped | ||
| class GetAllQuestionnairesQueryHandler( | ||
| private val questionnaireRepository: IQuestionnaireRepository, | ||
| ) : IQueryHandler<GetAllQuestionnairesQuery, List<Questionnaire>> { | ||
|
|
||
| override suspend fun handleAsync(query: GetAllQuestionnairesQuery): List<Questionnaire> { | ||
| return questionnaireRepository.getAll() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package org.ptss.support.infrastructure.persistence.entities | ||
|
|
||
| import org.ptss.support.domain.models.Questionnaire | ||
|
|
||
| data class QuestionnaireEntity( | ||
| val id: String, | ||
| val title: String, | ||
| val description: String, | ||
| val estimatedTimeOfCompletion: String, | ||
| val assignedAt: String, | ||
| val isFinished: Boolean, | ||
| ) { | ||
| fun toDomain(): Questionnaire { | ||
| return Questionnaire( | ||
| id = id, | ||
| title = title, | ||
| description = description, | ||
| estimatedTimeOfCompletion = estimatedTimeOfCompletion, | ||
| assignedAt = assignedAt, | ||
| isFinished = isFinished, | ||
| ) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| package org.ptss.support.infrastructure.repositories | ||
|
|
||
| import jakarta.inject.Inject | ||
| import org.ptss.support.infrastructure.config.PostgreSQLConfig | ||
| import java.sql.Connection | ||
| import java.sql.DriverManager | ||
|
|
||
| abstract class BaseRepository<T> { | ||
| @Inject | ||
| protected lateinit var config: PostgreSQLConfig | ||
|
|
||
| protected fun getConnection(): Connection { | ||
| return DriverManager.getConnection( | ||
| config.url(), | ||
| config.username(), | ||
| config.password(), | ||
| ) | ||
| } | ||
|
|
||
| fun <R> useConnection(block: (Connection) -> R): R { | ||
| return getConnection().use { conn -> | ||
| block(conn) | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package org.ptss.support.infrastructure.repositories | ||
|
|
||
| import jakarta.enterprise.context.ApplicationScoped | ||
| import org.ptss.support.domain.models.Questionnaire | ||
|
|
||
| @ApplicationScoped | ||
| class QuestionnaireBaseRepository : BaseRepository<Questionnaire>() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| package org.ptss.support.infrastructure.repositories | ||
|
|
||
| import jakarta.enterprise.context.ApplicationScoped | ||
| import jakarta.inject.Inject | ||
| import org.ptss.support.domain.interfaces.repositories.IQuestionnaireRepository | ||
| import org.ptss.support.domain.models.Questionnaire | ||
| import org.ptss.support.infrastructure.persistence.entities.QuestionnaireEntity | ||
|
|
||
| @ApplicationScoped | ||
| class QuestionnaireRepository @Inject constructor( | ||
| private val questionnaireBaseRepository: QuestionnaireBaseRepository | ||
| ) : IQuestionnaireRepository { | ||
| override fun getAll(): List<Questionnaire> { | ||
| return questionnaireBaseRepository.useConnection { connection -> | ||
| val questionnaires = mutableListOf<Questionnaire>() | ||
| val query = | ||
| "SELECT id, title, description, estimatedTimeOfCompletion, assignedAt, isFinished FROM questionnaires" | ||
|
|
||
| val result = connection.prepareStatement(query).executeQuery() | ||
|
|
||
| while (result.next()) { | ||
| val questionnaire = QuestionnaireEntity( | ||
| id = result.getString("id"), | ||
| title = result.getString("title"), | ||
| description = result.getString("description"), | ||
| estimatedTimeOfCompletion = result.getString("estimatedTimeOfCompletion"), | ||
| assignedAt = result.getString("assignedAt"), | ||
| isFinished = result.getBoolean("isFinished"), | ||
| ).toDomain() | ||
| questionnaires.add(questionnaire) | ||
| } | ||
|
|
||
| questionnaires | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check de nieuwste code van Daan, heeft nu namelijk andere env variables. Die heeft er nu namelijk 6 ofzo en die structuur moet je overnemen als je wilt dat je db werkt in openshift. Kijk ook naar zijn application.properties