diff --git a/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/IntegrationTestBase.kt b/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/IntegrationTestBase.kt index eb2379c..e362eb4 100644 --- a/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/IntegrationTestBase.kt +++ b/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/IntegrationTestBase.kt @@ -1,10 +1,13 @@ package uk.gov.justice.digital.hmpps.jobsboardintegrationapi.integration import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.extension.ExtendWith import org.mockito.junit.jupiter.MockitoExtension import org.mockito.kotlin.whenever import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace.NONE import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT import org.springframework.http.HttpHeaders @@ -37,6 +40,8 @@ import java.util.* MockitoExtension::class, ) @SpringBootTest(webEnvironment = RANDOM_PORT) +@AutoConfigureTestDatabase(replace = NONE) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) @ActiveProfiles("test") abstract class IntegrationTestBase { diff --git a/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/config/TestJpaConfig.kt b/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/config/TestJpaConfig.kt new file mode 100644 index 0000000..2f6fd14 --- /dev/null +++ b/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/config/TestJpaConfig.kt @@ -0,0 +1,22 @@ +package uk.gov.justice.digital.hmpps.jobsboardintegrationapi.integration.config + +import org.mockito.Mockito.mock +import org.springframework.boot.test.context.TestConfiguration +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Primary +import org.springframework.context.annotation.Profile +import org.springframework.data.auditing.DateTimeProvider +import org.springframework.data.jpa.repository.config.EnableJpaAuditing + +@TestConfiguration +@EnableJpaAuditing(dateTimeProviderRef = "dateTimeProvider") +@ComponentScan(basePackages = ["uk.gov.justice.digital.hmpps.jobsboardintegrationapi.integration.shared.infrastructure"]) +@Profile("test", "test-repo") +class TestJpaConfig { + @Primary + @Bean + fun dateTimeProvider(): DateTimeProvider { + return mock(DateTimeProvider::class.java) + } +} diff --git a/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/employers/infrastructure/EmployerExternalIdKeyRepositoryShould.kt b/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/employers/infrastructure/EmployerExternalIdKeyRepositoryShould.kt new file mode 100644 index 0000000..4c7f4d5 --- /dev/null +++ b/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/employers/infrastructure/EmployerExternalIdKeyRepositoryShould.kt @@ -0,0 +1,162 @@ +package uk.gov.justice.digital.hmpps.jobsboardintegrationapi.integration.employers.infrastructure + +import org.assertj.core.api.Assertions.assertThat +import org.hibernate.exception.ConstraintViolationException +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.springframework.dao.DataIntegrityViolationException +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.employers.domain.EmployerExternalId +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.employers.domain.EmployerObjects.sainsburys +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.employers.domain.EmployerObjects.tesco +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.integration.shared.infrastructure.RepositoryTestCase +import kotlin.test.assertFailsWith + +class EmployerExternalIdKeyRepositoryShould : RepositoryTestCase() { + + @Test + fun `return empty list, when nothing has been created yet`() { + employerExternalIdRepository.findAll().let { + assertThat(it).isEmpty() + } + } + + @Test + fun `return nothing, for any employer ID`() { + val employerId = randomId() + val actual = employerExternalIdRepository.findByKeyId(employerId) + assertThat(actual).isNull() + } + + @Test + fun `return nothing, for any employer external ID`() { + val externalId = randomExtId() + + val actual = employerExternalIdRepository.findByKeyExternalId(externalId) + assertThat(actual).isNull() + } + + @Nested + @DisplayName("Given an employer has been created") + inner class GivenAnEmployer { + private val employer = sainsburys + private val expectedExtId = randomExtId() + private val externalId = EmployerExternalId(employer.id, expectedExtId) + + @Nested + @DisplayName("And no external ID mapping has been created, for the given employer") + inner class AndNoExternalIdMapping { + @Test + fun `return nothing, for given employer ID`() { + val actual = employerExternalIdRepository.findByKeyId(employer.id) + assertThat(actual).isNull() + } + + @Test + fun `create external ID mapping`() { + val savedExternalId = employerExternalIdRepository.save(externalId) + + assertThat(savedExternalId.key.id).isEqualTo(employer.id) + assertThat(savedExternalId.key.externalId).isEqualTo(expectedExtId) + assertThat(savedExternalId).isEqualTo(externalId) + } + + @Test + fun `record timestamps, when creating external ID mapping`() { + val savedExternalId = employerExternalIdRepository.save(externalId) + with(savedExternalId) { + assertThat(this.createdAt).isEqualTo(currentTime) + assertThat(this.lastModifiedAt).isEqualTo(currentTime) + } + } + } + + @Nested + @DisplayName("And external ID mapping has been created, for the given employer") + inner class AndExternalIdMappingCreated { + + @BeforeEach + internal fun setUp() { + employerExternalIdRepository.saveAndFlush(externalId) + } + + @Test + fun `return employer external ID mapping, for given employer ID`() { + val actual = employerExternalIdRepository.findByKeyId(employer.id) + assertThat(actual).isNotNull.isEqualTo(externalId) + } + + @Test + fun `return employer external ID mapping, for given employer external ID`() { + val actual = employerExternalIdRepository.findByKeyExternalId(expectedExtId) + assertThat(actual).isNotNull.isEqualTo(externalId) + } + + @Test + fun `throw error, when creating with duplicate ID`() { + val newExternalId = EmployerExternalId(employer.id, randomExtId()) + + val exception = assertFailsWith { + employerExternalIdRepository.saveAndFlush(newExternalId) + } + + assertThat(exception.cause).isInstanceOfAny(ConstraintViolationException::class.java) + exception.cause!!.message!!.let { + assertThat(it) + .contains("ERROR: duplicate key value violates unique constraint") + .contains(employer.id) + } + } + } + } + + @Nested + @DisplayName("Given two employers have been created") + inner class GivenTwoEmployers { + private val employerA = sainsburys + private val externalIdOfEmployerA = randomExtId() + private val employerB = tesco + + private val employerExternalIdOfA = EmployerExternalId(employerA.id, externalIdOfEmployerA) + + @BeforeEach + internal fun setUp() { + employerExternalIdRepository.saveAndFlush(employerExternalIdOfA) + } + + @Test + fun `return nothing, for the employer without external ID mapped`() { + val actual = employerExternalIdRepository.findByKeyId(employerB.id) + assertThat(actual).isNull() + } + + @Test + fun `throw error, when creating with duplicate external ID`() { + val newExternalId = EmployerExternalId(employerB.id, externalIdOfEmployerA) + + val exception = assertFailsWith { + employerExternalIdRepository.saveAndFlush(newExternalId) + } + + assertThat(exception.cause).isInstanceOfAny(ConstraintViolationException::class.java) + exception.cause!!.message!!.let { + assertThat(it) + .contains("ERROR: duplicate key value violates unique constraint") + .contains(externalIdOfEmployerA.toString()) + } + } + + @Test + fun `create external ID mapping, without any duplicate ID or external ID`() { + val newExtId = randomExtId() + val newExternalId = EmployerExternalId(employerB.id, newExtId) + + val savedExternalId = employerExternalIdRepository.saveAndFlush(newExternalId) + + assertThat(savedExternalId.key.id).isEqualTo(employerB.id) + assertThat(savedExternalId.key.externalId).isEqualTo(newExtId) + assertThat(savedExternalId).isEqualTo(newExternalId) + } + } +} diff --git a/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/refdata/infrastructure/RefDataMappingRepositoryShould.kt b/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/refdata/infrastructure/RefDataMappingRepositoryShould.kt new file mode 100644 index 0000000..6c21dc8 --- /dev/null +++ b/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/refdata/infrastructure/RefDataMappingRepositoryShould.kt @@ -0,0 +1,63 @@ +package uk.gov.justice.digital.hmpps.jobsboardintegrationapi.integration.refdata.infrastructure + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.integration.shared.infrastructure.RepositoryTestCase +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.refdata.domain.RefDataMappingKey +import kotlin.test.assertTrue + +class RefDataMappingRepositoryShould : RepositoryTestCase() { + @Test + fun `return non empty list of reference data mapping(s)`() { + val refDataMappings = this.refDataMappingRepository.findAll() + assertThat(refDataMappings).isNotEmpty + } + + @Test + fun `return nothing for undefined reference data`() { + val unknownRefKey = RefDataMappingKey() + val refDataMapping = this.refDataMappingRepository.findById(unknownRefKey) + + assertTrue(refDataMapping.isEmpty, "Nothing should be found!") + } + + @Test + fun `return correct mapping, given reference data and data value`() { + val refData = "employer_status" + val dataValue = "GOLD" + val expectedExtId = 2L + + val mapping = refDataMappingRepository.findByDataRefDataAndDataValue(refData, dataValue) + + assertThat(mapping).hasSize(1) + assertThat(mapping.first().data.externalId).isEqualTo(expectedExtId) + } + + @Test + fun `return correct mapping, given reference data and data external ID`() { + val refData = "employer_sector" + val dataExternalId = 6L + val expectedDataValue = "CONSTRUCTION" + + val mapping = refDataMappingRepository.findByDataRefDataAndDataExternalId(refData, dataExternalId) + assertThat(mapping).hasSize(1) + assertThat(mapping.first().data.value).isEqualTo(expectedDataValue) + } + + @Nested + @DisplayName("Given reference data mappings for employer") + inner class GivenRefDataMappingsForEmployer { + @Test + fun `return mappings of Employer Status`() = assertRefDataMappingsHasSize("employer_status", 3) + + @Test + fun `return mappings of Employer Sector`() = assertRefDataMappingsHasSize("employer_sector", 19) + } + + private fun assertRefDataMappingsHasSize(refData: String, expectedSize: Int) { + val refDataMappings = this.refDataMappingRepository.findByDataRefData(refData) + assertThat(refDataMappings).hasSize(expectedSize) + } +} diff --git a/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/shared/infrastructure/RepositoryTestCase.kt b/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/shared/infrastructure/RepositoryTestCase.kt new file mode 100644 index 0000000..aaefd20 --- /dev/null +++ b/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/integration/shared/infrastructure/RepositoryTestCase.kt @@ -0,0 +1,112 @@ +package uk.gov.justice.digital.hmpps.jobsboardintegrationapi.integration.shared.infrastructure + +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.TestInstance +import org.mockito.kotlin.whenever +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace.NONE +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.context.annotation.Import +import org.springframework.data.auditing.DateTimeProvider +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.context.DynamicPropertyRegistry +import org.springframework.test.context.DynamicPropertySource +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.employers.domain.EmployerExternalIdRepository +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.integration.config.TestJpaConfig +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.integration.testcontainers.PostgresContainer +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.refdata.domain.RefDataMapping +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.refdata.domain.RefDataMappingKey +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.refdata.domain.RefDataMappingRepository +import java.security.SecureRandom +import java.time.Instant +import java.util.* + +@DataJpaTest +@Import(TestJpaConfig::class) +@AutoConfigureTestDatabase(replace = NONE) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@ActiveProfiles("test-repo") +abstract class RepositoryTestCase { + @Autowired + protected lateinit var dateTimeProvider: DateTimeProvider + + @Autowired + protected lateinit var refDataMappingRepository: RefDataMappingRepository + + @Autowired + protected lateinit var employerExternalIdRepository: EmployerExternalIdRepository + + @Autowired + private lateinit var refDataMappingTestOnlyRepository: RefDataMappingTestOnlyRepository + + protected final val defaultCurrentTime: Instant = Instant.parse("2025-01-01T00:00:00.00Z") + + protected val currentTime: Instant get() = defaultCurrentTime + + companion object { + private val postgresContainer = PostgresContainer.repositoryContainer + + @JvmStatic + @DynamicPropertySource + fun configureTestContainers(registry: DynamicPropertyRegistry) { + postgresContainer?.run { + registry.add("spring.datasource.url", postgresContainer::getJdbcUrl) + registry.add("spring.datasource.username", postgresContainer::getUsername) + registry.add("spring.datasource.password", postgresContainer::getPassword) + } + } + } + + @BeforeAll + fun setUpClass() { + refDataMappingTestOnlyRepository.saveAll(refDataMappingsForTests) + } + + @BeforeEach + fun setUp() { + employerExternalIdRepository.deleteAll() + + whenever(dateTimeProvider.now).thenAnswer { Optional.of(currentTime) } + } + + protected fun randomId() = UUID.randomUUID().toString() + protected fun randomExtId() = SecureRandom().nextLong() + + private val refDataMappingsForTests: List + get() = mapOf( + "employer_status" to mapOf( + "KEY_PARTNER" to 1L, + "GOLD" to 2, + "SILVER" to 3, + ), + "employer_sector" to mapOf( + "ADMIN_SUPPORT" to 14L, + "AGRICULTURE" to 1, + "ARTS_ENTERTAINMENT" to 18, + "CONSTRUCTION" to 6, + "EDUCATION" to 16, + "ENERGY" to 4, + "FINANCE" to 11, + "HEALTH_SOCIAL" to 17, + "HOSPITALITY_CATERING" to 9, + "LOGISTICS" to 8, + "MANUFACTURING" to 3, + "MINING" to 2, + "OTHER" to 19, + "PROFESSIONALS_SCIENTISTS_TECHNICIANS" to 13, + "PROPERTY" to 12, + "PUBLIC_ADMIN_DEFENCE" to 15, + "WASTE_MANAGEMENT" to 5, + "RETAIL" to 7, + "TECHNOLOGY" to 10, + ), + ).map { (refData, mapping) -> mapping.map { (value, externalId) -> RefDataMapping(refData, value, externalId) } } + .flatten() +} + +@Repository +internal interface RefDataMappingTestOnlyRepository : JpaRepository diff --git a/src/integrationTest/resources/application-test-repo.yml b/src/integrationTest/resources/application-test-repo.yml new file mode 100644 index 0000000..e826a1f --- /dev/null +++ b/src/integrationTest/resources/application-test-repo.yml @@ -0,0 +1,20 @@ +spring: + datasource: + url: 'jdbc:postgresql://${DATABASE_ENDPOINT}/${DATABASE_NAME}?sslmode=disable&autosave=conservative' + + jpa: + hibernate: + ddl-auto: create + show-sql: true + properties: + hibernate: + format_sql: true + + flyway: + enabled: false + +logging: + level: + org.hibernate.orm.jdbc.bind: trace + org.hibernate.sql: DEBUG + org.hibernate.type.descriptor.sql.BasicBinder: TRACE diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/employers/domain/EmployerExternalId.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/employers/domain/EmployerExternalId.kt new file mode 100644 index 0000000..31bfe69 --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/employers/domain/EmployerExternalId.kt @@ -0,0 +1,16 @@ +package uk.gov.justice.digital.hmpps.jobsboardintegrationapi.employers.domain + +import jakarta.persistence.EmbeddedId +import jakarta.persistence.Entity +import jakarta.persistence.Table +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.shared.domain.Auditable +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.shared.domain.ExternalIdKey + +@Entity +@Table(name = "employers_ext_ids") +data class EmployerExternalId( + @EmbeddedId var key: ExternalIdKey, +) : Auditable() { + constructor(id: String, externalId: Long) : this(ExternalIdKey(id, externalId)) + constructor() : this("", 0) +} diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/employers/domain/EmployerExternalIdRepository.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/employers/domain/EmployerExternalIdRepository.kt new file mode 100644 index 0000000..9681f34 --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/employers/domain/EmployerExternalIdRepository.kt @@ -0,0 +1,11 @@ +package uk.gov.justice.digital.hmpps.jobsboardintegrationapi.employers.domain + +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.shared.domain.ExternalIdKey + +@Repository +interface EmployerExternalIdRepository : JpaRepository { + fun findByKeyId(id: String): EmployerExternalId? + fun findByKeyExternalId(externalId: Long): EmployerExternalId? +} diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/refdata/domain/RefDataMapping.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/refdata/domain/RefDataMapping.kt new file mode 100644 index 0000000..bf18f1b --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/refdata/domain/RefDataMapping.kt @@ -0,0 +1,36 @@ +package uk.gov.justice.digital.hmpps.jobsboardintegrationapi.refdata.domain + +import jakarta.persistence.Column +import jakarta.persistence.Embeddable +import jakarta.persistence.EmbeddedId +import jakarta.persistence.Entity +import jakarta.persistence.Table +import org.springframework.stereotype.Repository +import uk.gov.justice.digital.hmpps.jobsboardintegrationapi.shared.domain.ReadOnlyRepository + +@Entity +@Table(name = "ref_data_mappings") +data class RefDataMapping( + @EmbeddedId var data: RefDataMappingKey, +) { + constructor(refData: String, value: String, externalId: Long) : this(RefDataMappingKey(refData, value, externalId)) + constructor() : this(RefDataMappingKey()) +} + +@Embeddable +data class RefDataMappingKey( + @Column(name = "ref_data") val refData: String, + @Column(name = "value") val value: String, + @Column(name = "ext_id") val externalId: Long, +) { + constructor() : this("", "", 0) +} + +@Repository +interface RefDataMappingRepository : ReadOnlyRepository { + fun findByDataRefData(refData: String): List + + fun findByDataRefDataAndDataValue(refData: String, dataValue: String): List + + fun findByDataRefDataAndDataExternalId(refData: String, dataExternalId: Long): List +} diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/shared/domain/Auditable.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/shared/domain/Auditable.kt new file mode 100644 index 0000000..fa66458 --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/shared/domain/Auditable.kt @@ -0,0 +1,22 @@ +package uk.gov.justice.digital.hmpps.jobsboardintegrationapi.shared.domain + +import jakarta.persistence.Column +import jakarta.persistence.EntityListeners +import jakarta.persistence.MappedSuperclass +import org.springframework.data.annotation.CreatedDate +import org.springframework.data.annotation.LastModifiedDate +import org.springframework.data.jpa.domain.support.AuditingEntityListener +import java.time.Instant + +@MappedSuperclass +@EntityListeners(AuditingEntityListener::class) +abstract class Auditable { + + @CreatedDate + @Column(name = "created_at", nullable = false, updatable = false) + var createdAt: Instant? = null + + @LastModifiedDate + @Column(name = "last_modified_at", nullable = false, updatable = true) + var lastModifiedAt: Instant? = null +} diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/shared/domain/ExternalIdKey.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/shared/domain/ExternalIdKey.kt new file mode 100644 index 0000000..08d37b4 --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/shared/domain/ExternalIdKey.kt @@ -0,0 +1,12 @@ +package uk.gov.justice.digital.hmpps.jobsboardintegrationapi.shared.domain + +import jakarta.persistence.Column +import jakarta.persistence.Embeddable + +@Embeddable +data class ExternalIdKey( + @Column(name = "id", unique = true) val id: String, + @Column(name = "ext_id", unique = true) val externalId: Long, +) { + constructor() : this("", 0) +} diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/shared/domain/ReadOnlyRepository.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/shared/domain/ReadOnlyRepository.kt new file mode 100644 index 0000000..199d557 --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/jobsboardintegrationapi/shared/domain/ReadOnlyRepository.kt @@ -0,0 +1,11 @@ +package uk.gov.justice.digital.hmpps.jobsboardintegrationapi.shared.domain + +import org.springframework.data.repository.NoRepositoryBean +import org.springframework.data.repository.Repository +import java.util.* + +@NoRepositoryBean +interface ReadOnlyRepository : Repository { + fun findById(id: ID): Optional + fun findAll(): List? +} diff --git a/src/main/resources/db/migration/R__RefDataMappings.sql b/src/main/resources/db/migration/R__RefDataMappings.sql new file mode 100644 index 0000000..9346f09 --- /dev/null +++ b/src/main/resources/db/migration/R__RefDataMappings.sql @@ -0,0 +1,45 @@ +DROP MATERIALIZED VIEW IF EXISTS ref_data_mappings; + +CREATE MATERIALIZED VIEW ref_data_mappings ( + ref_data, + value, + ext_id +) +AS +SELECT ref_data, value, ext_id +FROM ( + SELECT 'employer_status' as ref_data, value, id as ext_id FROM ( + SELECT 'KEY_PARTNER' AS value,1 as id + UNION ALL SELECT 'GOLD',2 + UNION ALL SELECT 'SILVER',3 + ) employer_statuses + UNION + SELECT 'employer_sector', value, id FROM ( + SELECT 'ADMIN_SUPPORT' AS value, 14 as id + UNION ALL SELECT 'AGRICULTURE',1 + UNION ALL SELECT 'ARTS_ENTERTAINMENT', 18 + UNION ALL SELECT 'CONSTRUCTION', 6 + UNION ALL SELECT 'EDUCATION', 16 + UNION ALL SELECT 'ENERGY', 4 + UNION ALL SELECT 'FINANCE',11 + UNION ALL SELECT 'HEALTH_SOCIAL',17 + UNION ALL SELECT 'HOSPITALITY_CATERING',9 + UNION ALL SELECT 'LOGISTICS',8 + UNION ALL SELECT 'MANUFACTURING',3 + UNION ALL SELECT 'MINING',2 + UNION ALL SELECT 'OTHER',19 + UNION ALL SELECT 'PROFESSIONALS_SCIENTISTS_TECHNICIANS',13 + UNION ALL SELECT 'PROPERTY',12 + UNION ALL SELECT 'PUBLIC_ADMIN_DEFENCE',15 + UNION ALL SELECT 'WASTE_MANAGEMENT',5 + UNION ALL SELECT 'RETAIL',7 + UNION ALL SELECT 'TECHNOLOGY',10 + ) employer_sectors +) ref_data_mappings +ORDER BY 1, 2 +WITH DATA; + +CREATE UNIQUE INDEX ref_data_mappings_data_value_key ON ref_data_mappings(ref_data, value); +CREATE UNIQUE INDEX ref_data_mappings_data_ext_id_key ON ref_data_mappings(ref_data, ext_id); + +REFRESH MATERIALIZED VIEW ref_data_mappings; diff --git a/src/main/resources/db/migration/V1_1__start.sql b/src/main/resources/db/migration/V1_1__start.sql new file mode 100644 index 0000000..dabd388 --- /dev/null +++ b/src/main/resources/db/migration/V1_1__start.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS employers_ext_ids +( + id VARCHAR(36) UNIQUE, + ext_id BIGINT UNIQUE, + created_at TIMESTAMP(6) NOT NULL, + last_modified_at TIMESTAMP(6) NOT NULL, + + PRIMARY KEY (id, ext_id) +);