Skip to content

Commit

Permalink
#724 - parse amount from csv
Browse files Browse the repository at this point in the history
  • Loading branch information
deadlocker8 committed Jan 11, 2023
1 parent 3a8e773 commit b2a9ece
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,16 @@ public String columnSettings(WebRequest request,
{
final String date = csvRow.getColumns().get(csvColumnSettings.columnDate() - 1);
final String name = csvRow.getColumns().get(csvColumnSettings.columnName() - 1);

final String amount = csvRow.getColumns().get(csvColumnSettings.columnAmount() - 1);
csvTransactions.add(new CsvTransaction(date, name, amount, CsvTransactionStatus.PENDING));
final Optional<Integer> parsedAmountOptional = AmountParser.parse(amount);
if(parsedAmountOptional.isEmpty())
{
errors.add(Localization.getString("transactions.import.error.parse.amount", i, csvRow));
continue;
}

csvTransactions.add(new CsvTransaction(date, name, parsedAmountOptional.get(), CsvTransactionStatus.PENDING));
}
catch(IndexOutOfBoundsException e)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package de.deadlocker8.budgetmaster.transactions.csvimport;

import java.text.MessageFormat;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AmountParser
{
private static final Pattern PATTERN_AMOUNT = Pattern.compile("^\\s*([-+]?)\\s*(\\d+(,\\d+)?(\\.\\d+)?)");

private AmountParser()
{
}

public static Optional<Integer> parse(String amountString)
{
if(amountString == null)
{
return Optional.empty();
}

final Matcher matcher = PATTERN_AMOUNT.matcher(amountString);
boolean matchFound = matcher.find();
if(matchFound)
{
final String sign = matcher.group(1);
String amount = matcher.group(2);
amount = amount.replace(',', '.');

final String parseableString = MessageFormat.format("{0}{1}", sign, amount);
try
{
final double parseDouble = Double.parseDouble(parseableString);
return Optional.of((int) (parseDouble * 100));
}
catch(NumberFormatException e)
{
return Optional.empty();
}
}
else
{
return Optional.empty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ public final class CsvTransaction
{
private final String date;
private String name;
private final String amount;
private final Integer amount;
private CsvTransactionStatus status;

public CsvTransaction(String date, String name, String amount, CsvTransactionStatus status)
public CsvTransaction(String date, String name, Integer amount, CsvTransactionStatus status)
{
this.date = date;
this.name = name;
Expand All @@ -32,7 +32,7 @@ public void setName(String name)
this.name = name;
}

public String getAmount()
public Integer getAmount()
{
return amount;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ transactions.import.status.imported=importiert
transactions.import.status.skipped=übersprungen
transactions.import.actions=Aktionen
transactions.import.error.column=Zugeordnete Spalten in Zeile {0} (Zählung beginnt relativ zu Anzahl übersprungener Zeilen) nicht gefunden: {1}
transactions.import.error.parse.amount=Fehler beim Parsen des Betrags in Zeile {0} (Zählung beginnt relativ zu Anzahl übersprungener Zeilen)

repeating.button.add=Wiederholung hinzufügen
repeating.button.remove=Wiederholung entfernen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ transactions.import.status.imported=imported
transactions.import.status.skipped=skipped
transactions.import.actions=Actions
transactions.import.error.column=Associated columns not found in row {0} (counting starts relative to the number of skipped rows): {1}
transactions.import.error.parse.amount=Error parsing the amount in line {0} (counting starts relative to number of skipped lines)

repeating.button.add=Add repetition
repeating.button.remove=Remove repetition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@
<input class="no-margin-bottom" type="text" name="name" required value="${csvTransaction.getName()}">
</div>
</td>
<td>${csvTransaction.getAmount()}</td>
<td>${currencyService.getCurrencyString(csvTransaction.getAmount())}</td>
<td>
<@header.buttonSubmit name='action' icon='save' localizationKey='' classes='text-white'/>&nbsp;
<div class="fixed-action-btn edit-transaction-button">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
package de.deadlocker8.budgetmaster.unit.transaction.csvimport;

import de.deadlocker8.budgetmaster.transactions.csvimport.AmountParser;
import de.deadlocker8.budgetmaster.unit.helpers.LocalizedTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import static org.assertj.core.api.Assertions.assertThat;

class AmountParserTest
{
@Test
void test_dot_positive_noCurrency()
{
assertThat(AmountParser.parse("12.03"))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_dot_negative_noCurrency()
{
assertThat(AmountParser.parse("-18.41"))
.isPresent()
.get().isEqualTo(-1841);
}

@Test
void test_dot_negativeWithSpace_noCurrency()
{
assertThat(AmountParser.parse("- 200.30"))
.isPresent()
.get().isEqualTo(-20030);
}

@Test
void test_dot_positive_currency()
{
assertThat(AmountParser.parse("12.03 €"))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_dot_negative_currency()
{
assertThat(AmountParser.parse("-18.41€"))
.isPresent()
.get().isEqualTo(-1841);
}

@Test
void test_dot_positiveWithSign_noCurrency()
{
assertThat(AmountParser.parse("+12.03"))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_dot_positiveWithSignWithSpace_noCurrency()
{
assertThat(AmountParser.parse("+ 12.03"))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_comma_positive_noCurrency()
{
assertThat(AmountParser.parse("12,03"))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_comma_negative_noCurrency()
{
assertThat(AmountParser.parse("-18,41"))
.isPresent()
.get().isEqualTo(-1841);
}

@Test
void test_comma_negativeWithSpace_noCurrency()
{
assertThat(AmountParser.parse("- 200,30"))
.isPresent()
.get().isEqualTo(-20030);
}

@Test
void test_comma_positive_currency()
{
assertThat(AmountParser.parse("12,03 €"))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_comma_negative_currency()
{
assertThat(AmountParser.parse("-18,41€"))
.isPresent()
.get().isEqualTo(-1841);
}

@Test
void test_comma_positiveWithSign_noCurrency()
{
assertThat(AmountParser.parse("+12,03"))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_comma_positiveWithSignWithSpace_noCurrency()
{
assertThat(AmountParser.parse("+12,03"))
.isPresent()
.get().isEqualTo(1203);
}

@Test
void test_invalid_null()
{
assertThat(AmountParser.parse(null))
.isEmpty();
}

@Test
void test_invalid_empty()
{
assertThat(AmountParser.parse(""))
.isEmpty();
}

@Test
void test_invalid_empty2()
{
assertThat(AmountParser.parse(" "))
.isEmpty();
}

@Test
void test_invalid()
{
assertThat(AmountParser.parse("abc.42€"))
.isEmpty();
}

@Test
void test_integer_positive_noCurrency()
{
assertThat(AmountParser.parse("12"))
.isPresent()
.get().isEqualTo(1200);
}

@Test
void test_integer_negative_noCurrency()
{
assertThat(AmountParser.parse("-18"))
.isPresent()
.get().isEqualTo(-1800);
}

@Test
void test_integer_negativeWithSpace_noCurrency()
{
assertThat(AmountParser.parse("- 200"))
.isPresent()
.get().isEqualTo(-20000);
}

@Test
void test_integer_positive_currency()
{
assertThat(AmountParser.parse("12 €"))
.isPresent()
.get().isEqualTo(1200);
}

@Test
void test_integer_negative_currency()
{
assertThat(AmountParser.parse("-18€"))
.isPresent()
.get().isEqualTo(-1800);
}

@Test
void test_integer_positiveWithSign_noCurrency()
{
assertThat(AmountParser.parse("+12"))
.isPresent()
.get().isEqualTo(1200);
}

@Test
void test_integer_positiveWithSignWithSpace_noCurrency()
{
assertThat(AmountParser.parse("+ 12"))
.isPresent()
.get().isEqualTo(1200);
}
}

0 comments on commit b2a9ece

Please sign in to comment.