diff --git a/legalconsenthub-backend/api/legalconsenthub.yml b/legalconsenthub-backend/api/legalconsenthub.yml index c18e340..89c45e4 100644 --- a/legalconsenthub-backend/api/legalconsenthub.yml +++ b/legalconsenthub-backend/api/legalconsenthub.yml @@ -656,6 +656,8 @@ components: $ref: "#/components/schemas/FormOptionDto" type: $ref: "#/components/schemas/FormElementType" + comments: + $ref: "#/components/schemas/PagedCommentDto" CreateFormElementDto: type: object @@ -714,20 +716,27 @@ components: required: - id - message + - formElementId - createdAt - modifiedAt + - createdBy properties: id: type: string format: uuid message: type: string + formElementId: + type: string + format: uuid createdAt: type: string format: date-time modifiedAt: type: string format: date-time + createdBy: + $ref: "#/components/schemas/UserDto" CreateCommentDto: type: object diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormMapper.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormMapper.kt index 87bef25..7de3179 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormMapper.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormMapper.kt @@ -1,5 +1,6 @@ package com.betriebsratkanzlei.legalconsenthub.application_form +import com.betriebsratkanzlei.legalconsenthub.form_element.FormElementMapper import com.betriebsratkanzlei.legalconsenthub.security.CustomJwtTokenPrincipal import com.betriebsratkanzlei.legalconsenthub.user.User import com.betriebsratkanzlei.legalconsenthub.user.UserMapper diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/PagedApplicationFormMapper.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/PagedApplicationFormMapper.kt index fe76e07..d642734 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/PagedApplicationFormMapper.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/PagedApplicationFormMapper.kt @@ -21,6 +21,4 @@ class PagedApplicationFormMapper(private val applicationFormMapper: ApplicationF first = pagedApplicationForm.isFirst, ) } - // fun toApplicationForm(applicationForm: ApplicationFormDto): ApplicationForm {} - // fun toApplicationForm(createApplicationFormDto: CreateApplicationFormDto): ApplicationForm } diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/Comment.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/Comment.kt new file mode 100644 index 0000000..4e967a2 --- /dev/null +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/Comment.kt @@ -0,0 +1,47 @@ +package com.betriebsratkanzlei.legalconsenthub.comment; + +import com.betriebsratkanzlei.legalconsenthub.form_element.FormElement +import com.betriebsratkanzlei.legalconsenthub.user.User +import jakarta.persistence.AttributeOverride +import jakarta.persistence.AttributeOverrides +import jakarta.persistence.Column +import jakarta.persistence.Embedded +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn +import jakarta.persistence.ManyToOne +import org.springframework.data.annotation.CreatedDate +import org.springframework.data.annotation.LastModifiedDate +import java.time.LocalDateTime + +import java.util.UUID; + +@Entity +class Comment( + @Id + @GeneratedValue + var id: UUID? = null, + + @Column(nullable = false) + var message: String = "", + + @Embedded + @AttributeOverrides( + AttributeOverride(name = "id", column = Column(name = "created_by_id", nullable = false)), + AttributeOverride(name = "name", column = Column(name = "created_by_name", nullable = false)) + ) + var createdBy: User, + + @CreatedDate + @Column(nullable = false) + var createdAt: LocalDateTime? = null, + + @LastModifiedDate + @Column(nullable = false) + var modifiedAt: LocalDateTime? = null, + + @ManyToOne + @JoinColumn(name = "form_element_id", nullable = false) + var formElement: FormElement? = null, +) diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentMapper.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentMapper.kt new file mode 100644 index 0000000..681291a --- /dev/null +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentMapper.kt @@ -0,0 +1,35 @@ +package com.betriebsratkanzlei.legalconsenthub.comment + +import com.betriebsratkanzlei.legalconsenthub.error.FormElementNotFoundException +import com.betriebsratkanzlei.legalconsenthub.form_element.FormElementRepository +import com.betriebsratkanzlei.legalconsenthub.user.UserMapper +import com.betriebsratkanzlei.legalconsenthub_api.model.CommentDto +import org.springframework.stereotype.Component +import java.time.LocalDateTime + +@Component +class CommentMapper(private val userMapper: UserMapper, private val formElementRepository: FormElementRepository) { + fun toCommentDto(comment: Comment): CommentDto { + return CommentDto( + id = comment.id ?: throw IllegalStateException("Comment ID must not be null!"), + message = comment.message, + createdAt = comment.createdAt ?: LocalDateTime.now(), + modifiedAt = comment.modifiedAt ?: LocalDateTime.now(), + createdBy = userMapper.toUserDto(comment.createdBy), + formElementId = comment.formElement?.id ?: throw IllegalStateException("FormElement ID must not be null!"), + ) + } + + fun toComment(commentDto: CommentDto): Comment { + val formElement = formElementRepository.findById(commentDto.formElementId).orElseThrow { FormElementNotFoundException(commentDto.formElementId) } + + return Comment( + id = commentDto.id, + message = commentDto.message, + createdAt = commentDto.createdAt, + modifiedAt = commentDto.modifiedAt, + createdBy = userMapper.toUser(commentDto.createdBy), + formElement = formElement + ) + } +} diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentRepository.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentRepository.kt new file mode 100644 index 0000000..d16f313 --- /dev/null +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/CommentRepository.kt @@ -0,0 +1,8 @@ +package com.betriebsratkanzlei.legalconsenthub.comment + +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository +import java.util.UUID + +@Repository +interface CommentRepository : JpaRepository diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/PagedCommentMapper.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/PagedCommentMapper.kt new file mode 100644 index 0000000..5698591 --- /dev/null +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/comment/PagedCommentMapper.kt @@ -0,0 +1,22 @@ +package com.betriebsratkanzlei.legalconsenthub.comment + +import com.betriebsratkanzlei.legalconsenthub_api.model.PagedCommentDto +import org.springframework.data.domain.Page +import org.springframework.stereotype.Component + +@Component +class PagedCommentMapper(private val commentMapper: CommentMapper) { + fun toPagedCommentDto(pagedComment: Page): PagedCommentDto { + return PagedCommentDto( + content = pagedComment.content.map { commentMapper.toCommentDto(it) }, + number = pagedComment.number, + propertySize = pagedComment.size, + numberOfElements = pagedComment.numberOfElements, + last = pagedComment.isLast, + totalPages = pagedComment.totalPages, + totalElements = pagedComment.totalElements, + empty = pagedComment.isEmpty, + first = pagedComment.isFirst, + ) + } +} diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/error/FormElementNotFoundException.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/error/FormElementNotFoundException.kt new file mode 100644 index 0000000..e960505 --- /dev/null +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/error/FormElementNotFoundException.kt @@ -0,0 +1,5 @@ +package com.betriebsratkanzlei.legalconsenthub.error + +import java.util.UUID + +class FormElementNotFoundException(id: UUID): RuntimeException("Couldn't find form element with ID: $id") diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormElement.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormElement.kt index 2790143..29381ef 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormElement.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormElement.kt @@ -1,7 +1,9 @@ package com.betriebsratkanzlei.legalconsenthub.form_element; import com.betriebsratkanzlei.legalconsenthub.application_form.ApplicationForm +import com.betriebsratkanzlei.legalconsenthub.comment.Comment import com.betriebsratkanzlei.legalconsenthub_api.model.FormElementType +import jakarta.persistence.CascadeType import jakarta.persistence.CollectionTable import jakarta.persistence.Column import jakarta.persistence.ElementCollection @@ -10,6 +12,7 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn import jakarta.persistence.ManyToOne +import jakarta.persistence.OneToMany import java.util.UUID; @@ -28,5 +31,8 @@ class FormElement ( var options: MutableList = mutableListOf(), @Column(nullable = false) - var type: FormElementType + var type: FormElementType, + + @OneToMany(mappedBy = "formElement", cascade = [CascadeType.ALL], orphanRemoval = true) + var comments: MutableList = mutableListOf(), ) diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/FormElementMapper.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormElementMapper.kt similarity index 56% rename from legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/FormElementMapper.kt rename to legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormElementMapper.kt index 686bedd..d75dac7 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/FormElementMapper.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormElementMapper.kt @@ -1,14 +1,21 @@ -package com.betriebsratkanzlei.legalconsenthub.application_form +package com.betriebsratkanzlei.legalconsenthub.form_element +import com.betriebsratkanzlei.legalconsenthub.application_form.ApplicationForm +import com.betriebsratkanzlei.legalconsenthub.application_form.ApplicationFormRepository +import com.betriebsratkanzlei.legalconsenthub.comment.CommentMapper +import com.betriebsratkanzlei.legalconsenthub.comment.PagedCommentMapper import com.betriebsratkanzlei.legalconsenthub.error.ApplicationFormNotFoundException -import com.betriebsratkanzlei.legalconsenthub.form_element.FormElement import com.betriebsratkanzlei.legalconsenthub_api.model.CreateFormElementDto import com.betriebsratkanzlei.legalconsenthub_api.model.FormElementDto +import org.springframework.data.domain.PageImpl +import org.springframework.data.domain.PageRequest import org.springframework.stereotype.Component @Component class FormElementMapper( private val formOptionMapper: FormOptionMapper, + private val commentMapper: CommentMapper, + private val pagedCommentMapper: PagedCommentMapper, private val applicationFormRepository: ApplicationFormRepository ) { fun toFormElementDto(formElement: FormElement): FormElementDto { @@ -17,19 +24,27 @@ class FormElementMapper( options = formElement.options.map { formOptionMapper.toFormOptionDto(it) }, type = formElement.type, applicationFormId = formElement.applicationForm?.id - ?: throw IllegalStateException("ApplicationForm ID must not be null!") + ?: throw IllegalStateException("ApplicationForm ID must not be null!"), + comments = if (formElement.comments.size > 0) pagedCommentMapper.toPagedCommentDto( + PageImpl( + formElement.comments.toList(), + PageRequest.of(0, formElement.comments.size), + formElement.comments.size.toLong() + ) + ) else null ) } fun toFormElement(formElement: FormElementDto): FormElement { val applicationForm = applicationFormRepository.findById(formElement.applicationFormId) - .orElseThrow { ApplicationFormNotFoundException(formElement.applicationFormId) } + .orElseThrow { ApplicationFormNotFoundException(formElement.applicationFormId) } return FormElement( id = formElement.id, options = formElement.options.map { formOptionMapper.toFormOption(it) }.toMutableList(), type = formElement.type, - applicationForm = applicationForm + applicationForm = applicationForm, + comments = formElement.comments?.content?.map { commentMapper.toComment(it) }?.toMutableList() ?: mutableListOf() ) } @@ -38,7 +53,7 @@ class FormElementMapper( id = null, options = formElement.options.map { formOptionMapper.toFormOption(it) }.toMutableList(), type = formElement.type, - applicationForm = applicationForm + applicationForm = applicationForm, ) } } diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormElementRepository.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormElementRepository.kt new file mode 100644 index 0000000..9791fff --- /dev/null +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormElementRepository.kt @@ -0,0 +1,11 @@ +package com.betriebsratkanzlei.legalconsenthub.form_element + +import com.betriebsratkanzlei.legalconsenthub.comment.Comment +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository +import java.util.UUID + +@Repository +interface FormElementRepository : JpaRepository diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/FormOptionMapper.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormOptionMapper.kt similarity index 85% rename from legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/FormOptionMapper.kt rename to legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormOptionMapper.kt index 868f49b..5568c0e 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/FormOptionMapper.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/form_element/FormOptionMapper.kt @@ -1,6 +1,5 @@ -package com.betriebsratkanzlei.legalconsenthub.application_form +package com.betriebsratkanzlei.legalconsenthub.form_element -import com.betriebsratkanzlei.legalconsenthub.form_element.FormOption import com.betriebsratkanzlei.legalconsenthub_api.model.FormOptionDto import org.springframework.stereotype.Component diff --git a/legalconsenthub-backend/src/main/resources/db/migrations/001-schema.sql b/legalconsenthub-backend/src/main/resources/db/migrations/001-schema.sql index 53f05f9..0ef19dd 100644 --- a/legalconsenthub-backend/src/main/resources/db/migrations/001-schema.sql +++ b/legalconsenthub-backend/src/main/resources/db/migrations/001-schema.sql @@ -13,6 +13,18 @@ create table application_form primary key (id) ); +create table comment +( + created_at timestamp(6) not null, + modified_at timestamp(6) not null, + form_element_id uuid not null, + id uuid not null, + created_by_id varchar(255) not null, + created_by_name varchar(255) not null, + message varchar(255) not null, + primary key (id) +); + create table form_element_options ( employee_data_category tinyint not null check (employee_data_category between 0 and 3), @@ -30,6 +42,11 @@ create table form_element primary key (id) ); +alter table if exists comment + add constraint FKfg84w0i76tw9os13950272c6f + foreign key (form_element_id) + references form_element; + alter table if exists form_element_options add constraint FKnq0lpby5nspv1xi27n9el6us6 foreign key (form_element_id)