Skip to content
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# PDF files generated by tests
*.pdf

mono_test.rest
.idea
mono-cli
102 changes: 102 additions & 0 deletions generate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package main

import (
"bufio"
"bytes"
"io/ioutil"
"os"
"testing"

"github.com/lungria/mono-cli/statementsPdf"
)

func TestGenerate(t *testing.T) {
var file *os.File
var fileReader *bufio.Reader

testData := [][]string{
{"qweqweqwe", "1569903114", "Нарахування відсотків за вересень", "4829", "true", "22", "22", "980", "0", "0", "1930"},
{"qwesdfqwe", "1569903114", "CARD2CARD UAMAB", "4829", "true", "5066", "5066", "980", "0", "0", "193550"},
}

err := statementsPdf.Generate("statementsPdf/testPdf/statement_test_actual.pdf", testData)
if err != nil {
t.Errorf("Pdf isn't generated, Error appear %v ", err)
}

// Open statement_test_actual.pdf
file, err = os.Open("statementsPdf/testPdf/statement_test_actual.pdf")
if err != nil {
t.Errorf("Open statement_test_actual.pdf failed. Error: %v \n", err)
}
fileReader = bufio.NewReader(file)
actualPdf, err := ioutil.ReadAll(fileReader)
if err != nil {
t.Errorf("Read from statement_test_actual.pdf failed. Error: %v \n", err)
}

// Open statement_test_expected.pdf
file, err = os.Open("statementsPdf/testPdf/statement_test_expected.pdf")
if err != nil {
t.Errorf("Open statement_test_expected,pdf failed. Error: %v \n", err)
}
fileReader = bufio.NewReader(file)
expectedPdf, err := ioutil.ReadAll(fileReader)
if err != nil {
t.Errorf("Read from statement_test_actual.pdf failed. Error: %v \n", err)
}

// Compare content of pdf files
result := bytes.Compare(actualPdf, expectedPdf)
if result != 1 {
t.Errorf("Pdf files aren't sames")
}
}

func TestGeneratePagination(t *testing.T) {
const maxRows = 20
var file *os.File
var fileReader *bufio.Reader
var multipliedTestData = make([][]string, maxRows)

testData := [][]string{
{"qweqweqwe", "1569903114", "Нарахування відсотків за вересень", "4829", "true", "22", "22", "980", "0", "0", "1930"},
}

for i := 0; i < maxRows; i++ {
multipliedTestData[i] = append(multipliedTestData[i], testData[0]...)
}

err := statementsPdf.Generate("statementsPdf/testPdf/statement_test_actual_pagination.pdf", multipliedTestData)
if err != nil {
t.Errorf("Pdf isn't generated, Error appear %v ", err)
}

// Open statement_test_actual.pdf
file, err = os.Open("statementsPdf/testPdf/statement_test_actual_pagination.pdf")
if err != nil {
t.Errorf("Open statement_test_actual.pdf failed. Error: %v \n", err)
}
fileReader = bufio.NewReader(file)
actualPdf, err := ioutil.ReadAll(fileReader)
if err != nil {
t.Errorf("Read from statement_test_actual.pdf failed. Error: %v \n", err)
}

// Open statement_test_expected.pdf
file, err = os.Open("statementsPdf/testPdf/statement_test_expected_pagination.pdf")
if err != nil {
t.Errorf("Open statement_test_expected,pdf failed. Error: %v \n", err)
}
fileReader = bufio.NewReader(file)
expectedPdf, err := ioutil.ReadAll(fileReader)
if err != nil {
t.Errorf("Read from statement_test_actual.pdf failed. Error: %v \n", err)
}

// Compare content of pdf files
result := bytes.Compare(actualPdf, expectedPdf)
if result != 1 {
t.Errorf("Pdf files aren't sames")
}
}
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ module github.com/lungria/mono-cli

go 1.12

