Skip to content

Commit

Permalink
Support for print logs (#106)
Browse files Browse the repository at this point in the history
* Support for print logs

* Ignore unsuccessful prints

* Update libpretixsync

* Bump libpretixsync
  • Loading branch information
raphaelm authored Oct 28, 2024
1 parent dae7f72 commit bc3fc55
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import android.net.NetworkRequest
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.ResultReceiver
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.util.Base64
Expand Down Expand Up @@ -1209,17 +1210,54 @@ class MainActivity : AppCompatActivity(), ReloadableActivity, ScannerView.Result

view_data.attention.set(result.isRequireAttention)

if (result.scanType != TicketCheckProvider.CheckInType.EXIT) {
if (result.position != null && result.type == TicketCheckProvider.CheckResult.Type.VALID && conf.printBadges && conf.autoPrintBadges) {
printBadge(this@MainActivity, application as PretixScan, result.position!!, result.eventSlug!!, null)
}
if (result.position != null && conf.printBadges) {
view_data.showPrint.set(getBadgeLayout(application as PretixScan, result.position!!, result.eventSlug!!) != null)
binding.ibPrint.setOnClickListener {
printBadge(this@MainActivity, application as PretixScan, result.position!!, result.eventSlug!!, null)
val isPrintable = (conf.printBadges &&
result.scanType != TicketCheckProvider.CheckInType.EXIT &&
result.position != null &&
getBadgeLayout(application as PretixScan, result.position!!, result.eventSlug!!) != null)

if (isPrintable) {

val recv = object : ResultReceiver(null) {
override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
super.onReceiveResult(resultCode, resultData)
if (resultCode == 0) {
val api = PretixApi.fromConfig(
conf,
AndroidHttpClientFactory(application as PretixScan)
)
logSuccessfulPrint(
api,
(application as PretixScan).data,
result.eventSlug!!,
result.position!!.getLong("id"),
"badge"
)
}
}
} else {
view_data.showPrint.set(false)
}

val shouldAutoPrint = (conf.autoPrintBadges &&
result.type == TicketCheckProvider.CheckResult.Type.VALID &&
!isPreviouslyPrinted((application as PretixScan).data, result.position!!))

if (shouldAutoPrint) {
printBadge(
this@MainActivity,
application as PretixScan,
result.position!!,
result.eventSlug!!,
recv
)
}
view_data.showPrint.set(true)
binding.ibPrint.setOnClickListener {
printBadge(
this@MainActivity,
application as PretixScan,
result.position!!,
result.eventSlug!!,
recv
)
}
} else {
view_data.showPrint.set(false)
Expand Down
126 changes: 105 additions & 21 deletions pretixscan/app/src/main/java/eu/pretix/pretixscan/droid/ui/PrintUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,22 @@ import android.os.Build
import android.os.Parcel
import android.os.ResultReceiver
import androidx.core.content.FileProvider
import eu.pretix.libpretixsync.api.PretixApi
import eu.pretix.libpretixsync.db.*
import eu.pretix.pretixscan.droid.AppConfig
import eu.pretix.pretixscan.droid.BuildConfig
import eu.pretix.pretixscan.droid.PretixScan
import io.requery.Persistable
import io.requery.BlockingEntityStore
import org.json.JSONArray
import org.json.JSONObject
import java.io.File
import java.nio.charset.Charset
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.TimeZone


fun getDefaultBadgeLayout(): BadgeLayout {
Expand All @@ -39,8 +47,8 @@ fun getBadgeLayout(application: PretixScan, position: JSONObject, eventSlug: Str
.get().firstOrNull().getId()

val litem = application.data.select(BadgeLayoutItem::class.java)
.where(BadgeLayoutItem.ITEM_ID.eq(itemid_local))
.get().firstOrNull()
.where(BadgeLayoutItem.ITEM_ID.eq(itemid_local))
.get().firstOrNull()
if (litem != null) {
if (litem.getLayout() == null) { // "Do not print badges" is configured for this product
return null
Expand All @@ -50,9 +58,9 @@ fun getBadgeLayout(application: PretixScan, position: JSONObject, eventSlug: Str
}

return application.data.select(BadgeLayout::class.java)
.where(BadgeLayout.IS_DEFAULT.eq(true))
.and(BadgeLayout.EVENT_SLUG.eq(eventSlug))
.get().firstOrNull() ?: getDefaultBadgeLayout()
.where(BadgeLayout.IS_DEFAULT.eq(true))
.and(BadgeLayout.EVENT_SLUG.eq(eventSlug))
.get().firstOrNull() ?: getDefaultBadgeLayout()
}

fun isPackageInstalled(packagename: String, packageManager: PackageManager): Boolean {
Expand All @@ -75,7 +83,13 @@ fun receiverForSending(actualReceiver: ResultReceiver): ResultReceiver {
}


fun printBadge(context: Context, application: PretixScan, position: JSONObject, eventSlug: String, recv: ResultReceiver?) {
fun printBadge(
context: Context,
application: PretixScan,
position: JSONObject,
eventSlug: String,
recv: ResultReceiver?
) {
val positions = JSONArray()
positions.put(position)
if (AppConfig(context).printBadgesTwice) {
Expand All @@ -101,7 +115,8 @@ fun printBadge(context: Context, application: PretixScan, position: JSONObject,
}

val etagMap = JSONObject()
val files = store.select(CachedPdfImage::class.java).where(CachedPdfImage.ORDERPOSITION_ID.eq(position.getLong("id"))).get().toList()
val files = store.select(CachedPdfImage::class.java)
.where(CachedPdfImage.ORDERPOSITION_ID.eq(position.getLong("id"))).get().toList()
for (f in files) {
mediaFiles.add(application.fileStorage.getFile("pdfimage_${f.getEtag()}.bin"))
etagMap.put(f.key, mediaFiles.size)
Expand All @@ -120,32 +135,52 @@ fun printBadge(context: Context, application: PretixScan, position: JSONObject,
}
intent.action = "eu.pretix.pretixpos.print.PRINT_BADGE"
val dataUri = FileProvider.getUriForFile(
context,
"${BuildConfig.APPLICATION_ID}.fileprovider",
dataFile)

context.grantUriPermission(intent.`package`, dataUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION)
context,
"${BuildConfig.APPLICATION_ID}.fileprovider",
dataFile
)

context.grantUriPermission(
intent.`package`,
dataUri,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
)
intent.clipData = ClipData.newRawUri(null, dataUri)

for (mediaFile in mediaFiles) {
val mediaUrl = FileProvider.getUriForFile(
context,
"${BuildConfig.APPLICATION_ID}.fileprovider",
mediaFile)
context.grantUriPermission(intent.`package`, mediaUrl, Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION)
context,
"${BuildConfig.APPLICATION_ID}.fileprovider",
mediaFile
)
context.grantUriPermission(
intent.`package`,
mediaUrl,
Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
)
intent.clipData!!.addItem(ClipData.Item(mediaUrl))
}

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

if (BuildConfig.DEBUG && isPackageInstalled("eu.pretix.pretixprint.debug", context.packageManager)) {
intent.component = ComponentName("eu.pretix.pretixprint.debug", "eu.pretix.pretixprint.print.PrintService")
if (BuildConfig.DEBUG && isPackageInstalled(
"eu.pretix.pretixprint.debug",
context.packageManager
)
) {
intent.component =
ComponentName("eu.pretix.pretixprint.debug", "eu.pretix.pretixprint.print.PrintService")
} else if (isPackageInstalled("eu.pretix.pretixprint", context.packageManager)) {
intent.component = ComponentName("eu.pretix.pretixprint", "eu.pretix.pretixprint.print.PrintService")
intent.component =
ComponentName("eu.pretix.pretixprint", "eu.pretix.pretixprint.print.PrintService")
} else if (isPackageInstalled("eu.pretix.pretixprint.debug", context.packageManager)) {
intent.component = ComponentName("eu.pretix.pretixprint.debug", "eu.pretix.pretixprint.print.PrintService")
intent.component =
ComponentName("eu.pretix.pretixprint.debug", "eu.pretix.pretixprint.print.PrintService")
} else if (isPackageInstalled("de.silpion.bleuartcompanion", context.packageManager)) {
intent.component = ComponentName("de.silpion.bleuartcompanion", "de.silpion.bleuartcompanion.services.print.PrintService")
intent.component = ComponentName(
"de.silpion.bleuartcompanion",
"de.silpion.bleuartcompanion.services.print.PrintService"
)
} else {
throw Exception("error_print_no_app");
}
Expand All @@ -157,4 +192,53 @@ fun printBadge(context: Context, application: PretixScan, position: JSONObject,
} else {
context.startService(intent)
}
}

fun isPreviouslyPrinted(data: BlockingEntityStore<Persistable>, position: JSONObject): Boolean {
if (position.has("print_logs")) {
val arr = position.getJSONArray("print_logs")
val arrlen = arr.length()
for (i in 0 until arrlen) {
val printlog = arr.getJSONObject(i)
if (!printlog.getBoolean("successful")) {
continue
}
if (printlog.optString("type", "?") == "badge") {
return true
}
}
}
if (data.count(QueuedCall::class.java)
.where(QueuedCall.URL.like("%orderpositions/" + position.getLong("id") + "/printlog/"))
.get().value() > 0
) {
return true
}
return false
}

fun logSuccessfulPrint(
api: PretixApi,
data: BlockingEntityStore<Persistable>,
eventSlug: String,
positionId: Long,
type: String
) {
val logbody = JSONObject()
logbody.put("source", "pretixSCAN")
logbody.put("type", type)
logbody.put("info", JSONObject())
val tz = TimeZone.getTimeZone("UTC")
val df: DateFormat = SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'",
Locale.ENGLISH
) // Quoted "Z" to indicate UTC, no timezone offset
df.timeZone = tz
logbody.put("datetime", df.format(Date()))

val log = QueuedCall()
log.setBody(logbody.toString())
log.setIdempotency_key(NonceGenerator.nextNonce())
log.setUrl(api.eventResourceUrl(eventSlug, "orderpositions") + positionId + "/printlog/")
data.insert(log)
}

0 comments on commit bc3fc55

Please sign in to comment.