feat: Add table logic for role and permission sections
This commit is contained in:
@@ -11,6 +11,7 @@ import com.betriebsratkanzlei.legalconsenthub_api.model.ApplicationFormSnapshotD
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.FormElementSectionSnapshotDto
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.FormElementSnapshotDto
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.FormElementSubSectionSnapshotDto
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.FormElementVisibilityCondition
|
||||
import com.fasterxml.jackson.core.type.TypeReference
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import org.springframework.stereotype.Service
|
||||
@@ -80,6 +81,7 @@ class ApplicationFormFormatService(
|
||||
title = LatexEscaper.escape(element.title ?: ""),
|
||||
description = LatexEscaper.escape(element.description ?: ""),
|
||||
value = renderElementValue(element),
|
||||
isTable = element.type.name == "TABLE",
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -152,8 +154,10 @@ class ApplicationFormFormatService(
|
||||
val rowCount = columnData.maxOfOrNull { col -> col.size } ?: 0
|
||||
if (rowCount == 0) return "Keine Daten"
|
||||
|
||||
val columnSpec = headers.joinToString(" | ") { "l" }
|
||||
val headerRow = headers.joinToString(" & ")
|
||||
// Use tabularx with Y columns (auto-wrapping) for flexible width distribution
|
||||
// Y is defined as >{\raggedright\arraybackslash}X in the template
|
||||
val columnSpec = headers.joinToString("") { "Y" }
|
||||
val headerRow = headers.joinToString(" & ") { "\\textbf{$it}" }
|
||||
val dataRows =
|
||||
(0 until rowCount).map { rowIndex ->
|
||||
columnData.joinToString(" & ") { col: List<String> ->
|
||||
@@ -163,15 +167,15 @@ class ApplicationFormFormatService(
|
||||
}
|
||||
|
||||
return buildString {
|
||||
appendLine("\\begin{tabular}{$columnSpec}")
|
||||
appendLine("\\hline")
|
||||
appendLine("\\begin{tabularx}{\\textwidth}{$columnSpec}")
|
||||
appendLine("\\toprule")
|
||||
appendLine("$headerRow \\\\")
|
||||
appendLine("\\hline")
|
||||
appendLine("\\midrule")
|
||||
dataRows.forEach { row: String ->
|
||||
appendLine("$row \\\\")
|
||||
}
|
||||
appendLine("\\hline")
|
||||
appendLine("\\end{tabular}")
|
||||
appendLine("\\bottomrule")
|
||||
appendLine("\\end{tabularx}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,8 +217,17 @@ class ApplicationFormFormatService(
|
||||
element: FormElementSnapshotDto,
|
||||
formElementsByRef: Map<String, FormElementSnapshotDto>,
|
||||
): Boolean {
|
||||
val condition = element.visibilityCondition ?: return true
|
||||
val conditions = element.visibilityConditions
|
||||
if (conditions.isNullOrEmpty()) return true
|
||||
|
||||
// All conditions must be met (AND logic)
|
||||
return conditions.all { condition -> evaluateSingleCondition(condition, formElementsByRef) }
|
||||
}
|
||||
|
||||
private fun evaluateSingleCondition(
|
||||
condition: FormElementVisibilityCondition,
|
||||
formElementsByRef: Map<String, FormElementSnapshotDto>,
|
||||
): Boolean {
|
||||
val sourceElement = formElementsByRef[condition.sourceFormElementReference] ?: return false
|
||||
val sourceValue = getFormElementValue(sourceElement)
|
||||
|
||||
|
||||
@@ -3,7 +3,10 @@ package com.betriebsratkanzlei.legalconsenthub.application_form.export.latex
|
||||
object LatexEscaper {
|
||||
fun escape(text: String?): String {
|
||||
if (text == null) return ""
|
||||
return text
|
||||
// First decode common HTML entities that may be present in user input
|
||||
val decoded = decodeHtmlEntities(text)
|
||||
// Then escape for LaTeX
|
||||
return decoded
|
||||
.replace("\\", "\\textbackslash{}")
|
||||
.replace("{", "\\{")
|
||||
.replace("}", "\\}")
|
||||
@@ -16,4 +19,14 @@ object LatexEscaper {
|
||||
.replace("~", "\\textasciitilde{}")
|
||||
.replace("\n", "\\\\")
|
||||
}
|
||||
|
||||
private fun decodeHtmlEntities(text: String): String =
|
||||
text
|
||||
.replace("&", "&")
|
||||
.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
.replace(""", "\"")
|
||||
.replace("'", "'")
|
||||
.replace("'", "'")
|
||||
.replace(" ", " ")
|
||||
}
|
||||
|
||||
@@ -28,4 +28,5 @@ data class LatexFormElement(
|
||||
val title: String,
|
||||
val description: String?,
|
||||
val value: String,
|
||||
val isTable: Boolean = false,
|
||||
)
|
||||
|
||||
@@ -8,14 +8,14 @@ import com.betriebsratkanzlei.legalconsenthub.form_element.FormElement
|
||||
import com.betriebsratkanzlei.legalconsenthub.form_element.FormElementSection
|
||||
import com.betriebsratkanzlei.legalconsenthub.form_element.FormElementSubSection
|
||||
import com.betriebsratkanzlei.legalconsenthub.form_element.FormElementVisibilityConditionMapper
|
||||
import com.betriebsratkanzlei.legalconsenthub.form_element.FormOption
|
||||
import com.betriebsratkanzlei.legalconsenthub.form_element.FormOptionMapper
|
||||
import com.betriebsratkanzlei.legalconsenthub.form_element.SectionSpawnTriggerMapper
|
||||
import com.betriebsratkanzlei.legalconsenthub.form_element.TableRowPresetMapper
|
||||
import com.betriebsratkanzlei.legalconsenthub.user.User
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.ApplicationFormSnapshotDto
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.FormElementSectionSnapshotDto
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.FormElementSnapshotDto
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.FormElementSubSectionSnapshotDto
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.FormOptionDto
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
@@ -28,6 +28,8 @@ class ApplicationFormVersionService(
|
||||
private val objectMapper: ObjectMapper,
|
||||
private val spawnTriggerMapper: SectionSpawnTriggerMapper,
|
||||
private val visibilityConditionMapper: FormElementVisibilityConditionMapper,
|
||||
private val tableRowPresetMapper: TableRowPresetMapper,
|
||||
private val formOptionMapper: FormOptionMapper,
|
||||
) {
|
||||
@Transactional
|
||||
fun createVersion(
|
||||
@@ -123,26 +125,22 @@ class ApplicationFormVersionService(
|
||||
title = element.title,
|
||||
description = element.description,
|
||||
type = element.type,
|
||||
options =
|
||||
element.options.map { option ->
|
||||
FormOptionDto(
|
||||
value = option.value,
|
||||
label = option.label,
|
||||
processingPurpose = option.processingPurpose,
|
||||
employeeDataCategory = option.employeeDataCategory,
|
||||
)
|
||||
},
|
||||
visibilityCondition =
|
||||
element.visibilityCondition?.let {
|
||||
visibilityConditionMapper.toFormElementVisibilityConditionDto(
|
||||
it,
|
||||
)
|
||||
},
|
||||
sectionSpawnTrigger =
|
||||
element.sectionSpawnTrigger?.let {
|
||||
options = element.options.map { formOptionMapper.toFormOptionDto(it) },
|
||||
visibilityConditions =
|
||||
element.visibilityConditions
|
||||
.map {
|
||||
visibilityConditionMapper
|
||||
.toFormElementVisibilityConditionDto(it)
|
||||
},
|
||||
sectionSpawnTriggers =
|
||||
element.sectionSpawnTriggers.map {
|
||||
spawnTriggerMapper.toSectionSpawnTriggerDto(it)
|
||||
},
|
||||
isClonable = element.isClonable,
|
||||
tableRowPreset =
|
||||
element.tableRowPreset?.let {
|
||||
tableRowPresetMapper.toTableRowPresetDto(it)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -185,23 +183,23 @@ class ApplicationFormVersionService(
|
||||
formElementSubSection = subsection,
|
||||
options =
|
||||
elementSnapshot.options
|
||||
.map { optionDto ->
|
||||
FormOption(
|
||||
value = optionDto.value,
|
||||
label = optionDto.label,
|
||||
processingPurpose = optionDto.processingPurpose,
|
||||
employeeDataCategory = optionDto.employeeDataCategory,
|
||||
)
|
||||
}.toMutableList(),
|
||||
visibilityCondition =
|
||||
elementSnapshot.visibilityCondition?.let {
|
||||
visibilityConditionMapper.toFormElementVisibilityCondition(it)
|
||||
},
|
||||
sectionSpawnTrigger =
|
||||
elementSnapshot.sectionSpawnTrigger?.let {
|
||||
spawnTriggerMapper.toSectionSpawnTrigger(it)
|
||||
},
|
||||
.map { formOptionMapper.toFormOption(it) }
|
||||
.toMutableList(),
|
||||
visibilityConditions =
|
||||
elementSnapshot.visibilityConditions
|
||||
?.map { visibilityConditionMapper.toFormElementVisibilityCondition(it) }
|
||||
?.toMutableList()
|
||||
?: mutableListOf(),
|
||||
sectionSpawnTriggers =
|
||||
elementSnapshot.sectionSpawnTriggers
|
||||
?.map { spawnTriggerMapper.toSectionSpawnTrigger(it) }
|
||||
?.toMutableList()
|
||||
?: mutableListOf(),
|
||||
isClonable = elementSnapshot.isClonable ?: false,
|
||||
tableRowPreset =
|
||||
elementSnapshot.tableRowPreset?.let {
|
||||
tableRowPresetMapper.toTableRowPreset(it)
|
||||
},
|
||||
)
|
||||
subsection.formElements.add(element)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.betriebsratkanzlei.legalconsenthub.form_element
|
||||
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.FormElementType
|
||||
import jakarta.persistence.AttributeOverride
|
||||
import jakarta.persistence.AttributeOverrides
|
||||
import jakarta.persistence.CollectionTable
|
||||
import jakarta.persistence.Column
|
||||
import jakarta.persistence.ElementCollection
|
||||
@@ -28,9 +30,25 @@ class FormElement(
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "form_element_sub_section_id", nullable = false)
|
||||
var formElementSubSection: FormElementSubSection? = null,
|
||||
@Embedded
|
||||
var visibilityCondition: FormElementVisibilityCondition? = null,
|
||||
@Embedded
|
||||
var sectionSpawnTrigger: SectionSpawnTrigger? = null,
|
||||
@ElementCollection
|
||||
@CollectionTable(name = "visibility_conditions", joinColumns = [JoinColumn(name = "form_element_id")])
|
||||
var visibilityConditions: MutableList<FormElementVisibilityCondition> = mutableListOf(),
|
||||
@ElementCollection
|
||||
@CollectionTable(name = "section_spawn_triggers", joinColumns = [JoinColumn(name = "form_element_id")])
|
||||
var sectionSpawnTriggers: MutableList<SectionSpawnTrigger> = mutableListOf(),
|
||||
var isClonable: Boolean = false,
|
||||
@Embedded
|
||||
@AttributeOverrides(
|
||||
AttributeOverride(name = "sourceTableReference", column = Column(name = "row_preset_source_table_ref")),
|
||||
AttributeOverride(
|
||||
name = "filterCondition.sourceColumnIndex",
|
||||
column = Column(name = "row_preset_filter_src_col_idx"),
|
||||
),
|
||||
AttributeOverride(
|
||||
name = "filterCondition.expectedValue",
|
||||
column = Column(name = "row_preset_filter_expected_val"),
|
||||
),
|
||||
AttributeOverride(name = "filterCondition.operator", column = Column(name = "row_preset_filter_operator")),
|
||||
)
|
||||
var tableRowPreset: TableRowPreset? = null,
|
||||
)
|
||||
|
||||
@@ -8,6 +8,7 @@ class FormElementMapper(
|
||||
private val formOptionMapper: FormOptionMapper,
|
||||
private val visibilityConditionMapper: FormElementVisibilityConditionMapper,
|
||||
private val spawnTriggerMapper: SectionSpawnTriggerMapper,
|
||||
private val tableRowPresetMapper: TableRowPresetMapper,
|
||||
) {
|
||||
fun toFormElementDto(formElement: FormElement): FormElementDto =
|
||||
FormElementDto(
|
||||
@@ -20,15 +21,19 @@ class FormElementMapper(
|
||||
formElementSubSectionId =
|
||||
formElement.formElementSubSection?.id
|
||||
?: throw IllegalStateException("FormElementSubSection ID must not be null!"),
|
||||
visibilityCondition =
|
||||
formElement.visibilityCondition?.let {
|
||||
visibilityConditions =
|
||||
formElement.visibilityConditions.map {
|
||||
visibilityConditionMapper.toFormElementVisibilityConditionDto(it)
|
||||
},
|
||||
sectionSpawnTrigger =
|
||||
formElement.sectionSpawnTrigger?.let {
|
||||
sectionSpawnTriggers =
|
||||
formElement.sectionSpawnTriggers.map {
|
||||
spawnTriggerMapper.toSectionSpawnTriggerDto(it)
|
||||
},
|
||||
isClonable = formElement.isClonable,
|
||||
tableRowPreset =
|
||||
formElement.tableRowPreset?.let {
|
||||
tableRowPresetMapper.toTableRowPresetDto(it)
|
||||
},
|
||||
)
|
||||
|
||||
fun toFormElement(
|
||||
@@ -43,15 +48,21 @@ class FormElementMapper(
|
||||
options = formElement.options.map { formOptionMapper.toFormOption(it) }.toMutableList(),
|
||||
type = formElement.type,
|
||||
formElementSubSection = formElementSubSection,
|
||||
visibilityCondition =
|
||||
formElement.visibilityCondition?.let {
|
||||
visibilityConditionMapper.toFormElementVisibilityCondition(it)
|
||||
},
|
||||
sectionSpawnTrigger =
|
||||
formElement.sectionSpawnTrigger?.let {
|
||||
spawnTriggerMapper.toSectionSpawnTrigger(it)
|
||||
},
|
||||
visibilityConditions =
|
||||
formElement.visibilityConditions
|
||||
?.map { visibilityConditionMapper.toFormElementVisibilityCondition(it) }
|
||||
?.toMutableList()
|
||||
?: mutableListOf(),
|
||||
sectionSpawnTriggers =
|
||||
formElement.sectionSpawnTriggers
|
||||
?.map { spawnTriggerMapper.toSectionSpawnTrigger(it) }
|
||||
?.toMutableList()
|
||||
?: mutableListOf(),
|
||||
isClonable = formElement.isClonable ?: false,
|
||||
tableRowPreset =
|
||||
formElement.tableRowPreset?.let {
|
||||
tableRowPresetMapper.toTableRowPreset(it)
|
||||
},
|
||||
)
|
||||
|
||||
fun toNewFormElement(
|
||||
@@ -66,14 +77,20 @@ class FormElementMapper(
|
||||
options = formElement.options.map { formOptionMapper.toFormOption(it) }.toMutableList(),
|
||||
type = formElement.type,
|
||||
formElementSubSection = formElementSubSection,
|
||||
visibilityCondition =
|
||||
formElement.visibilityCondition?.let {
|
||||
visibilityConditionMapper.toFormElementVisibilityCondition(it)
|
||||
},
|
||||
sectionSpawnTrigger =
|
||||
formElement.sectionSpawnTrigger?.let {
|
||||
spawnTriggerMapper.toSectionSpawnTrigger(it)
|
||||
},
|
||||
visibilityConditions =
|
||||
formElement.visibilityConditions
|
||||
?.map { visibilityConditionMapper.toFormElementVisibilityCondition(it) }
|
||||
?.toMutableList()
|
||||
?: mutableListOf(),
|
||||
sectionSpawnTriggers =
|
||||
formElement.sectionSpawnTriggers
|
||||
?.map { spawnTriggerMapper.toSectionSpawnTrigger(it) }
|
||||
?.toMutableList()
|
||||
?: mutableListOf(),
|
||||
isClonable = formElement.isClonable ?: false,
|
||||
tableRowPreset =
|
||||
formElement.tableRowPreset?.let {
|
||||
tableRowPresetMapper.toTableRowPreset(it)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,8 +2,11 @@ package com.betriebsratkanzlei.legalconsenthub.form_element
|
||||
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.EmployeeDataCategory
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.ProcessingPurpose
|
||||
import jakarta.persistence.AttributeOverride
|
||||
import jakarta.persistence.AttributeOverrides
|
||||
import jakarta.persistence.Column
|
||||
import jakarta.persistence.Embeddable
|
||||
import jakarta.persistence.Embedded
|
||||
|
||||
@Embeddable
|
||||
class FormOption(
|
||||
@@ -15,4 +18,21 @@ class FormOption(
|
||||
var processingPurpose: ProcessingPurpose,
|
||||
@Column(nullable = false)
|
||||
var employeeDataCategory: EmployeeDataCategory,
|
||||
@Embedded
|
||||
@AttributeOverrides(
|
||||
AttributeOverride(name = "sourceTableReference", column = Column(name = "col_config_source_table_ref")),
|
||||
AttributeOverride(name = "sourceColumnIndex", column = Column(name = "col_config_source_col_idx")),
|
||||
AttributeOverride(
|
||||
name = "filterCondition.sourceColumnIndex",
|
||||
column = Column(name = "col_config_filter_src_col_idx"),
|
||||
),
|
||||
AttributeOverride(
|
||||
name = "filterCondition.expectedValue",
|
||||
column = Column(name = "col_config_filter_expected_val"),
|
||||
),
|
||||
AttributeOverride(name = "filterCondition.operator", column = Column(name = "col_config_filter_operator")),
|
||||
AttributeOverride(name = "isReadOnly", column = Column(name = "col_config_is_read_only")),
|
||||
AttributeOverride(name = "isCheckbox", column = Column(name = "col_config_is_checkbox")),
|
||||
)
|
||||
var columnConfig: TableColumnConfig? = null,
|
||||
)
|
||||
|
||||
@@ -4,13 +4,16 @@ import com.betriebsratkanzlei.legalconsenthub_api.model.FormOptionDto
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class FormOptionMapper {
|
||||
class FormOptionMapper(
|
||||
private val columnConfigMapper: TableColumnConfigMapper,
|
||||
) {
|
||||
fun toFormOptionDto(formOption: FormOption): FormOptionDto =
|
||||
FormOptionDto(
|
||||
value = formOption.value,
|
||||
label = formOption.label,
|
||||
processingPurpose = formOption.processingPurpose,
|
||||
employeeDataCategory = formOption.employeeDataCategory,
|
||||
columnConfig = formOption.columnConfig?.let { columnConfigMapper.toTableColumnConfigDto(it) },
|
||||
)
|
||||
|
||||
fun toFormOption(formOptionDto: FormOptionDto): FormOption =
|
||||
@@ -19,5 +22,6 @@ class FormOptionMapper {
|
||||
label = formOptionDto.label,
|
||||
processingPurpose = formOptionDto.processingPurpose,
|
||||
employeeDataCategory = formOptionDto.employeeDataCategory,
|
||||
columnConfig = formOptionDto.columnConfig?.let { columnConfigMapper.toTableColumnConfig(it) },
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.betriebsratkanzlei.legalconsenthub.form_element
|
||||
|
||||
import jakarta.persistence.AttributeOverride
|
||||
import jakarta.persistence.AttributeOverrides
|
||||
import jakarta.persistence.Column
|
||||
import jakarta.persistence.Embeddable
|
||||
import jakarta.persistence.Embedded
|
||||
|
||||
@Embeddable
|
||||
data class TableColumnConfig(
|
||||
val sourceTableReference: String? = null,
|
||||
val sourceColumnIndex: Int? = null,
|
||||
@Embedded
|
||||
val filterCondition: TableColumnFilter? = null,
|
||||
@Embedded
|
||||
@AttributeOverrides(
|
||||
AttributeOverride(name = "constraintTableReference", column = Column(name = "row_constraint_table_reference")),
|
||||
AttributeOverride(name = "constraintKeyColumnIndex", column = Column(name = "row_constraint_key_column_index")),
|
||||
AttributeOverride(
|
||||
name = "constraintValueColumnIndex",
|
||||
column = Column(name = "row_constraint_value_column_index"),
|
||||
),
|
||||
AttributeOverride(
|
||||
name = "currentRowKeyColumnIndex",
|
||||
column = Column(name = "row_constraint_current_row_key_column_index"),
|
||||
),
|
||||
)
|
||||
val rowConstraint: TableRowConstraint? = null,
|
||||
val isReadOnly: Boolean = false,
|
||||
val isMultipleAllowed: Boolean = false,
|
||||
val isCheckbox: Boolean = false,
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.betriebsratkanzlei.legalconsenthub.form_element
|
||||
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.TableColumnConfigDto
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class TableColumnConfigMapper(
|
||||
private val filterMapper: TableColumnFilterMapper,
|
||||
private val rowConstraintMapper: TableRowConstraintMapper,
|
||||
) {
|
||||
fun toTableColumnConfigDto(config: TableColumnConfig): TableColumnConfigDto =
|
||||
TableColumnConfigDto(
|
||||
sourceTableReference = config.sourceTableReference,
|
||||
sourceColumnIndex = config.sourceColumnIndex,
|
||||
filterCondition = config.filterCondition?.let { filterMapper.toTableColumnFilterDto(it) },
|
||||
rowConstraint = config.rowConstraint?.let { rowConstraintMapper.toTableRowConstraintDto(it) },
|
||||
isReadOnly = config.isReadOnly,
|
||||
isMultipleAllowed = config.isMultipleAllowed,
|
||||
isCheckbox = config.isCheckbox,
|
||||
)
|
||||
|
||||
fun toTableColumnConfig(dto: TableColumnConfigDto): TableColumnConfig =
|
||||
TableColumnConfig(
|
||||
sourceTableReference = dto.sourceTableReference,
|
||||
sourceColumnIndex = dto.sourceColumnIndex,
|
||||
filterCondition = dto.filterCondition?.let { filterMapper.toTableColumnFilter(it) },
|
||||
rowConstraint = dto.rowConstraint?.let { rowConstraintMapper.toTableRowConstraint(it) },
|
||||
isReadOnly = dto.isReadOnly ?: false,
|
||||
isMultipleAllowed = dto.isMultipleAllowed ?: false,
|
||||
isCheckbox = dto.isCheckbox ?: false,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.betriebsratkanzlei.legalconsenthub.form_element
|
||||
|
||||
import jakarta.persistence.Embeddable
|
||||
import jakarta.persistence.EnumType
|
||||
import jakarta.persistence.Enumerated
|
||||
|
||||
@Embeddable
|
||||
data class TableColumnFilter(
|
||||
val sourceColumnIndex: Int? = null,
|
||||
val expectedValue: String? = null,
|
||||
@Enumerated(EnumType.STRING)
|
||||
val operator: VisibilityConditionOperator = VisibilityConditionOperator.EQUALS,
|
||||
)
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.betriebsratkanzlei.legalconsenthub.form_element
|
||||
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.TableColumnFilterDto
|
||||
import org.springframework.stereotype.Component
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.VisibilityConditionOperator as VisibilityConditionOperatorDto
|
||||
|
||||
@Component
|
||||
class TableColumnFilterMapper {
|
||||
fun toTableColumnFilterDto(filter: TableColumnFilter): TableColumnFilterDto =
|
||||
TableColumnFilterDto(
|
||||
sourceColumnIndex = filter.sourceColumnIndex,
|
||||
expectedValue = filter.expectedValue,
|
||||
operator = filter.operator.toDto(),
|
||||
)
|
||||
|
||||
fun toTableColumnFilter(dto: TableColumnFilterDto): TableColumnFilter =
|
||||
TableColumnFilter(
|
||||
sourceColumnIndex = dto.sourceColumnIndex,
|
||||
expectedValue = dto.expectedValue,
|
||||
operator = dto.operator?.toEntity() ?: VisibilityConditionOperator.EQUALS,
|
||||
)
|
||||
|
||||
private fun VisibilityConditionOperator.toDto(): VisibilityConditionOperatorDto =
|
||||
when (this) {
|
||||
VisibilityConditionOperator.EQUALS -> VisibilityConditionOperatorDto.EQUALS
|
||||
VisibilityConditionOperator.NOT_EQUALS -> VisibilityConditionOperatorDto.NOT_EQUALS
|
||||
VisibilityConditionOperator.IS_EMPTY -> VisibilityConditionOperatorDto.IS_EMPTY
|
||||
VisibilityConditionOperator.IS_NOT_EMPTY -> VisibilityConditionOperatorDto.IS_NOT_EMPTY
|
||||
}
|
||||
|
||||
private fun VisibilityConditionOperatorDto.toEntity(): VisibilityConditionOperator =
|
||||
when (this) {
|
||||
VisibilityConditionOperatorDto.EQUALS -> VisibilityConditionOperator.EQUALS
|
||||
VisibilityConditionOperatorDto.NOT_EQUALS -> VisibilityConditionOperator.NOT_EQUALS
|
||||
VisibilityConditionOperatorDto.IS_EMPTY -> VisibilityConditionOperator.IS_EMPTY
|
||||
VisibilityConditionOperatorDto.IS_NOT_EMPTY -> VisibilityConditionOperator.IS_NOT_EMPTY
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.betriebsratkanzlei.legalconsenthub.form_element
|
||||
|
||||
import jakarta.persistence.Embeddable
|
||||
|
||||
@Embeddable
|
||||
data class TableColumnMapping(
|
||||
val sourceColumnIndex: Int,
|
||||
val targetColumnIndex: Int,
|
||||
)
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.betriebsratkanzlei.legalconsenthub.form_element
|
||||
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.TableColumnMappingDto
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class TableColumnMappingMapper {
|
||||
fun toTableColumnMappingDto(mapping: TableColumnMapping): TableColumnMappingDto =
|
||||
TableColumnMappingDto(
|
||||
sourceColumnIndex = mapping.sourceColumnIndex,
|
||||
targetColumnIndex = mapping.targetColumnIndex,
|
||||
)
|
||||
|
||||
fun toTableColumnMapping(dto: TableColumnMappingDto): TableColumnMapping =
|
||||
TableColumnMapping(
|
||||
sourceColumnIndex = dto.sourceColumnIndex ?: 0,
|
||||
targetColumnIndex = dto.targetColumnIndex ?: 0,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.betriebsratkanzlei.legalconsenthub.form_element
|
||||
|
||||
import jakarta.persistence.Embeddable
|
||||
|
||||
@Embeddable
|
||||
data class TableRowConstraint(
|
||||
val constraintTableReference: String? = null,
|
||||
val constraintKeyColumnIndex: Int? = null,
|
||||
val constraintValueColumnIndex: Int? = null,
|
||||
val currentRowKeyColumnIndex: Int? = null,
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.betriebsratkanzlei.legalconsenthub.form_element
|
||||
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.TableRowConstraintDto
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class TableRowConstraintMapper {
|
||||
fun toTableRowConstraintDto(constraint: TableRowConstraint): TableRowConstraintDto =
|
||||
TableRowConstraintDto(
|
||||
constraintTableReference = constraint.constraintTableReference,
|
||||
constraintKeyColumnIndex = constraint.constraintKeyColumnIndex,
|
||||
constraintValueColumnIndex = constraint.constraintValueColumnIndex,
|
||||
currentRowKeyColumnIndex = constraint.currentRowKeyColumnIndex,
|
||||
)
|
||||
|
||||
fun toTableRowConstraint(dto: TableRowConstraintDto): TableRowConstraint =
|
||||
TableRowConstraint(
|
||||
constraintTableReference = dto.constraintTableReference,
|
||||
constraintKeyColumnIndex = dto.constraintKeyColumnIndex,
|
||||
constraintValueColumnIndex = dto.constraintValueColumnIndex,
|
||||
currentRowKeyColumnIndex = dto.currentRowKeyColumnIndex,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.betriebsratkanzlei.legalconsenthub.form_element
|
||||
|
||||
import jakarta.persistence.CollectionTable
|
||||
import jakarta.persistence.ElementCollection
|
||||
import jakarta.persistence.Embeddable
|
||||
import jakarta.persistence.Embedded
|
||||
import jakarta.persistence.JoinColumn
|
||||
|
||||
@Embeddable
|
||||
data class TableRowPreset(
|
||||
val sourceTableReference: String? = null,
|
||||
@Embedded
|
||||
val filterCondition: TableColumnFilter? = null,
|
||||
@ElementCollection
|
||||
@CollectionTable(name = "table_column_mappings", joinColumns = [JoinColumn(name = "form_element_id")])
|
||||
val columnMappings: MutableList<TableColumnMapping> = mutableListOf(),
|
||||
val canAddRows: Boolean? = null,
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.betriebsratkanzlei.legalconsenthub.form_element
|
||||
|
||||
import com.betriebsratkanzlei.legalconsenthub_api.model.TableRowPresetDto
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
@Component
|
||||
class TableRowPresetMapper(
|
||||
private val filterMapper: TableColumnFilterMapper,
|
||||
private val mappingMapper: TableColumnMappingMapper,
|
||||
) {
|
||||
fun toTableRowPresetDto(preset: TableRowPreset): TableRowPresetDto =
|
||||
TableRowPresetDto(
|
||||
sourceTableReference = preset.sourceTableReference,
|
||||
filterCondition = preset.filterCondition?.let { filterMapper.toTableColumnFilterDto(it) },
|
||||
columnMappings = preset.columnMappings.map { mappingMapper.toTableColumnMappingDto(it) },
|
||||
canAddRows = preset.canAddRows ?: true,
|
||||
)
|
||||
|
||||
fun toTableRowPreset(dto: TableRowPresetDto): TableRowPreset =
|
||||
TableRowPreset(
|
||||
sourceTableReference = dto.sourceTableReference,
|
||||
filterCondition = dto.filterCondition?.let { filterMapper.toTableColumnFilter(it) },
|
||||
columnMappings =
|
||||
dto.columnMappings?.map { mappingMapper.toTableColumnMapping(it) }?.toMutableList() ?: mutableListOf(),
|
||||
canAddRows = dto.canAddRows,
|
||||
)
|
||||
}
|
||||
@@ -53,33 +53,43 @@ create table comment
|
||||
|
||||
create table form_element_options
|
||||
(
|
||||
employee_data_category smallint not null check (employee_data_category between 0 and 3),
|
||||
processing_purpose smallint not null check (processing_purpose between 0 and 3),
|
||||
form_element_id uuid not null,
|
||||
label varchar(255) not null,
|
||||
option_value TEXT not null
|
||||
col_config_filter_src_col_idx integer,
|
||||
col_config_is_checkbox boolean,
|
||||
col_config_is_read_only boolean,
|
||||
col_config_source_col_idx integer,
|
||||
employee_data_category smallint not null check (employee_data_category between 0 and 3),
|
||||
is_multiple_allowed boolean,
|
||||
processing_purpose smallint not null check (processing_purpose between 0 and 3),
|
||||
row_constraint_current_row_key_column_index integer,
|
||||
row_constraint_key_column_index integer,
|
||||
row_constraint_value_column_index integer,
|
||||
form_element_id uuid not null,
|
||||
col_config_filter_expected_val varchar(255),
|
||||
col_config_filter_operator varchar(255) check (col_config_filter_operator in
|
||||
('EQUALS', 'NOT_EQUALS', 'IS_EMPTY',
|
||||
'IS_NOT_EMPTY')),
|
||||
col_config_source_table_ref varchar(255),
|
||||
label varchar(255) not null,
|
||||
option_value TEXT not null,
|
||||
row_constraint_table_reference varchar(255)
|
||||
);
|
||||
|
||||
create table form_element
|
||||
(
|
||||
form_element_order integer,
|
||||
is_clonable boolean not null,
|
||||
type smallint not null check (type between 0 and 7),
|
||||
form_element_sub_section_id uuid not null,
|
||||
id uuid not null,
|
||||
description varchar(255),
|
||||
form_element_condition_type varchar(255) check (form_element_condition_type in ('SHOW', 'HIDE')),
|
||||
form_element_expected_value varchar(255),
|
||||
form_element_operator varchar(255) check (form_element_operator in
|
||||
('EQUALS', 'NOT_EQUALS', 'IS_EMPTY', 'IS_NOT_EMPTY')),
|
||||
reference varchar(255),
|
||||
section_spawn_condition_type varchar(255) check (section_spawn_condition_type in ('SHOW', 'HIDE')),
|
||||
section_spawn_expected_value varchar(255),
|
||||
section_spawn_operator varchar(255) check (section_spawn_operator in
|
||||
('EQUALS', 'NOT_EQUALS', 'IS_EMPTY', 'IS_NOT_EMPTY')),
|
||||
source_form_element_reference varchar(255),
|
||||
template_reference varchar(255),
|
||||
title varchar(255),
|
||||
can_add_rows boolean,
|
||||
form_element_order integer,
|
||||
is_clonable boolean not null,
|
||||
row_preset_filter_src_col_idx integer,
|
||||
type smallint not null check (type between 0 and 8),
|
||||
form_element_sub_section_id uuid not null,
|
||||
id uuid not null,
|
||||
description varchar(255),
|
||||
reference varchar(255),
|
||||
row_preset_filter_expected_val varchar(255),
|
||||
row_preset_filter_operator varchar(255) check (row_preset_filter_operator in
|
||||
('EQUALS', 'NOT_EQUALS', 'IS_EMPTY', 'IS_NOT_EMPTY')),
|
||||
row_preset_source_table_ref varchar(255),
|
||||
title varchar(255),
|
||||
primary key (id)
|
||||
);
|
||||
|
||||
@@ -122,6 +132,33 @@ create table notification
|
||||
primary key (id)
|
||||
);
|
||||
|
||||
create table section_spawn_triggers
|
||||
(
|
||||
form_element_id uuid not null,
|
||||
section_spawn_condition_type varchar(255) check (section_spawn_condition_type in ('SHOW', 'HIDE')),
|
||||
section_spawn_expected_value varchar(255),
|
||||
section_spawn_operator varchar(255) check (section_spawn_operator in
|
||||
('EQUALS', 'NOT_EQUALS', 'IS_EMPTY', 'IS_NOT_EMPTY')),
|
||||
template_reference varchar(255)
|
||||
);
|
||||
|
||||
create table table_column_mappings
|
||||
(
|
||||
source_column_index integer,
|
||||
target_column_index integer,
|
||||
form_element_id uuid not null
|
||||
);
|
||||
|
||||
create table visibility_conditions
|
||||
(
|
||||
form_element_id uuid not null,
|
||||
form_element_condition_type varchar(255) check (form_element_condition_type in ('SHOW', 'HIDE')),
|
||||
form_element_expected_value varchar(255),
|
||||
form_element_operator varchar(255) check (form_element_operator in
|
||||
('EQUALS', 'NOT_EQUALS', 'IS_EMPTY', 'IS_NOT_EMPTY')),
|
||||
source_form_element_reference varchar(255)
|
||||
);
|
||||
|
||||
alter table if exists application_form
|
||||
add constraint FKhtad5onoy2jknhtyfmx6cvvey
|
||||
foreign key (created_by_id)
|
||||
@@ -182,3 +219,18 @@ alter table if exists notification
|
||||
add constraint FKeg1j4hnp0y4lbm0y35hgr4e8r
|
||||
foreign key (recipient_id)
|
||||
references app_user;
|
||||
|
||||
alter table if exists section_spawn_triggers
|
||||
add constraint FK7lf0hf8cepm2o9nty147x2ahm
|
||||
foreign key (form_element_id)
|
||||
references form_element;
|
||||
|
||||
alter table if exists table_column_mappings
|
||||
add constraint FK2t3a4fl5kqtqky39r7boqegf9
|
||||
foreign key (form_element_id)
|
||||
references form_element;
|
||||
|
||||
alter table if exists visibility_conditions
|
||||
add constraint FK5xuf7bd179ogpq5a1m3g8q7jb
|
||||
foreign key (form_element_id)
|
||||
references form_element;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,6 +15,12 @@
|
||||
\usepackage{xcolor}
|
||||
\usepackage{tcolorbox}
|
||||
\usepackage[normalem]{ulem}
|
||||
\usepackage{tabularx}
|
||||
\usepackage{array}
|
||||
\usepackage{booktabs}
|
||||
|
||||
% Define column type for auto-wrapping text
|
||||
\newcolumntype{Y}{>{\raggedright\arraybackslash}X}
|
||||
|
||||
\hypersetup{
|
||||
colorlinks=true,
|
||||
@@ -73,12 +79,22 @@ Dieses Dokument enthält die Details der Betriebsvereinbarung "[[${applicationFo
|
||||
\textit{\small [[${element.description}]]}
|
||||
[/]
|
||||
|
||||
[# th:if="${element.isTable}"]
|
||||
\vspace{0.5em}
|
||||
\noindent
|
||||
\small
|
||||
[(${element.value})]
|
||||
\normalsize
|
||||
\vspace{0.5em}
|
||||
[/]
|
||||
[# th:if="${!element.isTable}"]
|
||||
\begin{tcolorbox}[colback=gray!5, colframe=gray!20, arc=0mm, boxrule=0.5pt]
|
||||
[[${element.value}]]
|
||||
\end{tcolorbox}
|
||||
[/]
|
||||
[/]
|
||||
[/]
|
||||
[/]
|
||||
|
||||
\vspace{3cm}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user