require github.com/lungria/mono v0.0.10
require (
github.com/jung-kurt/gofpdf v1.15.1
github.com/lungria/mono v0.0.10
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,14 @@
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jung-kurt/gofpdf v1.15.1 h1:vcj3SN7gwT+H6MoeTzZ+L58/i4cAAGW64Rl+cxKdpV0=
github.com/jung-kurt/gofpdf v1.15.1/go.mod h1:1hl7y57EsiPAkLbOwzpzqgx1A30nQCk/YmFV8S2vmK0=
github.com/lungria/mono v0.0.10 h1:2UollwSdcqbJTbd8XhJj7Zn3HxbDcZjJjLb+LbAln3g=
github.com/lungria/mono v0.0.10/go.mod h1:1ENDA5dSTj5mqUy2Kp8345W0iCOkMXYM44H2ivaQd6s=
github.com/phpdave11/gofpdi v1.0.7/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
20 changes: 17 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"encoding/csv"
"errors"
"flag"
"fmt"
"log"
"os"
Expand All @@ -11,6 +12,8 @@ import (
"strconv"
"time"

"github.com/lungria/mono-cli/statementsPdf"

"github.com/lungria/mono"
)

Expand All @@ -27,6 +30,8 @@ func main() {
if err != nil {
log.Fatal(err)
}
pdfFile := flag.String("o", "", "Generate statements in PDF format. e.g: <mono-cli -o path/to/output/file.pdf>")
flag.Parse()

writer = csv.NewWriter(os.Stdout)

Expand All @@ -48,7 +53,15 @@ func main() {
}

statements = Sort(statements)
saveStatements(statements)
stmData := saveStatements(statements)

if *pdfFile != "" {
err = statementsPdf.Generate(*pdfFile, stmData)
if err != nil {
log.Fatal("Generate pdf failed :", err)
}
return
}
<-apiRateLimit
}
}
Expand Down Expand Up @@ -87,9 +100,9 @@ func parseConfig() (config, error) {
var newLineRegexp = regexp.MustCompile(`\r?\n`)
var headerPrinted = false

func saveStatements(items []mono.StatementItem) {
func saveStatements(items []mono.StatementItem) [][]string {
if len(items) == 0 {
return
return nil
}

if !headerPrinted {
Expand Down Expand Up @@ -128,4 +141,5 @@ func saveStatements(items []mono.StatementItem) {
if err != nil {
log.Fatal(err)
}
return csvData
}
Binary file added statementsPdf/fonts/Alice-Regular.ttf
Binary file not shown.
146 changes: 146 additions & 0 deletions statementsPdf/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package statementsPdf

import (
"strings"

"github.com/jung-kurt/gofpdf"
)

const (
colCount = 4
colWd = 45.0
marginH = 15.0
lineHt = 5.5
cellGap = 2.0
)

const (
imgFolder = "statementsPdf/img/"
fontsFolder = "statementsPdf/fonts/"
)

type cpdf struct {
gofpdf.Pdf
*gofpdf.Fpdf
gofpdf.FontLoader
}

// var colStrList [colCount]string
type cellType struct {
str string
list [][]byte
ht float64
}

var (
cellList [colCount]cellType
cell cellType
)

// Generate returns pdf file
func Generate(filename string, data [][]string) error {
statements, err := prettyCsvArr(data)
if err != nil {
return err
}
//Create new PDF
pdf := cpdf{Fpdf: gofpdf.New("P", "mm", "A4", "")}

// Add font with support cyrillic characters
pdf.AddUTF8Font("Alice-Regular", "", fontsFolder+"Alice-Regular.ttf")

// Set global margins
pdf.Fpdf.SetMargins(marginH, 35, marginH)
pdf.Fpdf.AddPage()
pdf.Fpdf.PageNo()

pdf.renderHeader()
pdf.renderTableHeaders(headers)
// Render table with statements with pagination
pdf.renderStatementsTable(statements, headers)

return pdf.Fpdf.OutputFileAndClose(filename)
}

func (p cpdf) renderStatementsTable(data [][]string, headers []string) {
y := p.Fpdf.GetY()
count := 0
for row := 0; row < len(data); row++ {
p.Fpdf.SetTextColor(24, 24, 24)
p.Fpdf.SetFillColor(255, 255, 255)
maxHt := lineHt
// Cell height calculation loop
for col := 0; col < colCount; col++ {
count++
if count > len(data) {
count = 1
}
cell.str = strings.Join(data[(len(data)-1)-row][col:col+1], " ")
cell.list = p.Fpdf.SplitLines([]byte(cell.str), colWd-cellGap-cellGap)
cell.ht = float64(len(cell.list)) * lineHt
if cell.ht > maxHt {
maxHt = cell.ht
}
cellList[col] = cell
}

// Cell render loop
x := marginH
for colJ := 0; colJ < colCount; colJ++ {
//pdf.Rect(x, y, colWd, maxHt+cellGap+cellGap, "D")
cell = cellList[colJ]
cellY := y + cellGap + (maxHt-cell.ht)/2
for splitJ := 0; splitJ < len(cell.list); splitJ++ {
p.Fpdf.SetXY(x+cellGap, cellY)
p.Fpdf.CellFormat(colWd-cellGap-cellGap, lineHt, string(cell.list[splitJ]), "", 0,
"C", false, 0, "")
cellY += lineHt
}
x += colWd
}
y += maxHt + cellGap + cellGap

y = p.addNextPages(y, headers)
}
}

func (p cpdf) renderHeader() {
p.Fpdf.SetFont("Alice-Regular", "", 24)
p.Fpdf.Text(marginH*3, 20, "Header of statements")
p.Fpdf.ImageOptions(
imgFolder+"mono-logo.jpg",
170, 8,
20, 20,
false,
gofpdf.ImageOptions{ImageType: "JPG", ReadDpi: true},
0,
"",
)

}

func (p cpdf) renderTableHeaders(headers []string) {
p.Fpdf.SetFont("Alice-Regular", "", 9)
p.Fpdf.SetTextColor(224, 224, 224)
p.Fpdf.SetFillColor(45, 45, 45)
// Fill headers to cells
for colJ := 0; colJ < colCount; colJ++ {
p.Fpdf.CellFormat(colWd, 10, headers[colJ], "1", 0, "CM", true, 0, "")
}
p.Fpdf.Ln(-1)
}

func (p cpdf) addNextPages(y float64, headers []string) float64 {
_, ht, _ := p.Fpdf.PageSize(p.Fpdf.PageNo())
if y+cell.ht*lineHt > ht {
p.Fpdf.SetMargins(marginH, 15, marginH)
p.Fpdf.AddPage()
y = p.Fpdf.GetY()
p.Fpdf.SetFont("Alice-Regular", "", 9)

p.renderTableHeaders(headers)

return p.Fpdf.GetY()
}
return y
}
Binary file added statementsPdf/img/mono-logo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading