diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser.java index cf714084c324c632788192339a77c4f888dd87e1..93887340ea2008c13842a1b9baa30d55bce25cbd 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser.java @@ -8,6 +8,7 @@ import de.deadlocker8.budgetmaster.database.model.v5.BackupDatabase_v5; import de.deadlocker8.budgetmaster.database.model.v6.BackupDatabase_v6; import de.deadlocker8.budgetmaster.database.model.v7.BackupDatabase_v7; import de.deadlocker8.budgetmaster.database.model.v8.BackupDatabase_v8; +import de.deadlocker8.budgetmaster.database.model.v9.BackupDatabase_v9; import de.thecodelabs.utils.util.Localization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,7 +20,7 @@ public class DatabaseParser final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); private static final int MINIMUM_VERSION = 4; - public static final int LATEST_VERSION = 8; + public static final int LATEST_VERSION = 9; private final String jsonString; @@ -74,6 +75,13 @@ public class DatabaseParser importedDatabase = parsedDatabase; } + if(version == 9) + { + BackupDatabase_v9 parsedDatabase = new DatabaseParser_v9(jsonString).parseDatabaseFromJSON(); + LOGGER.debug(MessageFormat.format("Parsed database with {0} transactions, {1} categories, {2} accounts, {3} templates {4} charts {5} images {6} icons and {7} transaction name keywords", parsedDatabase.getTransactions().size(), parsedDatabase.getCategories().size(), parsedDatabase.getAccounts().size(), parsedDatabase.getTemplates().size(), parsedDatabase.getCharts().size(), parsedDatabase.getImages().size(), parsedDatabase.getIcons().size(), parsedDatabase.getTransactionNameKeywords().size())); + importedDatabase = parsedDatabase; + } + if(importedDatabase == null) { throw new IllegalArgumentException(Localization.getString("error.database.import.unknown.version")); diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v9.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v9.java new file mode 100644 index 0000000000000000000000000000000000000000..95be80011a6edd282ea677cf02876c63ba2eff4b --- /dev/null +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v9.java @@ -0,0 +1,46 @@ +package de.deadlocker8.budgetmaster.database; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import de.deadlocker8.budgetmaster.database.model.v5.BackupChart_v5; +import de.deadlocker8.budgetmaster.database.model.v5.BackupImage_v5; +import de.deadlocker8.budgetmaster.database.model.v6.BackupTransaction_v6; +import de.deadlocker8.budgetmaster.database.model.v7.BackupAccount_v7; +import de.deadlocker8.budgetmaster.database.model.v7.BackupCategory_v7; +import de.deadlocker8.budgetmaster.database.model.v8.BackupDatabase_v8; +import de.deadlocker8.budgetmaster.database.model.v8.BackupIcon_v8; +import de.deadlocker8.budgetmaster.database.model.v8.BackupTemplateGroup_v8; +import de.deadlocker8.budgetmaster.database.model.v8.BackupTemplate_v8; +import de.deadlocker8.budgetmaster.database.model.v9.BackupDatabase_v9; +import de.deadlocker8.budgetmaster.database.model.v9.BackupTransactionNameKeyword_v9; + +public class DatabaseParser_v9 +{ + private final String jsonString; + + private BackupDatabase_v9 database; + + public DatabaseParser_v9(String json) + { + this.jsonString = json; + this.database = new BackupDatabase_v9(); + } + + public BackupDatabase_v9 parseDatabaseFromJSON() throws IllegalArgumentException + { + database = new BackupDatabase_v9(); + + final JsonObject root = JsonParser.parseString(jsonString).getAsJsonObject(); + database.setImages(BackupItemParser.parseItems(root.get("images").getAsJsonArray(), BackupImage_v5.class)); + database.setIcons(BackupItemParser.parseItems(root.get("icons").getAsJsonArray(), BackupIcon_v8.class)); + database.setAccounts(BackupItemParser.parseItems(root.get("accounts").getAsJsonArray(), BackupAccount_v7.class)); + database.setCategories(BackupItemParser.parseItems(root.get("categories").getAsJsonArray(), BackupCategory_v7.class)); + database.setTransactions(BackupItemParser.parseItems(root.get("transactions").getAsJsonArray(), BackupTransaction_v6.class)); + database.setTemplateGroups(BackupItemParser.parseItems(root.get("templateGroups").getAsJsonArray(), BackupTemplateGroup_v8.class)); + database.setTemplates(BackupItemParser.parseItems(root.get("templates").getAsJsonArray(), BackupTemplate_v8.class)); + database.setCharts(BackupItemParser.parseItems(root.get("charts").getAsJsonArray(), BackupChart_v5.class)); + database.setTransactionNameKeywords(BackupItemParser.parseItems(root.get("transactionNameKeywords").getAsJsonArray(), BackupTransactionNameKeyword_v9.class)); + + return database; + } +} \ No newline at end of file diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseService.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseService.java index 6e2e7c1e5c8b04a0743812a0f609c79fe6ae5221..64403d98bb966f1ed5129ca8a6c7da3d43637e67 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseService.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseService.java @@ -10,7 +10,7 @@ import de.deadlocker8.budgetmaster.charts.Chart; import de.deadlocker8.budgetmaster.charts.ChartService; import de.deadlocker8.budgetmaster.charts.ChartType; import de.deadlocker8.budgetmaster.database.model.BackupDatabase; -import de.deadlocker8.budgetmaster.database.model.v8.BackupDatabase_v8; +import de.deadlocker8.budgetmaster.database.model.v9.BackupDatabase_v9; import de.deadlocker8.budgetmaster.hints.HintService; import de.deadlocker8.budgetmaster.icon.Icon; import de.deadlocker8.budgetmaster.icon.IconService; @@ -26,6 +26,8 @@ import de.deadlocker8.budgetmaster.templates.Template; import de.deadlocker8.budgetmaster.templates.TemplateService; import de.deadlocker8.budgetmaster.transactions.Transaction; import de.deadlocker8.budgetmaster.transactions.TransactionService; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeyword; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeywordService; import de.deadlocker8.budgetmaster.utils.DateHelper; import de.thecodelabs.utils.io.PathUtils; import org.slf4j.Logger; @@ -66,11 +68,12 @@ public class DatabaseService private final ImageService imageService; private final IconService iconService; private final HintService hintService; + private final TransactionNameKeywordService transactionNameKeywordService; private final List<Resettable> services; @Autowired - public DatabaseService(AccountService accountService, CategoryService categoryService, TransactionService transactionService, TagService tagService, TemplateService templateService, TemplateGroupService templateGroupService, ChartService chartService, SettingsService settingsService, ImageService imageService, IconService iconService, HintService hintService) + public DatabaseService(AccountService accountService, CategoryService categoryService, TransactionService transactionService, TagService tagService, TemplateService templateService, TemplateGroupService templateGroupService, ChartService chartService, SettingsService settingsService, ImageService imageService, IconService iconService, HintService hintService, TransactionNameKeywordService transactionNameKeywordService) { this.accountService = accountService; this.categoryService = categoryService; @@ -83,7 +86,8 @@ public class DatabaseService this.imageService = imageService; this.iconService = iconService; this.hintService = hintService; - this.services = List.of(transactionService, templateService, templateGroupService, categoryService, accountService, tagService, chartService, iconService, imageService, tagService, hintService); + this.transactionNameKeywordService = transactionNameKeywordService; + this.services = List.of(transactionService, templateService, templateGroupService, categoryService, accountService, tagService, chartService, iconService, imageService, tagService, hintService, transactionNameKeywordService); } public void reset() @@ -218,12 +222,13 @@ public class DatabaseService List<Chart> charts = chartService.getRepository().findAllByType(ChartType.CUSTOM); List<Image> images = imageService.getRepository().findAll(); List<Icon> icons = iconService.getRepository().findAll(); + List<TransactionNameKeyword> transactionNameKeywords = transactionNameKeywordService.getRepository().findAll(); LOGGER.debug(MessageFormat.format("Reduced {0} transactions to {1}", transactions.size(), filteredTransactions.size())); - InternalDatabase database = new InternalDatabase(categories, accounts, filteredTransactions, templateGroups, templates, charts, images, icons); - LOGGER.debug(MessageFormat.format("Created database for JSON with {0} transactions, {1} categories, {2} accounts, {3} templates groups, {4} templates, {5} charts {6} images and {7} icons", database.getTransactions().size(), database.getCategories().size(), database.getAccounts().size(), database.getTemplateGroups().size(), database.getTemplates().size(), database.getCharts().size(), database.getImages().size(), database.getIcons().size())); + InternalDatabase database = new InternalDatabase(categories, accounts, filteredTransactions, templateGroups, templates, charts, images, icons, transactionNameKeywords); + LOGGER.debug(MessageFormat.format("Created database for JSON with {0} transactions, {1} categories, {2} accounts, {3} templates groups, {4} templates, {5} charts {6} images {7} icons and {8} transaction name keywords", database.getTransactions().size(), database.getCategories().size(), database.getAccounts().size(), database.getTemplateGroups().size(), database.getTemplates().size(), database.getCharts().size(), database.getImages().size(), database.getIcons().size(), database.getTransactionNameKeywords().size())); - BackupDatabase_v8 databaseInExternalForm = BackupDatabase_v8.createFromInternalEntities(database); + BackupDatabase_v9 databaseInExternalForm = BackupDatabase_v9.createFromInternalEntities(database); LOGGER.debug("Converted database to external form"); return databaseInExternalForm; } diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/InternalDatabase.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/InternalDatabase.java index 2e456b2cf1d0f50f082f5889729bf217682b45b0..4fe6fb0d67f8feec2a0442e90bfe08a3693abc8c 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/InternalDatabase.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/InternalDatabase.java @@ -10,6 +10,7 @@ import de.deadlocker8.budgetmaster.services.EntityType; import de.deadlocker8.budgetmaster.templategroup.TemplateGroup; import de.deadlocker8.budgetmaster.templates.Template; import de.deadlocker8.budgetmaster.transactions.Transaction; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeyword; import java.util.LinkedHashMap; import java.util.List; @@ -25,12 +26,13 @@ public class InternalDatabase private List<Chart> charts; private List<Image> images; private List<Icon> icons; + private List<TransactionNameKeyword> transactionNameKeywords; public InternalDatabase() { } - public InternalDatabase(List<Category> categories, List<Account> accounts, List<Transaction> transactions, List<TemplateGroup> templateGroups, List<Template> templates, List<Chart> charts, List<Image> images, List<Icon> icons) + public InternalDatabase(List<Category> categories, List<Account> accounts, List<Transaction> transactions, List<TemplateGroup> templateGroups, List<Template> templates, List<Chart> charts, List<Image> images, List<Icon> icons, List<TransactionNameKeyword> transactionNameKeywords) { this.categories = categories; this.accounts = accounts; @@ -40,6 +42,7 @@ public class InternalDatabase this.charts = charts; this.images = images; this.icons = icons; + this.transactionNameKeywords = transactionNameKeywords; } public List<Category> getCategories() @@ -82,6 +85,11 @@ public class InternalDatabase return icons; } + public List<TransactionNameKeyword> getTransactionNameKeywords() + { + return transactionNameKeywords; + } + public Map<EntityType, Integer> getNumberOfEntitiesByType() { final Map<EntityType, Integer> numberOfEntitiesByType = new LinkedHashMap<>(); diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/importer/AccountImporter.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/importer/AccountImporter.java index 8af71ac8da33675ad68d986ea07f1774f828a651..85dd087bc6d5970bd1bc2adb0b1b607d1dddcd09 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/importer/AccountImporter.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/importer/AccountImporter.java @@ -33,7 +33,7 @@ public class AccountImporter extends ItemImporter<Account> if(repository.findByName(account.getName()) != null) { - throw new ImportException(MessageFormat.format("An account with name: {0} already exist. Account names must be unique. Delete or rename the existing account first.", account.getName())); + throw new ImportException(MessageFormat.format("An account with name: {0} already exists. Account names must be unique. Delete or rename the existing account first.", account.getName())); } LOGGER.debug(MessageFormat.format("Importing account with name: {0}", account.getName())); diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/importer/TransactionNameKeywordImporter.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/importer/TransactionNameKeywordImporter.java new file mode 100644 index 0000000000000000000000000000000000000000..4b3cfae3da0f360a3d718f7b001fb4cc88e50455 --- /dev/null +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/importer/TransactionNameKeywordImporter.java @@ -0,0 +1,48 @@ +package de.deadlocker8.budgetmaster.database.importer; + +import de.deadlocker8.budgetmaster.services.EntityType; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeyword; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeywordRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.MessageFormat; + +public class TransactionNameKeywordImporter extends ItemImporter<TransactionNameKeyword> +{ + private static final Logger LOGGER = LoggerFactory.getLogger(TransactionNameKeywordImporter.class); + + public TransactionNameKeywordImporter(TransactionNameKeywordRepository keywordRepository) + { + super(keywordRepository, EntityType.TRANSACTION_NAME_KEYWORD); + } + + @Override + protected int importSingleItem(TransactionNameKeyword keyword) throws ImportException + { + if(!(repository instanceof TransactionNameKeywordRepository repository)) + { + throw new IllegalArgumentException("Invalid repository type"); + } + + final TransactionNameKeyword existingKeyword = repository.findByValue(keyword.getValue()); + if(existingKeyword != null) + { + LOGGER.debug(MessageFormat.format("Skipping {0} (a transaction name keyword with this value already exists)", keyword.getValue())); + return existingKeyword.getID(); + } + + final TransactionNameKeyword keywordToCreate = new TransactionNameKeyword(); + keywordToCreate.setValue(keyword.getValue()); + + final TransactionNameKeyword savedKeyword = repository.save(keywordToCreate); + + return savedKeyword.getID(); + } + + @Override + protected String getNameForItem(TransactionNameKeyword item) + { + return String.valueOf(item.getValue()); + } +} diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/TransactionNameKeywordConverter.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/TransactionNameKeywordConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..e7d1cb7b84c274e017312e3efb25a6060aa25097 --- /dev/null +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/TransactionNameKeywordConverter.java @@ -0,0 +1,33 @@ +package de.deadlocker8.budgetmaster.database.model.converter; + +import de.deadlocker8.budgetmaster.database.model.Converter; +import de.deadlocker8.budgetmaster.database.model.v9.BackupTransactionNameKeyword_v9; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeyword; + +public class TransactionNameKeywordConverter implements Converter<TransactionNameKeyword, BackupTransactionNameKeyword_v9> +{ + public TransactionNameKeyword convertToInternalForm(BackupTransactionNameKeyword_v9 backupKeyword) + { + if(backupKeyword == null) + { + return null; + } + + final TransactionNameKeyword keyword = new TransactionNameKeyword(); + keyword.setValue(backupKeyword.getValue()); + return keyword; + } + + @Override + public BackupTransactionNameKeyword_v9 convertToExternalForm(TransactionNameKeyword internalItem) + { + if(internalItem == null) + { + return null; + } + + final BackupTransactionNameKeyword_v9 keyword = new BackupTransactionNameKeyword_v9(); + keyword.setValue(internalItem.getValue()); + return keyword; + } +} diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/model/v8/BackupDatabase_v8.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/model/v8/BackupDatabase_v8.java index 6625e9343d0d005a9c000847ff7431b1168e4d8c..6e5f1cba74063cacc6f09b33b73840eeb516bdb7 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/model/v8/BackupDatabase_v8.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/model/v8/BackupDatabase_v8.java @@ -1,22 +1,14 @@ package de.deadlocker8.budgetmaster.database.model.v8; -import de.deadlocker8.budgetmaster.accounts.Account; -import de.deadlocker8.budgetmaster.categories.Category; -import de.deadlocker8.budgetmaster.charts.Chart; import de.deadlocker8.budgetmaster.database.InternalDatabase; import de.deadlocker8.budgetmaster.database.JSONIdentifier; import de.deadlocker8.budgetmaster.database.model.BackupDatabase; -import de.deadlocker8.budgetmaster.database.model.converter.*; import de.deadlocker8.budgetmaster.database.model.v5.BackupChart_v5; import de.deadlocker8.budgetmaster.database.model.v5.BackupImage_v5; import de.deadlocker8.budgetmaster.database.model.v6.BackupTransaction_v6; import de.deadlocker8.budgetmaster.database.model.v7.BackupAccount_v7; import de.deadlocker8.budgetmaster.database.model.v7.BackupCategory_v7; -import de.deadlocker8.budgetmaster.icon.Icon; -import de.deadlocker8.budgetmaster.images.Image; -import de.deadlocker8.budgetmaster.templategroup.TemplateGroup; -import de.deadlocker8.budgetmaster.templates.Template; -import de.deadlocker8.budgetmaster.transactions.Transaction; +import de.deadlocker8.budgetmaster.database.model.v9.BackupDatabase_v9; import java.util.List; @@ -141,16 +133,7 @@ public class BackupDatabase_v8 implements BackupDatabase public InternalDatabase convertToInternal() { - final List<Image> convertedImages = convertItemsToInternal(this.images, new ImageConverter()); - final List<Icon> convertedIcons = convertItemsToInternal(this.icons, new IconConverter(convertedImages)); - final List<Category> convertedCategories = convertItemsToInternal(categories, new CategoryConverter(convertedIcons)); - final List<Account> convertedAccounts = convertItemsToInternal(accounts, new AccountConverter(convertedIcons)); - final List<Transaction> convertedTransactions = convertItemsToInternal(this.transactions, new TransactionConverter(convertedCategories, convertedAccounts)); - final List<TemplateGroup> convertedTemplateGroups = convertItemsToInternal(this.templateGroups, new TemplateGroupConverter()); - final List<Template> convertedTemplates = convertItemsToInternal(this.templates, new TemplateConverter(convertedIcons, convertedCategories, convertedAccounts, convertedTemplateGroups)); - final List<Chart> convertedCharts = convertItemsToInternal(this.charts, new ChartConverter()); - - return new InternalDatabase(convertedCategories, convertedAccounts, convertedTransactions, convertedTemplateGroups, convertedTemplates, convertedCharts, convertedImages, convertedIcons); + throw new UnsupportedOperationException(); } @Override @@ -162,22 +145,18 @@ public class BackupDatabase_v8 implements BackupDatabase @Override public BackupDatabase upgrade() { - throw new UnsupportedOperationException(); - } - - public static BackupDatabase_v8 createFromInternalEntities(InternalDatabase database) - { - final BackupDatabase_v8 externalDatabase = new BackupDatabase_v8(); + final BackupDatabase_v9 upgradedDatabase = new BackupDatabase_v9(); - externalDatabase.setIcons(externalDatabase.convertItemsToExternal(database.getIcons(), new IconConverter(null))); - externalDatabase.setCategories(externalDatabase.convertItemsToExternal(database.getCategories(), new CategoryConverter(null))); - externalDatabase.setAccounts(externalDatabase.convertItemsToExternal(database.getAccounts(), new AccountConverter(null))); - externalDatabase.setTransactions(externalDatabase.convertItemsToExternal(database.getTransactions(), new TransactionConverter(null, null))); - externalDatabase.setTemplateGroups(externalDatabase.convertItemsToExternal(database.getTemplateGroups(), new TemplateGroupConverter())); - externalDatabase.setTemplates(externalDatabase.convertItemsToExternal(database.getTemplates(), new TemplateConverter(null, null, null, null))); - externalDatabase.setCharts(externalDatabase.convertItemsToExternal(database.getCharts(), new ChartConverter())); - externalDatabase.setImages(externalDatabase.convertItemsToExternal(database.getImages(), new ImageConverter())); + upgradedDatabase.setCategories(categories); + upgradedDatabase.setAccounts(accounts); + upgradedDatabase.setTransactions(transactions); + upgradedDatabase.setTemplateGroups(templateGroups); + upgradedDatabase.setTemplates(templates); + upgradedDatabase.setCharts(charts); + upgradedDatabase.setImages(images); + upgradedDatabase.setIcons(icons); + upgradedDatabase.setTransactionNameKeywords(List.of()); - return externalDatabase; + return upgradedDatabase; } } diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/model/v9/BackupDatabase_v9.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/model/v9/BackupDatabase_v9.java new file mode 100644 index 0000000000000000000000000000000000000000..f2c75ba39ad42f58bf8ddfc8a21b536a0faedabc --- /dev/null +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/database/model/v9/BackupDatabase_v9.java @@ -0,0 +1,201 @@ +package de.deadlocker8.budgetmaster.database.model.v9; + +import de.deadlocker8.budgetmaster.accounts.Account; +import de.deadlocker8.budgetmaster.categories.Category; +import de.deadlocker8.budgetmaster.charts.Chart; +import de.deadlocker8.budgetmaster.database.InternalDatabase; +import de.deadlocker8.budgetmaster.database.JSONIdentifier; +import de.deadlocker8.budgetmaster.database.model.BackupDatabase; +import de.deadlocker8.budgetmaster.database.model.converter.*; +import de.deadlocker8.budgetmaster.database.model.v5.BackupChart_v5; +import de.deadlocker8.budgetmaster.database.model.v5.BackupImage_v5; +import de.deadlocker8.budgetmaster.database.model.v6.BackupTransaction_v6; +import de.deadlocker8.budgetmaster.database.model.v7.BackupAccount_v7; +import de.deadlocker8.budgetmaster.database.model.v7.BackupCategory_v7; +import de.deadlocker8.budgetmaster.database.model.v8.BackupIcon_v8; +import de.deadlocker8.budgetmaster.database.model.v8.BackupTemplateGroup_v8; +import de.deadlocker8.budgetmaster.database.model.v8.BackupTemplate_v8; +import de.deadlocker8.budgetmaster.icon.Icon; +import de.deadlocker8.budgetmaster.images.Image; +import de.deadlocker8.budgetmaster.templategroup.TemplateGroup; +import de.deadlocker8.budgetmaster.templates.Template; +import de.deadlocker8.budgetmaster.transactions.Transaction; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeyword; + +import java.util.List; + +public class BackupDatabase_v9 implements BackupDatabase +{ + @SuppressWarnings("unused") + private final String TYPE = JSONIdentifier.BUDGETMASTER_DATABASE.toString(); + + @SuppressWarnings({"FieldCanBeLocal", "squid:S1170"}) + // field can not be static, since static field won't be exported to JSON by GSON + private final int VERSION = 9; + + @SuppressWarnings({"unused", "squid:S2065", "squid:S1170"}) + // field can not be static, since static field won't be exported to JSON by GSON + private final transient String INTRODUCED_IN_VERSION = "v2.11.0"; + + private List<BackupCategory_v7> categories; + private List<BackupAccount_v7> accounts; + private List<BackupTransaction_v6> transactions; + private List<BackupTemplateGroup_v8> templateGroups; + private List<BackupTemplate_v8> templates; + private List<BackupChart_v5> charts; + private List<BackupImage_v5> images; + private List<BackupIcon_v8> icons; + private List<BackupTransactionNameKeyword_v9> transactionNameKeywords; + + public BackupDatabase_v9() + { + // for GSON + } + + public BackupDatabase_v9(List<BackupCategory_v7> categories, List<BackupAccount_v7> accounts, List<BackupTransaction_v6> transactions, List<BackupTemplateGroup_v8> templateGroups, List<BackupTemplate_v8> templates, List<BackupChart_v5> charts, List<BackupImage_v5> images, List<BackupIcon_v8> icons, List<BackupTransactionNameKeyword_v9> transactionNameKeywords) + { + this.categories = categories; + this.accounts = accounts; + this.transactions = transactions; + this.templateGroups = templateGroups; + this.templates = templates; + this.charts = charts; + this.images = images; + this.icons = icons; + this.transactionNameKeywords = transactionNameKeywords; + } + + public List<BackupCategory_v7> getCategories() + { + return categories; + } + + public void setCategories(List<BackupCategory_v7> categories) + { + this.categories = categories; + } + + public List<BackupAccount_v7> getAccounts() + { + return accounts; + } + + public void setAccounts(List<BackupAccount_v7> accounts) + { + this.accounts = accounts; + } + + public List<BackupTransaction_v6> getTransactions() + { + return transactions; + } + + public void setTransactions(List<BackupTransaction_v6> transactions) + { + this.transactions = transactions; + } + + public List<BackupTemplate_v8> getTemplates() + { + return templates; + } + + public void setTemplates(List<BackupTemplate_v8> templates) + { + this.templates = templates; + } + + public List<BackupChart_v5> getCharts() + { + return charts; + } + + public void setCharts(List<BackupChart_v5> charts) + { + this.charts = charts; + } + + public List<BackupImage_v5> getImages() + { + return images; + } + + public void setImages(List<BackupImage_v5> images) + { + this.images = images; + } + + public List<BackupIcon_v8> getIcons() + { + return icons; + } + + public void setIcons(List<BackupIcon_v8> icons) + { + this.icons = icons; + } + + public List<BackupTemplateGroup_v8> getTemplateGroups() + { + return templateGroups; + } + + public void setTemplateGroups(List<BackupTemplateGroup_v8> templateGroups) + { + this.templateGroups = templateGroups; + } + + public List<BackupTransactionNameKeyword_v9> getTransactionNameKeywords() + { + return transactionNameKeywords; + } + + public void setTransactionNameKeywords(List<BackupTransactionNameKeyword_v9> transactionNameKeywords) + { + this.transactionNameKeywords = transactionNameKeywords; + } + + public InternalDatabase convertToInternal() + { + final List<Image> convertedImages = convertItemsToInternal(this.images, new ImageConverter()); + final List<Icon> convertedIcons = convertItemsToInternal(this.icons, new IconConverter(convertedImages)); + final List<Category> convertedCategories = convertItemsToInternal(categories, new CategoryConverter(convertedIcons)); + final List<Account> convertedAccounts = convertItemsToInternal(accounts, new AccountConverter(convertedIcons)); + final List<Transaction> convertedTransactions = convertItemsToInternal(this.transactions, new TransactionConverter(convertedCategories, convertedAccounts)); + final List<TemplateGroup> convertedTemplateGroups = convertItemsToInternal(this.templateGroups, new TemplateGroupConverter()); + final List<Template> convertedTemplates = convertItemsToInternal(this.templates, new TemplateConverter(convertedIcons, convertedCategories, convertedAccounts, convertedTemplateGroups)); + final List<Chart> convertedCharts = convertItemsToInternal(this.charts, new ChartConverter()); + final List<TransactionNameKeyword> convertedKeywords = convertItemsToInternal(this.transactionNameKeywords, new TransactionNameKeywordConverter()); + + return new InternalDatabase(convertedCategories, convertedAccounts, convertedTransactions, convertedTemplateGroups, convertedTemplates, convertedCharts, convertedImages, convertedIcons, convertedKeywords); + } + + @Override + public int getVersion() + { + return VERSION; + } + + @Override + public BackupDatabase upgrade() + { + throw new UnsupportedOperationException(); + } + + public static BackupDatabase_v9 createFromInternalEntities(InternalDatabase database) + { + final BackupDatabase_v9 externalDatabase = new BackupDatabase_v9(); + + externalDatabase.setIcons(externalDatabase.convertItemsToExternal(database.getIcons(), new IconConverter(null))); + externalDatabase.setCategories(externalDatabase.convertItemsToExternal(database.getCategories(), new CategoryConverter(null))); + externalDatabase.setAccounts(externalDatabase.convertItemsToExternal(database.getAccounts(), new AccountConverter(null))); + externalDatabase.setTransactions(externalDatabase.convertItemsToExternal(database.getTransactions(), new TransactionConverter(null, null))); + externalDatabase.setTemplateGroups(externalDatabase.convertItemsToExternal(database.getTemplateGroups(), new TemplateGroupConverter())); + externalDatabase.setTemplates(externalDatabase.convertItemsToExternal(database.getTemplates(), new TemplateConverter(null, null, null, null))); + externalDatabase.setCharts(externalDatabase.convertItemsToExternal(database.getCharts(), new ChartConverter())); + externalDatabase.setImages(externalDatabase.convertItemsToExternal(database.getImages(), new ImageConverter())); + externalDatabase.setTransactionNameKeywords(externalDatabase.convertItemsToExternal(database.getTransactionNameKeywords(), new TransactionNameKeywordConverter())); + + return externalDatabase; + } +} diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/services/EntityType.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/services/EntityType.java index c34260a78946f2182f6bcef26f18747f39aa5849..df05dde04f4817bdfac635a08dd3f2102584461f 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/services/EntityType.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/services/EntityType.java @@ -18,8 +18,8 @@ public enum EntityType implements LocalizedEnum HOTKEYS("keyboard", "background-grey", ImportRequired.NONE, null, null), ABOUT("info", "background-grey", ImportRequired.NONE, null, null), TEMPLATE_GROUP("folder", "background-orange-dark", ImportRequired.OPTIONAL, "template groups", "template group"), - ICON("icon", "background-grey", ImportRequired.NONE, "icons", "icon"); - + ICON("icon", "background-grey", ImportRequired.NONE, "icons", "icon"), + TRANSACTION_NAME_KEYWORD("transaction_name_keyword", "background-grey", ImportRequired.NONE, "keywords", "keyword"); public enum ImportRequired { diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/services/ImportService.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/services/ImportService.java index 9d23f5052d9b7b2342a6b0ac5fd3f0fdc7dcb89d..a0348aa08d39104c17bc599f8bcabc90c9751141 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/services/ImportService.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/services/ImportService.java @@ -14,6 +14,7 @@ import de.deadlocker8.budgetmaster.templategroup.TemplateGroupRepository; import de.deadlocker8.budgetmaster.templategroup.TemplateGroupType; import de.deadlocker8.budgetmaster.templates.TemplateRepository; import de.deadlocker8.budgetmaster.transactions.TransactionRepository; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeywordRepository; import de.deadlocker8.budgetmaster.utils.DateHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,13 +39,14 @@ public class ImportService private final RepeatingTransactionUpdater repeatingTransactionUpdater; private final AccountRepository accountRepository; private final IconRepository iconRepository; + private final TransactionNameKeywordRepository transactionNameKeywordRepository; private InternalDatabase database; @Autowired public ImportService(CategoryRepository categoryRepository, TransactionRepository transactionRepository, TemplateGroupRepository templateGroupRepository, TemplateRepository templateRepository, - TagRepository tagRepository, ChartService chartService, ImageRepository imageRepository, RepeatingTransactionUpdater repeatingTransactionUpdater, AccountRepository accountRepository, IconRepository iconRepository) + TagRepository tagRepository, ChartService chartService, ImageRepository imageRepository, RepeatingTransactionUpdater repeatingTransactionUpdater, AccountRepository accountRepository, IconRepository iconRepository, TransactionNameKeywordRepository transactionNameKeywordRepository) { this.categoryRepository = categoryRepository; this.transactionRepository = transactionRepository; @@ -56,6 +58,7 @@ public class ImportService this.repeatingTransactionUpdater = repeatingTransactionUpdater; this.accountRepository = accountRepository; this.iconRepository = iconRepository; + this.transactionNameKeywordRepository = transactionNameKeywordRepository; } public List<ImportResultItem> importDatabase(InternalDatabase database, Boolean importTemplateGroups, Boolean importTemplates, Boolean importCharts) @@ -101,6 +104,8 @@ public class ImportService importResultItems.add(new ImportResultItem(EntityType.CHART, 0, 0, List.of())); } + new TransactionNameKeywordImporter(transactionNameKeywordRepository).importItems(database.getTransactionNameKeywords()); + LOGGER.debug("Updating repeating transactions..."); repeatingTransactionUpdater.updateRepeatingTransactions(DateHelper.getCurrentDate()); diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/keywords/TransactionNameKeywordRepository.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/keywords/TransactionNameKeywordRepository.java index e7cc1bcfab920124674ab818fb1706bbe58907de..b9bbae424a49a043b925864d9d4a69bad08ca598 100644 --- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/keywords/TransactionNameKeywordRepository.java +++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/keywords/TransactionNameKeywordRepository.java @@ -7,4 +7,5 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; public interface TransactionNameKeywordRepository extends JpaRepository<TransactionNameKeyword, Integer>, JpaSpecificationExecutor<Transaction> { + TransactionNameKeyword findByValue(String value); } \ No newline at end of file diff --git a/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseExportTest.java b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseExportTest.java index b8592c120b906b6a7ea2ba82bb711e85d3338b5e..b6f3b4f44e0fbc701cbcb68d373da2de2665564b 100644 --- a/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseExportTest.java +++ b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseExportTest.java @@ -38,6 +38,9 @@ import de.deadlocker8.budgetmaster.templates.TemplateService; import de.deadlocker8.budgetmaster.transactions.Transaction; import de.deadlocker8.budgetmaster.transactions.TransactionRepository; import de.deadlocker8.budgetmaster.transactions.TransactionService; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeyword; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeywordRepository; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeywordService; import de.thecodelabs.utils.util.Localization; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -115,6 +118,9 @@ class DatabaseExportTest @Mock private HintService hintService; + @Mock + private TransactionNameKeywordService transactionNameKeywordService; + @InjectMocks private DatabaseService databaseService; @@ -162,6 +168,10 @@ class DatabaseExportTest Mockito.when(iconRepositoryMock.findAll()).thenReturn(List.of()); Mockito.when(iconService.getRepository()).thenReturn(iconRepositoryMock); + // transaction name keywords + TransactionNameKeywordRepository transactionNameKeywordRepository = Mockito.mock(TransactionNameKeywordRepository.class); + Mockito.when(transactionNameKeywordRepository.findAll()).thenReturn(List.of()); + Mockito.when(transactionNameKeywordService.getRepository()).thenReturn(transactionNameKeywordRepository); // act Path exportPath = Files.createFile(tempFolder.resolve("exportTest.json")); @@ -293,6 +303,13 @@ class DatabaseExportTest Mockito.when(iconRepositoryMock.findAll()).thenReturn(List.of(iconImage, iconBuiltin)); Mockito.when(iconService.getRepository()).thenReturn(iconRepositoryMock); + // transaction name keywords + final TransactionNameKeyword keyword1 = new TransactionNameKeyword(1, "income"); + final TransactionNameKeyword keyword2 = new TransactionNameKeyword(2, "abc"); + + TransactionNameKeywordRepository transactionNameKeywordRepository = Mockito.mock(TransactionNameKeywordRepository.class); + Mockito.when(transactionNameKeywordRepository.findAll()).thenReturn(List.of(keyword1, keyword2)); + Mockito.when(transactionNameKeywordService.getRepository()).thenReturn(transactionNameKeywordRepository); // act Path exportPath = Files.createFile(tempFolder.resolve("exportTest.json")); @@ -311,5 +328,6 @@ class DatabaseExportTest assertThat(importedDatabase.getCharts()).containsExactly(chart); assertThat(importedDatabase.getImages()).containsExactly(image); assertThat(importedDatabase.getIcons()).containsExactly(iconImage, iconBuiltin); + assertThat(importedDatabase.getTransactionNameKeywords()).containsExactly(new TransactionNameKeyword( "income"), new TransactionNameKeyword( "abc")); } } diff --git a/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v9Test.java b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v9Test.java new file mode 100644 index 0000000000000000000000000000000000000000..925ee9141b1e11179cf9a6cca4e6ce18a8bbaf23 --- /dev/null +++ b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v9Test.java @@ -0,0 +1,276 @@ +package de.deadlocker8.budgetmaster.unit.database; + +import de.deadlocker8.budgetmaster.accounts.AccountState; +import de.deadlocker8.budgetmaster.accounts.AccountType; +import de.deadlocker8.budgetmaster.categories.CategoryType; +import de.deadlocker8.budgetmaster.charts.ChartType; +import de.deadlocker8.budgetmaster.database.DatabaseParser_v9; +import de.deadlocker8.budgetmaster.database.model.v4.BackupRepeatingEndOption_v4; +import de.deadlocker8.budgetmaster.database.model.v4.BackupRepeatingModifier_v4; +import de.deadlocker8.budgetmaster.database.model.v4.BackupRepeatingOption_v4; +import de.deadlocker8.budgetmaster.database.model.v4.BackupTag_v4; +import de.deadlocker8.budgetmaster.database.model.v5.BackupChart_v5; +import de.deadlocker8.budgetmaster.database.model.v6.BackupTransaction_v6; +import de.deadlocker8.budgetmaster.database.model.v7.BackupAccount_v7; +import de.deadlocker8.budgetmaster.database.model.v7.BackupCategory_v7; +import de.deadlocker8.budgetmaster.database.model.v8.BackupIcon_v8; +import de.deadlocker8.budgetmaster.database.model.v8.BackupTemplateGroup_v8; +import de.deadlocker8.budgetmaster.database.model.v8.BackupTemplate_v8; +import de.deadlocker8.budgetmaster.database.model.v9.BackupDatabase_v9; +import de.deadlocker8.budgetmaster.database.model.v9.BackupTransactionNameKeyword_v9; +import de.deadlocker8.budgetmaster.images.ImageFileExtension; +import de.deadlocker8.budgetmaster.repeating.endoption.RepeatingEndAfterXTimes; +import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierDays; +import de.deadlocker8.budgetmaster.templategroup.TemplateGroupType; +import de.thecodelabs.utils.util.Localization; +import de.thecodelabs.utils.util.Localization.LocalizationDelegate; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; + + +class DatabaseParser_v9Test +{ + @BeforeEach + public void before() + { + Localization.setDelegate(new LocalizationDelegate() + { + @Override + public Locale getLocale() + { + return Locale.ENGLISH; + } + + @Override + public String getBaseResource() + { + return "languages/base"; + } + }); + Localization.load(); + } + + @Test + void test_Charts() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 parser = new DatabaseParser_v9(json); + BackupDatabase_v9 database = parser.parseDatabaseFromJSON(); + + final BackupChart_v5 chart = new BackupChart_v5(9, "The best chart", "/* This list will be dynamically filled with all the transactions between\r\n* the start and and date you select on the \"Show Chart\" page\r\n* and filtered according to your specified filter.\r\n* An example entry for this list and tutorial about how to create custom charts ca be found in the BudgetMaster wiki:\r\n* https://github.com/deadlocker8/BudgetMaster/wiki/How-to-create-custom-charts\r\n*/\r\nvar transactionData \u003d [];\r\n\r\n// Prepare your chart settings here (mandatory)\r\nvar plotlyData \u003d [{\r\n x: [],\r\n y: [],\r\n type: \u0027bar\u0027\r\n}];\r\n\r\n// Add your Plotly layout settings here (optional)\r\nvar plotlyLayout \u003d {};\r\n\r\n// Add your Plotly configuration settings here (optional)\r\nvar plotlyConfig \u003d {\r\n showSendToCloud: false,\r\n displaylogo: false,\r\n showLink: false,\r\n responsive: true\r\n};\r\n\r\n// Don\u0027t touch this line\r\nPlotly.newPlot(\"containerID\", plotlyData, plotlyLayout, plotlyConfig);\r\n", ChartType.CUSTOM, 7); + + assertThat(database.getCharts()).hasSize(1) + .contains(chart); + } + + @Test + void test_Categories() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 parser = new DatabaseParser_v9(json); + BackupDatabase_v9 database = parser.parseDatabaseFromJSON(); + + final BackupCategory_v7 category = new BackupCategory_v7(3, "0815", "#ffcc00", CategoryType.CUSTOM, 2); + + assertThat(database.getCategories()).hasSize(3) + .contains(category); + } + + @Test + void test_Accounts() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 parser = new DatabaseParser_v9(json); + BackupDatabase_v9 database = parser.parseDatabaseFromJSON(); + + final BackupAccount_v7 account = new BackupAccount_v7(3, "Second Account", AccountState.FULL_ACCESS, AccountType.CUSTOM, 1); + + assertThat(database.getAccounts()).hasSize(3) + .contains(account); + assertThat(database.getAccounts().get(2).getIconReferenceID()) + .isOne(); + } + + @Test + void test_Images() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 parser = new DatabaseParser_v9(json); + BackupDatabase_v9 database = parser.parseDatabaseFromJSON(); + + assertThat(database.getImages()).hasSize(1); + assertThat(database.getImages().get(0)).hasFieldOrPropertyWithValue("fileExtension", ImageFileExtension.PNG); + assertThat(database.getImages().get(0).getImage()) + .isNotNull() + .hasSizeGreaterThan(1); + } + + @Test + void test_TemplateGroups() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 parser = new DatabaseParser_v9(json); + BackupDatabase_v9 database = parser.parseDatabaseFromJSON(); + + BackupTemplateGroup_v8 templateGroup = new BackupTemplateGroup_v8(); + templateGroup.setID(1); + templateGroup.setName("My Template Group Deluxe"); + templateGroup.setType(TemplateGroupType.CUSTOM); + + assertThat(database.getTemplateGroups()).hasSize(1) + .contains(templateGroup); + } + + @Test + void test_Templates() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 parser = new DatabaseParser_v9(json); + BackupDatabase_v9 database = parser.parseDatabaseFromJSON(); + + BackupTemplate_v8 template = new BackupTemplate_v8(); + template.setTemplateName("Template with icon"); + template.setExpenditure(true); + template.setIconReferenceID(1); + template.setTags(List.of()); + + BackupTemplate_v8 templateWithGroup = new BackupTemplate_v8(); + templateWithGroup.setTemplateName("Template with associated group"); + templateWithGroup.setTags(List.of()); + templateWithGroup.setTemplateGroupID(1); + + assertThat(database.getTemplates()).hasSize(5) + .contains(template, templateWithGroup); + assertThat(database.getTemplates().get(3).getIconReferenceID()) + .isOne(); + } + + @Test + void test_Transactions() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 parser = new DatabaseParser_v9(json); + BackupDatabase_v9 database = parser.parseDatabaseFromJSON(); + + BackupTransaction_v6 normalTransaction_1 = new BackupTransaction_v6(); + normalTransaction_1.setAmount(35000); + normalTransaction_1.setDate("2018-03-13"); + normalTransaction_1.setCategoryID(1); + normalTransaction_1.setName("Income"); + normalTransaction_1.setDescription("Lorem Ipsum"); + normalTransaction_1.setTags(new ArrayList<>()); + normalTransaction_1.setAccountID(2); + normalTransaction_1.setExpenditure(false); + + BackupTransaction_v6 normalTransaction_2 = new BackupTransaction_v6(); + normalTransaction_2.setAmount(-2000); + normalTransaction_2.setDate("2018-06-15"); + normalTransaction_2.setName("Simple"); + normalTransaction_2.setDescription(""); + normalTransaction_2.setAccountID(3); + normalTransaction_2.setCategoryID(3); + normalTransaction_2.setExpenditure(true); + + List<BackupTag_v4> tags = new ArrayList<>(); + BackupTag_v4 tag = new BackupTag_v4("0815"); + tags.add(tag); + normalTransaction_2.setTags(tags); + + BackupTransaction_v6 repeatingTransaction_1 = new BackupTransaction_v6(); + repeatingTransaction_1.setAmount(-12300); + String repeatingTransaction_1Date = "2018-03-13"; + repeatingTransaction_1.setDate(repeatingTransaction_1Date); + repeatingTransaction_1.setCategoryID(1); + repeatingTransaction_1.setName("Test"); + repeatingTransaction_1.setDescription(""); + repeatingTransaction_1.setAccountID(2); + BackupRepeatingOption_v4 repeatingOption_1 = new BackupRepeatingOption_v4(); + repeatingOption_1.setModifier(new BackupRepeatingModifier_v4(10, new RepeatingModifierDays(10).getLocalizationKey())); + repeatingOption_1.setStartDate(repeatingTransaction_1Date); + BackupRepeatingEndOption_v4 endOption = new BackupRepeatingEndOption_v4(); + endOption.setTimes(2); + endOption.setLocalizationKey(new RepeatingEndAfterXTimes(2).getLocalizationKey()); + repeatingOption_1.setEndOption(endOption); + repeatingTransaction_1.setRepeatingOption(repeatingOption_1); + repeatingTransaction_1.setTags(new ArrayList<>()); + repeatingTransaction_1.setExpenditure(true); + + BackupTransaction_v6 transferTransaction = new BackupTransaction_v6(); + transferTransaction.setAmount(-250); + transferTransaction.setDate("2018-06-15"); + transferTransaction.setName("Transfer"); + transferTransaction.setDescription(""); + transferTransaction.setAccountID(3); + transferTransaction.setTransferAccountID(2); + transferTransaction.setCategoryID(3); + transferTransaction.setTags(new ArrayList<>()); + transferTransaction.setExpenditure(true); + + BackupTransaction_v6 repeatingTransferTransaction = new BackupTransaction_v6(); + repeatingTransferTransaction.setAmount(-6000); + String repeatingTransferTransaction_Date = "2018-03-15"; + repeatingTransferTransaction.setDate(repeatingTransferTransaction_Date); + repeatingTransferTransaction.setCategoryID(1); + repeatingTransferTransaction.setName("repeat my transfer"); + repeatingTransferTransaction.setDescription(""); + repeatingTransferTransaction.setAccountID(2); + BackupRepeatingOption_v4 repeatingOption_2 = new BackupRepeatingOption_v4(); + repeatingOption_2.setModifier(new BackupRepeatingModifier_v4(10, new RepeatingModifierDays(10).getLocalizationKey())); + repeatingOption_2.setStartDate(repeatingTransferTransaction_Date); + BackupRepeatingEndOption_v4 endOption_2 = new BackupRepeatingEndOption_v4(); + endOption_2.setTimes(2); + endOption_2.setLocalizationKey(new RepeatingEndAfterXTimes(2).getLocalizationKey()); + repeatingOption_2.setEndOption(endOption_2); + repeatingTransferTransaction.setRepeatingOption(repeatingOption_2); + repeatingTransferTransaction.setTags(new ArrayList<>()); + repeatingTransferTransaction.setExpenditure(true); + repeatingTransferTransaction.setTransferAccountID(2); + + assertThat(database.getTransactions()).hasSize(5) + .contains(normalTransaction_1, + normalTransaction_2, + repeatingTransaction_1, + transferTransaction, + repeatingTransferTransaction); + } + + @Test + void test_Icons() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 parser = new DatabaseParser_v9(json); + BackupDatabase_v9 database = parser.parseDatabaseFromJSON(); + + final BackupIcon_v8 expectedIconWithImage = new BackupIcon_v8(1, 1, null, null); + final BackupIcon_v8 expectedIBuiltinIcon = new BackupIcon_v8(2, null, "fas fa-icons", "#FF0000"); + + assertThat(database.getIcons()) + .hasSize(2) + .containsExactlyInAnyOrder(expectedIconWithImage, expectedIBuiltinIcon); + } + + @Test + void test_TransactionNameKeywords() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 parser = new DatabaseParser_v9(json); + BackupDatabase_v9 database = parser.parseDatabaseFromJSON(); + + final BackupTransactionNameKeyword_v9 expectedKeyword1 = new BackupTransactionNameKeyword_v9("income"); + final BackupTransactionNameKeyword_v9 expectedKeyword2 = new BackupTransactionNameKeyword_v9("xyz"); + + assertThat(database.getTransactionNameKeywords()) + .hasSize(2) + .containsExactlyInAnyOrder(expectedKeyword1, expectedKeyword2); + } +} \ No newline at end of file diff --git a/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v8_convertToInternalTest.java b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v9_convertToInternalTest.java similarity index 87% rename from BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v8_convertToInternalTest.java rename to BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v9_convertToInternalTest.java index 147ac69aea745064800790f6e0d769adbaab1f89..739e398bc9e2a832a126903eb6fe13612e8c502a 100644 --- a/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v8_convertToInternalTest.java +++ b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v9_convertToInternalTest.java @@ -8,7 +8,7 @@ import de.deadlocker8.budgetmaster.charts.Chart; import de.deadlocker8.budgetmaster.charts.ChartDisplayType; import de.deadlocker8.budgetmaster.charts.ChartGroupType; import de.deadlocker8.budgetmaster.charts.ChartType; -import de.deadlocker8.budgetmaster.database.DatabaseParser_v8; +import de.deadlocker8.budgetmaster.database.DatabaseParser_v9; import de.deadlocker8.budgetmaster.database.InternalDatabase; import de.deadlocker8.budgetmaster.icon.Icon; import de.deadlocker8.budgetmaster.images.Image; @@ -19,6 +19,7 @@ import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierDays; import de.deadlocker8.budgetmaster.tags.Tag; import de.deadlocker8.budgetmaster.templates.Template; import de.deadlocker8.budgetmaster.transactions.Transaction; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeyword; import de.thecodelabs.utils.util.Localization; import de.thecodelabs.utils.util.Localization.LocalizationDelegate; import org.junit.jupiter.api.BeforeEach; @@ -36,7 +37,7 @@ import java.util.Locale; import static org.assertj.core.api.Assertions.assertThat; -class DatabaseParser_v8_convertToInternalTest +class DatabaseParser_v9_convertToInternalTest { @BeforeEach public void before() @@ -63,8 +64,8 @@ class DatabaseParser_v8_convertToInternalTest { try { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v8Test.json").toURI()))); - DatabaseParser_v8 importer = new DatabaseParser_v8(json); + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 importer = new DatabaseParser_v9(json); InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); final Chart chart = new Chart("The best chart", "/* This list will be dynamically filled with all the transactions between\r\n* the start and and date you select on the \"Show Chart\" page\r\n* and filtered according to your specified filter.\r\n* An example entry for this list and tutorial about how to create custom charts ca be found in the BudgetMaster wiki:\r\n* https://github.com/deadlocker8/BudgetMaster/wiki/How-to-create-custom-charts\r\n*/\r\nvar transactionData \u003d [];\r\n\r\n// Prepare your chart settings here (mandatory)\r\nvar plotlyData \u003d [{\r\n x: [],\r\n y: [],\r\n type: \u0027bar\u0027\r\n}];\r\n\r\n// Add your Plotly layout settings here (optional)\r\nvar plotlyLayout \u003d {};\r\n\r\n// Add your Plotly configuration settings here (optional)\r\nvar plotlyConfig \u003d {\r\n showSendToCloud: false,\r\n displaylogo: false,\r\n showLink: false,\r\n responsive: true\r\n};\r\n\r\n// Don\u0027t touch this line\r\nPlotly.newPlot(\"containerID\", plotlyData, plotlyLayout, plotlyConfig);\r\n", ChartType.CUSTOM, 7, ChartDisplayType.CUSTOM, ChartGroupType.NONE, null); @@ -84,8 +85,8 @@ class DatabaseParser_v8_convertToInternalTest { try { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v8Test.json").toURI()))); - DatabaseParser_v8 importer = new DatabaseParser_v8(json); + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 importer = new DatabaseParser_v9(json); InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); final Icon icon = new Icon("fas fa-icons"); @@ -109,8 +110,8 @@ class DatabaseParser_v8_convertToInternalTest { try { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v8Test.json").toURI()))); - DatabaseParser_v8 importer = new DatabaseParser_v8(json); + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 importer = new DatabaseParser_v9(json); InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); final Image accountImage = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); @@ -141,8 +142,8 @@ class DatabaseParser_v8_convertToInternalTest { try { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v8Test.json").toURI()))); - DatabaseParser_v8 importer = new DatabaseParser_v8(json); + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 importer = new DatabaseParser_v9(json); InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); final Image image = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); @@ -165,8 +166,8 @@ class DatabaseParser_v8_convertToInternalTest { try { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v8Test.json").toURI()))); - DatabaseParser_v8 importer = new DatabaseParser_v8(json); + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 importer = new DatabaseParser_v9(json); InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); final Image templateImage = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); @@ -200,8 +201,8 @@ class DatabaseParser_v8_convertToInternalTest { try { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v8Test.json").toURI()))); - DatabaseParser_v8 importer = new DatabaseParser_v8(json); + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 importer = new DatabaseParser_v9(json); InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); Account account1 = new Account("Default", AccountType.CUSTOM); @@ -316,8 +317,8 @@ class DatabaseParser_v8_convertToInternalTest @Test void test_Icons() throws IOException, URISyntaxException { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v8Test.json").toURI()))); - DatabaseParser_v8 importer = new DatabaseParser_v8(json); + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 importer = new DatabaseParser_v9(json); InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); final Image image = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); @@ -337,4 +338,19 @@ class DatabaseParser_v8_convertToInternalTest .isNotNull() .hasSizeGreaterThan(1); } + + @Test + void test_TransactionNameKeywords() throws IOException, URISyntaxException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v9Test.json").toURI()))); + DatabaseParser_v9 importer = new DatabaseParser_v9(json); + InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); + + final TransactionNameKeyword keyword1 = new TransactionNameKeyword("income"); + final TransactionNameKeyword keyword2 = new TransactionNameKeyword("xyz"); + + assertThat(database.getTransactionNameKeywords()) + .hasSize(2) + .containsExactly(keyword1, keyword2); + } } \ No newline at end of file diff --git a/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseServiceTest.java b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseServiceTest.java index 2f4b634890bcb28be26924fc45e070c4bcba113e..40f97509acc28d96eb7a4534be45df68c1dbb11f 100644 --- a/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseServiceTest.java +++ b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseServiceTest.java @@ -16,6 +16,7 @@ import de.deadlocker8.budgetmaster.tags.TagService; import de.deadlocker8.budgetmaster.templategroup.TemplateGroupService; import de.deadlocker8.budgetmaster.templates.TemplateService; import de.deadlocker8.budgetmaster.transactions.TransactionService; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeywordService; import de.deadlocker8.budgetmaster.unit.helpers.LoggerTestUtil; import org.assertj.core.groups.Tuple; import org.junit.jupiter.api.Test; @@ -69,6 +70,9 @@ class DatabaseServiceTest @Mock private HintService hintService; + @Mock + private TransactionNameKeywordService transactionNameKeywordService; + @InjectMocks private DatabaseService databaseService; diff --git a/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/ImportServiceTest.java b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/ImportServiceTest.java index f3738af0bfbe220cc93283adc71e0e51751888a7..6b1c1ddc76a2f6c4c09902d3ff2973ea93dfaa83 100644 --- a/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/ImportServiceTest.java +++ b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/ImportServiceTest.java @@ -32,6 +32,8 @@ import de.deadlocker8.budgetmaster.templates.Template; import de.deadlocker8.budgetmaster.templates.TemplateRepository; import de.deadlocker8.budgetmaster.transactions.Transaction; import de.deadlocker8.budgetmaster.transactions.TransactionRepository; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeyword; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeywordService; import de.deadlocker8.budgetmaster.utils.Strings; import de.thecodelabs.utils.util.Localization; import org.junit.jupiter.api.BeforeEach; @@ -131,6 +133,9 @@ class ImportServiceTest @Autowired private IconService iconService; + @Autowired + private TransactionNameKeywordService transactionNameKeywordService; + @Autowired private ImportService importService; @@ -388,6 +393,19 @@ class ImportServiceTest transactionRepeatingTransfer, transactionIncomeWithTags); + // assert transaction name keywords + // default keywords + final TransactionNameKeyword defaultKeyword1 = new TransactionNameKeyword(1, "income"); + final TransactionNameKeyword defaultKeyword2 = new TransactionNameKeyword(2, "einnahme"); + + // keywords from json + final TransactionNameKeyword keyword1 = new TransactionNameKeyword(3, "xyz"); + + assertThat(transactionNameKeywordService.getRepository().findAll()) + .hasSize(3) + .containsExactly(defaultKeyword1, defaultKeyword2, keyword1); + + assertThat(importService.getCollectedErrorMessages(importResultItems)).isEmpty(); } @@ -434,7 +452,7 @@ class ImportServiceTest template.setTags(new ArrayList<>()); // database - InternalDatabase database = new InternalDatabase(List.of(), List.of(), List.of(), List.of(), List.of(template), List.of(), List.of(), List.of()); + InternalDatabase database = new InternalDatabase(List.of(), List.of(), List.of(), List.of(), List.of(template), List.of(), List.of(), List.of(), List.of()); // act importService.importDatabase(database, true, false, true); @@ -457,7 +475,7 @@ class ImportServiceTest Mockito.when(templateGroupRepository.findFirstByType(TemplateGroupType.DEFAULT)).thenReturn(templateGroupDefault); // database - InternalDatabase database = new InternalDatabase(List.of(), List.of(), List.of(), List.of(templateGroup), List.of(templateWithGroup), List.of(), List.of(), List.of()); + InternalDatabase database = new InternalDatabase(List.of(), List.of(), List.of(), List.of(templateGroup), List.of(templateWithGroup), List.of(), List.of(), List.of(), List.of()); // act importService.importDatabase(database, false, true, true); @@ -487,7 +505,7 @@ class ImportServiceTest chart.setVersion(7); // database - InternalDatabase database = new InternalDatabase(List.of(), List.of(), List.of(), List.of(), List.of(), List.of(chart), List.of(), List.of()); + InternalDatabase database = new InternalDatabase(List.of(), List.of(), List.of(), List.of(), List.of(), List.of(chart), List.of(), List.of(), List.of()); Mockito.when(chartService.getHighestUsedID()).thenReturn(8); final ChartRepository chartRepositoryMock = Mockito.mock(ChartRepository.class); diff --git a/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/importer/TransactionNameKeywordImporterTest.java b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/importer/TransactionNameKeywordImporterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..489d35ca68dcb066c3f6c09d19b5c4f00ec8469c --- /dev/null +++ b/BudgetMasterServer/src/test/java/de/deadlocker8/budgetmaster/unit/database/importer/TransactionNameKeywordImporterTest.java @@ -0,0 +1,62 @@ +package de.deadlocker8.budgetmaster.unit.database.importer; + +import de.deadlocker8.budgetmaster.database.importer.IconImporter; +import de.deadlocker8.budgetmaster.database.importer.TransactionImporter; +import de.deadlocker8.budgetmaster.database.importer.TransactionNameKeywordImporter; +import de.deadlocker8.budgetmaster.icon.Icon; +import de.deadlocker8.budgetmaster.icon.IconRepository; +import de.deadlocker8.budgetmaster.images.Image; +import de.deadlocker8.budgetmaster.images.ImageFileExtension; +import de.deadlocker8.budgetmaster.images.ImageRepository; +import de.deadlocker8.budgetmaster.services.EntityType; +import de.deadlocker8.budgetmaster.services.ImportResultItem; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeyword; +import de.deadlocker8.budgetmaster.transactions.keywords.TransactionNameKeywordRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +import static org.assertj.core.api.Assertions.as; +import static org.assertj.core.api.Assertions.assertThat; + +class TransactionNameKeywordImporterTest extends ImporterTestBase +{ + @Override + List<String> getTableNamesToResetSequence() + { + return List.of("transaction_name_keyword"); + } + + @Autowired + private TransactionNameKeywordRepository keywordRepository; + + @Test + void test_importKeywords() + { + final TransactionNameKeyword keyword1 = new TransactionNameKeyword(12, "income"); + final TransactionNameKeyword keyword2 = new TransactionNameKeyword(13, "xyz"); + + final TransactionNameKeywordImporter importer = new TransactionNameKeywordImporter(keywordRepository); + final ImportResultItem resultItem = importer.importItems(List.of(keyword1, keyword2)); + + final ImportResultItem expected = new ImportResultItem(EntityType.TRANSACTION_NAME_KEYWORD, 2, 2, List.of()); + assertThat(resultItem).isEqualTo(expected); + assertThat(keyword1).hasFieldOrPropertyWithValue("ID", 1); + assertThat(keyword2).hasFieldOrPropertyWithValue("ID", 2); + } + + @Test + void test_importKeywords_skipAlreadyExisting() + { + final TransactionNameKeyword existingKeyword = new TransactionNameKeyword(12, "income"); + keywordRepository.save(existingKeyword); + + final TransactionNameKeywordImporter importer = new TransactionNameKeywordImporter(keywordRepository); + final ImportResultItem resultItem = importer.importItems(List.of(existingKeyword)); + + final ImportResultItem expected = new ImportResultItem(EntityType.TRANSACTION_NAME_KEYWORD, 1, 1, List.of()); + assertThat(resultItem).isEqualTo(expected); + assertThat(keywordRepository.findAll()).hasSize(1); + } +} \ No newline at end of file diff --git a/BudgetMasterServer/src/test/resources/DatabaseParser_v9Test.json b/BudgetMasterServer/src/test/resources/DatabaseParser_v9Test.json new file mode 100644 index 0000000000000000000000000000000000000000..5ca00f987251b646b971e654cd69cfa448ca67a6 --- /dev/null +++ b/BudgetMasterServer/src/test/resources/DatabaseParser_v9Test.json @@ -0,0 +1,3346 @@ +{ + "TYPE": "BUDGETMASTER_DATABASE", + "VERSION": 7, + "categories": [ + { + "ID": 1, + "name": "Keine Kategorie", + "color": "#FFFFFF", + "type": "NONE" + }, + { + "ID": 2, + "name": "Übertrag", + "color": "#FFFF00", + "type": "REST" + }, + { + "ID": 3, + "name": "0815", + "color": "#ffcc00", + "type": "CUSTOM", + "iconReferenceID": 2 + } + ], + "accounts": [ + { + "ID": 1, + "name": "Placeholder", + "accountState": "FULL_ACCESS", + "type": "ALL" + }, + { + "ID": 2, + "name": "Default", + "accountState": "FULL_ACCESS", + "type": "CUSTOM" + }, + { + "ID": 3, + "name": "Second Account", + "accountState": "FULL_ACCESS", + "type": "CUSTOM", + "iconReferenceID": 1 + } + ], + "transactions": [ + { + "ID": 5, + "amount": 35000, + "isExpenditure": false, + "date": "2018-03-13", + "accountID": 2, + "categoryID": 1, + "name": "Income", + "description": "Lorem Ipsum", + "tags": [] + }, + { + "ID": 12, + "amount": -2000, + "isExpenditure": true, + "date": "2018-06-15", + "accountID": 3, + "categoryID": 3, + "name": "Simple", + "description": "", + "tags": [ + { + "ID": 1, + "name": "0815" + } + ] + }, + { + "ID": 13, + "amount": -12300, + "isExpenditure": true, + "date": "2018-03-13", + "accountID": 2, + "categoryID": 1, + "name": "Test", + "description": "", + "tags": [], + "repeatingOption": { + "ID": 2, + "startDate": "2018-03-13", + "modifier": { + "ID": 3, + "quantity": 10, + "localizationKey": "repeating.modifier.days" + }, + "endOption": { + "times": 2, + "ID": 3, + "localizationKey": "repeating.end.key.afterXTimes" + } + } + }, + { + "ID": 16, + "amount": -250, + "isExpenditure": true, + "date": "2018-06-15", + "accountID": 3, + "categoryID": 3, + "name": "Transfer", + "description": "", + "tags": [], + "transferAccountID": 2 + }, + { + "ID": 17, + "amount": -6000, + "isExpenditure": true, + "date": "2018-03-15", + "accountID": 2, + "categoryID": 1, + "name": "repeat my transfer", + "description": "", + "tags": [], + "transferAccountID": 2, + "repeatingOption": { + "ID": 3, + "startDate": "2018-03-15", + "modifier": { + "ID": 3, + "quantity": 10, + "localizationKey": "repeating.modifier.days" + }, + "endOption": { + "times": 2, + "ID": 3, + "localizationKey": "repeating.end.key.afterXTimes" + } + } + } + ], + "templateGroups": [ + { + "ID": 1, + "name": "My Template Group Deluxe", + "type": "CUSTOM" + } + ], + "templates": [ + { + "ID": 5, + "amount": 1500, + "accountID": 2, + "categoryID": 1, + "name": "Income", + "templateName": "My Simple Template", + "description": "Lorem Ipsum", + "tags": [ + { + "name": "0815" + } + ] + }, + { + "ID": 6, + "templateName": "My Minimal Template", + "tags": [] + }, + { + "ID": 7, + "amount": -35000, + "accountID": 3, + "categoryID": 3, + "name": "Income", + "templateName": "My Transfer Template", + "description": "Lorem Ipsum", + "tags": [ + { + "name": "0815" + } + ], + "transferAccountID": 2 + }, + { + "ID": 8, + "templateName": "Template with icon", + "isExpenditure": true, + "tags": [], + "iconReferenceID": 1 + }, + { + "ID": 9, + "templateName": "Template with associated group", + "tags": [], + "templateGroupID": 1 + } + ], + "charts": [ + { + "ID": 9, + "name": "The best chart", + "script": "/* This list will be dynamically filled with all the transactions between\r\n* the start and and date you select on the \"Show Chart\" page\r\n* and filtered according to your specified filter.\r\n* An example entry for this list and tutorial about how to create custom charts ca be found in the BudgetMaster wiki:\r\n* https://github.com/deadlocker8/BudgetMaster/wiki/How-to-create-custom-charts\r\n*/\r\nvar transactionData \u003d [];\r\n\r\n// Prepare your chart settings here (mandatory)\r\nvar plotlyData \u003d [{\r\n x: [],\r\n y: [],\r\n type: \u0027bar\u0027\r\n}];\r\n\r\n// Add your Plotly layout settings here (optional)\r\nvar plotlyLayout \u003d {};\r\n\r\n// Add your Plotly configuration settings here (optional)\r\nvar plotlyConfig \u003d {\r\n showSendToCloud: false,\r\n displaylogo: false,\r\n showLink: false,\r\n responsive: true\r\n};\r\n\r\n// Don\u0027t touch this line\r\nPlotly.newPlot(\"containerID\", plotlyData, plotlyLayout, plotlyConfig);\r\n", + "type": "CUSTOM", + "version": 7 + } + ], + "images": [ + { + "ID": 1, + "image": [ + -119, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + -76, + 0, + 0, + 0, + -76, + 8, + 6, + 0, + 0, + 0, + 61, + -51, + 6, + 50, + 0, + 0, + 11, + -14, + 73, + 68, + 65, + 84, + 120, + -100, + -19, + -35, + 79, + 108, + 84, + -41, + 21, + -57, + 113, + -85, + 21, + -91, + 73, + 85, + 117, + 31, + -87, + 93, + 84, + -35, + 53, + -72, + 106, + -73, + 93, + -92, + -35, + -107, + 101, + -108, + -126, + -64, + 6, + 20, + 112, + -30, + -40, + -109, + -72, + -31, + -97, + -120, + -99, + -80, + -120, + 42, + 85, + -79, + -33, + -104, + 58, + -111, + 72, + -112, + -6, + 7, + 37, + -87, + -102, + 98, + 4, + 111, + -58, + 99, + -20, + 98, + 76, + -109, + 66, + -101, + 82, + -64, + 48, + 80, + 100, + 91, + 14, + -123, + 96, + -89, + 82, + 9, + 18, + -119, + 106, + 53, + -76, + -58, + -40, + -89, + -117, + -26, + -103, + 97, + 124, + 103, + 124, + -17, + 123, + -9, + -34, + 115, + -17, + 123, + -65, + -81, + 116, + -106, + -58, + -29, + 59, + 31, + 14, + -113, + -7, + -25, + -122, + 6, + -124, + 16, + -110, + 41, + -105, + -53, + 125, + -46, + -34, + -34, + 78, + -43, + -61, + 125, + -69, + 16, + 82, + -86, + -75, + -75, + 117, + -107, + 8, + 50, + 96, + 35, + -17, + -54, + -27, + 114, + 45, + 50, + -104, + -127, + 26, + 121, + -111, + 10, + 102, + -96, + 70, + 78, + 23, + 7, + 51, + 64, + 35, + 103, + -117, + 11, + 26, + -88, + -111, + -109, + 1, + 52, + -14, + 62, + -39, + 71, + 52, + 100, + 38, + -105, + -53, + -123, + -36, + 63, + 15, + -54, + 88, + -71, + 92, + -18, + 51, + 93, + -128, + -79, + -71, + 17, + 75, + -19, + -19, + -19, + 115, + 54, + 17, + 3, + 55, + -46, + -34, + -38, + -75, + 107, + 87, + 115, + 3, + 6, + 110, + 79, + 107, + -20, + 26, + 33, + 87, + -26, + -47, + -82, + 17, + 118, + -84, + -14, + -45, + -58, + 126, + 94, + -107, + -13, + -19, + -82, + 19, + -33, + -25, + -74, + -60, + 30, + -9, + -99, + -32, + 26, + -28, + -25, + 95, + 120, + -122, + 94, + -23, + 111, + -10, + 26, + 54, + -73, + 41, + -74, + -72, + 15, + 62, + 26, + 110, + -60, + -47, + -28, + 11, + 77, + 75, + 19, + -25, + -21, + -71, + -49, + -79, + 98, + -58, + -72, + 109, + 89, + -49, + -127, + 67, + 119, + 6, + -13, + 75, + -81, + 109, + 125, + 0, + 115, + 18, + -44, + 79, + -25, + -74, + -77, + -97, + 105, + 99, + 87, + 6, + -73, + 52, + -9, + -127, + 127, + -73, + 115, + -104, + 29, + 114, + -11, + 86, + -82, + -98, + -82, + -34, + 109, + -79, + -1, + 92, + -18, + -13, + 109, + 124, + -15, + -60, + 21, + 110, + 99, + 86, + -29, + 60, + -20, + 31, + -19, + -6, + 53, + 59, + -28, + -18, + -61, + -51, + 117, + 49, + 39, + -39, + -46, + -82, + -96, + -26, + 54, + 102, + -83, + -58, + -50, + -29, + -9, + 56, + 15, + -102, + 27, + -77, + 12, + -28, + 52, + -96, + -26, + 118, + 102, + -83, + -84, + 98, + 14, + 20, + 33, + 71, + -45, + -79, + -93, + -51, + 75, + -44, + -36, + -50, + -84, + -107, + 69, + -52, + 113, + 32, + -21, + -38, + -46, + 45, + -49, + -18, + 1, + 104, + -109, + -15, + 96, + 78, + -74, + -27, + -72, + 32, + -5, + 124, + -23, + -63, + -19, + -52, + 90, + -103, + -40, + -50, + 109, + 122, + 49, + -25, + 11, + 77, + -44, + -42, + -106, + -28, + 54, + -27, + 0, + -38, + 84, + -74, + 15, + -74, + -83, + 61, + -25, + -19, + 86, + -10, + 121, + 75, + 115, + 59, + -77, + 86, + 90, + -73, + 115, + -101, + -127, + -83, + -84, + 19, + -11, + 51, + -19, + 29, + 0, + 109, + 34, + -107, + 67, + -47, + -111, + -17, + 91, + 121, + 25, + -24, + 4, + -105, + 30, + 73, + 3, + 104, + 65, + 54, + 65, + 47, + 44, + 44, + -104, + -59, + -100, + -77, + -117, + 57, + -23, + -106, + 6, + 104, + 3, + -39, + 4, + -35, + -46, + -46, + -30, + -51, + 86, + -18, + 27, + -38, + 68, + 65, + -72, + -47, + 40, + 106, + -128, + 54, + -112, + 77, + -48, + 38, + 32, + -17, + -2, + -23, + 83, + -38, + 49, + 15, + -50, + -20, + 94, + 26, + -128, + -10, + 44, + -37, + -41, + -48, + 58, + -45, + 13, + -7, + -32, + -103, + -42, + 7, + 48, + -85, + -94, + -74, + 29, + 64, + 11, + -14, + 17, + -12, + -47, + 63, + -65, + 106, + 116, + 43, + 87, + -113, + -20, + -45, + -28, + 61, + -31, + 122, + -85, + -25, + 0, + -48, + -126, + 124, + 3, + -83, + 27, + -14, + -47, + -85, + -37, + -21, + 98, + 118, + 121, + 75, + 3, + -76, + 32, + 95, + 64, + -9, + -124, + -21, + -83, + 110, + 101, + 31, + 80, + 3, + -76, + 32, + 31, + 64, + -21, + -122, + 92, + -102, + -34, + -91, + -116, + 89, + 5, + 116, + 80, + -40, + 104, + -27, + 92, + 0, + 90, + -112, + -53, + -96, + -69, + 29, + -40, + -54, + 46, + 111, + 105, + -128, + 22, + -28, + 42, + 104, + -41, + 32, + -69, + -120, + 26, + -96, + 5, + -71, + 6, + 90, + -27, + -55, + 12, + 14, + -52, + 42, + -96, + -5, + 79, + -25, + -115, + -98, + 21, + 64, + 11, + 114, + 9, + -76, + -21, + -112, + 93, + -37, + -46, + 0, + 45, + -56, + 5, + -48, + -70, + 33, + 7, + -122, + 49, + 15, + -50, + -20, + -90, + -30, + -11, + -99, + -20, + -88, + 1, + 90, + 16, + 55, + 104, + -97, + -74, + 114, + -36, + 45, + 61, + -3, + -15, + -108, + -111, + -77, + 3, + 104, + 65, + 92, + -96, + 117, + 67, + -18, + 45, + 53, + 91, + -59, + -20, + -62, + -91, + 7, + 64, + 11, + -78, + 13, + 122, + -18, + -18, + 127, + -68, + -34, + -54, + -43, + -13, + -42, + -7, + 54, + 54, + -44, + 0, + 45, + -56, + 38, + 104, + -35, + -112, + -33, + -8, + -61, + 86, + 86, + -52, + -86, + 91, + -6, + -18, + -4, + -100, + 6, + -58, + -9, + 3, + 104, + 65, + 54, + 64, + -113, + 125, + 48, + -102, + -86, + -83, + -20, + -54, + -91, + 7, + 64, + 11, + 50, + 13, + 90, + 55, + -28, + 119, + -2, + -10, + 28, + 59, + 94, + -47, + -12, + 13, + 109, + -74, + -114, + 26, + -96, + 5, + -103, + 4, + -99, + -10, + -83, + -52, + -67, + -91, + 1, + 90, + -112, + 15, + -96, + -117, + 31, + -18, + 100, + -57, + -22, + 34, + 106, + -128, + 22, + -28, + -6, + 37, + 7, + 55, + 80, + -43, + -23, + 81, + 120, + -22, + 30, + -96, + 13, + 100, + 26, + -12, + 127, + 99, + 62, + 76, + 87, + -102, + -26, + -57, + -23, + -6, + -106, + 6, + 104, + 65, + -90, + 65, + 19, + -87, + 111, + 105, + 110, + -112, + -66, + -96, + 6, + 104, + 65, + 54, + 64, + -85, + -96, + -26, + -122, + -88, + 107, + 100, + 95, + 53, + 24, + -124, + 27, + 0, + 90, + 103, + -74, + 64, + 79, + -50, + -116, + 101, + 14, + -75, + -23, + 45, + 13, + -48, + -126, + 108, + -127, + 38, + -110, + -33, + -46, + -59, + -21, + -2, + 60, + -86, + -63, + -119, + 26, + -96, + 5, + -39, + 4, + -83, + -126, + -102, + 27, + -94, + -82, + 9, + 66, + -71, + -97, + -73, + 59, + -4, + 49, + 64, + -21, + -56, + 54, + -24, + -73, + -33, + 125, + 57, + 115, + -88, + 77, + 109, + 105, + -128, + 22, + 100, + 27, + 52, + 81, + -10, + -74, + -76, + 41, + -44, + 0, + 45, + -120, + 3, + 116, + 22, + 81, + -53, + -2, + -68, + 7, + -122, + 119, + 0, + 116, + -110, + -72, + 64, + -65, + 114, + -28, + 113, + -96, + -82, + -102, + 114, + -71, + 76, + -27, + 114, + -103, + 46, + 94, + -68, + 8, + -48, + 113, + -29, + 2, + 77, + -108, + -67, + 45, + 61, + 56, + 45, + 70, + -3, + -50, + -24, + -66, + 37, + -52, + -47, + 0, + 116, + -52, + 56, + 65, + 103, + 17, + 117, + -83, + -83, + 44, + 26, + -128, + -114, + 17, + 55, + 104, + -39, + -49, + -84, + 11, + -62, + -115, + -20, + 24, + 117, + -94, + 62, + 125, + -10, + 100, + 93, + -52, + 50, + -105, + 30, + 0, + 45, + -120, + 27, + 52, + 81, + -10, + -74, + -12, + 74, + -112, + 101, + -73, + 52, + 64, + 11, + 114, + 1, + -76, + -53, + -88, + 117, + 126, + 127, + 21, + -56, + 50, + -88, + 1, + 90, + -112, + 43, + -96, + -125, + -126, + -20, + -117, + 121, + -52, + 95, + 122, + 28, + 120, + 111, + -101, + -10, + -65, + 92, + 113, + 49, + -105, + -53, + 101, + -102, + -100, + -100, + 4, + 104, + -39, + 92, + 1, + 77, + -28, + -58, + -106, + -34, + 63, + -6, + -92, + -12, + -19, + -112, + -71, + 61, + 73, + 32, + -81, + -76, + -91, + 1, + 90, + -112, + 75, + -96, + 93, + 64, + -83, + -118, + -71, + -10, + 109, + -38, + -91, + 13, + 115, + 45, + -44, + 0, + 45, + -56, + 87, + -48, + -7, + 34, + -33, + -89, + -118, + -42, + -101, + 35, + 83, + -37, + -75, + 67, + -114, + -26, + -42, + -83, + 91, + 0, + -67, + 82, + -82, + -127, + 86, + 65, + -19, + 26, + -24, + 32, + -36, + 96, + 12, + -77, + 104, + 75, + 3, + -76, + 32, + 23, + 65, + 115, + -96, + 78, + -118, + -39, + 52, + 100, + 17, + 106, + -128, + 22, + -28, + 59, + -24, + -41, + 53, + 125, + 28, + 88, + 92, + -56, + 61, + -31, + 122, + -85, + -104, + -53, + -27, + 50, + -51, + -49, + -49, + 3, + 116, + -83, + 92, + 5, + -83, + -126, + -102, + 11, + -76, + 109, + -56, + -43, + 91, + 26, + -96, + 5, + -71, + 12, + 122, + -10, + -50, + -89, + -42, + 80, + -85, + 64, + 126, + 125, + -16, + 39, + -84, + -104, + -93, + 1, + 104, + 65, + 46, + -125, + 38, + -110, + -33, + -46, + -3, + -29, + 29, + 86, + 64, + 115, + 35, + -82, + -100, + 111, + -18, + 57, + 14, + -48, + -43, + -71, + 14, + 90, + 5, + -75, + 73, + -48, + -91, + 83, + 111, + -79, + 3, + 78, + -78, + -91, + -71, + -99, + 89, + -53, + 7, + -48, + -89, + -82, + 28, + 49, + -114, + -38, + -105, + -83, + 28, + 23, + 53, + -73, + 51, + 107, + -7, + 0, + -102, + 72, + 126, + 75, + -105, + 110, + -24, + -5, + 45, + -79, + 127, + 29, + 123, + -97, + 29, + -85, + -52, + -84, + 1, + -24, + -5, + -7, + 2, + 90, + 5, + -75, + 14, + -48, + -36, + 72, + 117, + 111, + 105, + 110, + 103, + -42, + -14, + 9, + -12, + -2, + 33, + -7, + -33, + 103, + 18, + 23, + -12, + -91, + -14, + 37, + 118, + -100, + 38, + 80, + 115, + 59, + -77, + -106, + 79, + -96, + -119, + -52, + 109, + -23, + -46, + -76, + -2, + 23, + 19, + 1, + 52, + 67, + -66, + -127, + 38, + -46, + -113, + -102, + 27, + -94, + 13, + -44, + -36, + -50, + -84, + -27, + 35, + -24, + -18, + -93, + -21, + -76, + -96, + 46, + 25, + 120, + -119, + -89, + 11, + 3, + -48, + -98, + -127, + 38, + 74, + -66, + -91, + -71, + -47, + 1, + -76, + -95, + 124, + 5, + 77, + 20, + 15, + 117, + 105, + 102, + 39, + 59, + 56, + 14, + -44, + -36, + -50, + -84, + -27, + 51, + -24, + 32, + -36, + 32, + 5, + 58, + 122, + 31, + 34, + 55, + 50, + -101, + 115, + -31, + 66, + 25, + -96, + 125, + 3, + 77, + 36, + -73, + -91, + 3, + 15, + 31, + 87, + -42, + -67, + -91, + -71, + -99, + 89, + -53, + 119, + -48, + 68, + -11, + 81, + 115, + -93, + -30, + -100, + -30, + -24, + 89, + -128, + -10, + 17, + -76, + -24, + 35, + 16, + 126, + 53, + -68, + -105, + 29, + 20, + -25, + 68, + -25, + 0, + -48, + 30, + -126, + 38, + 34, + 108, + -27, + -49, + -25, + -19, + -111, + -97, + 45, + -5, + -53, + 13, + -48, + 30, + -126, + 38, + 34, + 58, + -7, + -105, + 65, + 118, + 80, + 46, + 108, + -27, + -22, + 89, + -45, + 9, + -48, + 94, + -126, + -26, + 6, + -59, + 53, + -67, + -123, + 45, + 43, + -2, + -57, + -104, + -37, + -103, + -75, + -46, + 4, + -6, + -26, + -51, + -101, + -20, + -72, + 108, + 79, + 32, + -7, + 88, + 124, + 102, + 80, + -89, + 9, + 52, + 81, + 118, + -74, + 116, + 105, + -26, + -2, + -21, + -66, + 1, + -70, + -94, + -76, + -127, + 38, + 74, + 63, + -22, + 36, + -17, + -119, + -28, + -10, + 102, + -68, + 52, + -126, + 30, + 31, + 31, + 103, + 71, + 103, + 6, + 114, + -19, + 119, + -29, + -32, + -46, + -29, + -13, + -46, + 8, + -102, + 40, + 125, + 91, + 90, + -25, + 59, + -41, + -71, + -51, + 25, + 45, + -83, + -96, + -119, + -46, + -127, + 90, + -9, + -69, + -41, + 83, + -113, + 26, + -96, + 93, + -99, + 75, + -44, + 115, + 84, + -3, + -61, + -35, + 101, + 65, + -25, + 11, + 77, + 11, + -36, + -10, + -116, + -92, + 5, + -12, + -28, + 87, + 106, + -49, + -62, + 93, + 123, + -126, + 5, + -15, + -61, + 84, + -97, + 90, + 47, + 125, + -59, + -106, + -106, + 40, + 54, + -24, + 122, + -120, + 107, + 13, + 83, + -36, + 64, + 101, + 103, + -20, + -62, + -7, + 101, + -24, + -30, + -128, + -50, + 52, + 106, + 101, + -48, + 19, + 95, + -117, + -121, + -103, + 17, + 54, + 55, + 84, + -43, + -83, + 108, + 19, + 116, + 111, + -79, + -7, + -97, + -36, + 6, + -75, + -90, + 4, + 58, + 41, + 100, + -96, + 94, + 54, + -57, + 78, + -1, + -74, + 46, + -72, + -72, + -96, + 51, + -69, + -91, + 89, + 48, + 71, + -13, + -39, + 7, + -103, + 70, + 45, + -125, + 45, + 9, + -24, + -46, + -12, + -82, + -20, + -95, + 102, + -61, + -52, + -80, + -87, + -71, + 1, + 71, + 115, + -32, + -40, + 78, + 105, + 104, + 73, + 64, + -85, + 93, + 122, + 52, + -3, + -110, + -37, + -94, + -106, + 88, + 49, + 103, + 16, + -75, + -62, + -61, + 106, + 90, + 64, + 103, + -18, + -46, + -93, + 30, + -26, + 71, + -10, + -100, + -80, + 3, + 58, + 3, + -88, + -69, + 67, + -7, + -49, + 18, + -47, + 13, + -6, + -56, + -44, + -13, + -39, + 65, + -51, + -66, + -99, + 51, + 0, + 58, + 14, + -28, + 124, + -95, + -119, + -6, + -122, + 54, + 107, + 1, + -83, + -78, + -91, + -13, + 3, + 91, + 26, + -71, + 77, + 38, + -86, + 22, + -26, + 117, + -35, + -121, + -20, + -126, + 78, + 33, + -22, + -96, + 32, + -9, + 49, + 11, + 38, + -73, + 115, + -26, + 46, + 61, + -100, + -40, + -50, + 12, + -96, + 23, + 22, + 22, + -100, + -36, + -54, + -47, + 4, + 6, + 64, + -1, + -30, + 79, + 79, + -91, + 31, + 117, + 86, + 65, + 19, + -103, + -39, + -46, + -79, + -2, + -103, + -73, + -80, + -99, + 85, + 111, + -45, + -31, + -61, + -21, + -66, + -56, + 109, + 51, + 86, + 78, + -127, + -10, + 28, + 117, + -30, + -21, + 87, + -61, + -104, + 51, + 113, + -23, + 33, + -62, + -4, + -40, + -34, + -31, + -52, + -128, + -98, + -99, + -99, + 53, + 6, + -71, + 122, + -126, + 112, + -7, + -25, + -121, + -40, + -58, + 60, + 56, + -77, + -101, + 126, + 62, + -40, + -100, + 94, + -44, + 34, + -48, + 31, + -99, + -7, + 65, + 102, + 64, + 19, + 37, + -39, + -46, + -105, + 18, + -63, + 26, + -120, + -7, + -5, + 96, + -80, + -91, + -21, + 36, + -66, + -36, + 88, + -107, + 41, + -48, + 113, + 80, + 115, + 65, + 4, + -22, + 21, + 18, + -127, + 126, + -13, + -48, + -34, + -52, + -127, + -66, + 118, + -19, + -102, + 20, + -28, + 51, + -25, + 79, + -77, + 67, + -44, + 53, + 50, + -105, + 64, + -34, + -95, + 22, + -127, + -2, + -58, + 11, + 22, + -97, + 33, + 116, + 4, + 52, + -47, + -54, + 91, + -38, + -10, + -75, + 46, + -74, + 116, + -116, + -100, + 122, + -108, + 99, + 98, + 21, + 43, + -24, + 90, + -88, + 15, + -99, + -20, + 91, + 118, + 7, + -1, + -18, + -54, + 115, + -20, + 24, + -127, + 90, + -112, + 83, + -96, + 29, + -24, + -14, + -27, + -53, + -46, + 79, + -112, + 112, + 67, + -44, + 53, + -87, + -6, + 8, + 4, + -128, + 94, + 94, + -71, + 92, + -90, + -66, + -127, + 22, + 39, + 30, + 51, + -58, + -106, + 86, + -52, + -103, + 23, + 39, + -115, + 127, + -127, + -37, + -15, + 3, + -55, + -34, + -63, + 3, + 31, + -14, + 61, + -12, + 6, + -44, + -126, + -100, + 1, + -19, + 96, + -78, + 119, + 48, + 55, + 68, + -37, + -96, + -13, + -59, + -90, + 57, + 110, + -73, + 53, + 115, + -30, + 5, + -2, + -41, + -73, + 113, + -37, + 21, + 118, + 112, + -76, + 11, + -88, + 125, + -37, + -46, + 43, + -127, + 126, + -94, + -89, + 63, + -109, + -37, + 57, + 42, + 107, + -96, + 75, + -66, + -93, + -106, + 123, + 79, + -31, + -105, + -36, + -57, + 60, + 123, + 78, + -4, + -25, + 79, + 36, + -1, + 30, + 89, + 67, + 45, + -5, + -13, + -10, + 14, + 52, + -97, + -29, + -10, + -69, + 44, + 25, + -48, + -58, + 80, + 39, + -19, + 31, + 61, + -118, + -33, + -13, + -31, + 88, + -33, + 70, + -12, + 75, + -119, + -128, + -38, + -47, + 45, + 45, + 11, + -70, + -79, + 107, + -124, + 104, + 126, + -42, + 13, + -52, + -13, + -1, + 78, + -10, + -67, + 99, + 60, + -127, + 3, + -48, + -98, + -96, + 86, + 2, + 29, + -59, + -71, + -107, + 25, + -1, + -123, + -56, + 10, + 106, + 21, + -52, + -7, + 66, + 19, + -19, + 43, + 110, + -38, + -62, + -19, + 120, + -87, + 88, + -96, + -105, + 112, + -83, + -106, + -57, + -77, + -72, + -24, + 22, + -26, + 24, + -88, + 101, + 47, + 61, + -126, + -48, + 79, + -44, + -86, + -112, + -99, + -36, + -46, + -119, + 64, + 87, + 55, + 119, + -101, + 104, + -22, + 59, + 68, + -73, + -113, + -59, + 20, + 91, + 39, + 19, + -104, + 99, + -96, + 78, + -29, + -106, + 30, + -72, + 33, + -1, + 9, + 75, + -50, + -93, + -42, + 10, + -38, + 84, + 38, + 49, + 103, + 28, + -75, + 14, + -56, + -47, + -68, + -4, + -34, + -109, + 95, + -26, + -10, + 12, + -48, + -47, + 76, + 60, + 36, + 125, + 115, + 100, + -17, + 96, + 19, + -17, + -36, + -42, + 53, + -3, + 19, + 29, + 90, + 49, + 99, + 67, + -53, + 102, + 3, + 115, + -58, + -74, + -76, + 110, + -56, + -67, + -59, + -26, + 78, + 110, + -57, + 75, + 57, + 13, + 122, + -15, + -98, + 93, + -48, + 41, + 71, + -3, + -58, + -69, + 91, + -45, + -71, + -107, + 43, + 115, + 26, + -76, + 109, + -52, + -122, + 64, + -65, + -6, + 123, + 125, + 31, + -23, + -27, + -54, + 86, + -34, + 87, + -36, + -16, + 117, + 110, + -69, + -62, + 0, + 58, + 62, + 104, + 34, + -9, + -73, + 116, + 111, + 81, + -2, + 35, + 11, + -68, + -35, + -54, + -107, + 1, + 116, + 50, + -44, + -13, + -9, + -26, + -99, + 69, + -99, + 41, + -56, + 81, + -50, + -126, + -42, + -7, + 52, + -69, + 35, + 91, + -6, + -32, + -103, + 86, + 43, + -112, + -125, + 80, + 47, + 100, + 111, + 48, + 55, + 52, + 56, + 12, + -6, + -22, + 15, + -67, + 1, + 77, + -28, + -50, + -91, + 71, + 102, + 33, + 71, + 57, + 11, + -102, + 11, + 115, + 76, + -48, + 55, + 63, + -7, + -120, + 21, + -75, + 110, + -56, + 94, + 98, + 110, + 104, + 112, + 24, + -12, + -11, + -57, + -67, + 2, + 77, + 36, + -65, + -91, + 11, + 127, + -33, + -31, + 52, + 102, + 110, + -109, + -119, + 114, + 22, + -12, + -62, + 93, + -17, + 64, + 19, + -39, + -67, + -12, + -48, + -66, + -107, + -117, + -98, + 99, + 110, + 104, + 112, + 24, + 52, + 17, + 15, + -26, + -124, + 31, + 118, + 115, + 124, + -20, + 55, + 86, + 80, + 99, + 43, + -41, + 8, + -96, + -11, + 109, + -25, + 40, + -109, + -96, + 117, + 67, + -18, + 45, + 54, + -35, + -31, + 54, + -88, + 53, + -128, + -42, + 15, + -102, + 72, + 63, + -22, + -16, + -22, + 14, + 108, + 101, + -103, + -100, + 6, + 77, + 100, + 25, + 116, + -68, + -9, + 28, + -118, + 122, + 109, + -16, + 105, + 109, + -88, + 13, + 92, + 43, + -97, + -30, + 118, + 103, + 44, + -128, + -42, + -65, + -99, + -93, + -110, + -126, + 126, + -13, + 92, + 27, + -74, + -78, + 106, + -50, + -125, + 38, + -78, + -125, + 121, + -30, + -85, + 70, + 110, + 122, + 92, + -44, + -70, + 33, + 7, + -123, + 77, + 79, + 112, + 91, + -77, + -110, + 23, + -96, + 39, + 30, + -10, + 110, + 59, + 71, + 5, + -95, + -4, + -17, + 42, + 28, + -100, + -39, + 77, + 125, + 67, + -101, + -75, + 99, + 110, + -20, + 26, + 73, + -1, + 102, + -114, + -14, + 2, + 52, + -111, + -105, + -104, + -93, + -76, + 95, + 3, + 75, + -50, + -9, + 94, + 26, + 90, + -70, + -17, + -72, + -99, + 89, + -53, + 27, + -48, + 68, + 94, + 98, + -114, + -78, + -115, + -71, + -6, + -66, + -29, + 118, + 102, + 45, + -81, + 64, + 19, + -3, + -1, + -67, + 127, + -98, + 97, + 38, + 82, + -5, + -12, + -91, + 36, + -13, + 104, + -89, + -8, + -66, + -29, + 118, + 102, + 45, + -17, + 64, + 71, + 37, + -127, + -4, + -81, + -9, + 89, + 110, + -78, + -19, + -83, + 12, + -48, + 62, + -127, + -114, + 82, + -127, + 124, + -11, + 49, + -18, + 91, + 107, + 4, + -14, + 26, + -119, + -5, + -114, + -37, + -103, + -75, + -68, + 7, + 93, + -39, + -115, + 61, + -9, + 47, + 73, + 38, + 30, + 34, + -102, + 122, + -124, + -5, + 22, + 45, + 75, + 47, + -26, + -115, + -46, + -9, + 29, + -73, + 51, + 107, + -91, + 10, + -76, + 39, + -23, + -64, + 76, + 68, + -46, + -9, + 27, + 64, + 3, + -76, + -47, + 22, + 23, + 23, + 99, + 67, + -18, + 9, + -41, + 47, + -3, + 57, + 0, + 45, + 8, + -96, + 121, + -118, + -69, + -107, + 43, + 3, + 104, + 65, + 0, + -51, + -105, + 44, + -28, + -3, + 67, + -49, + 10, + -65, + 30, + -96, + 5, + 1, + 52, + 95, + -77, + 119, + 62, + 85, + -34, + -54, + -107, + 1, + -76, + 32, + -128, + -26, + -83, + 22, + -28, + 63, + 94, + 14, + 87, + -4, + 90, + -128, + 22, + 4, + -48, + -4, + -87, + 108, + -27, + -54, + 0, + 90, + 16, + 64, + -13, + 55, + 126, + -29, + 44, + -27, + 11, + 77, + 116, + 123, + -10, + 99, + -91, + -81, + 3, + 104, + 65, + 0, + -19, + 111, + 0, + 45, + 8, + -96, + -3, + 13, + -96, + 5, + 1, + -76, + -65, + 1, + -76, + 32, + -128, + -10, + 55, + -128, + 22, + 4, + -48, + -2, + 6, + -48, + -126, + 84, + 14, + 5, + -29, + -17, + 112, + 59, + -77, + 22, + -9, + 65, + 99, + 0, + 90, + 107, + -36, + 7, + -115, + 1, + 104, + -83, + 113, + 31, + 52, + 6, + -96, + -75, + -58, + 125, + -48, + 24, + -128, + -42, + 26, + -9, + 65, + 99, + 0, + 90, + 107, + -115, + 47, + -98, + 96, + 63, + 108, + 12, + 64, + 107, + -115, + -5, + -80, + 49, + 0, + -83, + 53, + -18, + -61, + -58, + 0, + -76, + -42, + -72, + 15, + 27, + 3, + -52, + -38, + -29, + 62, + 116, + 12, + 64, + 107, + -19, + 91, + 29, + -61, + -85, + -71, + 15, + 30, + 3, + -52, + -38, + -29, + -66, + 3, + 48, + -64, + -116, + -112, + -109, + -3, + 15, + 62, + -114, + 31, + -125, + -73, + -124, + 107, + 78, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + -82, + 66, + 96, + -126 + ], + "fileName": "awesomeIcon.png", + "fileExtension": "PNG" + } + ], + "icons": [ + { + "ID": 1, + "imageID": 1 + }, + { + "ID": 2, + "builtinIdentifier": "fas fa-icons", + "fontColor": "#FF0000" + } + ], + "transactionNameKeywords": [ + { + "value": "income" + }, + { + "value": "xyz" + } + ] +} \ No newline at end of file diff --git a/BudgetMasterServer/src/test/resources/ImportServiceTest.json b/BudgetMasterServer/src/test/resources/ImportServiceTest.json index 5878e8ee5df0d780e0098002f7c5154165288ec7..02a4193a41d1d95928a49107b421d79dab9ab382 100644 --- a/BudgetMasterServer/src/test/resources/ImportServiceTest.json +++ b/BudgetMasterServer/src/test/resources/ImportServiceTest.json @@ -1,6 +1,6 @@ { "TYPE": "BUDGETMASTER_DATABASE", - "VERSION": 8, + "VERSION": 9, "categories": [ { "ID": 3, @@ -2237,5 +2237,13 @@ "ID": 18, "imageID": 1 } + ], + "transactionNameKeywords": [ + { + "value": "income" + }, + { + "value": "xyz" + } ] } \ No newline at end of file