blob: 5e8ae0803346c0facb6fc34edc4b24dca94331bb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.cn.accounting.importer;
import org.apache.fineract.cn.accounting.api.v1.client.AccountAlreadyExistsException;
import org.apache.fineract.cn.accounting.api.v1.client.LedgerManager;
import org.apache.fineract.cn.accounting.api.v1.domain.Account;
import org.apache.fineract.cn.accounting.api.v1.domain.Ledger;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.slf4j.Logger;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
/**
* @author Myrle Krantz
*/
@SuppressWarnings("unused")
public class AccountImporter {
private static final String TYPE_COLUMN = "type";
private static final String IDENTIFIER_COLUMN = "identifier";
private static final String NAME_COLUMN = "name";
private static final String PARENT_IDENTIFIER_COLUMN = "parentIdentifier";
private static final String HOLDERS_COLUMN = "holders";
private static final String AUTHORITIES_COLUMN = "authorities";
private static final String BALANCE_COLUMN = "balance";
private final LedgerManager ledgerManager;
private final Logger logger;
public AccountImporter(final LedgerManager ledgerManager, final Logger logger) {
this.ledgerManager = ledgerManager;
this.logger = logger;
}
public void importCSV(final URL toImport) throws IOException {
final CSVParser parser = CSVParser.parse(toImport, StandardCharsets.UTF_8, CSVFormat.RFC4180.withHeader());
final List<RecordFromLineNumber<Account>> ledgerList = StreamSupport.stream(parser.spliterator(), false)
.map(this::toAccount)
.collect(Collectors.toList()); //File should fully parse, correctly, before we begin creating ledgers/accounts.
ledgerList.forEach(this::createAccount);
}
private void createAccount(final RecordFromLineNumber<Account> toCreate) {
try {
ledgerManager.createAccount(toCreate.getRecord());
}
catch (final AccountAlreadyExistsException ignored) {
final Account account = ledgerManager.findAccount(toCreate.getRecord().getIdentifier());
if ((!Objects.equals(account.getBalance(), toCreate.getRecord().getBalance())) ||
(!Objects.equals(account.getIdentifier(), toCreate.getRecord().getIdentifier())) ||
(!Objects.equals(account.getHolders(), toCreate.getRecord().getHolders())) ||
(!Objects.equals(account.getLedger(), toCreate.getRecord().getLedger())) ||
(!Objects.equals(account.getName(), toCreate.getRecord().getName())) ||
(!Objects.equals(account.getSignatureAuthorities(), toCreate.getRecord().getSignatureAuthorities())) ||
(!Objects.equals(account.getType(), toCreate.getRecord().getType())))
{
logger.error("Creation of account {} failed, because an account with the same identifier but different properties already exists {}", toCreate.getRecord(), account);
}
}
}
private RecordFromLineNumber<Account> toAccount(final CSVRecord csvRecord) {
try {
final String ledgerIdentifier = csvRecord.get(PARENT_IDENTIFIER_COLUMN);
String type;
try {
type = csvRecord.get(TYPE_COLUMN);
}
catch (final IllegalArgumentException e) {
final Ledger ledger = ledgerManager.findLedger(ledgerIdentifier);
type = ledger.getType();
}
final String identifier = csvRecord.get(IDENTIFIER_COLUMN);
String name;
try {
name = csvRecord.get(NAME_COLUMN);
}
catch (final IllegalArgumentException e) {
name = identifier;
}
Set<String> holders;
try {
holders = new HashSet<>(Arrays.asList(csvRecord.get(HOLDERS_COLUMN).split("/")));
}
catch (final IllegalArgumentException e) {
holders = Collections.emptySet();
}
Set<String> authorities;
try {
authorities = new HashSet<>(Arrays.asList(csvRecord.get(AUTHORITIES_COLUMN).split("/")));
}
catch (final IllegalArgumentException e) {
authorities = Collections.emptySet();
}
Double balance;
try {
balance = Double.valueOf(csvRecord.get(BALANCE_COLUMN));
}
catch (final IllegalArgumentException e) {
balance = 0.0;
}
final Account account = new Account();
account.setType(type);
account.setIdentifier(identifier);
account.setName(name);
account.setHolders(holders);
account.setSignatureAuthorities(authorities);
account.setLedger(ledgerIdentifier);
account.setBalance(balance);
return new RecordFromLineNumber<>(csvRecord.getRecordNumber(), account);
}
catch (final NumberFormatException e) {
logger.warn("Number parsing failed on record {}", csvRecord.getRecordNumber());
throw e;
}
catch (final IllegalArgumentException e) {
logger.warn("Parsing failed on record {}", csvRecord.getRecordNumber());
throw e;
}
}
}