Skip to content

Commit 5bfd711

Browse files
committed
Merge branch 'main' into kontoregister-oppsett
2 parents 1f90378 + 6ebbb4c commit 5bfd711

34 files changed

+690
-155
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package no.nav.mulighetsrommet.kafka
2+
3+
import kotliquery.Row
4+
import kotliquery.queryOf
5+
import no.nav.common.kafka.producer.feilhandtering.KafkaProducerRepository
6+
import no.nav.common.kafka.producer.feilhandtering.StoredProducerRecord
7+
import no.nav.mulighetsrommet.database.Database
8+
import no.nav.mulighetsrommet.database.createTextArray
9+
import org.intellij.lang.annotations.Language
10+
11+
class KafkaProducerRepositoryImpl(private val db: Database) : KafkaProducerRepository {
12+
override fun storeRecord(record: StoredProducerRecord): Long = db.session { session ->
13+
@Language("PostgreSQL")
14+
val sql = """
15+
insert into kafka_producer_record (topic, key, value, headers_json) values (?, ?, ?, ?)
16+
returning id
17+
""".trimIndent()
18+
19+
val query = queryOf(sql, record.topic, record.key, record.value, record.headersJson)
20+
21+
session.single(query) { it.long("id") }!!
22+
}
23+
24+
override fun deleteRecords(ids: List<Long>): Unit = db.session { session ->
25+
@Language("PostgreSQL")
26+
val sql = """
27+
delete from kafka_producer_record where id = any(?::bigint[])
28+
""".trimIndent()
29+
30+
session.update(queryOf(sql, session.createArrayOf("bigint", ids)))
31+
}
32+
33+
override fun getRecords(maxMessages: Int): List<StoredProducerRecord> = db.session { session ->
34+
@Language("PostgreSQL")
35+
val sql = """
36+
select * from kafka_producer_record order by id limit ?
37+
""".trimIndent()
38+
39+
val query = queryOf(sql, maxMessages)
40+
41+
session.list(query) { toStoredProducerRecord(it) }
42+
}
43+
44+
override fun getRecords(maxMessages: Int, topics: List<String>): List<StoredProducerRecord> = db.session { session ->
45+
@Language("PostgreSQL")
46+
val sql = """
47+
select * from kafka_producer_record where topic = any(?::text[]) order by id limit ?
48+
""".trimIndent()
49+
50+
val query = queryOf(sql, session.createTextArray(topics), maxMessages)
51+
52+
session.list(query) { toStoredProducerRecord(it) }
53+
}
54+
}
55+
56+
private fun toStoredProducerRecord(row: Row) = StoredProducerRecord(
57+
row.long("id"),
58+
row.string("topic"),
59+
row.bytes("key"),
60+
row.bytes("value"),
61+
row.string("headers_json"),
62+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package no.nav.mulighetsrommet.kafka
2+
3+
import io.kotest.core.spec.style.FunSpec
4+
import io.kotest.matchers.shouldBe
5+
import no.nav.common.kafka.producer.feilhandtering.StoredProducerRecord
6+
import no.nav.mulighetsrommet.database.kotest.extensions.FlywayDatabaseTestListener
7+
8+
class KafkaProducerRepositoryTest : FunSpec({
9+
val database = extension(FlywayDatabaseTestListener(testDatabaseConfig))
10+
11+
lateinit var kafkaProducerRepository: KafkaProducerRepositoryImpl
12+
13+
beforeSpec {
14+
kafkaProducerRepository = KafkaProducerRepositoryImpl(database.db)
15+
}
16+
17+
test("should store records") {
18+
val records = (0..2).map {
19+
StoredProducerRecord(
20+
"topic$it",
21+
"key$it".toByteArray(),
22+
"value$it".toByteArray(),
23+
"{}",
24+
)
25+
}
26+
27+
records.forEach { kafkaProducerRepository.storeRecord(it) }
28+
29+
database.assertTable("kafka_producer_record").hasNumberOfRows(3)
30+
}
31+
32+
test("should delete records") {
33+
kafkaProducerRepository.deleteRecords(listOf(1, 2))
34+
database.assertTable("kafka_producer_record").hasNumberOfRows(1)
35+
}
36+
37+
test("should get all records") {
38+
val result = kafkaProducerRepository.getRecords(10)
39+
result.size shouldBe 1
40+
result[0].id shouldBe 3
41+
}
42+
43+
test("should get records by topics") {
44+
kafkaProducerRepository.storeRecord(
45+
StoredProducerRecord(
46+
"topic1",
47+
"key1".toByteArray(),
48+
"value1".toByteArray(),
49+
"{}",
50+
),
51+
)
52+
53+
val result = kafkaProducerRepository.getRecords(10, listOf("topic1"))
54+
result.size shouldBe 1
55+
}
56+
})

common/kafka/src/test/resources/db/migration/V1__test-database.sql

+10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ create table failed_events
2424
unique (topic, partition, record_offset)
2525
);
2626

27+
create table kafka_producer_record
28+
(
29+
id bigint generated always as identity,
30+
topic text not null,
31+
key bytea,
32+
value bytea,
33+
headers_json text,
34+
created_at timestamp default current_timestamp not null
35+
);
36+
2737
create type topic_type as enum ('CONSUMER', 'PRODUCER');
2838

2939
create table topics

frontend/mr-admin-flate/src/components/tilsagn/prismodell/TilsagnBeregningPreview.tsx

+12-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function TilsagnBeregningPreview(props: Props) {
3737
useEffect(() => {
3838
beregnTilsagn(input, { onSuccess: handleTilsagnBeregnet, onError: setValidationErrors });
3939
// eslint-disable-next-line react-hooks/exhaustive-deps
40-
}, [beregnTilsagn, ...Object.values(input)]);
40+
}, [beregnTilsagn, ...extractRelevantDeps(input)]);
4141

4242
return (
4343
<>
@@ -49,3 +49,14 @@ export function TilsagnBeregningPreview(props: Props) {
4949
</>
5050
);
5151
}
52+
53+
function extractRelevantDeps(obj: any): any[] {
54+
if (!obj || typeof obj !== "object") return [obj];
55+
56+
return Object.entries(obj).flatMap(([, value]) => {
57+
if (typeof value === "object" && value !== null) {
58+
return extractRelevantDeps(value); // Recursively flatten nested objects
59+
}
60+
return value; // Keep primitive values
61+
});
62+
}

frontend/mr-admin-flate/src/pages/gjennomforing/tilsagn/rediger/RedigerTilsagnFormPage.tsx

+10-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { tilsagnQuery } from "../detaljer/tilsagnDetaljerLoader";
1515
import { godkjenteTilsagnQuery } from "../opprett/opprettTilsagnLoader";
1616
import { TilsagnTabell } from "../tabell/TilsagnTabell";
1717
import { Laster } from "@/components/laster/Laster";
18+
import { formaterDatoSomYYYYMMDD, subtractDays } from "@/utils/Utils";
1819

1920
function useRedigerTilsagnFormData() {
2021
const { gjennomforingId, tilsagnId } = useParams();
@@ -25,7 +26,12 @@ function useRedigerTilsagnFormData() {
2526
...godkjenteTilsagnQuery(gjennomforingId),
2627
});
2728

28-
return { avtale, gjennomforing, godkjenteTilsagn, tilsagn: tilsagnDetaljer.data.tilsagn };
29+
return {
30+
avtale,
31+
gjennomforing,
32+
godkjenteTilsagn: godkjenteTilsagn.data.filter((t) => t.id !== tilsagnDetaljer.data.tilsagn.id),
33+
tilsagn: tilsagnDetaljer.data.tilsagn,
34+
};
2935
}
3036

