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) + } +}