From 673f8a0f7e6ff09d7c2bde4b22946abafca44931 Mon Sep 17 00:00:00 2001 From: martinrichter Date: Mon, 24 Aug 2026 10:44:51 +0200 Subject: [PATCH 1/5] Add simulation support to ticket check-in API and providers --- .../eu/pretix/libpretixsync/check/TicketCheckProvider.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/TicketCheckProvider.kt b/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/TicketCheckProvider.kt index b0838d08..10d8d35b 100644 --- a/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/TicketCheckProvider.kt +++ b/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/TicketCheckProvider.kt @@ -55,6 +55,13 @@ interface TicketCheckProvider { // required for de-serialization constructor() {} } + data class AddonInfo( + val itemName: String? = null, + val variationName: String? = null, + val attendeeName: String? = null, + val isBundled: Boolean = false, + val checkedIn: Boolean? = null, + ) class CheckResult { enum class Type { @@ -75,6 +82,7 @@ interface TicketCheckProvider { var positionId: Long? = null var firstScanned: Date? = null var addonText: String? = null + var addons: List? = null var reasonExplanation: String? = null var checkinTexts: List? = null var isRequireAttention = false From 1cc95265329335eccdc563cf4f5fc1820f40e7f4 Mon Sep 17 00:00:00 2001 From: martinrichter Date: Mon, 24 Aug 2026 10:54:28 +0200 Subject: [PATCH 2/5] Add simulation support to ticket check-in API and providers --- .../libpretixsync/check/AsyncCheckProvider.kt | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/AsyncCheckProvider.kt b/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/AsyncCheckProvider.kt index d23af64a..d2e28b28 100644 --- a/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/AsyncCheckProvider.kt +++ b/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/AsyncCheckProvider.kt @@ -960,6 +960,34 @@ class AsyncCheckProvider(private val config: ConfigStore, private val db: SyncDa return Pair(results, errors) } + private fun collectAddons( + order: OrderModel, + position: OrderPositionModel, + ): List { + return db.orderPositionQueries.selectForOrder(order.id) + .executeAsList() + .map { it.toModel() } + .filter { it.addonToServerId == position.serverId } + .map { addon -> + val addonItem = db.itemQueries.selectById(addon.itemId).executeAsOne().toModel() + val varid = addon.variationServerId + val variation = if (varid != null && varid > 0) { + try { + addonItem.getVariation(varid) + } catch (e: JSONException) { + sentry.captureException(e) + null + } + } else null + + TicketCheckProvider.AddonInfo( + itemName = addonItem.internalName, + variationName = variation?.stringValue, + attendeeName = addon.attendeeName, + ) + } + } + private fun checkOfflineWithData( eventsAndCheckinLists: Map, secret: String, @@ -1129,7 +1157,7 @@ class AsyncCheckProvider(private val config: ConfigStore, private val db: SyncDa res.isRequireAttention = require_attention || variation?.isCheckin_attention == true res.checkinTexts = listOfNotNull(order.checkInText?.trim(), variation?.checkin_text?.trim(), item.checkInText?.trim()).filterNot { it.isBlank() || it == "null" } - + res.addons = collectAddons(order, position) val storedCheckIns = db.checkInQueries.selectByPositionId(position.id).executeAsList().map { it.toModel() } val checkIns = storedCheckIns.filter { it.listServerId == listId && it.localAnnulled == null From 6f5b226e6f14e2cf7fabfa5568d192dfc33fa1f6 Mon Sep 17 00:00:00 2001 From: martinrichter Date: Tue, 25 Aug 2026 13:02:17 +0200 Subject: [PATCH 3/5] Include addon information in online check results --- .../check/OnlineCheckProvider.kt | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/OnlineCheckProvider.kt b/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/OnlineCheckProvider.kt index 404aa7a8..b40e21bd 100644 --- a/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/OnlineCheckProvider.kt +++ b/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/OnlineCheckProvider.kt @@ -226,6 +226,7 @@ class OnlineCheckProvider( res.locale = posjson.getString("order__locale") } res.position = posjson + res.addons = collectAddons(posjson.getLong("id")) val checkins = posjson.getJSONArray("checkins") for (i in 0 until checkins.length()) { val ci = checkins.getJSONObject(i) @@ -356,6 +357,34 @@ class OnlineCheckProvider( return check(eventsAndCheckinLists, ticketid, source_type, ArrayList(), false, true, TicketCheckProvider.CheckInType.ENTRY) } + private fun collectAddons(positionServerId: Long): List { + val position = db.orderPositionQueries.selectByServerId(positionServerId) + .executeAsOneOrNull()?.toModel() ?: return emptyList() + + return db.orderPositionQueries.selectForOrder(position.orderId) + .executeAsList() + .map { it.toModel() } + .filter { it.addonToServerId == positionServerId } + .map { addon -> + val addonItem = db.itemQueries.selectById(addon.itemId).executeAsOneOrNull()?.toModel() + val varid = addon.variationServerId + val variation = if (addonItem != null && varid != null && varid > 0) { + try { + addonItem.getVariation(varid) + } catch (e: JSONException) { + sentry.captureException(e) + null + } + } else null + + TicketCheckProvider.AddonInfo( + itemName = addonItem?.internalName, + variationName = variation?.stringValue, + attendeeName = addon.attendeeName, + ) + } + } + override fun annul( eventsAndCheckinLists: Map, nonce: String, From a56dcaee25e10ab2727475d0145fb6589d4b29c5 Mon Sep 17 00:00:00 2001 From: martinrichter Date: Tue, 25 Aug 2026 14:15:24 +0200 Subject: [PATCH 4/5] Drop add-on collection from OnlineCheckProvider --- .../check/OnlineCheckProvider.kt | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/OnlineCheckProvider.kt b/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/OnlineCheckProvider.kt index b40e21bd..404aa7a8 100644 --- a/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/OnlineCheckProvider.kt +++ b/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/OnlineCheckProvider.kt @@ -226,7 +226,6 @@ class OnlineCheckProvider( res.locale = posjson.getString("order__locale") } res.position = posjson - res.addons = collectAddons(posjson.getLong("id")) val checkins = posjson.getJSONArray("checkins") for (i in 0 until checkins.length()) { val ci = checkins.getJSONObject(i) @@ -357,34 +356,6 @@ class OnlineCheckProvider( return check(eventsAndCheckinLists, ticketid, source_type, ArrayList(), false, true, TicketCheckProvider.CheckInType.ENTRY) } - private fun collectAddons(positionServerId: Long): List { - val position = db.orderPositionQueries.selectByServerId(positionServerId) - .executeAsOneOrNull()?.toModel() ?: return emptyList() - - return db.orderPositionQueries.selectForOrder(position.orderId) - .executeAsList() - .map { it.toModel() } - .filter { it.addonToServerId == positionServerId } - .map { addon -> - val addonItem = db.itemQueries.selectById(addon.itemId).executeAsOneOrNull()?.toModel() - val varid = addon.variationServerId - val variation = if (addonItem != null && varid != null && varid > 0) { - try { - addonItem.getVariation(varid) - } catch (e: JSONException) { - sentry.captureException(e) - null - } - } else null - - TicketCheckProvider.AddonInfo( - itemName = addonItem?.internalName, - variationName = variation?.stringValue, - attendeeName = addon.attendeeName, - ) - } - } - override fun annul( eventsAndCheckinLists: Map, nonce: String, From 21c855d849c18d79bfe6ca33b619daeedd350605 Mon Sep 17 00:00:00 2001 From: martinrichter Date: Thu, 27 Aug 2026 14:30:00 +0200 Subject: [PATCH 5/5] Include and parse addons in online check-in results --- .../eu/pretix/libpretixsync/api/PretixApi.kt | 2 +- .../check/OnlineCheckProvider.kt | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/libpretixsync/src/main/java/eu/pretix/libpretixsync/api/PretixApi.kt b/libpretixsync/src/main/java/eu/pretix/libpretixsync/api/PretixApi.kt index 89aa5904..cdc24371 100644 --- a/libpretixsync/src/main/java/eu/pretix/libpretixsync/api/PretixApi.kt +++ b/libpretixsync/src/main/java/eu/pretix/libpretixsync/api/PretixApi.kt @@ -160,7 +160,7 @@ open class PretixApi(url: String, key: String, orgaSlug: String, version: Int, h if (exchange_medium_type != null) body.put("exchange_medium_type", exchange_medium_type) if (exchange_medium_identifier != null) body.put("exchange_medium_identifier", exchange_medium_identifier) if (simulate) body.put("simulate", true) - var pd = "?expand=answers.question" + var pd = "?expand=answers.question&expand=addons" if (pdf_data) { pd += "&pdf_data=true" } diff --git a/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/OnlineCheckProvider.kt b/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/OnlineCheckProvider.kt index 404aa7a8..5684362e 100644 --- a/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/OnlineCheckProvider.kt +++ b/libpretixsync/src/main/java/eu/pretix/libpretixsync/check/OnlineCheckProvider.kt @@ -226,6 +226,26 @@ class OnlineCheckProvider( res.locale = posjson.getString("order__locale") } res.position = posjson + val addonsJson = posjson.optJSONArray("addons") + if (addonsJson != null) { + val addons = mutableListOf() + for (i in 0 until addonsJson.length()) { + val a = addonsJson.getJSONObject(i) + val addonItem = db.itemQueries.selectByServerId(a.getLong("item")).executeAsOneOrNull()?.toModel() + val variation = if (addonItem != null && a.optLong("variation", 0) > 0) { + addonItem.getVariation(a.getLong("variation")) + } else null + addons.add( + TicketCheckProvider.AddonInfo( + itemName = addonItem?.internalName, + variationName = variation?.stringValue, + attendeeName = if (a.isNull("attendee_name")) null else a.optString("attendee_name"), + ) + ) + } + res.addons = addons + } + val checkins = posjson.getJSONArray("checkins") for (i in 0 until checkins.length()) { val ci = checkins.getJSONObject(i)