Skip to content

Commit

Permalink
Fix Excel import bug with AOT
Browse files Browse the repository at this point in the history
  • Loading branch information
ystxn committed Oct 19, 2024
1 parent 1f0db69 commit b794a55
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 38 deletions.
12 changes: 5 additions & 7 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,11 @@ dependencies {
implementation ("com.opencsv:opencsv:5.9") {
exclude group: "commons-logging", module: "commons-logging"
}
implementation ("org.jxls:jxls-jexcel:1.0.9") {
exclude group: "commons-logging", module: "commons-logging"
exclude group: "log4j", module: "log4j"
}
implementation "org.apache.poi:poi:5.3.0"
developmentOnly "org.springframework.boot:spring-boot-devtools"

testRuntimeOnly "org.junit.platform:junit-platform-launcher:1.11.0-M2"
testImplementation "org.junit.jupiter:junit-jupiter:5.11.0-M2"
testRuntimeOnly "org.junit.platform:junit-platform-launcher:1.11.2"
testImplementation "org.junit.jupiter:junit-jupiter:5.11.2"
testImplementation "org.springframework.boot:spring-boot-starter-test"
testImplementation "org.springframework.security:spring-security-test"
testImplementation "org.testcontainers:testcontainers:$testContainersVersion"
Expand Down Expand Up @@ -89,7 +86,8 @@ bootBuildImage {
createdDate = "now"
environment = [
"BP_JVM_VERSION": "23",
"BP_SPRING_CLOUD_BINDINGS_DISABLED": "true"
"BP_SPRING_CLOUD_BINDINGS_DISABLED": "true",
"BP_NATIVE_IMAGE_BUILD_ARGUMENTS": "-H:+AddAllCharsets"
]
docker {
publishRegistry {
Expand Down
15 changes: 13 additions & 2 deletions src/main/java/tech/sledger/config/AotHints.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package tech.sledger.config;

import static org.springframework.aot.hint.MemberCategory.*;
import static org.springframework.aot.hint.MemberCategory.DECLARED_FIELDS;
import static org.springframework.aot.hint.MemberCategory.INVOKE_DECLARED_CONSTRUCTORS;
import static org.springframework.aot.hint.MemberCategory.INVOKE_DECLARED_METHODS;
import static org.springframework.aot.hint.MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS;
import static org.springframework.aot.hint.MemberCategory.INVOKE_PUBLIC_METHODS;
import static org.springframework.aot.hint.MemberCategory.PUBLIC_FIELDS;
import org.apache.logging.log4j.message.DefaultFlowMessageFactory;
import org.apache.logging.log4j.message.ParameterizedMessageFactory;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.lang.NonNull;
Expand Down Expand Up @@ -29,7 +37,10 @@ public void registerHints(@NonNull RuntimeHints hints, ClassLoader classLoader)
CategoryInsight.class,
ChartResponse.class,
OcbcImporter.class,
UobImporter.class
UobImporter.class,
HSSFWorkbook.class,
DefaultFlowMessageFactory.class,
ParameterizedMessageFactory.class
).forEach(c -> {
hints.reflection().registerType(c, INVOKE_DECLARED_CONSTRUCTORS);
hints.reflection().registerType(c, INVOKE_PUBLIC_CONSTRUCTORS);
Expand Down
85 changes: 56 additions & 29 deletions src/main/java/tech/sledger/service/importer/UobImporter.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package tech.sledger.service.importer;

import jxl.Sheet;
import jxl.Workbook;
import static org.apache.poi.ss.usermodel.CellType.NUMERIC;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.util.StringUtils.hasText;
import static tech.sledger.model.account.AccountType.Cash;
import static tech.sledger.model.account.AccountType.Credit;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.springframework.web.server.ResponseStatusException;
import tech.sledger.model.account.Account;
import tech.sledger.model.account.AccountType;
Expand All @@ -11,18 +18,17 @@
import tech.sledger.model.tx.CreditTransaction;
import tech.sledger.model.tx.Template;
import tech.sledger.model.tx.Transaction;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.util.StringUtils.hasText;
import static tech.sledger.model.account.AccountType.Cash;
import static tech.sledger.model.account.AccountType.Credit;
import java.util.Map;

@Slf4j
public class UobImporter implements Importer {
Expand All @@ -32,36 +38,56 @@ public class UobImporter implements Importer {
public List<Transaction> process(
Account account, InputStream inputStream, List<Template> templates
) {
try {
Sheet sheet = Workbook.getWorkbook(inputStream).getSheet(0);
long accountNumberLength = sheet.getCell(1, 4).getContents().length();
if (
(account.getType() == Cash && accountNumberLength != 10) ||
(account.getType() == Credit && accountNumberLength != 16)
) {
throw new ResponseStatusException(BAD_REQUEST, "Invalid import file");
Map<Integer, List<Object>> data = parseExcel(inputStream);

String accountNumber = data.get(4).get(1).toString();
long accountNumberLength = accountNumber.length();

if (
(account.getType() == Cash && accountNumberLength != 10) ||
(account.getType() == Credit && accountNumberLength != 16)
) {
throw new ResponseStatusException(BAD_REQUEST, "Invalid import file");
}

return account.getType() == AccountType.Cash ?
processCash(data, account, templates) : processCredit(data, account, templates);
}

private Map<Integer, List<Object>> parseExcel(InputStream inputStream) {
Map<Integer, List<Object>> data = new HashMap<>();

try (HSSFWorkbook workbook = new HSSFWorkbook(inputStream)) {
HSSFSheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
List<Object> dataRow = new ArrayList<>();
for (Cell cell : row) {
var value = cell.getCellType().equals(NUMERIC) ?
cell.getNumericCellValue() : cell.getStringCellValue();
dataRow.add(value);
}
data.put(row.getRowNum(), dataRow);
}
return account.getType() == AccountType.Cash ?
processCash(sheet, account, templates) : processCredit(sheet, account, templates);
} catch (Exception e) {
log.error("Error importing UOB file", e);
} catch (IOException e) {
throw new ResponseStatusException(BAD_REQUEST, "Invalid import file");
}
return data;
}

private List<Transaction> processCash(Sheet sheet, Account account, List<Template> templates) {
private List<Transaction> processCash(Map<Integer, List<Object>> data, Account account, List<Template> templates) {
List<Transaction> output = new ArrayList<>();

for (int i = 8; i < sheet.getRows(); i++) {
String dateContents = sheet.getCell(0, i).getContents();
for (int i = 8; i < data.size(); i++) {
List<Object> dataRow = data.get(i);
String dateContents = dataRow.getFirst().toString();
if (!hasText(dateContents)) {
continue;
}
Instant date = LocalDate.parse(dateContents, dateFormat)
.atStartOfDay(ZoneOffset.UTC).toInstant();
String remarks = sheet.getCell(1, i).getContents().trim();
BigDecimal debit = parseDecimal(sheet.getCell(2, i).getContents());
BigDecimal credit = parseDecimal(sheet.getCell(3, i).getContents());
String remarks = dataRow.get(1).toString().trim();
BigDecimal debit = parseDecimal(dataRow.get(2).toString());
BigDecimal credit = parseDecimal(dataRow.get(3).toString());
Template template = matchTemplate(remarks, templates);

output.add(CashTransaction.builder()
Expand All @@ -77,16 +103,17 @@ private List<Transaction> processCash(Sheet sheet, Account account, List<Templat
}

private List<Transaction> processCredit(
Sheet sheet, Account account, List<Template> templates
Map<Integer, List<Object>> data, Account account, List<Template> templates
) {
List<Transaction> output = new ArrayList<>();

for (int i = 11; i < sheet.getRows(); i++) {
LocalDate localDate = LocalDate.parse(sheet.getCell(0, i).getContents(), dateFormat);
for (int i = 11; i <= data.size(); i++) {
List<Object> dataRow = data.get(i);
LocalDate localDate = LocalDate.parse(dataRow.getFirst().toString(), dateFormat);
Instant date = localDate.atStartOfDay(ZoneOffset.UTC).toInstant();
Instant billingMonth = getBillingMonth(localDate, (CreditAccount) account);
String remarks = sheet.getCell(2, i).getContents().trim();
BigDecimal amount = parseDecimal(sheet.getCell(6, i).getContents());
String remarks = dataRow.get(2).toString().trim();
BigDecimal amount = parseDecimal(dataRow.get(6).toString());
Template template = matchTemplate(remarks, templates);

if (amount.compareTo(BigDecimal.ZERO) == 0) {
Expand Down
Binary file modified src/test/resources/uob-cash.xls
Binary file not shown.
Binary file modified src/test/resources/uob-credit.xls
Binary file not shown.

0 comments on commit b794a55

Please sign in to comment.