diff --git a/.gitignore b/.gitignore index 6edf947..000541f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ *.aab *.apk google-services.json + +.worktrees diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ee181a..bcbb3cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,16 @@ All notable changes to this project will be documented in this file. - **TBD** Configuration response error handling +## [3.5.2] - 2026-09-01 + +### Fixed + +- Fixed crash when printing invoices whose journal header has fewer lines than expected (e.g. proforma receipts) + +### Added + +- Temporary diagnostic logging of journal format during PDF printing to identify malformed journal payloads + ## [3.5.1] - 2025-12-16 ### Added diff --git a/app/build.gradle b/app/build.gradle index 32597be..1c5840b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,7 +8,7 @@ apply plugin: 'com.google.firebase.crashlytics' def versionMajor = 3 def versionMinor = 5 -def versionPatch = 1 +def versionPatch = 2 def versionBuild = 1 def appVersionBuild = Integer.valueOf(System.env.GITHUB_RUN_NUMBER ?: versionBuild) diff --git a/app/src/main/java/online/taxcore/pos/utils/CreatePdf.kt b/app/src/main/java/online/taxcore/pos/utils/CreatePdf.kt index a8c3443..37f5cd0 100644 --- a/app/src/main/java/online/taxcore/pos/utils/CreatePdf.kt +++ b/app/src/main/java/online/taxcore/pos/utils/CreatePdf.kt @@ -1,5 +1,7 @@ package online.taxcore.pos.utils +import android.util.Log +import com.google.firebase.crashlytics.FirebaseCrashlytics import com.itextpdf.text.* import com.itextpdf.text.pdf.BaseFont import com.itextpdf.text.pdf.PdfPCell @@ -28,11 +30,32 @@ object CreatePdf { val delimiter = "========================================\r\n" val invoiceHeader = invoiceJournal.split(delimiter).first() + // Header line count varies per taxpayer; drop/take instead of subList + // so short headers don't throw IndexOutOfBoundsException val headerElements = invoiceHeader.split("\r\n".toRegex()) + .dropLastWhile { it.isEmpty() } + + // [DEBUG-pdf] temporary diagnostics: which journal shape reaches the PDF parser + val delimiterHits = invoiceJournal.split(delimiter).size - 1 + val debugMsg = "[DEBUG-pdf] len=${invoiceJournal.length}" + + " crlf=${invoiceJournal.contains("\r\n")}" + + " lfOnly=${!invoiceJournal.contains("\r\n") && invoiceJournal.contains("\n")}" + + " delimiterHits=$delimiterHits" + + " headerLines=${headerElements.size}" + Log.d("CreatePdf", debugMsg) + if (delimiterHits == 0 || headerElements.size < 6) { + // journal content only on the malformed path, so receipt data + // isn't sent to Crashlytics for every print + val first120 = invoiceJournal.take(120) + .replace("\r", "\\r").replace("\n", "\\n") + FirebaseCrashlytics.getInstance().log("$debugMsg first120='$first120'") + FirebaseCrashlytics.getInstance() + .recordException(IllegalStateException("Malformed invoice journal: $debugMsg")) + } - val headerStart = headerElements.first() - val companyHeader = headerElements.subList(1, 6).joinToString("\r\n") { it.trim() } - val headerInfo = headerElements.subList(6, headerElements.size - 1).joinToString("\r\n") + val headerStart = headerElements.firstOrNull().orEmpty() + val companyHeader = headerElements.drop(1).take(5).joinToString("\r\n") { it.trim() } + val headerInfo = headerElements.drop(6).joinToString("\r\n") val invoiceFooter = invoiceJournal.split(delimiter).last() val invoiceMain = invoiceJournal