Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@
*.aab
*.apk
google-services.json

.worktrees
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
29 changes: 26 additions & 3 deletions app/src/main/java/online/taxcore/pos/utils/CreatePdf.kt
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down
Loading