From 8cd1376240eb603736e31f0bdddf291e0914493c Mon Sep 17 00:00:00 2001 From: John Ahlroos Date: Tue, 20 Apr 2021 14:22:33 +0300 Subject: [PATCH] Add Caruna/Helen composite parser --- .gitignore | 1 + README.md | 11 ++- .../com/devsoap/parsers/caruna/Parser.class | Bin 6640 -> 0 bytes .../compileJava/source-classes-mapping.txt | 2 - .../parsers/{helen => caruna}/Parser.java | 81 ++++++++--------- composite-parsers/build.gradle | 6 ++ .../parsers/composites/CarunaHelenParser.java | 40 +++++++++ .../devsoap/parsers/helen/Parser$Period.class | Bin 1224 -> 0 bytes .../com/devsoap/parsers/helen/Parser.class | Bin 8474 -> 0 bytes .../compileJava/source-classes-mapping.txt | 3 - .../com/devsoap/parsers/helen/Parser.java | 84 ++++++++---------- settings.gradle | 1 + 12 files changed, 135 insertions(+), 94 deletions(-) delete mode 100644 caruna-invoice/build/classes/java/main/com/devsoap/parsers/caruna/Parser.class delete mode 100644 caruna-invoice/build/tmp/compileJava/source-classes-mapping.txt rename caruna-invoice/src/main/java/com/devsoap/parsers/{helen => caruna}/Parser.java (58%) create mode 100644 composite-parsers/build.gradle create mode 100644 composite-parsers/src/main/java/com/devsoap/parsers/composites/CarunaHelenParser.java delete mode 100644 helen-invoice/build/classes/java/main/com/devsoap/parsers/helen/Parser$Period.class delete mode 100644 helen-invoice/build/classes/java/main/com/devsoap/parsers/helen/Parser.class delete mode 100644 helen-invoice/build/tmp/compileJava/source-classes-mapping.txt diff --git a/.gitignore b/.gitignore index bffa164..e0d53d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .gradle .idea +build diff --git a/README.md b/README.md index dd60e8f..9160e14 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,18 @@ PDF parser to parse Caruna invoices. Usage: ``./gradlew :caruna-invoice:run --args="/path/to/pdf"`` - ### Helen Invoice Parser PDF parser to parse Helen invoices. -Usage: ``./gradlew :helen-invoice:run --args="/path/to/pdf"`` +Usage: ``./gradlew :helen-invoice:run --args="/path/to/pdf :dayKwh :nightKwh"`` + + +### Helen/Caruna Composite Parser +PDF parser to combine Helen/Caruna invoices into single lines + +Usage: ``./gradlew gradle :composite-parsers:run --args=".pdf .pdf""`` + + diff --git a/caruna-invoice/build/classes/java/main/com/devsoap/parsers/caruna/Parser.class b/caruna-invoice/build/classes/java/main/com/devsoap/parsers/caruna/Parser.class deleted file mode 100644 index 3d50a8a273151a0899f78289d7b779367d920db7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6640 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 diff --git a/caruna-invoice/build/tmp/compileJava/source-classes-mapping.txt b/caruna-invoice/build/tmp/compileJava/source-classes-mapping.txt deleted file mode 100644 index 9ed8ac7..0000000 --- a/caruna-invoice/build/tmp/compileJava/source-classes-mapping.txt +++ /dev/null @@ -1,2 +0,0 @@ -com/devsoap/parsers/caruna/Parser.java - com.devsoap.parsers.caruna.Parser diff --git a/caruna-invoice/src/main/java/com/devsoap/parsers/helen/Parser.java b/caruna-invoice/src/main/java/com/devsoap/parsers/caruna/Parser.java similarity index 58% rename from caruna-invoice/src/main/java/com/devsoap/parsers/helen/Parser.java rename to caruna-invoice/src/main/java/com/devsoap/parsers/caruna/Parser.java index 1ad5363..747077f 100644 --- a/caruna-invoice/src/main/java/com/devsoap/parsers/helen/Parser.java +++ b/caruna-invoice/src/main/java/com/devsoap/parsers/caruna/Parser.java @@ -1,19 +1,17 @@ -package com.devsoap.parsers.helen; +package com.devsoap.parsers.caruna; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfReader; import com.itextpdf.kernel.pdf.canvas.parser.PdfTextExtractor; -import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Path; import java.nio.file.Paths; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.time.format.TextStyle; -import java.util.Locale; -import java.util.Objects; -import java.util.Scanner; +import java.util.*; import java.util.regex.Pattern; public class Parser { @@ -29,78 +27,81 @@ public class Parser { .ofLocalizedDate(FormatStyle.SHORT) .withLocale(FI_LOCALE); + public static class Period { + public double basicPay = 0.0; + public double transferDayPrice = 0.0; + public double transferDayTotal = 0.0; + public int transferDayKwh = 0; + public double transferNightPrice = 0.0; + public double transferNightTotal = 0.0; + public int transferNightKwh = 0; + public double tax = 0.0; + } + public static void main(String[] args) { var filename = args[0]; var file = Paths.get(filename); + + System.out.println("Kuukausi,Perusmaksu (energia),Perusmaksu (siirto),Päiväenergia (kWh),Päiväenergia " + + "(EUR),Yöenergia (kWh),Yöenergia (EUR),Päiväsiirto (kWh),Päiväsiirto (EUR),Yösiirto (kWh)" + + ",Yösiirto (EUR),Vero"); + + parse(file).forEach((n,p) -> { + var csv = String.format("%s,,%.02f,,,,,%d, %.02f,%d, %.02f, %.02f", + n, p.basicPay, p.transferDayKwh, p.transferDayTotal, p.transferNightKwh, p.transferNightTotal, p.tax); + System.out.println(csv); + }); + } + + public static Map parse(Path file) { try(var reader = new PdfReader(file.toFile())) { var document = new PdfDocument(reader); var page2 = document.getPage(2); var text = PdfTextExtractor.getTextFromPage(page2); - var scanner = new Scanner(text); - var month = ""; - var basicPay = 0.0; - var transferDayPrice = 0.0; - var transferDayTotal = 0.0; - var transforDayKwh = 0L; - var transferNightPrice = 0.0; - var transferNightTotal = 0.0; - var transforNightKwh = 0L; - var tax = 0.0; - - System.out.println("Kuukausi,Perusmaksu (energia),Perusmaksu (siirto),Päiväenergia (kWh),Päiväenergia " + - "(EUR),Yöenergia (kWh),Yöenergia (EUR),Päiväsiirto (kWh),Päiväsiirto (EUR),Yösiirto (kWh)" + - ",Yösiirto (EUR),Vero"); + var periods = new HashMap(); + Period currentPeriod = null; while(scanner.hasNextLine()) { var line = scanner.nextLine(); if(DATE_RANGE_PATTERN.asPredicate().test(line)) { - if(!Objects.equals(month, "")) { - var csv = String.format("%s,,%.02f,,,,,%d, %.02f,%d, %.02f, %.02f", - month, basicPay, transforDayKwh, transferDayTotal, transforNightKwh, transferNightTotal, tax); - System.out.println(csv); - } - var matcher = DATE_RANGE_PATTERN.matcher(line); while(matcher.find()) { - month = LocalDate.from( FI_DATE.parse(matcher.group(1))) + var month = LocalDate.from( FI_DATE.parse(matcher.group(1))) .getMonth() .getDisplayName(TextStyle.FULL, new Locale("FI","fi")); month = month.substring(0,1).toUpperCase() + month.substring(1, month.length()-2); + currentPeriod = periods.computeIfAbsent(month, s -> new Period()); } } else if(PERUSMAKSU_PATTERN.asPredicate().test(line)) { var matcher = PERUSMAKSU_PATTERN.matcher(line); while (matcher.find()) { - basicPay = Double.parseDouble(matcher.group(1).replace(",", ".")); + currentPeriod.basicPay = Double.parseDouble(matcher.group(1).replace(",", ".")); } } else if(P_SIIRTO_PATTERN.asPredicate().test(line)) { var matcher = P_SIIRTO_PATTERN.matcher(line); while (matcher.find()) { - transferDayPrice = Double.parseDouble(matcher.group(1).replace(",", ".")) / 100.0; - transferDayTotal = Double.parseDouble(matcher.group(2).replace(",", ".")); - transforDayKwh = Math.round(transferDayTotal / transferDayPrice); + currentPeriod.transferDayPrice = Double.parseDouble(matcher.group(1).replace(",", ".")) / 100.0; + currentPeriod.transferDayTotal = Double.parseDouble(matcher.group(2).replace(",", ".")); + currentPeriod.transferDayKwh = (int) Math.round(currentPeriod.transferDayTotal / currentPeriod.transferDayPrice); } } else if(O_SIIRTO_PATTERN.asPredicate().test(line)) { var matcher = O_SIIRTO_PATTERN.matcher(line); while (matcher.find()) { - transferNightPrice = Double.parseDouble(matcher.group(1).replace(",", ".")) / 100.0; - transferNightTotal = Double.parseDouble(matcher.group(2).replace(",", ".")); - transforNightKwh = Math.round(transferNightTotal / transferNightPrice); + currentPeriod.transferNightPrice = Double.parseDouble(matcher.group(1).replace(",", ".")) / 100.0; + currentPeriod.transferNightTotal = Double.parseDouble(matcher.group(2).replace(",", ".")); + currentPeriod.transferNightKwh = (int) Math.round(currentPeriod.transferNightTotal / currentPeriod.transferNightPrice); } } else if(TAX_PATTERN.asPredicate().test(line)) { var matcher = TAX_PATTERN.matcher(line); while (matcher.find()) { - tax = Double.parseDouble(matcher.group(1).replace(",", ".")); + currentPeriod.tax = Double.parseDouble(matcher.group(1).replace(",", ".")); } } } - var csv = String.format("%s,,%.02f,,,,,%d, %.02f,%d, %.02f, %.02f", - month, basicPay, transforDayKwh, transferDayTotal, transforNightKwh, transferNightTotal, tax); - System.out.println(csv); - } catch (FileNotFoundException e) { - e.printStackTrace(); + return periods; } catch (IOException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } } diff --git a/composite-parsers/build.gradle b/composite-parsers/build.gradle new file mode 100644 index 0000000..0ad4b05 --- /dev/null +++ b/composite-parsers/build.gradle @@ -0,0 +1,6 @@ +dependencies { + implementation project(':caruna-invoice') + implementation project(':helen-invoice') +} + +application.mainClass='com.devsoap.parsers.composites.CarunaHelenParser' diff --git a/composite-parsers/src/main/java/com/devsoap/parsers/composites/CarunaHelenParser.java b/composite-parsers/src/main/java/com/devsoap/parsers/composites/CarunaHelenParser.java new file mode 100644 index 0000000..0e73d54 --- /dev/null +++ b/composite-parsers/src/main/java/com/devsoap/parsers/composites/CarunaHelenParser.java @@ -0,0 +1,40 @@ +package com.devsoap.parsers.composites; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Map; +import java.util.stream.Collectors; + +public class CarunaHelenParser { + + public static void main(String[] args) { + var carunaFile = Path.of("/home/john/Downloads/caruna-lasku.pdf"); + var helenFile = Path.of("/home/john/Downloads/helen-lasku.pdf"); + + var carunaPeriods = com.devsoap.parsers.caruna.Parser.parse(carunaFile); + var nightSiirto = carunaPeriods.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().transferNightKwh)); + var daySiirto = carunaPeriods.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().transferDayKwh)); + var helenPeriods = com.devsoap.parsers.helen.Parser.parse(helenFile, daySiirto, nightSiirto); + + System.out.println("Kuukausi,Perusmaksu (energia),Perusmaksu (siirto),Päiväenergia (kWh),Päiväenergia " + + "(EUR),Yöenergia (kWh),Yöenergia (EUR),Päiväsiirto (kWh),Päiväsiirto (EUR),Yösiirto (kWh)" + + ",Yösiirto (EUR),Vero"); + + var months = new HashSet<>(carunaPeriods.keySet()); + months.addAll(helenPeriods.keySet()); + months.forEach(month -> { + var hp = helenPeriods.getOrDefault(month, new com.devsoap.parsers.helen.Parser.Period()); + var cp = carunaPeriods.getOrDefault(month, new com.devsoap.parsers.caruna.Parser.Period()); + + var csv = String.format("%s,%.02f,%.02f,%d,%.02f,%d,%.02f,%d,%.02f,%d,%.02f,%.02f", + month, hp.basicPay, cp.basicPay, hp.dayEnergy, hp.dayEnergyEur, hp.nightEnergy, + hp.nightEnergyEur, cp.transferDayKwh, cp.transferDayTotal, cp.transferNightKwh, + cp.transferNightTotal, cp.tax); + csv = csv.replace(",0,",",,").replace(",0.00",","); + System.out.println(csv); + }); + } +} \ No newline at end of file diff --git a/helen-invoice/build/classes/java/main/com/devsoap/parsers/helen/Parser$Period.class b/helen-invoice/build/classes/java/main/com/devsoap/parsers/helen/Parser$Period.class deleted file mode 100644 index 7a6c516e75ee55e24b90d972ab1105334e7cc8db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1224 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 OI?3}qEFY9d5dJX)>Ql!6 diff --git a/helen-invoice/build/tmp/compileJava/source-classes-mapping.txt b/helen-invoice/build/tmp/compileJava/source-classes-mapping.txt deleted file mode 100644 index 7b6ed76..0000000 --- a/helen-invoice/build/tmp/compileJava/source-classes-mapping.txt +++ /dev/null @@ -1,3 +0,0 @@ -com/devsoap/parsers/helen/Parser.java - com.devsoap.parsers.helen.Parser - com.devsoap.parsers.helen.Parser$Period diff --git a/helen-invoice/src/main/java/com/devsoap/parsers/helen/Parser.java b/helen-invoice/src/main/java/com/devsoap/parsers/helen/Parser.java index d7726d9..640f216 100644 --- a/helen-invoice/src/main/java/com/devsoap/parsers/helen/Parser.java +++ b/helen-invoice/src/main/java/com/devsoap/parsers/helen/Parser.java @@ -6,17 +6,15 @@ import com.itextpdf.kernel.pdf.canvas.parser.PdfTextExtractor; import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Path; import java.nio.file.Paths; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.FormatStyle; import java.time.format.TextStyle; -import java.util.HashMap; -import java.util.Locale; -import java.util.Objects; -import java.util.Scanner; -import java.util.function.Function; +import java.util.*; import java.util.regex.Pattern; +import java.util.stream.Collectors; public class Parser { @@ -31,46 +29,44 @@ public class Parser { .ofLocalizedDate(FormatStyle.SHORT) .withLocale(FI_LOCALE); - - - static class Period { - double basicPay = 0.0; - int dayEnergy = 0; - int nightEnergy = 0; - double dayEnergyEur = 0.0; - double nightEnergyEur = 0.0; - - @Override - public String toString() { - return "Period{" + - "basicPay=" + basicPay + - ", dayEnergy=" + dayEnergy + - ", nightEnergy=" + nightEnergy + - ", dayEnergyEur=" + dayEnergyEur + - ", nightEnergyEur=" + nightEnergyEur + - '}'; - } + public static class Period { + public double basicPay = 0.0; + public int dayEnergy = 0; + public int nightEnergy = 0; + public double dayEnergyEur = 0.0; + public double nightEnergyEur = 0.0; } public static void main(String[] args) { - var filename = args[0]; - var daySiirtoKwh = 937; - var nightSiirtoKwh = 920; + var filename = Path.of(args[0]); + var daySiirtoKwh = Arrays + .stream(args[1].split(",")) + .map(period -> period.split(":")) + .collect(Collectors.toMap(values -> values[0], values -> Integer.parseInt(values[1]))); + var nightSiirtoKwh = Arrays + .stream(args[2].split(",")) + .map(period -> period.split(":")) + .collect(Collectors.toMap(values -> values[0], values -> Integer.parseInt(values[1]))); - var file = Paths.get(filename); + System.out.println("Kuukausi,Perusmaksu (energia),Perusmaksu (siirto),Päiväenergia (kWh),Päiväenergia " + + "(EUR),Yöenergia (kWh),Yöenergia (EUR),Päiväsiirto (kWh),Päiväsiirto (EUR),Yösiirto (kWh)" + + ",Yösiirto (EUR),Vero"); + + parse(filename,daySiirtoKwh, nightSiirtoKwh).forEach((month,period ) -> { + var csv = String.format("%s,%.02f,,%d,%.02f,%d,%.02f,,,,", month, + period.dayEnergy, period.dayEnergyEur,period.nightEnergy, period.nightEnergyEur); + System.out.println(csv); + }); + } + + public static Map parse(Path file, Map daySiirtoKwh, + Map nightSiirtoKwh) { try(var reader = new PdfReader(file.toFile())) { var document = new PdfDocument(reader); var page2 = document.getPage(2); var text = PdfTextExtractor.getTextFromPage(page2); - var scanner = new Scanner(text); - - System.out.println("Kuukausi,Perusmaksu (energia),Perusmaksu (siirto),Päiväenergia (kWh),Päiväenergia " + - "(EUR),Yöenergia (kWh),Yöenergia (EUR),Päiväsiirto (kWh),Päiväsiirto (EUR),Yösiirto (kWh)" + - ",Yösiirto (EUR),Vero"); - var periods = new HashMap(); - while(scanner.hasNextLine()) { var line = scanner.nextLine(); if(PERUSMAKSU_PATTERN.asPredicate().test(line)) { @@ -99,28 +95,22 @@ public class Parser { var eurPerKwh = Double.parseDouble(matcher.group(4) .replace(",", ".")) / 100.0; + var nightSiirto = nightSiirtoKwh.getOrDefault(month,0); + var daySriirto = daySiirtoKwh.getOrDefault(month,0); periods.computeIfAbsent(month, s -> new Period()); periods.computeIfPresent(month, (s,p) -> { - p.dayEnergy = totalEnergy - nightSiirtoKwh; + p.dayEnergy = totalEnergy - nightSiirto; p.dayEnergyEur = p.dayEnergy * eurPerKwh; - p.nightEnergy = totalEnergy - daySiirtoKwh; + p.nightEnergy = totalEnergy - daySriirto; p.nightEnergyEur = p.nightEnergy * eurPerKwh; return p; }); } } } - - periods.forEach((month,period ) -> { - var csv = String.format("%s,%.02f,,%d,%.02f,%d,%.02f,,,,", month, period.basicPay, - period.dayEnergy, period.dayEnergyEur,period.nightEnergy, period.nightEnergyEur); - System.out.println(csv); - }); - - } catch (FileNotFoundException e) { - e.printStackTrace(); + return periods; } catch (IOException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } } diff --git a/settings.gradle b/settings.gradle index fba2639..ea42789 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,5 @@ rootProject.name = 'pdf-parsers' include 'caruna-invoice' include 'helen-invoice' +include 'composite-parsers'