Skip to content
Snippets Groups Projects
Commit f9602315 authored by Robert Goldmann's avatar Robert Goldmann
Browse files

Fixed #259 - Import databases from version < 2.0.0

parent 04925b24
No related branches found
No related tags found
No related merge requests found
Pipeline #224 passed
...@@ -29,7 +29,13 @@ public class AccountController extends BaseController ...@@ -29,7 +29,13 @@ public class AccountController extends BaseController
public String selectAccount(HttpServletRequest request, @PathVariable("ID") Integer ID) public String selectAccount(HttpServletRequest request, @PathVariable("ID") Integer ID)
{ {
accountService.selectAccount(ID); accountService.selectAccount(ID);
return "redirect:" + request.getHeader("Referer");
String referer = request.getHeader("Referer");
if(referer.contains("database/import"))
{
return "redirect:/settings";
}
return "redirect:" + referer;
} }
@RequestMapping("/accounts") @RequestMapping("/accounts")
......
...@@ -2,15 +2,15 @@ package de.deadlocker8.budgetmaster.controller; ...@@ -2,15 +2,15 @@ package de.deadlocker8.budgetmaster.controller;
import de.deadlocker8.budgetmaster.authentication.User; import de.deadlocker8.budgetmaster.authentication.User;
import de.deadlocker8.budgetmaster.authentication.UserRepository; import de.deadlocker8.budgetmaster.authentication.UserRepository;
import de.deadlocker8.budgetmaster.database.DatabaseImporter;
import de.deadlocker8.budgetmaster.database.accountmatches.AccountMatchList;
import de.deadlocker8.budgetmaster.database.Database; import de.deadlocker8.budgetmaster.database.Database;
import de.deadlocker8.budgetmaster.database.DatabaseParser; import de.deadlocker8.budgetmaster.database.DatabaseParser;
import de.deadlocker8.budgetmaster.database.accountmatches.AccountMatchList;
import de.deadlocker8.budgetmaster.entities.Settings; import de.deadlocker8.budgetmaster.entities.Settings;
import de.deadlocker8.budgetmaster.repositories.AccountRepository; import de.deadlocker8.budgetmaster.repositories.AccountRepository;
import de.deadlocker8.budgetmaster.repositories.SettingsRepository; import de.deadlocker8.budgetmaster.repositories.SettingsRepository;
import de.deadlocker8.budgetmaster.services.DatabaseService; import de.deadlocker8.budgetmaster.services.DatabaseService;
import de.deadlocker8.budgetmaster.services.HelpersService; import de.deadlocker8.budgetmaster.services.HelpersService;
import de.deadlocker8.budgetmaster.services.ImportService;
import de.deadlocker8.budgetmaster.utils.LanguageType; import de.deadlocker8.budgetmaster.utils.LanguageType;
import de.deadlocker8.budgetmaster.utils.Strings; import de.deadlocker8.budgetmaster.utils.Strings;
import org.joda.time.DateTime; import org.joda.time.DateTime;
...@@ -20,7 +20,11 @@ import org.springframework.stereotype.Controller; ...@@ -20,7 +20,11 @@ import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError; import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.WebRequest; import org.springframework.web.context.request.WebRequest;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.mvc.support.RedirectAttributes;
...@@ -30,7 +34,6 @@ import tools.Localization; ...@@ -30,7 +34,6 @@ import tools.Localization;
import tools.RandomCreations; import tools.RandomCreations;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
...@@ -54,6 +57,9 @@ public class SettingsController extends BaseController ...@@ -54,6 +57,9 @@ public class SettingsController extends BaseController
@Autowired @Autowired
private AccountRepository accountRepository; private AccountRepository accountRepository;
@Autowired
private ImportService importService;
@RequestMapping("/settings") @RequestMapping("/settings")
public String settings(WebRequest request, Model model) public String settings(WebRequest request, Model model)
{ {
...@@ -229,9 +235,8 @@ public class SettingsController extends BaseController ...@@ -229,9 +235,8 @@ public class SettingsController extends BaseController
@RequestMapping("/settings/database/import") @RequestMapping("/settings/database/import")
public String importDatabase(WebRequest request, @ModelAttribute("Import") AccountMatchList accountMatchList) public String importDatabase(WebRequest request, @ModelAttribute("Import") AccountMatchList accountMatchList)
{ {
DatabaseImporter importer = new DatabaseImporter((Database)request.getAttribute("database", WebRequest.SCOPE_SESSION), accountMatchList); importService.importDatabase((Database)request.getAttribute("database", WebRequest.SCOPE_SESSION), accountMatchList);
importer.importDatabase(); request.removeAttribute("database", RequestAttributes.SCOPE_SESSION);
return "settings"; return "settings";
} }
} }
\ No newline at end of file
...@@ -18,7 +18,6 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -18,7 +18,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.ArrayList; import java.util.ArrayList;
......
...@@ -34,12 +34,16 @@ public class DatabaseParser ...@@ -34,12 +34,16 @@ public class DatabaseParser
if(version == 2) if(version == 2)
{ {
return new LegacyParser(jsonString).parseDatabaseFromJSON(); Database database = new LegacyParser(jsonString).parseDatabaseFromJSON();
LOGGER.debug("Parsed database with " + database.getTransactions().size() + " transactions, " + database.getCategories().size() + " categories and " + database.getAccounts().size() + " accounts");
return database;
} }
if(version == 3) if(version == 3)
{ {
return new DatabaseParser_v3(jsonString).parseDatabaseFromJSON(); Database database = new DatabaseParser_v3(jsonString).parseDatabaseFromJSON();
LOGGER.debug("Parsed database with " + database.getTransactions().size() + " transactions, " + database.getCategories().size() + " categories and " + database.getAccounts().size() + " accounts");
return database;
} }
throw new IllegalArgumentException(Localization.getString("error.database.import.unknown.version")); throw new IllegalArgumentException(Localization.getString("error.database.import.unknown.version"));
......
package de.deadlocker8.budgetmaster.database; package de.deadlocker8.budgetmaster.services;
import de.deadlocker8.budgetmaster.database.Database;
import de.deadlocker8.budgetmaster.database.accountmatches.AccountMatch;
import de.deadlocker8.budgetmaster.database.accountmatches.AccountMatchList; import de.deadlocker8.budgetmaster.database.accountmatches.AccountMatchList;
import de.deadlocker8.budgetmaster.entities.Category; import de.deadlocker8.budgetmaster.entities.Category;
import de.deadlocker8.budgetmaster.entities.CategoryType; import de.deadlocker8.budgetmaster.entities.CategoryType;
import de.deadlocker8.budgetmaster.entities.Tag;
import de.deadlocker8.budgetmaster.entities.Transaction; import de.deadlocker8.budgetmaster.entities.Transaction;
import de.deadlocker8.budgetmaster.repositories.CategoryRepository; import de.deadlocker8.budgetmaster.repositories.CategoryRepository;
import de.deadlocker8.budgetmaster.repositories.TagRepository;
import de.deadlocker8.budgetmaster.repositories.TransactionRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class DatabaseImporter @Service
public class ImportService
{ {
private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
@Autowired @Autowired
private CategoryRepository categoryRepository; private CategoryRepository categoryRepository;
@Autowired
private TransactionRepository transactionRepository;
@Autowired
private TagRepository tagRepository;
private Database database; @Autowired
private AccountMatchList accountMatchList; public ImportService(CategoryRepository categoryRepository, TransactionRepository transactionRepository, TagRepository tagRepository)
public DatabaseImporter(Database database, AccountMatchList accountMatchList)
{ {
this.database = database; this.categoryRepository = categoryRepository;
this.accountMatchList = accountMatchList; this.transactionRepository = transactionRepository;
this.tagRepository = tagRepository;
} }
public void importDatabase() public void importDatabase(Database database, AccountMatchList accountMatchList)
{ {
importCategories(); importCategories(database);
// importAccounts(database, accountMatchList);
// for(AccountMatch accountMatch : accountMatchList.getAccountMatches()) importTransactions(database);
// {
//
// }
} }
private void importCategories() private void importCategories(Database database)
{ {
List<Transaction> alreadyUpdatedTransactions = new ArrayList<>(); List<Transaction> alreadyUpdatedTransactions = new ArrayList<>();
...@@ -47,8 +57,6 @@ public class DatabaseImporter ...@@ -47,8 +57,6 @@ public class DatabaseImporter
int newCategoryID = -1; int newCategoryID = -1;
System.out.println("Importing category: " + category);
Category existingCategory = categoryRepository.findByNameAndColorAndType(category.getName(), category.getColor(), category.getType()); Category existingCategory = categoryRepository.findByNameAndColorAndType(category.getName(), category.getColor(), category.getType());
if(existingCategory == null) if(existingCategory == null)
{ {
...@@ -67,16 +75,20 @@ public class DatabaseImporter ...@@ -67,16 +75,20 @@ public class DatabaseImporter
int oldCategoryID = category.getID(); int oldCategoryID = category.getID();
List<Transaction> transactions = database.getTransactions(); if(oldCategoryID == newCategoryID)
{
continue;
}
List<Transaction> transactions = new ArrayList<>(database.getTransactions());
transactions.removeAll(alreadyUpdatedTransactions); transactions.removeAll(alreadyUpdatedTransactions);
alreadyUpdatedTransactions.addAll(updateCategoriesForTransactions(transactions, oldCategoryID, newCategoryID)); alreadyUpdatedTransactions.addAll(updateCategoriesForTransactions(transactions, oldCategoryID, newCategoryID));
} }
} }
private List<Transaction> updateCategoriesForTransactions(List<Transaction> transactions, int oldCategoryID, int newCategoryID) public List<Transaction> updateCategoriesForTransactions(List<Transaction> transactions, int oldCategoryID, int newCategoryID)
{ {
System.out.println("Replacing category id " + oldCategoryID + " with " + newCategoryID);
List<Transaction> updatedTransactions = new ArrayList<>(); List<Transaction> updatedTransactions = new ArrayList<>();
for(Transaction transaction : transactions) for(Transaction transaction : transactions)
{ {
...@@ -89,4 +101,78 @@ public class DatabaseImporter ...@@ -89,4 +101,78 @@ public class DatabaseImporter
return updatedTransactions; return updatedTransactions;
} }
private void importAccounts(Database database, AccountMatchList accountMatchList)
{
List<Transaction> alreadyUpdatedTransactions = new ArrayList<>();
for(AccountMatch accountMatch : accountMatchList.getAccountMatches())
{
List<Transaction> transactions = new ArrayList<>(database.getTransactions());
transactions.removeAll(alreadyUpdatedTransactions);
alreadyUpdatedTransactions.addAll(updateAccountsForTransactions(transactions, accountMatch.getAccountSource().getID(), accountMatch.getAccountDestination().getID()));
}
}
private List<Transaction> updateAccountsForTransactions(List<Transaction> transactions, int oldAccountID, int newAccountID)
{
List<Transaction> updatedTransactions = new ArrayList<>();
for(Transaction transaction : transactions)
{
// legacy database
if(oldAccountID == -1)
{
transaction.getAccount().setID(newAccountID);
updatedTransactions.add(transaction);
}
else if(transaction.getAccount().getID() == oldAccountID)
{
transaction.getAccount().setID(newAccountID);
updatedTransactions.add(transaction);
}
}
return updatedTransactions;
}
private void importTransactions(Database database)
{
for(Transaction transaction : database.getTransactions())
{
updateTagsForTransaction(transaction);
// if(transaction.isRepeating())
// {
// transaction.getRepeatingOption().setID(null);
// }
transaction.setID(null);
try
{
transactionRepository.save(transaction);
}
catch(Exception e)
{
System.out.println(transaction);
}
}
}
private void updateTagsForTransaction(Transaction transaction)
{
List<Tag> tags = transaction.getTags();
for(int i = 0; i < tags.size(); i++)
{
Tag currentTag = tags.get(i);
Tag existingTag = tagRepository.findByName(currentTag.getName());
if(existingTag == null)
{
tagRepository.save(new Tag(currentTag.getName()));
tags.set(i, tagRepository.findByName(currentTag.getName()));
}
else
{
tags.set(i, existingTag);
}
}
}
} }
...@@ -12,23 +12,37 @@ $( document ).ready(function() { ...@@ -12,23 +12,37 @@ $( document ).ready(function() {
function validateForm() function validateForm()
{ {
// handle account matches // handle account matches
var accountSources = $('.account-source'); var accountSourcesIDs = $('.account-source-id');
var accountSourcesNames= $('.account-source');
var accountDestinations = $('select.account-destination'); var accountDestinations = $('select.account-destination');
var parent = document.getElementById("hidden-account-matches"); var parent = document.getElementById("hidden-account-matches");
for(var i = 0; i < accountSources.length; i++) for(var i = 0; i < accountSourcesIDs.length; i++)
{ {
var input = document.createElement("input"); var inputSourceID = document.createElement("input");
input.setAttribute("type", "hidden"); inputSourceID.setAttribute("type", "hidden");
input.setAttribute("name", "accountMatches[" + i + "].accountSource.name"); inputSourceID.setAttribute("name", "accountMatches[" + i + "].accountSource.ID");
input.setAttribute("value", accountSources[i].innerText); inputSourceID.setAttribute("value", accountSourcesIDs[i].innerText);
parent.appendChild(input); parent.appendChild(inputSourceID);
var inputSourceName = document.createElement("input");
inputSourceName.setAttribute("type", "hidden");
inputSourceName.setAttribute("name", "accountMatches[" + i + "].accountSource.name");
inputSourceName.setAttribute("value", accountSourcesNames[i].innerText);
parent.appendChild(inputSourceName);
var inputDestinationID = document.createElement("input");
inputDestinationID.setAttribute("type", "hidden");
inputDestinationID.setAttribute("name", "accountMatches[" + i + "].accountDestination.ID");
inputDestinationID.setAttribute("value", accountDestinations[i].value);
parent.appendChild(inputDestinationID);
var inputDestination = document.createElement("input"); var inputDestinationNames = document.createElement("input");
inputDestination.setAttribute("type", "hidden"); inputDestinationNames.setAttribute("type", "hidden");
inputDestination.setAttribute("name", "accountMatches[" + i + "].accountDestination.name"); inputDestinationNames.setAttribute("name", "accountMatches[" + i + "].accountDestination.name");
inputDestination.setAttribute("value", accountDestinations[i].value); inputDestinationNames.setAttribute("value", accountDestinations[i].innerText);
parent.appendChild(inputDestination); parent.appendChild(inputDestinationNames);
} }
return true; return true;
......
...@@ -24,12 +24,13 @@ ...@@ -24,12 +24,13 @@
<#list helpers.getAccountMatches(database.getAccounts()) as accountMatch> <#list helpers.getAccountMatches(database.getAccounts()) as accountMatch>
<tr> <tr>
<td class="import-text">${locale.getString("info.database.import.source")}</td> <td class="import-text">${locale.getString("info.database.import.source")}</td>
<td class="account-source-id hidden"><#if accountMatch.getAccountSource().getID()??>${accountMatch.getAccountSource().getID()}<#else>-1</#if> </td>
<td class="account-source">${accountMatch.getAccountSource().getName()}</td> <td class="account-source">${accountMatch.getAccountSource().getName()}</td>
<td class="import-text">${locale.getString("info.database.import.destination")}</td> <td class="import-text">${locale.getString("info.database.import.destination")}</td>
<td> <td>
<select class="account-destination"> <select class="account-destination">
<#list availableAccounts as account> <#list availableAccounts as account>
<option value="${account.getName()}">${account.getName()}</option> <option value="${account.getID()}">${account.getName()}</option>
</#list> </#list>
</select> </select>
</td> </td>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment