From b1f21f263ff30a698dc5f1ef93088859e3a56683 Mon Sep 17 00:00:00 2001 From: Gerard Paligot Date: Mon, 25 May 2026 16:10:14 +0200 Subject: [PATCH] fix(server): point digest social media query at communication_plans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DigestRepositoryExposed.querySocialMediaDue read PartnershipsTable.communication_publication_date, which was deprecated by MigratePartnershipCommunicationsMigration and is no longer written by any endpoint. The "Communication prévue aujourd'hui" digest section had been silently empty since the migration. Switch to CommunicationPlanEntity.scheduledDate, keeping only entries linked to a non-declined partnership. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../application/DigestRepositoryExposed.kt | 16 ++- .../infrastructure/db/PartnershipEntity.kt | 15 --- .../application/DigestSocialMediaTest.kt | 101 ++++++++++++++++++ 3 files changed, 115 insertions(+), 17 deletions(-) create mode 100644 server/application/src/test/kotlin/fr/devlille/partners/connect/digest/application/DigestSocialMediaTest.kt diff --git a/server/application/src/main/kotlin/fr/devlille/partners/connect/digest/application/DigestRepositoryExposed.kt b/server/application/src/main/kotlin/fr/devlille/partners/connect/digest/application/DigestRepositoryExposed.kt index e28e6f2ca..9dad834a7 100644 --- a/server/application/src/main/kotlin/fr/devlille/partners/connect/digest/application/DigestRepositoryExposed.kt +++ b/server/application/src/main/kotlin/fr/devlille/partners/connect/digest/application/DigestRepositoryExposed.kt @@ -26,7 +26,9 @@ import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDateTime import org.jetbrains.exposed.v1.core.and import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.greaterEq import org.jetbrains.exposed.v1.core.isNotNull +import org.jetbrains.exposed.v1.core.less import org.jetbrains.exposed.v1.jdbc.transactions.transaction import java.util.UUID @@ -107,8 +109,18 @@ class DigestRepositoryExposed : DigestRepository { END_OF_DAY_MINUTE, END_OF_DAY_SECOND, ) - return PartnershipEntity.findSocialMediaDue(eventId, startOfDay, endOfDay) - .map { DigestEntry(it.company.name, buildLink(eventSlug, it.id.value)) } + return CommunicationPlanEntity + .find { + (CommunicationPlansTable.eventId eq eventId) and + CommunicationPlansTable.scheduledDate.isNotNull() and + (CommunicationPlansTable.scheduledDate greaterEq startOfDay) and + (CommunicationPlansTable.scheduledDate less endOfDay) + } + .mapNotNull { plan -> + val partnership = plan.partnership ?: return@mapNotNull null + if (partnership.declinedAt != null) return@mapNotNull null + DigestEntry(partnership.company.name, buildLink(eventSlug, partnership.id.value)) + } } private fun queryPendingJobOffers(eventId: UUID, eventSlug: String): List = diff --git a/server/application/src/main/kotlin/fr/devlille/partners/connect/partnership/infrastructure/db/PartnershipEntity.kt b/server/application/src/main/kotlin/fr/devlille/partners/connect/partnership/infrastructure/db/PartnershipEntity.kt index 9e18a0e4b..85a18cc91 100644 --- a/server/application/src/main/kotlin/fr/devlille/partners/connect/partnership/infrastructure/db/PartnershipEntity.kt +++ b/server/application/src/main/kotlin/fr/devlille/partners/connect/partnership/infrastructure/db/PartnershipEntity.kt @@ -8,10 +8,8 @@ import kotlinx.datetime.LocalDateTime import org.jetbrains.exposed.v1.core.and import org.jetbrains.exposed.v1.core.dao.id.EntityID import org.jetbrains.exposed.v1.core.eq -import org.jetbrains.exposed.v1.core.greaterEq import org.jetbrains.exposed.v1.core.isNotNull import org.jetbrains.exposed.v1.core.isNull -import org.jetbrains.exposed.v1.core.less import org.jetbrains.exposed.v1.core.neq import org.jetbrains.exposed.v1.dao.java.UUIDEntity import org.jetbrains.exposed.v1.dao.java.UUIDEntityClass @@ -92,19 +90,6 @@ class PartnershipEntity(id: EntityID) : UUIDEntity(id) { PartnershipsTable.selectedPackId.isNotNull() }.toList() - fun findSocialMediaDue( - eventId: UUID, - startOfDay: LocalDateTime, - endOfDay: LocalDateTime, - ): List = - find { - (PartnershipsTable.eventId eq eventId) and - PartnershipsTable.declinedAt.isNull() and - PartnershipsTable.communicationPublicationDate.isNotNull() and - (PartnershipsTable.communicationPublicationDate greaterEq startOfDay) and - (PartnershipsTable.communicationPublicationDate less endOfDay) - }.toList() - fun singleByEventAndCompany(eventId: UUID, companyId: UUID): PartnershipEntity? = this .find { (PartnershipsTable.eventId eq eventId) and (PartnershipsTable.companyId eq companyId) } .singleOrNull() diff --git a/server/application/src/test/kotlin/fr/devlille/partners/connect/digest/application/DigestSocialMediaTest.kt b/server/application/src/test/kotlin/fr/devlille/partners/connect/digest/application/DigestSocialMediaTest.kt new file mode 100644 index 000000000..e1c70cc65 --- /dev/null +++ b/server/application/src/test/kotlin/fr/devlille/partners/connect/digest/application/DigestSocialMediaTest.kt @@ -0,0 +1,101 @@ +package fr.devlille.partners.connect.digest.application + +import fr.devlille.partners.connect.companies.factories.insertMockedCompany +import fr.devlille.partners.connect.events.factories.insertMockedFutureEventWithSlug +import fr.devlille.partners.connect.internal.moduleSharedDb +import fr.devlille.partners.connect.organisations.factories.insertMockedOrganisationEntity +import fr.devlille.partners.connect.partnership.factories.insertMockedCommunicationPlan +import fr.devlille.partners.connect.partnership.factories.insertMockedPartnership +import fr.devlille.partners.connect.sponsoring.factories.insertMockedSponsoringPack +import fr.devlille.partners.connect.users.factories.insertMockedUser +import io.ktor.client.request.get +import io.ktor.server.testing.testApplication +import kotlinx.coroutines.runBlocking +import kotlinx.datetime.LocalDate +import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toLocalDateTime +import org.jetbrains.exposed.v1.jdbc.transactions.transaction +import java.util.UUID +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.time.Clock + +class DigestSocialMediaTest { + @Test + @Suppress("LongMethod") + fun `socialMediaItems lists only partnerships with a communication plan scheduled today`() = testApplication { + val today = LocalDate(2026, 5, 25) + val userId = UUID.randomUUID() + val orgId = UUID.randomUUID() + val eventId = UUID.randomUUID() + val eventSlug = "event-${UUID.randomUUID()}" + val packId = UUID.randomUUID() + val todayCompanyId = UUID.randomUUID() + val tomorrowCompanyId = UUID.randomUUID() + val declinedCompanyId = UUID.randomUUID() + val todayPartnershipId = UUID.randomUUID() + val tomorrowPartnershipId = UUID.randomUUID() + val declinedPartnershipId = UUID.randomUUID() + + application { + moduleSharedDb(userId) + transaction { + insertMockedUser(userId) + insertMockedOrganisationEntity(orgId) + insertMockedFutureEventWithSlug(eventId, slug = eventSlug, orgId = orgId) + insertMockedSponsoringPack(id = packId, eventId = eventId) + insertMockedCompany(todayCompanyId) + insertMockedCompany(tomorrowCompanyId) + insertMockedCompany(declinedCompanyId) + insertMockedPartnership( + id = todayPartnershipId, + eventId = eventId, + companyId = todayCompanyId, + selectedPackId = packId, + ) + insertMockedPartnership( + id = tomorrowPartnershipId, + eventId = eventId, + companyId = tomorrowCompanyId, + selectedPackId = packId, + ) + insertMockedPartnership( + id = declinedPartnershipId, + eventId = eventId, + companyId = declinedCompanyId, + selectedPackId = packId, + declinedAt = Clock.System.now().toLocalDateTime(TimeZone.UTC), + ) + insertMockedCommunicationPlan( + eventId = eventId, + partnershipId = todayPartnershipId, + scheduledDate = LocalDateTime(2026, 5, 25, 10, 0), + ) + insertMockedCommunicationPlan( + eventId = eventId, + partnershipId = tomorrowPartnershipId, + scheduledDate = LocalDateTime(2026, 5, 26, 10, 0), + ) + insertMockedCommunicationPlan( + eventId = eventId, + partnershipId = declinedPartnershipId, + scheduledDate = LocalDateTime(2026, 5, 25, 11, 0), + ) + insertMockedCommunicationPlan( + eventId = eventId, + partnershipId = null, + scheduledDate = LocalDateTime(2026, 5, 25, 12, 0), + ) + } + } + client.get("/") + + val digest = runBlocking { + DigestRepositoryExposed().queryDigest(eventSlug, today) + } + + assertEquals(1, digest.socialMediaItems.size, "Only today's non-declined partnership plan should surface") + assertEquals(todayCompanyId.toString(), digest.socialMediaItems.first().companyName) + } +}