3137
export function RedigerTilsagnFormPage() {
@@ -50,7 +56,7 @@ export function RedigerTilsagnFormPage() {
5056
id: tilsagn.id,
5157
type: tilsagn.type,
5258
periodeStart: tilsagn.periode.start,
53-
periodeSlutt: tilsagn.periode.slutt,
59+
periodeSlutt: formaterDatoSomYYYYMMDD(subtractDays(tilsagn.periode.slutt, 1)),
5460
kostnadssted: tilsagn.kostnadssted.enhetsnummer,
5561
beregning: tilsagn.beregning.input,
5662
gjennomforingId: gjennomforing.id,
@@ -84,8 +90,8 @@ export function RedigerTilsagnFormPage() {
8490
<WhitePaddedBox>
8591
<VStack gap="4">
8692
<Heading size="medium">Aktive tilsagn</Heading>
87-
{godkjenteTilsagn.data.length > 0 ? (
88-
<TilsagnTabell tilsagn={godkjenteTilsagn.data} />
93+
{godkjenteTilsagn.length > 0 ? (
94+
<TilsagnTabell tilsagn={godkjenteTilsagn} />
8995
) : (
9096
<Alert variant="info">Det finnes ingen tilsagn for dette tiltaket</Alert>
9197
)}

iac/kafka-manager/dev/kafka-manager-dev.yaml

+13-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,19 @@ spec:
109109
"valueDeserializerType": "STRING"
110110
},
111111
{
112-
"name": "team-mulighetsrommet.tiltaksokonomi-bestilling-v1",
112+
"name": "team-mulighetsrommet.tiltaksokonomi.bestillinger-v1",
113+
"location": "AIVEN",
114+
"keyDeserializerType": "STRING",
115+
"valueDeserializerType": "STRING"
116+
},
117+
{
118+
"name": "team-mulighetsrommet.tiltaksokonomi.bestilling-status-v1",
119+
"location": "AIVEN",
120+
"keyDeserializerType": "STRING",
121+
"valueDeserializerType": "STRING"
122+
},
123+
{
124+
"name": "team-mulighetsrommet.tiltaksokonomi.faktura-status-v1",
113125
"location": "AIVEN",
114126
"keyDeserializerType": "STRING",
115127
"valueDeserializerType": "STRING"

iac/kafka-manager/prod/kafka-manager-prod.yaml

+13-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,19 @@ spec:
109109
"valueDeserializerType": "STRING"
110110
},
111111
{
112-
"name": "team-mulighetsrommet.tiltaksokonomi-bestilling-v1",
112+
"name": "team-mulighetsrommet.tiltaksokonomi.bestillinger-v1",
113+
"location": "AIVEN",
114+
"keyDeserializerType": "STRING",
115+
"valueDeserializerType": "STRING"
116+
},
117+
{
118+
"name": "team-mulighetsrommet.tiltaksokonomi.bestilling-status-v1",
119+
"location": "AIVEN",
120+
"keyDeserializerType": "STRING",
121+
"valueDeserializerType": "STRING"
122+
},
123+
{
124+
"name": "team-mulighetsrommet.tiltaksokonomi.faktura-status-v1",
113125
"location": "AIVEN",
114126
"keyDeserializerType": "STRING",
115127
"valueDeserializerType": "STRING"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
apiVersion: kafka.nais.io/v1
2+
kind: Topic
3+
metadata:
4+
name: tiltaksokonomi.bestilling-status-v1
5+
namespace: team-mulighetsrommet
6+
labels:
7+
team: team-mulighetsrommet
8+
spec:
9+
pool: nav-dev
10+
config:
11+
cleanupPolicy: compact
12+
minimumInSyncReplicas: 2
13+
partitions: 2
14+
replication: 3
15+
retentionHours: 1
16+
segmentHours: 1
17+
acl:
18+
- team: team-mulighetsrommet
19+
application: tiltaksokonomi
20+
access: readwrite
21+
- team: team-mulighetsrommet
22+
application: mulighetsrommet-api
23+
access: read
24+
- team: team-mulighetsrommet
25+
application: mulighetsrommet-kafka-manager
26+
access: read

iac/kafka-topics/dev/tiltaksokonomi-bestilling-v1.yaml iac/kafka-topics/dev/tiltaksokonomi.bestillinger-v1.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
apiVersion: kafka.nais.io/v1
22
kind: Topic
33
metadata:
4-
name: tiltaksokonomi-bestilling-v1
4+
name: tiltaksokonomi.bestillinger-v1
55
namespace: team-mulighetsrommet
66
labels:
77
team: team-mulighetsrommet
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
apiVersion: kafka.nais.io/v1
2+
kind: Topic
3+
metadata:
4+
name: tiltaksokonomi.faktura-status-v1
5+
namespace: team-mulighetsrommet
6+
labels:
7+
team: team-mulighetsrommet
8+
spec:
9+
pool: nav-dev
10+
config:
11+
cleanupPolicy: compact
12+
minimumInSyncReplicas: 2
13+
partitions: 2
14+
replication: 3
15+
retentionHours: 1
16+
segmentHours: 1
17+
acl:
18+
- team: team-mulighetsrommet
19+
application: tiltaksokonomi
20+
access: readwrite
21+
- team: team-mulighetsrommet
22+
application: mulighetsrommet-api
23+
access: read
24+
- team: team-mulighetsrommet
25+
application: mulighetsrommet-kafka-manager
26+
access: read
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apiVersion: kafka.nais.io/v1
2+
kind: Topic
3+
metadata:
4+
name: tiltaksokonomi.bestilling-status-v1
5+
namespace: team-mulighetsrommet
6+
labels:
7+
team: team-mulighetsrommet
8+
spec:
9+
pool: nav-prod
10+
config:
11+
cleanupPolicy: compact
12+
minimumInSyncReplicas: 2
13+
partitions: 2
14+
replication: 3
15+
acl:
16+
- team: team-mulighetsrommet
17+
application: tiltaksokonomi
18+
access: readwrite
19+
- team: team-mulighetsrommet
20+
application: mulighetsrommet-api
21+
access: read
22+
- team: team-mulighetsrommet
23+
application: mulighetsrommet-kafka-manager
24+
access: read

iac/kafka-topics/prod/tiltaksokonomi-bestilling-v1.yaml iac/kafka-topics/prod/tiltaksokonomi.bestillinger-v1.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
apiVersion: kafka.nais.io/v1
22
kind: Topic
33
metadata:
4-
name: tiltaksokonomi-bestilling-v1
4+
name: tiltaksokonomi.bestillinger-v1
55
namespace: team-mulighetsrommet
66
labels:
77
team: team-mulighetsrommet
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apiVersion: kafka.nais.io/v1
2+
kind: Topic
3+
metadata:
4+
name: tiltaksokonomi.faktura-status-v1
5+
namespace: team-mulighetsrommet
6+
labels:
7+
team: team-mulighetsrommet
8+
spec:
9+
pool: nav-prod
10+
config:
11+
cleanupPolicy: compact
12+
minimumInSyncReplicas: 2
13+
partitions: 2
14+
replication: 3
15+
acl:
16+
- team: team-mulighetsrommet
17+
application: tiltaksokonomi
18+
access: readwrite
19+
- team: team-mulighetsrommet
20+
application: mulighetsrommet-api
21+
access: read
22+
- team: team-mulighetsrommet
23+
application: mulighetsrommet-kafka-manager
24+
access: read

mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/ApplicationConfigDev.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ val ApplicationConfigDev = AppConfig(
5555
producerTopic = "team-mulighetsrommet.datavarehus-tiltak-v1",
5656
),
5757
okonomiBestilling = OkonomiBestillingService.Config(
58-
topic = "team-mulighetsrommet.tiltaksokonomi-bestilling-v1",
58+
topic = "team-mulighetsrommet.tiltaksokonomi.bestillinger-v1",
5959
),
6060
),
6161
consumers = KafkaConsumers(

mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/ApplicationConfigLocal.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ val ApplicationConfigLocal = AppConfig(
6767
producerTopic = "team-mulighetsrommet.datavarehus-tiltak-v1",
6868
),
6969
okonomiBestilling = OkonomiBestillingService.Config(
70-
topic = "tiltaksokonomi-bestilling-v1",
70+
topic = "tiltaksokonomi.bestillinger-v1",
7171
),
7272
),
7373
consumers = KafkaConsumers(

mulighetsrommet-api/src/main/kotlin/no/nav/mulighetsrommet/api/ApplicationConfigProd.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ val ApplicationConfigProd = AppConfig(
5555
producerTopic = "team-mulighetsrommet.datavarehus-tiltak-v1",
5656
),
5757
okonomiBestilling = OkonomiBestillingService.Config(
58-
topic = "team-mulighetsrommet.tiltaksokonomi-bestilling-v1",
58+
topic = "team-mulighetsrommet.tiltaksokonomi.bestillinger-v1",
5959
),
6060
),
6161
consumers = KafkaConsumers(

0 commit comments

Comments
 (0)