From 46d643174791e5b1294de661a1a5fc1358c0c840 Mon Sep 17 00:00:00 2001 From: Denis Lugowski Date: Tue, 23 Dec 2025 19:19:06 +0100 Subject: [PATCH] feat(#28): Initialize backend with application form template --- CLAUDE.md | 2 +- .../application_form/ApplicationFormMapper.kt | 12 +++- .../ApplicationFormRepository.kt | 2 + .../InitialApplicationFormTemplateSeeder.kt | 69 +++++++++++++++++++ .../initial_application_form_template.json | 0 5 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/seed/InitialApplicationFormTemplateSeeder.kt rename testdata.json => legalconsenthub-backend/src/main/resources/seed/initial_application_form_template.json (100%) diff --git a/CLAUDE.md b/CLAUDE.md index ac9fc20..506fc67 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -770,5 +770,5 @@ act -n - CI/CD Pipeline: `.github/workflows/pipeline.yaml` - Act Configuration: `.actrc` and `.secrets.example` - Database Management Script: `manage-db.sh` -- Test Data: `testdata.json` +- Initial Application Form Template: `initial_application_form_template.json` - IT System Config: `it-system.json` 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 bb342f1..9febeff 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,6 +1,7 @@ package com.betriebsratkanzlei.legalconsenthub.application_form import com.betriebsratkanzlei.legalconsenthub.form_element.FormElementSectionMapper +import com.betriebsratkanzlei.legalconsenthub.user.User import com.betriebsratkanzlei.legalconsenthub.user.UserMapper import com.betriebsratkanzlei.legalconsenthub.user.UserService import com.betriebsratkanzlei.legalconsenthub_api.model.ApplicationFormDto @@ -37,6 +38,13 @@ class ApplicationFormMapper( fun toNewApplicationForm(applicationFormDto: ApplicationFormDto): ApplicationForm { val currentUser = userService.getCurrentUser() + return toNewApplicationForm(applicationFormDto, currentUser) + } + + fun toNewApplicationForm( + applicationFormDto: ApplicationFormDto, + user: User, + ): ApplicationForm { val applicationForm = ApplicationForm( id = null, @@ -46,8 +54,8 @@ class ApplicationFormMapper( status = applicationFormDto.status ?: com.betriebsratkanzlei.legalconsenthub_api.model.ApplicationFormStatus.DRAFT, - createdBy = currentUser, - lastModifiedBy = currentUser, + createdBy = user, + lastModifiedBy = user, ) applicationForm.formElementSections = applicationFormDto.formElementSections diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormRepository.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormRepository.kt index 9ebc98d..f74c05b 100644 --- a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormRepository.kt +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/application_form/ApplicationFormRepository.kt @@ -11,6 +11,8 @@ import java.util.UUID interface ApplicationFormRepository : JpaRepository { fun findAllByIsTemplateTrue(page: Pageable): Page + fun existsByIsTemplateTrue(): Boolean + @Query( "SELECT c FROM ApplicationForm c WHERE (c.isTemplate IS false) AND (:organizationId is null or c.organizationId = :organizationId)", ) diff --git a/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/seed/InitialApplicationFormTemplateSeeder.kt b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/seed/InitialApplicationFormTemplateSeeder.kt new file mode 100644 index 0000000..aa3262a --- /dev/null +++ b/legalconsenthub-backend/src/main/kotlin/com/betriebsratkanzlei/legalconsenthub/seed/InitialApplicationFormTemplateSeeder.kt @@ -0,0 +1,69 @@ +package com.betriebsratkanzlei.legalconsenthub.seed + +import com.betriebsratkanzlei.legalconsenthub.application_form.ApplicationFormMapper +import com.betriebsratkanzlei.legalconsenthub.application_form.ApplicationFormRepository +import com.betriebsratkanzlei.legalconsenthub.user.User +import com.betriebsratkanzlei.legalconsenthub.user.UserRepository +import com.betriebsratkanzlei.legalconsenthub_api.model.ApplicationFormDto +import com.fasterxml.jackson.databind.ObjectMapper +import org.slf4j.LoggerFactory +import org.springframework.boot.ApplicationArguments +import org.springframework.boot.ApplicationRunner +import org.springframework.core.io.ClassPathResource +import org.springframework.stereotype.Component +import org.springframework.transaction.annotation.Transactional + +@Component +class InitialApplicationFormTemplateSeeder( + private val applicationFormRepository: ApplicationFormRepository, + private val applicationFormMapper: ApplicationFormMapper, + private val userRepository: UserRepository, + private val objectMapper: ObjectMapper, +) : ApplicationRunner { + override fun run(args: ApplicationArguments) { + seedInitialTemplateIfMissing() + } + + @Transactional + fun seedInitialTemplateIfMissing() { + if (applicationFormRepository.existsByIsTemplateTrue()) { + log.info( + "At least one application form template already present, skipping initial template seed", + ) + return + } + + val seedingUser = getOrCreateSeedingUser() + val dto = loadInitialTemplateDto() + val applicationForm = applicationFormMapper.toNewApplicationForm(dto.copy(isTemplate = true), seedingUser) + + applicationFormRepository.save(applicationForm) + log.info("Seeded initial application form template (name={})", applicationForm.name) + } + + private fun loadInitialTemplateDto(): ApplicationFormDto = + ClassPathResource(INITIAL_TEMPLATE_RESOURCE_PATH).inputStream.use { inputStream -> + objectMapper.readValue(inputStream, ApplicationFormDto::class.java) + } + + private fun getOrCreateSeedingUser(): User { + val existing = userRepository.findById(SEEDING_USER_ID) + if (existing.isPresent) return existing.get() + + val user = + User( + keycloakId = SEEDING_USER_ID, + name = "System Seeder", + organizationId = null, + email = null, + ) + return userRepository.save(user) + } + + companion object { + private val log = LoggerFactory.getLogger(InitialApplicationFormTemplateSeeder::class.java) + + private const val INITIAL_TEMPLATE_RESOURCE_PATH = "seed/initial_application_form_template.json" + private const val SEEDING_USER_ID = "system-seeder" + } +} diff --git a/testdata.json b/legalconsenthub-backend/src/main/resources/seed/initial_application_form_template.json similarity index 100% rename from testdata.json rename to legalconsenthub-backend/src/main/resources/seed/initial_application_form_template.json