feat: better PDF
This commit is contained in:
68
report/invoice/reference.go
Normal file
68
report/invoice/reference.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package invoice
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func generateReference() string {
|
||||
// 1) Build the 26-digit payload from time + random suffix
|
||||
now := time.Now().UTC()
|
||||
ts := now.Format("20060102150405") // YYYYMMDDHHMMSS -> 14 chars
|
||||
ns := now.Nanosecond() // 0..999999999
|
||||
// format nanoseconds as 9 digits, zero padded
|
||||
nsStr := fmt.Sprintf("%09d", ns)
|
||||
|
||||
// 3-digit random suffix (000..999) to reach 26 digits
|
||||
randBytes := make([]byte, 2) // we'll read 2 bytes and map to 0..999
|
||||
rand.Read(randBytes)
|
||||
|
||||
// convert to number 0..65535 then mod 1000
|
||||
rnum := int(randBytes[0])<<8 | int(randBytes[1])
|
||||
rnum = rnum % 1000
|
||||
randStr := fmt.Sprintf("%03d", rnum)
|
||||
|
||||
// compose 26-digit payload: 14 + 9 + 3 = 26
|
||||
payload := ts + nsStr + randStr
|
||||
|
||||
// Safety: ensure payload is 26 digits (should always be true)
|
||||
if len(payload) != 26 {
|
||||
panic(fmt.Errorf("internal error: payload length %d != 26", len(payload)))
|
||||
}
|
||||
|
||||
// 2) Compute Modulo-10 recursive check digit
|
||||
check := mod10RecursiveChecksum(payload)
|
||||
|
||||
// 3) Build full 27-digit reference
|
||||
full := payload + fmt.Sprintf("%d", check)
|
||||
|
||||
// 4) Format with grouping: 2-5-5-5-5-5
|
||||
formatted := fmt.Sprintf("%s %s %s %s %s %s",
|
||||
full[0:2],
|
||||
full[2:7],
|
||||
full[7:12],
|
||||
full[12:17],
|
||||
full[17:22],
|
||||
full[22:27],
|
||||
)
|
||||
return formatted
|
||||
}
|
||||
|
||||
// mod10RecursiveChecksum computes the Mod10 recursive check digit for a numeric string.
|
||||
// Implements the table-based recursive mod10 described in Swiss Annex B / ISR implementations.
|
||||
func mod10RecursiveChecksum(digits string) int {
|
||||
// table as used in ISR/QR implementations
|
||||
arrTable := [10]int{0, 9, 4, 6, 8, 2, 7, 1, 3, 5}
|
||||
carry := 0
|
||||
for i := 0; i < len(digits); i++ {
|
||||
ch := digits[i]
|
||||
// assume digits are ASCII '0'..'9'
|
||||
n := int(ch - '0')
|
||||
// update carry
|
||||
idx := (carry + n) % 10
|
||||
carry = arrTable[idx]
|
||||
}
|
||||
// final check digit
|
||||
return (10 - carry) % 10
|
||||
}
|
||||
Reference in New Issue
Block a user