diff --git a/Dockerfile b/Dockerfile index aa9f097f1bc2be277eb30d1f71a97fad9ba67d23..00addd9fd022f6645a79ad3958a0df1c069e09ab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM tomcat:9-jdk11 RUN rm -rf /usr/local/tomcat/webapps/* -COPY build/2.6.0/BudgetMaster-v2.6.0.war $CATALINA_HOME/webapps/ROOT.war +COPY build/2.6.1/BudgetMaster-v2.6.1.war $CATALINA_HOME/webapps/ROOT.war COPY src/main/resources/config/templates/settings-docker.properties /root/.Deadlocker/BudgetMaster/settings.properties EXPOSE 8080 \ No newline at end of file diff --git a/README.md b/README.md index ff138ef234963268572196b07a4b935ca461504c..b9f4333b62faa77ae2829a1a8d927a19f9a40a71 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Manage your monthly budget easily with BudgetMaster - __start:__ 17.12.16 -- __current release:__ v2.6.0 (31) from 10.05.21 +- __current release:__ v2.6.1 (32) from 30.05.21 ## Key Features - Keep your data private - Host your own BudgetMaster server or use it in standalone mode. All data remains on your machines. diff --git a/pom.xml b/pom.xml index b8ec60be572bac8d6a554ed03a58e140fb60e1ff..0bc83e802fc72f29091134021ddd6043dfd278bb 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ <groupId>de.deadlocker8</groupId> <artifactId>BudgetMaster</artifactId> - <version>2.6.0</version> + <version>2.6.1</version> <name>BudgetMaster</name> <repositories> @@ -76,7 +76,7 @@ <app.versionDate>${maven.build.timestamp}</app.versionDate> <maven.build.timestamp.format>dd.MM.yy</maven.build.timestamp.format> - <app.versionCode>31</app.versionCode> + <app.versionCode>32</app.versionCode> <app.author>Robert Goldmann</app.author> <project.outputDirectory>build/${project.version}</project.outputDirectory> diff --git a/src/main/java/de/deadlocker8/budgetmaster/Main.java b/src/main/java/de/deadlocker8/budgetmaster/Main.java index f459cd307ad1c3e09cba43f14485e2aba24d2d98..577c74b2e5191a04140587e46914a22177479c72 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/Main.java +++ b/src/main/java/de/deadlocker8/budgetmaster/Main.java @@ -147,7 +147,7 @@ public class Main extends SpringBootServletInitializer implements ApplicationRun Path applicationSupportFolder = prepare(args); Path logPath = applicationSupportFolder.resolve("error.log"); - String loggingArgument = "--logging.file=" + logPath.toString(); + String loggingArgument = "--logging.file.name=" + logPath; List<String> arguments = new ArrayList<>(ProgramArgs.getArgs()); if(!arguments.contains(loggingArgument)) { diff --git a/src/main/java/de/deadlocker8/budgetmaster/accounts/Account.java b/src/main/java/de/deadlocker8/budgetmaster/accounts/Account.java index c1647ca760e5ee6508f5e78197ac61b6cb5cef47..8f2adfa3ad25882da8fb2c1296526ed837ddb84e 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/accounts/Account.java +++ b/src/main/java/de/deadlocker8/budgetmaster/accounts/Account.java @@ -3,6 +3,7 @@ package de.deadlocker8.budgetmaster.accounts; import com.google.gson.annotations.Expose; import de.deadlocker8.budgetmaster.images.Image; import de.deadlocker8.budgetmaster.transactions.Transaction; +import de.deadlocker8.budgetmaster.utils.ProvidesID; import javax.persistence.*; import javax.validation.constraints.NotNull; @@ -11,7 +12,7 @@ import java.util.List; import java.util.Objects; @Entity -public class Account +public class Account implements ProvidesID { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/de/deadlocker8/budgetmaster/categories/Category.java b/src/main/java/de/deadlocker8/budgetmaster/categories/Category.java index 835ce0bbd772e9a21bd56b5719621efefe177413..502aef8cbe4f1129cb4650f516da1fc5175a3dff 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/categories/Category.java +++ b/src/main/java/de/deadlocker8/budgetmaster/categories/Category.java @@ -2,6 +2,7 @@ package de.deadlocker8.budgetmaster.categories; import com.google.gson.annotations.Expose; import de.deadlocker8.budgetmaster.transactions.Transaction; +import de.deadlocker8.budgetmaster.utils.ProvidesID; import de.thecodelabs.utils.util.Color; import de.thecodelabs.utils.util.ColorUtilsNonJavaFX; @@ -12,7 +13,7 @@ import java.util.List; import java.util.Objects; @Entity -public class Category +public class Category implements ProvidesID { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/de/deadlocker8/budgetmaster/controller/AboutController.java b/src/main/java/de/deadlocker8/budgetmaster/controller/AboutController.java index fc679c96726d1ae09692461ceb720a3bfeaa991c..f0a0563ddf3aa105914d6d75eba1f1cb7e32d044 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/controller/AboutController.java +++ b/src/main/java/de/deadlocker8/budgetmaster/controller/AboutController.java @@ -36,6 +36,8 @@ public class AboutController extends BaseController public String whatsNewModal(Model model) { final List<NewsEntry> newsEntries = new ArrayList<>(); + newsEntries.add(NewsEntry.createWithLocalizationKeys("news.fix.backup.size.headline", "news.fix.backup.size.description")); + newsEntries.add(NewsEntry.createWithLocalizationKeys("news.fix.readonly.accounts.headline", "news.fix.readonly.accounts.description")); newsEntries.add(NewsEntry.createWithLocalizationKeys("news.designOffensive.headline", "news.designOffensive.description")); newsEntries.add(NewsEntry.createWithLocalizationKeys("news.gitBackup.headline", "news.gitBackup.description")); newsEntries.add(NewsEntry.createWithLocalizationKeys("news.backupCharts.headline", "news.backupCharts.description")); diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/BackupItemParser.java b/src/main/java/de/deadlocker8/budgetmaster/database/BackupItemParser.java new file mode 100644 index 0000000000000000000000000000000000000000..bda62e21f9eee1b06b46108db226a1adff0d8b86 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/BackupItemParser.java @@ -0,0 +1,26 @@ +package de.deadlocker8.budgetmaster.database; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; + +import java.util.ArrayList; +import java.util.List; + +public class BackupItemParser +{ + private BackupItemParser() + { + } + + public static <T> List<T> parseItems(JsonArray jsonArray, Class<T> itemType) + { + List<T> parsedItems = new ArrayList<>(); + for(JsonElement currentItem : jsonArray) + { + parsedItems.add(new Gson().fromJson(currentItem, itemType)); + } + + return parsedItems; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser.java b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser.java index fa3d609762d4476df901116d3b193539bdcb045c..67209c484ada1ae4005deaa4b3e18139e76c3184 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser.java +++ b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser.java @@ -2,8 +2,10 @@ package de.deadlocker8.budgetmaster.database; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import de.deadlocker8.budgetmaster.database.legacy.LegacyParser; -import de.deadlocker8.budgetmaster.categories.Category; +import de.deadlocker8.budgetmaster.database.model.BackupDatabase; +import de.deadlocker8.budgetmaster.database.model.v4.BackupDatabase_v4; +import de.deadlocker8.budgetmaster.database.model.v5.BackupDatabase_v5; +import de.deadlocker8.budgetmaster.database.model.v6.BackupDatabase_v6; import de.thecodelabs.utils.util.Localization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,16 +15,58 @@ import java.text.MessageFormat; public class DatabaseParser { final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); + + private static final int MINIMUM_VERSION = 4; + public static final int LATEST_VERSION = 6; + private final String jsonString; - private final Category categoryNone; - public DatabaseParser(String json, Category categoryNone) + public DatabaseParser(String json) { this.jsonString = json; - this.categoryNone = categoryNone; } - public Database parseDatabaseFromJSON() throws IllegalArgumentException + public InternalDatabase parseDatabaseFromJSON() throws IllegalArgumentException + { + int version = parseVersion(); + + if(version < MINIMUM_VERSION) + { + throw new IllegalArgumentException(Localization.getString("error.database.import.version.too.old", version, MINIMUM_VERSION)); + } + + BackupDatabase importedDatabase = null; + + if(version == 4) + { + BackupDatabase_v4 parsedDatabase = new DatabaseParser_v4(jsonString).parseDatabaseFromJSON(); + LOGGER.debug(MessageFormat.format("Parsed database with {0} transactions, {1} categories, {2} accounts and {3} templates", parsedDatabase.getTransactions().size(), parsedDatabase.getCategories().size(), parsedDatabase.getAccounts().size(), parsedDatabase.getTemplates().size())); + importedDatabase = parsedDatabase; + } + + if(version == 5) + { + BackupDatabase_v5 parsedDatabase = new DatabaseParser_v5(jsonString).parseDatabaseFromJSON(); + LOGGER.debug(MessageFormat.format("Parsed database with {0} transactions, {1} categories, {2} accounts, {3} templates {4} charts and {5} images", parsedDatabase.getTransactions().size(), parsedDatabase.getCategories().size(), parsedDatabase.getAccounts().size(), parsedDatabase.getTemplates().size(), parsedDatabase.getCharts().size(), parsedDatabase.getImages().size())); + importedDatabase = parsedDatabase; + } + + if(version == 6) + { + BackupDatabase_v6 parsedDatabase = new DatabaseParser_v6(jsonString).parseDatabaseFromJSON(); + LOGGER.debug(MessageFormat.format("Parsed database with {0} transactions, {1} categories, {2} accounts, {3} templates {4} charts and {5} images", parsedDatabase.getTransactions().size(), parsedDatabase.getCategories().size(), parsedDatabase.getAccounts().size(), parsedDatabase.getTemplates().size(), parsedDatabase.getCharts().size(), parsedDatabase.getImages().size())); + importedDatabase = parsedDatabase; + } + + if(importedDatabase == null) + { + throw new IllegalArgumentException(Localization.getString("error.database.import.unknown.version")); + } + + return upgradeDatabase(importedDatabase); + } + + private int parseVersion() { try { @@ -35,36 +79,7 @@ public class DatabaseParser int version = root.get("VERSION").getAsInt(); LOGGER.info(MessageFormat.format("Parsing BudgetMaster database with version {0}", version)); - - if(version == 2) - { - final Database database = new LegacyParser(jsonString, categoryNone).parseDatabaseFromJSON(); - LOGGER.debug(MessageFormat.format("Parsed database with {0} transactions, {1} categories and {2} accounts", database.getTransactions().size(), database.getCategories().size(), database.getAccounts().size())); - return database; - } - - if(version == 3) - { - final Database database = new DatabaseParser_v3(jsonString).parseDatabaseFromJSON(); - LOGGER.debug(MessageFormat.format("Parsed database with {0} transactions, {1} categories and {2} accounts", database.getTransactions().size(), database.getCategories().size(), database.getAccounts().size())); - return database; - } - - if(version == 4) - { - final Database database = new DatabaseParser_v4(jsonString).parseDatabaseFromJSON(); - LOGGER.debug(MessageFormat.format("Parsed database with {0} transactions, {1} categories, {2} accounts and {3} templates", database.getTransactions().size(), database.getCategories().size(), database.getAccounts().size(), database.getTemplates().size())); - return database; - } - - if(version == 5) - { - final Database database = new DatabaseParser_v5(jsonString).parseDatabaseFromJSON(); - LOGGER.debug(MessageFormat.format("Parsed database with {0} transactions, {1} categories, {2} accounts, {3} templates and {4} charts", database.getTransactions().size(), database.getCategories().size(), database.getAccounts().size(), database.getTemplates().size(), database.getCharts().size())); - return database; - } - - throw new IllegalArgumentException(Localization.getString("error.database.import.unknown.version")); + return version; } catch(Exception e) { @@ -72,4 +87,17 @@ public class DatabaseParser throw new IllegalArgumentException(Localization.getString("error.database.import.invalid.json"), e); } } + + private InternalDatabase upgradeDatabase(BackupDatabase importedDatabase) + { + BackupDatabase upgradedDatabase = importedDatabase; + while(upgradedDatabase.getVersion() < LATEST_VERSION) + { + LOGGER.debug(MessageFormat.format("Upgrading database from version {0} to {1}", upgradedDatabase.getVersion(), upgradedDatabase.getVersion() + 1)); + upgradedDatabase = upgradedDatabase.upgrade(); + } + + LOGGER.debug(MessageFormat.format("Converting database with version {0} to internal entities", upgradedDatabase.getVersion())); + return upgradedDatabase.convertToInternal(); + } } \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v3.java b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v3.java deleted file mode 100644 index e66c202b7593b4df1f183d664cf1f52a9ac536e9..0000000000000000000000000000000000000000 --- a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v3.java +++ /dev/null @@ -1,205 +0,0 @@ -package de.deadlocker8.budgetmaster.database; - -import com.google.gson.*; -import de.deadlocker8.budgetmaster.accounts.Account; -import de.deadlocker8.budgetmaster.accounts.AccountState; -import de.deadlocker8.budgetmaster.accounts.AccountType; -import de.deadlocker8.budgetmaster.categories.Category; -import de.deadlocker8.budgetmaster.repeating.RepeatingOption; -import de.deadlocker8.budgetmaster.repeating.endoption.*; -import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifier; -import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierType; -import de.deadlocker8.budgetmaster.tags.Tag; -import de.deadlocker8.budgetmaster.transactions.Transaction; -import de.thecodelabs.utils.util.Localization; -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -public class DatabaseParser_v3 -{ - final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); - private final String jsonString; - protected List<Category> categories; - protected List<Account> accounts; - - public DatabaseParser_v3(String json) - { - this.jsonString = json; - } - - public Database parseDatabaseFromJSON() throws IllegalArgumentException - { - JsonObject root = JsonParser.parseString(jsonString).getAsJsonObject(); - categories = parseCategories(root); - accounts = parseAccounts(root); - List<Transaction> transactions = parseTransactions(root); - - return new Database(categories, accounts, transactions, new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); - } - - protected List<Category> parseCategories(JsonObject root) - { - List<Category> parsedCategories = new ArrayList<>(); - JsonArray jsonCategories = root.get("categories").getAsJsonArray(); - for(JsonElement currentCategory : jsonCategories) - { - Category parsedCategory = new Gson().fromJson(currentCategory, Category.class); - parsedCategories.add(parsedCategory); - } - - return parsedCategories; - } - - protected List<Account> parseAccounts(JsonObject root) - { - List<Account> parsedAccounts = new ArrayList<>(); - JsonArray jsonAccounts = root.get("accounts").getAsJsonArray(); - for(JsonElement currentAccount : jsonAccounts) - { - final JsonObject accountObject = currentAccount.getAsJsonObject(); - Integer ID = accountObject.get("ID").getAsInt(); - String name = accountObject.get("name").getAsString(); - AccountType accountType = AccountType.valueOf(accountObject.get("type").getAsString()); - - AccountState accountState = AccountState.FULL_ACCESS; - if(accountObject.has("accountState")) - { - accountState = AccountState.valueOf(accountObject.get("accountState").getAsString()); - } - - Account parsedAccount = new Account(name, accountType, null); - parsedAccount.setID(ID); - parsedAccount.setAccountState(accountState); - - parsedAccounts.add(parsedAccount); - } - - return parsedAccounts; - } - - protected List<Transaction> parseTransactions(JsonObject root) - { - List<Transaction> parsedTransactions = new ArrayList<>(); - JsonArray transactions = root.get("transactions").getAsJsonArray(); - for(JsonElement currentTransaction : transactions) - { - int amount = currentTransaction.getAsJsonObject().get("amount").getAsInt(); - String name = currentTransaction.getAsJsonObject().get("name").getAsString(); - String description = currentTransaction.getAsJsonObject().get("description").getAsString(); - - Transaction transaction = new Transaction(); - transaction.setAmount(amount); - transaction.setName(name); - transaction.setDescription(description); - transaction.setTags(parseTags(currentTransaction.getAsJsonObject())); - - int categoryID = currentTransaction.getAsJsonObject().get("category").getAsJsonObject().get("ID").getAsInt(); - transaction.setCategory(getCategoryByID(categoryID)); - - int accountID = currentTransaction.getAsJsonObject().get("account").getAsJsonObject().get("ID").getAsInt(); - transaction.setAccount(getAccountByID(accountID)); - - JsonElement transferAccount = currentTransaction.getAsJsonObject().get("transferAccount"); - if(transferAccount != null) - { - int transferAccountID = transferAccount.getAsJsonObject().get("ID").getAsInt(); - transaction.setTransferAccount(getAccountByID(transferAccountID)); - } - - String date = currentTransaction.getAsJsonObject().get("date").getAsString(); - DateTime parsedDate = DateTime.parse(date, DateTimeFormat.forPattern("yyyy-MM-dd")); - transaction.setDate(parsedDate); - - transaction.setRepeatingOption(parseRepeatingOption(currentTransaction.getAsJsonObject(), parsedDate)); - - parsedTransactions.add(transaction); - } - - return parsedTransactions; - } - - protected RepeatingOption parseRepeatingOption(JsonObject transaction, DateTime startDate) - { - if(!transaction.has("repeatingOption")) - { - return null; - } - - JsonObject option = transaction.get("repeatingOption").getAsJsonObject(); - - JsonObject repeatingModifier = option.get("modifier").getAsJsonObject(); - String repeatingModifierType = repeatingModifier.get("localizationKey").getAsString(); - - RepeatingModifierType type = RepeatingModifierType.getByLocalization(Localization.getString(repeatingModifierType)); - RepeatingModifier modifier = RepeatingModifier.fromModifierType(type, repeatingModifier.get("quantity").getAsInt()); - - JsonObject repeatingEnd = option.get("endOption").getAsJsonObject(); - String repeatingEndType = repeatingEnd.get("localizationKey").getAsString(); - - RepeatingEnd endOption = null; - RepeatingEndType endType = RepeatingEndType.getByLocalization(Localization.getString(repeatingEndType)); - switch(endType) - { - case NEVER: - endOption = new RepeatingEndNever(); - break; - case AFTER_X_TIMES: - endOption = new RepeatingEndAfterXTimes(repeatingEnd.get("times").getAsInt()); - break; - case DATE: - DateTime endDate = DateTime.parse(repeatingEnd.get("endDate").getAsString(), DateTimeFormat.forPattern("yyyy-MM-dd")); - endOption = new RepeatingEndDate(endDate); - break; - } - - RepeatingOption repeatingOption = new RepeatingOption(); - repeatingOption.setStartDate(startDate); - repeatingOption.setEndOption(endOption); - repeatingOption.setModifier(modifier); - - return repeatingOption; - } - - protected List<Tag> parseTags(JsonObject transaction) - { - List<Tag> parsedTags = new ArrayList<>(); - JsonArray tags = transaction.get("tags").getAsJsonArray(); - for(JsonElement currentTag : tags) - { - parsedTags.add(new Gson().fromJson(currentTag, Tag.class)); - } - - return parsedTags; - } - - protected Category getCategoryByID(int ID) - { - for(Category category : categories) - { - if(category.getID() == ID) - { - return category; - } - } - - return null; - } - - protected Account getAccountByID(int ID) - { - for(Account account : accounts) - { - if(account.getID() == ID) - { - return account; - } - } - - return null; - } -} \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v4.java b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v4.java index c73b40efa5fe99cba3feda7e2ac61b06e04097bf..713f704eaad5b7e2b2d9686fbd8a2fb7a6db84aa 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v4.java +++ b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v4.java @@ -1,169 +1,54 @@ package de.deadlocker8.budgetmaster.database; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import de.deadlocker8.budgetmaster.templates.Template; -import de.deadlocker8.budgetmaster.transactions.Transaction; -import de.deadlocker8.budgetmaster.transactions.TransactionBase; -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import de.deadlocker8.budgetmaster.database.model.v4.*; -import java.util.ArrayList; import java.util.List; -import java.util.Optional; -public class DatabaseParser_v4 extends DatabaseParser_v3 +public class DatabaseParser_v4 { - final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); private final String jsonString; - protected List<Transaction> transactions; - protected List<Template> templates; - public DatabaseParser_v4(String json) { - super(json); this.jsonString = json; } - @Override - public Database parseDatabaseFromJSON() throws IllegalArgumentException - { - final JsonObject root = JsonParser.parseString(jsonString).getAsJsonObject(); - super.categories = super.parseCategories(root); - super.accounts = super.parseAccounts(root); - this.transactions = parseTransactions(root); - this.templates = parseTemplates(root); - - return new Database(categories, accounts, transactions, templates, new ArrayList<>(), new ArrayList<>()); - } - - @Override - protected List<Transaction> parseTransactions(JsonObject root) + public BackupDatabase_v4 parseDatabaseFromJSON() throws IllegalArgumentException { - List<Transaction> parsedTransactions = new ArrayList<>(); - JsonArray transactionsToImport = root.get("transactions").getAsJsonArray(); - for(JsonElement currentTransaction : transactionsToImport) - { - final JsonObject transactionObject = currentTransaction.getAsJsonObject(); - - int amount = transactionObject.get("amount").getAsInt(); - String name = transactionObject.get("name").getAsString(); - String description = transactionObject.get("description").getAsString(); - - Transaction transaction = new Transaction(); - transaction.setAmount(amount); - transaction.setName(name); - transaction.setDescription(description); - transaction.setTags(parseTags(transactionObject)); - - int categoryID = transactionObject.get("category").getAsJsonObject().get("ID").getAsInt(); - transaction.setCategory(getCategoryByID(categoryID)); - - int accountID = transactionObject.get("account").getAsJsonObject().get("ID").getAsInt(); - transaction.setAccount(getAccountByID(accountID)); + BackupDatabase_v4 database = new BackupDatabase_v4(); - JsonElement transferAccount = transactionObject.get("transferAccount"); - if(transferAccount != null) - { - int transferAccountID = transferAccount.getAsJsonObject().get("ID").getAsInt(); - transaction.setTransferAccount(getAccountByID(transferAccountID)); - } - - String date = transactionObject.get("date").getAsString(); - DateTime parsedDate = DateTime.parse(date, DateTimeFormat.forPattern("yyyy-MM-dd")); - transaction.setDate(parsedDate); - - transaction.setRepeatingOption(super.parseRepeatingOption(transactionObject, parsedDate)); + final JsonObject root = JsonParser.parseString(jsonString).getAsJsonObject(); + database.setAccounts(BackupItemParser.parseItems(root.get("accounts").getAsJsonArray(), BackupAccount_v4.class)); + database.setCategories(BackupItemParser.parseItems(root.get("categories").getAsJsonArray(), BackupCategory_v4.class)); - handleIsExpenditure(transactionObject, transaction); + database.setTransactions(BackupItemParser.parseItems(root.get("transactions").getAsJsonArray(), BackupTransaction_v4.class)); + fixMissingIsExpenditure(database.getTransactions()); - parsedTransactions.add(transaction); - } + database.setTemplates(BackupItemParser.parseItems(root.get("templates").getAsJsonArray(), BackupTemplate_v4.class)); + fixMissingIsExpenditure(database.getTemplates()); - return parsedTransactions; + return database; } - protected List<Template> parseTemplates(JsonObject root) + private void fixMissingIsExpenditure(List<? extends BackupTransactionBase_v4> items) { - final List<Template> parsedTemplates = new ArrayList<>(); - final JsonArray templatesToImport = root.get("templates").getAsJsonArray(); - for(JsonElement currentTemplate : templatesToImport) + for(BackupTransactionBase_v4 item : items) { - final JsonObject templateObject = currentTemplate.getAsJsonObject(); - - final String templateName = templateObject.get("templateName").getAsString(); - - final Template template = new Template(); - template.setTemplateName(templateName); - template.setTags(super.parseTags(templateObject)); - - final JsonElement element = templateObject.get("amount"); - if(element != null) + if(item.getExpenditure() != null) { - template.setAmount(element.getAsInt()); + continue; } - final JsonElement name = templateObject.get("name"); - if(name != null) + if(item.getAmount() == null) { - template.setName(name.getAsString()); - } - - final JsonElement description = templateObject.get("description"); - if(description != null) - { - template.setDescription(description.getAsString()); - } - - final Optional<Integer> categoryOptional = parseIDOfElementIfExists(templateObject, "category"); - categoryOptional.ifPresent(integer -> template.setCategory(super.getCategoryByID(integer))); - - final Optional<Integer> accountOptional = parseIDOfElementIfExists(templateObject, "account"); - accountOptional.ifPresent(integer -> template.setAccount(super.getAccountByID(integer))); - - final Optional<Integer> transferAccountOptional = parseIDOfElementIfExists(templateObject, "transferAccount"); - transferAccountOptional.ifPresent(integer -> template.setTransferAccount(super.getAccountByID(integer))); - - handleIsExpenditure(templateObject, template); - - parsedTemplates.add(template); - } - - return parsedTemplates; - } - - protected Optional<Integer> parseIDOfElementIfExists(JsonObject jsonObject, String elementName) - { - final JsonElement element = jsonObject.get(elementName); - if(element != null) - { - return Optional.of(element.getAsJsonObject().get("ID").getAsInt()); - } - return Optional.empty(); - } - - protected void handleIsExpenditure(JsonObject jsonObject, TransactionBase transactionBase) - { - final JsonElement isExpenditure = jsonObject.get("isExpenditure"); - if(isExpenditure == null) - { - if(transactionBase.getAmount() == null) - { - transactionBase.setIsExpenditure(true); + item.setExpenditure(true); } else { - transactionBase.setIsExpenditure(transactionBase.getAmount() <= 0); + item.setExpenditure(item.getAmount() <= 0); } } - else - { - transactionBase.setIsExpenditure(isExpenditure.getAsBoolean()); - } } } \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v5.java b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v5.java index 39278f1404fe469cb73dbad0af8ee160fff9ec33..df94a65f4b97e9993308de920984f52997f99443 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v5.java +++ b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v5.java @@ -1,165 +1,33 @@ package de.deadlocker8.budgetmaster.database; -import com.google.gson.*; -import de.deadlocker8.budgetmaster.accounts.Account; -import de.deadlocker8.budgetmaster.accounts.AccountState; -import de.deadlocker8.budgetmaster.accounts.AccountType; -import de.deadlocker8.budgetmaster.charts.Chart; -import de.deadlocker8.budgetmaster.images.Image; -import de.deadlocker8.budgetmaster.templates.Template; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import de.deadlocker8.budgetmaster.database.model.v5.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -public class DatabaseParser_v5 extends DatabaseParser_v4 +public class DatabaseParser_v5 { - final Logger LOGGER = LoggerFactory.getLogger(this.getClass()); private final String jsonString; - protected List<Chart> charts; - protected List<Image> images; + private BackupDatabase_v5 database; public DatabaseParser_v5(String json) { - super(json); this.jsonString = json; + this.database = new BackupDatabase_v5(); } - @Override - public Database parseDatabaseFromJSON() throws IllegalArgumentException - { - final JsonObject root = JsonParser.parseString(jsonString).getAsJsonObject(); - - this.images = parseImages(root); - super.accounts = parseAccounts(root); - - super.categories = super.parseCategories(root); - super.transactions = super.parseTransactions(root); - - super.templates = parseTemplates(root); - - this.charts = parseCharts(root); - - return new Database(categories, accounts, transactions, templates, charts, images); - } - - @Override - protected List<Account> parseAccounts(JsonObject root) - { - List<Account> parsedAccounts = new ArrayList<>(); - JsonArray accounts = root.get("accounts").getAsJsonArray(); - for(JsonElement currentAccount : accounts) - { - final JsonObject accountObject = currentAccount.getAsJsonObject(); - Integer ID = accountObject.get("ID").getAsInt(); - String name = accountObject.get("name").getAsString(); - AccountType accountType = AccountType.valueOf(accountObject.get("type").getAsString()); - - AccountState accountState = AccountState.FULL_ACCESS; - if(accountObject.has("accountState")) - { - accountState = AccountState.valueOf(accountObject.get("accountState").getAsString()); - } - - Image icon = null; - if(accountObject.has("icon")) - { - final Integer iconID = accountObject.get("icon").getAsJsonObject().get("ID").getAsInt(); - icon = this.images.stream().filter(image -> image.getID().equals(iconID)).findFirst().orElseThrow(); - } - - Account parsedAccount = new Account(name, accountType, icon); - parsedAccount.setID(ID); - parsedAccount.setAccountState(accountState); - - parsedAccounts.add(parsedAccount); - } - - return parsedAccounts; - } - - protected List<Chart> parseCharts(JsonObject root) - { - List<Chart> parsedCharts = new ArrayList<>(); - - JsonArray chartsToImport = root.get("charts").getAsJsonArray(); - for(JsonElement currentChart : chartsToImport) - { - parsedCharts.add(new Gson().fromJson(currentChart, Chart.class)); - } - - return parsedCharts; - } - - protected List<Image> parseImages(JsonObject root) - { - List<Image> parsedImages = new ArrayList<>(); - - JsonArray imagesToImport = root.get("images").getAsJsonArray(); - for(JsonElement currentImage : imagesToImport) - { - parsedImages.add(new Gson().fromJson(currentImage, Image.class)); - } - - return parsedImages; - } - - @Override - protected List<Template> parseTemplates(JsonObject root) + public BackupDatabase_v5 parseDatabaseFromJSON() throws IllegalArgumentException { - final List<Template> parsedTemplates = new ArrayList<>(); - final JsonArray templatesToImport = root.get("templates").getAsJsonArray(); - for(JsonElement currentTemplate : templatesToImport) - { - final JsonObject templateObject = currentTemplate.getAsJsonObject(); - - final String templateName = templateObject.get("templateName").getAsString(); - - final Template template = new Template(); - template.setTemplateName(templateName); - template.setTags(super.parseTags(templateObject)); + database = new BackupDatabase_v5(); - final JsonElement element = templateObject.get("amount"); - if(element != null) - { - template.setAmount(element.getAsInt()); - } - - final JsonElement name = templateObject.get("name"); - if(name != null) - { - template.setName(name.getAsString()); - } - - final JsonElement description = templateObject.get("description"); - if(description != null) - { - template.setDescription(description.getAsString()); - } - - if(templateObject.has("icon")) - { - final Integer iconID = templateObject.get("icon").getAsJsonObject().get("ID").getAsInt(); - template.setIcon(this.images.stream().filter(image -> image.getID().equals(iconID)).findFirst().orElseThrow()); - } - - final Optional<Integer> categoryOptional = parseIDOfElementIfExists(templateObject, "category"); - categoryOptional.ifPresent(integer -> template.setCategory(super.getCategoryByID(integer))); - - final Optional<Integer> accountOptional = parseIDOfElementIfExists(templateObject, "account"); - accountOptional.ifPresent(integer -> template.setAccount(super.getAccountByID(integer))); - - final Optional<Integer> transferAccountOptional = parseIDOfElementIfExists(templateObject, "transferAccount"); - transferAccountOptional.ifPresent(integer -> template.setTransferAccount(super.getAccountByID(integer))); - - handleIsExpenditure(templateObject, template); - - parsedTemplates.add(template); - } - - return parsedTemplates; + final JsonObject root = JsonParser.parseString(jsonString).getAsJsonObject(); + database.setImages(BackupItemParser.parseItems(root.get("images").getAsJsonArray(), BackupImage_v5.class)); + database.setAccounts(BackupItemParser.parseItems(root.get("accounts").getAsJsonArray(), BackupAccount_v5.class)); + database.setCategories(BackupItemParser.parseItems(root.get("categories").getAsJsonArray(), BackupCategory_v5.class)); + database.setTransactions(BackupItemParser.parseItems(root.get("transactions").getAsJsonArray(), BackupTransaction_v5.class)); + database.setTemplates(BackupItemParser.parseItems(root.get("templates").getAsJsonArray(), BackupTemplate_v5.class)); + database.setCharts(BackupItemParser.parseItems(root.get("charts").getAsJsonArray(), BackupChart_v5.class)); + + return database; } } \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v6.java b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v6.java new file mode 100644 index 0000000000000000000000000000000000000000..1ed808a67416e5adf84e4c0c33456d137078e0cd --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseParser_v6.java @@ -0,0 +1,39 @@ +package de.deadlocker8.budgetmaster.database; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import de.deadlocker8.budgetmaster.database.model.v5.BackupCategory_v5; +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.BackupAccount_v6; +import de.deadlocker8.budgetmaster.database.model.v6.BackupDatabase_v6; +import de.deadlocker8.budgetmaster.database.model.v6.BackupTemplate_v6; +import de.deadlocker8.budgetmaster.database.model.v6.BackupTransaction_v6; + +public class DatabaseParser_v6 +{ + private final String jsonString; + + private BackupDatabase_v6 database; + + public DatabaseParser_v6(String json) + { + this.jsonString = json; + this.database = new BackupDatabase_v6(); + } + + public BackupDatabase_v6 parseDatabaseFromJSON() throws IllegalArgumentException + { + database = new BackupDatabase_v6(); + + final JsonObject root = JsonParser.parseString(jsonString).getAsJsonObject(); + database.setImages(BackupItemParser.parseItems(root.get("images").getAsJsonArray(), BackupImage_v5.class)); + database.setAccounts(BackupItemParser.parseItems(root.get("accounts").getAsJsonArray(), BackupAccount_v6.class)); + database.setCategories(BackupItemParser.parseItems(root.get("categories").getAsJsonArray(), BackupCategory_v5.class)); + database.setTransactions(BackupItemParser.parseItems(root.get("transactions").getAsJsonArray(), BackupTransaction_v6.class)); + database.setTemplates(BackupItemParser.parseItems(root.get("templates").getAsJsonArray(), BackupTemplate_v6.class)); + database.setCharts(BackupItemParser.parseItems(root.get("charts").getAsJsonArray(), BackupChart_v5.class)); + + return database; + } +} \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseService.java b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseService.java index eb87c103be50e7871278e7431395d15e219f19e2..d6f74c31cb40bde0ba419797ba646756dde4d59a 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseService.java +++ b/src/main/java/de/deadlocker8/budgetmaster/database/DatabaseService.java @@ -2,8 +2,6 @@ package de.deadlocker8.budgetmaster.database; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializer; import de.deadlocker8.budgetmaster.accounts.Account; import de.deadlocker8.budgetmaster.accounts.AccountService; import de.deadlocker8.budgetmaster.categories.Category; @@ -11,6 +9,8 @@ import de.deadlocker8.budgetmaster.categories.CategoryService; import de.deadlocker8.budgetmaster.charts.Chart; import de.deadlocker8.budgetmaster.charts.ChartService; import de.deadlocker8.budgetmaster.charts.ChartType; +import de.deadlocker8.budgetmaster.database.model.v5.BackupDatabase_v5; +import de.deadlocker8.budgetmaster.database.model.v6.BackupDatabase_v6; import de.deadlocker8.budgetmaster.images.Image; import de.deadlocker8.budgetmaster.images.ImageService; import de.deadlocker8.budgetmaster.repeating.RepeatingOption; @@ -22,7 +22,6 @@ import de.deadlocker8.budgetmaster.transactions.Transaction; import de.deadlocker8.budgetmaster.transactions.TransactionService; import de.thecodelabs.utils.io.PathUtils; import org.joda.time.DateTime; -import org.joda.time.format.ISODateTimeFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,10 +43,7 @@ import java.util.stream.Stream; @Service public class DatabaseService { - public static final Gson GSON = new GsonBuilder() - .excludeFieldsWithoutExposeAnnotation() - .registerTypeAdapter(DateTime.class, (JsonSerializer<DateTime>) (json, typeOfSrc, context) -> new JsonPrimitive(ISODateTimeFormat.date().print(json))) - .create(); + public static final Gson GSON = new GsonBuilder().create(); private static final Logger LOGGER = LoggerFactory.getLogger(DatabaseService.class); private final AccountService accountService; @@ -222,7 +218,7 @@ public class DatabaseService @Transactional public void exportDatabase(Path backupPath) { - final Database database = getDatabaseForJsonSerialization(); + final BackupDatabase_v6 database = getDatabaseForJsonSerialization(); try(Writer writer = new FileWriter(backupPath.toString())) { @@ -247,7 +243,7 @@ public class DatabaseService return "BudgetMasterDatabase_" + DateTime.now().toString(formatString) + ".json"; } - public Database getDatabaseForJsonSerialization() + public BackupDatabase_v6 getDatabaseForJsonSerialization() { List<Category> categories = categoryService.getAllEntitiesAsc(); List<Account> accounts = accountService.getRepository().findAll(); @@ -258,9 +254,12 @@ public class DatabaseService List<Image> images = imageService.getRepository().findAll(); LOGGER.debug(MessageFormat.format("Reduced {0} transactions to {1}", transactions.size(), filteredTransactions.size())); - Database database = new Database(categories, accounts, filteredTransactions, templates, charts, images); + InternalDatabase database = new InternalDatabase(categories, accounts, filteredTransactions, templates, charts, images); LOGGER.debug(MessageFormat.format("Created database for JSON with {0} transactions, {1} categories, {2} accounts, {3} templates, {4} charts and {5} images", database.getTransactions().size(), database.getCategories().size(), database.getAccounts().size(), database.getTemplates().size(), database.getCharts().size(), database.getImages())); - return database; + + BackupDatabase_v6 databaseInExternalForm = BackupDatabase_v6.createFromInternalEntities(database); + LOGGER.debug("Converted database to external form"); + return databaseInExternalForm; } private List<Transaction> filterRepeatingTransactions(List<Transaction> transactions) diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/Database.java b/src/main/java/de/deadlocker8/budgetmaster/database/InternalDatabase.java similarity index 83% rename from src/main/java/de/deadlocker8/budgetmaster/database/Database.java rename to src/main/java/de/deadlocker8/budgetmaster/database/InternalDatabase.java index 15ead6533389c1255a8ee1378ca04be99627cd6c..a3a1f0d6d693aa5c114c93e41bb6fff3775b45b5 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/database/Database.java +++ b/src/main/java/de/deadlocker8/budgetmaster/database/InternalDatabase.java @@ -1,6 +1,5 @@ package de.deadlocker8.budgetmaster.database; -import com.google.gson.annotations.Expose; import de.deadlocker8.budgetmaster.accounts.Account; import de.deadlocker8.budgetmaster.accounts.AccountType; import de.deadlocker8.budgetmaster.categories.Category; @@ -15,37 +14,20 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -public class Database +public class InternalDatabase { - @Expose - private final String TYPE = "BUDGETMASTER_DATABASE"; - - @Expose - private final int VERSION = 5; - - @Expose private List<Category> categories; - - @Expose private List<Account> accounts; - - @Expose private List<Transaction> transactions; - - @Expose private List<Template> templates; - - @Expose private List<Chart> charts; - - @Expose private List<Image> images; - public Database() + public InternalDatabase() { } - public Database(List<Category> categories, List<Account> accounts, List<Transaction> transactions, List<Template> templates, List<Chart> charts, List<Image> images) + public InternalDatabase(List<Category> categories, List<Account> accounts, List<Transaction> transactions, List<Template> templates, List<Chart> charts, List<Image> images) { this.categories = categories; this.accounts = accounts; diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/legacy/LegacyParser.java b/src/main/java/de/deadlocker8/budgetmaster/database/legacy/LegacyParser.java deleted file mode 100644 index 372c8ccd3b15e54e0b6d18ed177984e0f5e88419..0000000000000000000000000000000000000000 --- a/src/main/java/de/deadlocker8/budgetmaster/database/legacy/LegacyParser.java +++ /dev/null @@ -1,255 +0,0 @@ -package de.deadlocker8.budgetmaster.database.legacy; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import de.deadlocker8.budgetmaster.database.Database; -import de.deadlocker8.budgetmaster.accounts.Account; -import de.deadlocker8.budgetmaster.accounts.AccountType; -import de.deadlocker8.budgetmaster.categories.Category; -import de.deadlocker8.budgetmaster.categories.CategoryType; -import de.deadlocker8.budgetmaster.transactions.Transaction; -import de.deadlocker8.budgetmaster.repeating.RepeatingOption; -import de.deadlocker8.budgetmaster.repeating.endoption.RepeatingEndDate; -import de.deadlocker8.budgetmaster.repeating.endoption.RepeatingEndNever; -import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierDays; -import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierMonths; -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -@SuppressWarnings("deprecation") -public class LegacyParser -{ - private final String DATE_FORMAT = "yyyy-MM-dd"; - - private Account account; - private String jsonString; - private List<Category> categories; - private List<Tag> tags; - private List<TagMatch> tagMatches; - private Category categoryNone; - - public LegacyParser(String json, Category categoryNone) - { - this.jsonString = json; - this.account = new Account("LEGACY_IMPORT", AccountType.CUSTOM); - this.categoryNone = categoryNone; - } - - public Database parseDatabaseFromJSON() - { - JsonObject root = JsonParser.parseString(jsonString).getAsJsonObject(); - categories = new ArrayList<>(parseCategories(root)); - tags = parseTags(root); - tagMatches = parseTagMatches(root); - List<Transaction> transactions = parsePayments(root); - - List<Account> accounts = new ArrayList<>(); - accounts.add(account); - - return new Database(categories, accounts, transactions, new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); - } - - private Set<Category> parseCategories(JsonObject root) - { - Set<Category> parsedCategories = new HashSet<>(); - JsonArray jsonCategories = root.get("categories").getAsJsonArray(); - for(JsonElement currentCategory : jsonCategories) - { - int ID = currentCategory.getAsJsonObject().get("ID").getAsInt(); - String name = currentCategory.getAsJsonObject().get("name").getAsString(); - String color = currentCategory.getAsJsonObject().get("color").getAsString(); - - if(name.equals("NONE") || name.equals("Übertrag")|| name.equals("Rest")) - { - continue; - } - - Category category = new Category(name, color, CategoryType.CUSTOM); - category.setID(ID); - parsedCategories.add(category); - } - - return parsedCategories; - } - - private List<Tag> parseTags(JsonObject root) - { - List<Tag> parsedTags = new ArrayList<>(); - JsonArray jsonTags = root.get("tags").getAsJsonArray(); - for(JsonElement currentTag : jsonTags) - { - int ID = currentTag.getAsJsonObject().get("ID").getAsInt(); - String name = currentTag.getAsJsonObject().get("name").getAsString(); - - parsedTags.add(new Tag(ID, name)); - } - - return parsedTags; - } - - private List<TagMatch> parseTagMatches(JsonObject root) - { - List<TagMatch> parsedTagMatches = new ArrayList<>(); - JsonArray jsonTagMatches = root.get("tagMatches").getAsJsonArray(); - for(JsonElement currentTagMatch : jsonTagMatches) - { - int tagID = currentTagMatch.getAsJsonObject().get("tagID").getAsInt(); - int paymentID = currentTagMatch.getAsJsonObject().get("paymentID").getAsInt(); - int repeatingPaymentID = currentTagMatch.getAsJsonObject().get("repeatingPaymentID").getAsInt(); - - parsedTagMatches.add(new TagMatch(getTagByID(tagID).getName(), paymentID, repeatingPaymentID)); - } - - return parsedTagMatches; - } - - private List<Transaction> parsePayments(JsonObject root) - { - List<Transaction> parsedTransactions = new ArrayList<>(); - parsedTransactions.addAll(parseNormalPayments(root)); - parsedTransactions.addAll(parseRepeatingPayments(root)); - - return parsedTransactions; - } - - private List<Transaction> parseNormalPayments(JsonObject root) - { - List<Transaction> parsedTransactions = new ArrayList<>(); - JsonArray payments = root.get("normalPayments").getAsJsonArray(); - for(JsonElement currentPayment : payments) - { - int ID = currentPayment.getAsJsonObject().get("ID").getAsInt(); - int amount = currentPayment.getAsJsonObject().get("amount").getAsInt(); - String date = currentPayment.getAsJsonObject().get("date").getAsString(); - int categoryID = currentPayment.getAsJsonObject().get("categoryID").getAsInt(); - String name = currentPayment.getAsJsonObject().get("name").getAsString(); - String description = currentPayment.getAsJsonObject().get("description").getAsString(); - - Transaction transaction = new Transaction(); - transaction.setAmount(amount); - transaction.setName(name); - transaction.setDescription(description); - transaction.setCategory(getCategoryByID(categoryID)); - transaction.setAccount(account); - transaction.setRepeatingOption(null); - transaction.setTags(getTagsByPaymentID(ID)); - - DateTime parsedDate = DateTime.parse(date, DateTimeFormat.forPattern(DATE_FORMAT)); - transaction.setDate(parsedDate); - - parsedTransactions.add(transaction); - } - - return parsedTransactions; - } - - private List<Transaction> parseRepeatingPayments(JsonObject root) - { - List<Transaction> parsedTransactions = new ArrayList<>(); - JsonArray payments = root.get("repeatingPayments").getAsJsonArray(); - for(JsonElement currentPayment : payments) - { - int ID = currentPayment.getAsJsonObject().get("ID").getAsInt(); - int amount = currentPayment.getAsJsonObject().get("amount").getAsInt(); - String date = currentPayment.getAsJsonObject().get("date").getAsString(); - int categoryID = currentPayment.getAsJsonObject().get("categoryID").getAsInt(); - String name = currentPayment.getAsJsonObject().get("name").getAsString(); - String description = currentPayment.getAsJsonObject().get("description").getAsString(); - - Transaction transaction = new Transaction(); - transaction.setAmount(amount); - transaction.setName(name); - transaction.setDescription(description); - transaction.setCategory(getCategoryByID(categoryID)); - transaction.setTags(getTagsByPaymentID(ID)); - transaction.setAccount(account); - - DateTime parsedDate = DateTime.parse(date, DateTimeFormat.forPattern(DATE_FORMAT)); - transaction.setDate(parsedDate); - - transaction.setRepeatingOption(parseRepeatingOption(currentPayment.getAsJsonObject(), parsedDate)); - - parsedTransactions.add(transaction); - } - - return parsedTransactions; - } - - private RepeatingOption parseRepeatingOption(JsonObject repeatingPayment, DateTime startDate) - { - RepeatingOption repeatingOption = new RepeatingOption(); - repeatingOption.setStartDate(startDate); - - // end option - if(repeatingPayment.has("repeatEndDate")) - { - String repeatEndDate = repeatingPayment.get("repeatEndDate").getAsString(); - repeatingOption.setEndOption(new RepeatingEndDate(DateTime.parse(repeatEndDate, DateTimeFormat.forPattern(DATE_FORMAT)))); - } - else - { - repeatingOption.setEndOption(new RepeatingEndNever()); - } - - // modifier - int repeatMonthDay = repeatingPayment.get("repeatMonthDay").getAsInt(); - if(repeatMonthDay == 0) - { - int repeatInterval = repeatingPayment.get("repeatInterval").getAsInt(); - repeatingOption.setModifier(new RepeatingModifierDays(repeatInterval)); - } - else - { - repeatingOption.setModifier(new RepeatingModifierMonths(1)); - } - - return repeatingOption; - } - - private Category getCategoryByID(int ID) - { - for(Category category : categories) - { - if(category.getID() == ID) - { - return category; - } - } - - return categoryNone; - } - - private Tag getTagByID(int ID) - { - for(Tag tag : tags) - { - if(tag.getID() == ID) - { - return tag; - } - } - - return null; - } - - private List<de.deadlocker8.budgetmaster.tags.Tag> getTagsByPaymentID(int paymentID) - { - List<de.deadlocker8.budgetmaster.tags.Tag> paymentTags = new ArrayList<>(); - for(TagMatch tagMatch : tagMatches) - { - if(tagMatch.getPaymentID() == paymentID) - { - paymentTags.add(new de.deadlocker8.budgetmaster.tags.Tag(tagMatch.getTagName())); - } - } - - return paymentTags; - } -} \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/legacy/Tag.java b/src/main/java/de/deadlocker8/budgetmaster/database/legacy/Tag.java deleted file mode 100644 index f3336919863e385f0ee6b3e6809fd89be568457e..0000000000000000000000000000000000000000 --- a/src/main/java/de/deadlocker8/budgetmaster/database/legacy/Tag.java +++ /dev/null @@ -1,24 +0,0 @@ -package de.deadlocker8.budgetmaster.database.legacy; - -@Deprecated -public class Tag -{ - private int ID; - private String name; - - public Tag(int ID, String name) - { - this.ID = ID; - this.name = name; - } - - public int getID() - { - return ID; - } - - public String getName() - { - return name; - } -} \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/legacy/TagMatch.java b/src/main/java/de/deadlocker8/budgetmaster/database/legacy/TagMatch.java deleted file mode 100644 index 516e4848c566f50f30c455d36ab2f9896fe8311b..0000000000000000000000000000000000000000 --- a/src/main/java/de/deadlocker8/budgetmaster/database/legacy/TagMatch.java +++ /dev/null @@ -1,36 +0,0 @@ -package de.deadlocker8.budgetmaster.database.legacy; - -@Deprecated -public class TagMatch -{ - private String tagName; - private int paymentID; - private int repeatingPaymentID; - - public TagMatch(String tagName, int paymentID, int repeatingPaymentID) - { - this.tagName = tagName; - this.paymentID = paymentID; - this.repeatingPaymentID = repeatingPaymentID; - } - - public String getTagName() - { - return tagName; - } - - public void setTagName(String tagName) - { - this.tagName = tagName; - } - - public int getPaymentID() - { - return paymentID; - } - - public int getRepeatingPaymentID() - { - return repeatingPaymentID; - } -} \ No newline at end of file diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/BackupDatabase.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/BackupDatabase.java new file mode 100644 index 0000000000000000000000000000000000000000..07a2070f75ce187f07ec1b40a508992a030535ac --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/BackupDatabase.java @@ -0,0 +1,45 @@ +package de.deadlocker8.budgetmaster.database.model; + +import de.deadlocker8.budgetmaster.database.InternalDatabase; + +import java.util.ArrayList; +import java.util.List; + +public interface BackupDatabase +{ + int getVersion(); + + BackupDatabase upgrade(); + + InternalDatabase convertToInternal(); + + default <T> List<T> upgradeItems(List<? extends Upgradeable<T>> items) + { + List<T> upgradedItems = new ArrayList<>(); + for(Upgradeable<T> item : items) + { + upgradedItems.add(item.upgrade()); + } + return upgradedItems; + } + + default <T, S> List<T> convertItemsToInternal(List<S> backupItems, Converter<T, S> converter) + { + List<T> convertedItems = new ArrayList<>(); + for(S backupItem : backupItems) + { + convertedItems.add(converter.convertToInternalForm(backupItem)); + } + return convertedItems; + } + + default <T, S> List<S> convertItemsToExternal(List<T> backupItems, Converter<T, S> converter) + { + List<S> convertedItems = new ArrayList<>(); + for(T backupItem : backupItems) + { + convertedItems.add(converter.convertToExternalForm(backupItem)); + } + return convertedItems; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/Converter.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/Converter.java new file mode 100644 index 0000000000000000000000000000000000000000..a48e7e8745c7f6f22adf4d7a3e9ad919550858d7 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/Converter.java @@ -0,0 +1,19 @@ +package de.deadlocker8.budgetmaster.database.model; + +import de.deadlocker8.budgetmaster.utils.ProvidesID; + +import java.util.List; + +public interface Converter<T, S> +{ + T convertToInternalForm(S backupItem); + + S convertToExternalForm(T internalItem); + + default <U extends ProvidesID> U getItemById(List<U> items, Integer ID) + { + return items.stream() + .filter(item -> item.getID().equals(ID)) + .findFirst().orElse(null); + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/Upgradeable.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/Upgradeable.java new file mode 100644 index 0000000000000000000000000000000000000000..4da81d2064df374be9b07025b9d734ee232ccc84 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/Upgradeable.java @@ -0,0 +1,6 @@ +package de.deadlocker8.budgetmaster.database.model; + +public interface Upgradeable<T> +{ + T upgrade(); +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/AccountConverter.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/AccountConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..0c1d1c851de8171b562777ea0d4bfaebbb4c7a23 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/AccountConverter.java @@ -0,0 +1,64 @@ +package de.deadlocker8.budgetmaster.database.model.converter; + +import de.deadlocker8.budgetmaster.accounts.Account; +import de.deadlocker8.budgetmaster.database.model.Converter; +import de.deadlocker8.budgetmaster.database.model.v6.BackupAccount_v6; +import de.deadlocker8.budgetmaster.images.Image; + +import java.util.List; + +public class AccountConverter implements Converter<Account, BackupAccount_v6> +{ + private final List<Image> availableIcons; + + public AccountConverter(List<Image> availableIcons) + { + this.availableIcons = availableIcons; + } + + public Account convertToInternalForm(BackupAccount_v6 backupAccount) + { + if(backupAccount == null) + { + return null; + } + + final Account account = new Account(); + account.setID(backupAccount.getID()); + account.setName(backupAccount.getName()); + account.setDefault(false); + account.setSelected(false); + account.setAccountState(backupAccount.getAccountState()); + account.setType(backupAccount.getType()); + account.setIcon(getIconById(backupAccount.getIconID())); + return account; + } + + private Image getIconById(Integer iconID) + { + return availableIcons.stream() + .filter(icon -> icon.getID().equals(iconID)) + .findFirst().orElse(null); + } + + @Override + public BackupAccount_v6 convertToExternalForm(Account internalAccount) + { + if(internalAccount == null) + { + return null; + } + + final BackupAccount_v6 account = new BackupAccount_v6(); + account.setID(internalAccount.getID()); + account.setName(internalAccount.getName()); + account.setAccountState(internalAccount.getAccountState()); + account.setType(internalAccount.getType()); + + if(internalAccount.getIcon() != null) + { + account.setIconID(internalAccount.getIcon().getID()); + } + return account; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/CategoryConverter.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/CategoryConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..51c40bc0306a5e2b295c2b107bf6b7d2dd30a8f5 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/CategoryConverter.java @@ -0,0 +1,41 @@ +package de.deadlocker8.budgetmaster.database.model.converter; + +import de.deadlocker8.budgetmaster.categories.Category; +import de.deadlocker8.budgetmaster.database.model.Converter; +import de.deadlocker8.budgetmaster.database.model.v5.BackupCategory_v5; + +public class CategoryConverter implements Converter<Category, BackupCategory_v5> +{ + public Category convertToInternalForm(BackupCategory_v5 backupCategory) + { + if(backupCategory == null) + { + return null; + } + + final Category category = new Category(); + category.setID(backupCategory.getID()); + category.setName(backupCategory.getName()); + category.setColor(backupCategory.getColor()); + category.setType(backupCategory.getType()); + category.setIcon(backupCategory.getIcon()); + return category; + } + + @Override + public BackupCategory_v5 convertToExternalForm(Category internalItem) + { + if(internalItem == null) + { + return null; + } + + final BackupCategory_v5 category = new BackupCategory_v5(); + category.setID(internalItem.getID()); + category.setName(internalItem.getName()); + category.setColor(internalItem.getColor()); + category.setType(internalItem.getType()); + category.setIcon(internalItem.getIcon()); + return category; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/ChartConverter.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/ChartConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..77525beb6d89e44b8a7337ab4ae65537598acc97 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/ChartConverter.java @@ -0,0 +1,41 @@ +package de.deadlocker8.budgetmaster.database.model.converter; + +import de.deadlocker8.budgetmaster.charts.Chart; +import de.deadlocker8.budgetmaster.database.model.Converter; +import de.deadlocker8.budgetmaster.database.model.v5.BackupChart_v5; + +public class ChartConverter implements Converter<Chart, BackupChart_v5> +{ + public Chart convertToInternalForm(BackupChart_v5 backupChart) + { + if(backupChart == null) + { + return null; + } + + final Chart chart = new Chart(); + chart.setID(backupChart.getID()); + chart.setName(backupChart.getName()); + chart.setType(backupChart.getType()); + chart.setVersion(backupChart.getVersion()); + chart.setScript(backupChart.getScript()); + return chart; + } + + @Override + public BackupChart_v5 convertToExternalForm(Chart internalItem) + { + if(internalItem == null) + { + return null; + } + + final BackupChart_v5 chart = new BackupChart_v5(); + chart.setID(internalItem.getID()); + chart.setName(internalItem.getName()); + chart.setType(internalItem.getType()); + chart.setVersion(internalItem.getVersion()); + chart.setScript(internalItem.getScript()); + return chart; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/ImageConverter.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/ImageConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..22ce5df09dcca1650a05c31e971e3bc8df5d4573 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/ImageConverter.java @@ -0,0 +1,39 @@ +package de.deadlocker8.budgetmaster.database.model.converter; + +import de.deadlocker8.budgetmaster.database.model.Converter; +import de.deadlocker8.budgetmaster.database.model.v5.BackupImage_v5; +import de.deadlocker8.budgetmaster.images.Image; + +public class ImageConverter implements Converter<Image, BackupImage_v5> +{ + public Image convertToInternalForm(BackupImage_v5 backupImage) + { + if(backupImage == null) + { + return null; + } + + final Image image = new Image(); + image.setID(backupImage.getID()); + image.setFileName(backupImage.getFileName()); + image.setFileExtension(backupImage.getFileExtension()); + image.setImage(backupImage.getImage()); + return image; + } + + @Override + public BackupImage_v5 convertToExternalForm(Image internalItem) + { + if(internalItem == null) + { + return null; + } + + final BackupImage_v5 image = new BackupImage_v5(); + image.setID(internalItem.getID()); + image.setFileName(internalItem.getFileName()); + image.setFileExtension(internalItem.getFileExtension()); + image.setImage(internalItem.getImage()); + return image; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/RepeatingEndOptionConverter.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/RepeatingEndOptionConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..d4190ccfd5fdb7958b82efd4956365e29378c49f --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/RepeatingEndOptionConverter.java @@ -0,0 +1,66 @@ +package de.deadlocker8.budgetmaster.database.model.converter; + +import de.deadlocker8.budgetmaster.database.model.Converter; +import de.deadlocker8.budgetmaster.database.model.v4.BackupRepeatingEndOption_v4; +import de.deadlocker8.budgetmaster.repeating.endoption.*; +import de.thecodelabs.utils.util.Localization; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; + +public class RepeatingEndOptionConverter implements Converter<RepeatingEnd, BackupRepeatingEndOption_v4> +{ + @Override + public RepeatingEnd convertToInternalForm(BackupRepeatingEndOption_v4 backupItem) + { + if(backupItem == null) + { + return null; + } + + RepeatingEnd endOption = null; + RepeatingEndType endType = RepeatingEndType.getByLocalization(Localization.getString(backupItem.getLocalizationKey())); + switch(endType) + { + case NEVER: + endOption = new RepeatingEndNever(); + break; + case AFTER_X_TIMES: + endOption = new RepeatingEndAfterXTimes(backupItem.getTimes()); + break; + case DATE: + DateTime endDate = DateTime.parse(backupItem.getEndDate(), DateTimeFormat.forPattern("yyyy-MM-dd")); + endDate = endDate.withHourOfDay(12).withMinuteOfHour(0).withSecondOfMinute(0); + endOption = new RepeatingEndDate(endDate); + break; + } + + return endOption; + } + + @Override + public BackupRepeatingEndOption_v4 convertToExternalForm(RepeatingEnd internalItem) + { + if(internalItem == null) + { + return null; + } + + final BackupRepeatingEndOption_v4 repeatingEndOption = new BackupRepeatingEndOption_v4(); + repeatingEndOption.setLocalizationKey(internalItem.getLocalizationKey()); + + if(internalItem instanceof RepeatingEndDate) + { + RepeatingEndDate repeatingEndDate = (RepeatingEndDate) internalItem; + final DateTime endDate = (DateTime) repeatingEndDate.getValue(); + repeatingEndOption.setEndDate(endDate.toString(DateTimeFormat.forPattern("yyyy-MM-dd"))); + } + + if(internalItem instanceof RepeatingEndAfterXTimes) + { + RepeatingEndAfterXTimes repeatingEndAfterXTimes = (RepeatingEndAfterXTimes) internalItem; + repeatingEndOption.setTimes((int) repeatingEndAfterXTimes.getValue()); + } + + return repeatingEndOption; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/RepeatingModifierConverter.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/RepeatingModifierConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..189a67ea75f75fdb7b6fe9856bf1ff11afb50bf7 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/RepeatingModifierConverter.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.v4.BackupRepeatingModifier_v4; +import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifier; +import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierType; +import de.thecodelabs.utils.util.Localization; + +public class RepeatingModifierConverter implements Converter<RepeatingModifier, BackupRepeatingModifier_v4> +{ + @Override + public RepeatingModifier convertToInternalForm(BackupRepeatingModifier_v4 backupItem) + { + if(backupItem == null) + { + return null; + } + + RepeatingModifierType type = RepeatingModifierType.getByLocalization(Localization.getString(backupItem.getLocalizationKey())); + return RepeatingModifier.fromModifierType(type, backupItem.getQuantity()); + } + + @Override + public BackupRepeatingModifier_v4 convertToExternalForm(RepeatingModifier internalItem) + { + if(internalItem == null) + { + return null; + } + + return new BackupRepeatingModifier_v4(internalItem.getQuantity(), internalItem.getLocalizationKey()); + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/RepeatingOptionConverter.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/RepeatingOptionConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..06ab54dea48444a37afcfa9911b05a2968341da0 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/RepeatingOptionConverter.java @@ -0,0 +1,44 @@ +package de.deadlocker8.budgetmaster.database.model.converter; + +import de.deadlocker8.budgetmaster.database.model.Converter; +import de.deadlocker8.budgetmaster.database.model.v4.BackupRepeatingOption_v4; +import de.deadlocker8.budgetmaster.repeating.RepeatingOption; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; + +public class RepeatingOptionConverter implements Converter<RepeatingOption, BackupRepeatingOption_v4> +{ + @Override + public RepeatingOption convertToInternalForm(BackupRepeatingOption_v4 backupItem) + { + if(backupItem == null) + { + return null; + } + + final RepeatingOption repeatingOption = new RepeatingOption(); + + DateTime startDate = DateTime.parse(backupItem.getStartDate(), DateTimeFormat.forPattern("yyyy-MM-dd")); + startDate = startDate.withHourOfDay(12).withMinuteOfHour(0).withSecondOfMinute(0); + repeatingOption.setStartDate(startDate); + + repeatingOption.setModifier(new RepeatingModifierConverter().convertToInternalForm(backupItem.getModifier())); + repeatingOption.setEndOption(new RepeatingEndOptionConverter().convertToInternalForm(backupItem.getEndOption())); + return repeatingOption; + } + + @Override + public BackupRepeatingOption_v4 convertToExternalForm(RepeatingOption internalItem) + { + if(internalItem == null) + { + return null; + } + + final BackupRepeatingOption_v4 repeatingOption = new BackupRepeatingOption_v4(); + repeatingOption.setStartDate(internalItem.getStartDate().toString(DateTimeFormat.forPattern("yyyy-MM-dd"))); + repeatingOption.setModifier(new RepeatingModifierConverter().convertToExternalForm(internalItem.getModifier())); + repeatingOption.setEndOption(new RepeatingEndOptionConverter().convertToExternalForm(internalItem.getEndOption())); + return repeatingOption; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/TagConverter.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/TagConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..caf5a059924e5fcccb2fa8243e6206a96dff1520 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/TagConverter.java @@ -0,0 +1,29 @@ +package de.deadlocker8.budgetmaster.database.model.converter; + +import de.deadlocker8.budgetmaster.database.model.Converter; +import de.deadlocker8.budgetmaster.database.model.v4.BackupTag_v4; +import de.deadlocker8.budgetmaster.tags.Tag; + +public class TagConverter implements Converter<Tag, BackupTag_v4> +{ + public Tag convertToInternalForm(BackupTag_v4 backupTag) + { + if(backupTag == null) + { + return null; + } + + return new Tag(backupTag.getName()); + } + + @Override + public BackupTag_v4 convertToExternalForm(Tag internalItem) + { + if(internalItem == null) + { + return null; + } + + return new BackupTag_v4(internalItem.getName()); + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/TemplateConverter.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/TemplateConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..f1374ae3d7c300ac0dd9e20e66282056662df7b4 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/TemplateConverter.java @@ -0,0 +1,112 @@ +package de.deadlocker8.budgetmaster.database.model.converter; + +import de.deadlocker8.budgetmaster.accounts.Account; +import de.deadlocker8.budgetmaster.categories.Category; +import de.deadlocker8.budgetmaster.database.model.Converter; +import de.deadlocker8.budgetmaster.database.model.v4.BackupTag_v4; +import de.deadlocker8.budgetmaster.database.model.v6.BackupTemplate_v6; +import de.deadlocker8.budgetmaster.images.Image; +import de.deadlocker8.budgetmaster.tags.Tag; +import de.deadlocker8.budgetmaster.templates.Template; + +import java.util.ArrayList; +import java.util.List; + +public class TemplateConverter implements Converter<Template, BackupTemplate_v6> +{ + private final List<Image> availableIcons; + private final List<Category> availableCategories; + private final List<Account> availableAccounts; + + public TemplateConverter(List<Image> availableIcons, List<Category> availableCategories, List<Account> availableAccounts) + { + this.availableIcons = availableIcons; + this.availableCategories = availableCategories; + this.availableAccounts = availableAccounts; + } + + public Template convertToInternalForm(BackupTemplate_v6 backupTemplate) + { + if(backupTemplate == null) + { + return null; + } + + final Template template = new Template(); + template.setAmount(backupTemplate.getAmount()); + template.setName(backupTemplate.getName()); + template.setCategory(getItemById(availableCategories, backupTemplate.getCategoryID())); + template.setDescription(backupTemplate.getDescription()); + + if(backupTemplate.getExpenditure() == null) + { + template.setIsExpenditure(true); + } + else + { + template.setIsExpenditure(backupTemplate.getExpenditure()); + } + + template.setAccount(getItemById(availableAccounts, backupTemplate.getAccountID())); + template.setTransferAccount(getItemById(availableAccounts, backupTemplate.getTransferAccountID())); + + List<Tag> convertedTags = new ArrayList<>(); + TagConverter tagConverter = new TagConverter(); + for(BackupTag_v4 tag : backupTemplate.getTags()) + { + convertedTags.add(tagConverter.convertToInternalForm(tag)); + } + template.setTags(convertedTags); + + template.setTemplateName(backupTemplate.getTemplateName()); + template.setIcon(getItemById(availableIcons, backupTemplate.getIconID())); + return template; + } + + @Override + public BackupTemplate_v6 convertToExternalForm(Template internalItem) + { + if(internalItem == null) + { + return null; + } + + final BackupTemplate_v6 template = new BackupTemplate_v6(); + template.setAmount(internalItem.getAmount()); + template.setName(internalItem.getName()); + + if(internalItem.getCategory() != null) + { + template.setCategoryID(internalItem.getCategory().getID()); + } + + template.setDescription(internalItem.getDescription()); + template.setExpenditure(internalItem.getExpenditure()); + + if(internalItem.getAccount() != null) + { + template.setAccountID(internalItem.getAccount().getID()); + } + + if(internalItem.getTransferAccount() != null) + { + template.setTransferAccountID(internalItem.getTransferAccount().getID()); + } + + List<BackupTag_v4> convertedTags = new ArrayList<>(); + TagConverter tagConverter = new TagConverter(); + for(Tag tag : internalItem.getTags()) + { + convertedTags.add(tagConverter.convertToExternalForm(tag)); + } + template.setTags(convertedTags); + + template.setTemplateName(internalItem.getTemplateName()); + + if(internalItem.getIcon() != null) + { + template.setIconID(internalItem.getIcon().getID()); + } + return template; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/TransactionConverter.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/TransactionConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..d923ce5fe8c954f3104c7f496c8d951971f306f6 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/converter/TransactionConverter.java @@ -0,0 +1,93 @@ +package de.deadlocker8.budgetmaster.database.model.converter; + +import de.deadlocker8.budgetmaster.accounts.Account; +import de.deadlocker8.budgetmaster.categories.Category; +import de.deadlocker8.budgetmaster.database.model.Converter; +import de.deadlocker8.budgetmaster.database.model.v4.BackupTag_v4; +import de.deadlocker8.budgetmaster.database.model.v6.BackupTransaction_v6; +import de.deadlocker8.budgetmaster.tags.Tag; +import de.deadlocker8.budgetmaster.transactions.Transaction; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; + +import java.util.ArrayList; +import java.util.List; + +public class TransactionConverter implements Converter<Transaction, BackupTransaction_v6> +{ + private final List<Category> availableCategories; + private final List<Account> availableAccounts; + + public TransactionConverter(List<Category> availableCategories, List<Account> availableAccounts) + { + this.availableCategories = availableCategories; + this.availableAccounts = availableAccounts; + } + + public Transaction convertToInternalForm(BackupTransaction_v6 backupTransaction) + { + if(backupTransaction == null) + { + return null; + } + + final Transaction transaction = new Transaction(); + transaction.setAmount(backupTransaction.getAmount()); + transaction.setName(backupTransaction.getName()); + transaction.setCategory(getItemById(availableCategories, backupTransaction.getCategoryID())); + transaction.setDescription(backupTransaction.getDescription()); + transaction.setIsExpenditure(backupTransaction.getExpenditure()); + transaction.setAccount(getItemById(availableAccounts, backupTransaction.getAccountID())); + transaction.setTransferAccount(getItemById(availableAccounts, backupTransaction.getTransferAccountID())); + + DateTime date = DateTime.parse(backupTransaction.getDate(), DateTimeFormat.forPattern("yyyy-MM-dd")); + date = date.withHourOfDay(12).withMinuteOfHour(0).withSecondOfMinute(0); + transaction.setDate(date); + + List<Tag> convertedTags = new ArrayList<>(); + TagConverter tagConverter = new TagConverter(); + for(BackupTag_v4 tag : backupTransaction.getTags()) + { + convertedTags.add(tagConverter.convertToInternalForm(tag)); + } + transaction.setTags(convertedTags); + + transaction.setRepeatingOption(new RepeatingOptionConverter().convertToInternalForm(backupTransaction.getRepeatingOption())); + return transaction; + } + + @Override + public BackupTransaction_v6 convertToExternalForm(Transaction internalItem) + { + if(internalItem == null) + { + return null; + } + + final BackupTransaction_v6 transaction = new BackupTransaction_v6(); + transaction.setAmount(internalItem.getAmount()); + transaction.setName(internalItem.getName()); + transaction.setCategoryID(internalItem.getCategory().getID()); + transaction.setDescription(internalItem.getDescription()); + transaction.setExpenditure(internalItem.getExpenditure()); + transaction.setAccountID(internalItem.getAccount().getID()); + + if(internalItem.getTransferAccount() != null) + { + transaction.setTransferAccountID(internalItem.getTransferAccount().getID()); + } + + transaction.setDate(internalItem.getDate().toString(DateTimeFormat.forPattern("yyyy-MM-dd"))); + + List<BackupTag_v4> convertedTags = new ArrayList<>(); + TagConverter tagConverter = new TagConverter(); + for(Tag tag : internalItem.getTags()) + { + convertedTags.add(tagConverter.convertToExternalForm(tag)); + } + transaction.setTags(convertedTags); + + transaction.setRepeatingOption(new RepeatingOptionConverter().convertToExternalForm(internalItem.getRepeatingOption())); + return transaction; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupAccount_v4.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupAccount_v4.java new file mode 100644 index 0000000000000000000000000000000000000000..a6c890fb16ed59c26548c51ed63223e5952cf406 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupAccount_v4.java @@ -0,0 +1,88 @@ +package de.deadlocker8.budgetmaster.database.model.v4; + +import de.deadlocker8.budgetmaster.accounts.AccountState; +import de.deadlocker8.budgetmaster.accounts.AccountType; +import de.deadlocker8.budgetmaster.database.model.Upgradeable; +import de.deadlocker8.budgetmaster.database.model.v5.BackupAccount_v5; + +import java.util.Objects; + +public class BackupAccount_v4 implements Upgradeable<BackupAccount_v5> +{ + private Integer ID; + private String name; + private AccountType type; + + public BackupAccount_v4() + { + // for GSON + } + + public BackupAccount_v4(Integer ID, String name, AccountType type) + { + this.ID = ID; + this.name = name; + this.type = type; + } + + public Integer getID() + { + return ID; + } + + public void setID(Integer ID) + { + this.ID = ID; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + + public AccountType getType() + { + return type; + } + + public void setType(AccountType type) + { + this.type = type; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupAccount_v4 that = (BackupAccount_v4) o; + return Objects.equals(ID, that.ID) && Objects.equals(name, that.name) && type == that.type; + } + + @Override + public int hashCode() + { + return Objects.hash(ID, name, type); + } + + @Override + public String toString() + { + return "BackupAccount_v4{" + + "ID=" + ID + + ", name='" + name + '\'' + + ", type=" + type + + '}'; + } + + public BackupAccount_v5 upgrade() + { + return new BackupAccount_v5(ID, name, AccountState.FULL_ACCESS, type, null); + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupCategory_v4.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupCategory_v4.java new file mode 100644 index 0000000000000000000000000000000000000000..deb61fbe872351eb6d1d00e8603ae11937e79873 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupCategory_v4.java @@ -0,0 +1,99 @@ +package de.deadlocker8.budgetmaster.database.model.v4; + +import de.deadlocker8.budgetmaster.categories.CategoryType; +import de.deadlocker8.budgetmaster.database.model.Upgradeable; +import de.deadlocker8.budgetmaster.database.model.v5.BackupCategory_v5; + +import java.util.Objects; + +public class BackupCategory_v4 implements Upgradeable<BackupCategory_v5> +{ + private Integer ID; + private String name; + private String color; + private CategoryType type; + + public BackupCategory_v4() + { + // for GSON + } + + public BackupCategory_v4(Integer ID, String name, String color, CategoryType type) + { + this.ID = ID; + this.name = name; + this.color = color; + this.type = type; + } + + public Integer getID() + { + return ID; + } + + public void setID(Integer ID) + { + this.ID = ID; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getColor() + { + return color; + } + + public void setColor(String color) + { + this.color = color; + } + + public CategoryType getType() + { + return type; + } + + public void setType(CategoryType type) + { + this.type = type; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupCategory_v4 that = (BackupCategory_v4) o; + return Objects.equals(ID, that.ID) && Objects.equals(name, that.name) && Objects.equals(color, that.color) && type == that.type; + } + + @Override + public int hashCode() + { + return Objects.hash(ID, name, color, type); + } + + @Override + public String toString() + { + return "BackupCategory_v4{" + + "ID=" + ID + + ", name='" + name + '\'' + + ", color='" + color + '\'' + + ", type=" + type + + '}'; + } + + public BackupCategory_v5 upgrade() + { + return new BackupCategory_v5(ID, name, color, type, null); + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupDatabase_v4.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupDatabase_v4.java new file mode 100644 index 0000000000000000000000000000000000000000..1e86a765687a1ebcc9266cb47c6d628582651b61 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupDatabase_v4.java @@ -0,0 +1,103 @@ +package de.deadlocker8.budgetmaster.database.model.v4; + +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.v5.BackupDatabase_v5; + +import java.util.ArrayList; +import java.util.List; + +public class BackupDatabase_v4 implements BackupDatabase +{ + @SuppressWarnings("unused") + private final String TYPE = JSONIdentifier.BUDGETMASTER_DATABASE.toString(); + + @SuppressWarnings("FieldCanBeLocal") + private final int VERSION = 4; + + private List<BackupCategory_v4> categories; + private List<BackupAccount_v4> accounts; + private List<BackupTransaction_v4> transactions; + private List<BackupTemplate_v4> templates; + + public BackupDatabase_v4() + { + // for GSON + } + + public BackupDatabase_v4(List<BackupCategory_v4> categories, List<BackupAccount_v4> accounts, List<BackupTransaction_v4> transactions, List<BackupTemplate_v4> templates) + { + this.categories = categories; + this.accounts = accounts; + this.transactions = transactions; + this.templates = templates; + } + + public List<BackupCategory_v4> getCategories() + { + return categories; + } + + public void setCategories(List<BackupCategory_v4> categories) + { + this.categories = categories; + } + + public List<BackupAccount_v4> getAccounts() + { + return accounts; + } + + public void setAccounts(List<BackupAccount_v4> accounts) + { + this.accounts = accounts; + } + + public List<BackupTransaction_v4> getTransactions() + { + return transactions; + } + + public void setTransactions(List<BackupTransaction_v4> transactions) + { + this.transactions = transactions; + } + + public List<BackupTemplate_v4> getTemplates() + { + return templates; + } + + public void setTemplates(List<BackupTemplate_v4> templates) + { + this.templates = templates; + } + + @Override + public int getVersion() + { + return this.VERSION; + } + + @Override + public BackupDatabase upgrade() + { + final BackupDatabase_v5 upgradedDatabase = new BackupDatabase_v5(); + + upgradedDatabase.setCategories(upgradeItems(categories)); + upgradedDatabase.setAccounts(upgradeItems(accounts)); + upgradedDatabase.setTransactions(upgradeItems(transactions)); + upgradedDatabase.setTemplates(upgradeItems(templates)); + upgradedDatabase.setCharts(new ArrayList<>()); + upgradedDatabase.setImages(new ArrayList<>()); + + return upgradedDatabase; + } + + @Override + public InternalDatabase convertToInternal() + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupRepeatingEndOption_v4.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupRepeatingEndOption_v4.java new file mode 100644 index 0000000000000000000000000000000000000000..2c9dfc5f993805b5d725340946071f2d71316d55 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupRepeatingEndOption_v4.java @@ -0,0 +1,70 @@ +package de.deadlocker8.budgetmaster.database.model.v4; + +import java.util.Objects; + +public class BackupRepeatingEndOption_v4 +{ + private String localizationKey; + private int times; + private String endDate; + + public BackupRepeatingEndOption_v4() + { + // for GSON + } + + public String getLocalizationKey() + { + return localizationKey; + } + + public void setLocalizationKey(String localizationKey) + { + this.localizationKey = localizationKey; + } + + public int getTimes() + { + return times; + } + + public void setTimes(int times) + { + this.times = times; + } + + public String getEndDate() + { + return endDate; + } + + public void setEndDate(String endDate) + { + this.endDate = endDate; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupRepeatingEndOption_v4 that = (BackupRepeatingEndOption_v4) o; + return times == that.times && Objects.equals(localizationKey, that.localizationKey) && Objects.equals(endDate, that.endDate); + } + + @Override + public int hashCode() + { + return Objects.hash(localizationKey, times, endDate); + } + + @Override + public String toString() + { + return "BackupRepeatingEndOption_v4{" + + "localizationKey='" + localizationKey + '\'' + + ", times=" + times + + ", endDate='" + endDate + '\'' + + '}'; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupRepeatingModifier_v4.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupRepeatingModifier_v4.java new file mode 100644 index 0000000000000000000000000000000000000000..c50f252c2475660829750b774fbddddac186c813 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupRepeatingModifier_v4.java @@ -0,0 +1,64 @@ +package de.deadlocker8.budgetmaster.database.model.v4; + +import java.util.Objects; + +public class BackupRepeatingModifier_v4 +{ + private Integer quantity; + private String localizationKey; + + public BackupRepeatingModifier_v4() + { + // for GSON + } + + public BackupRepeatingModifier_v4(Integer quantity, String localizationKey) + { + this.quantity = quantity; + this.localizationKey = localizationKey; + } + + public Integer getQuantity() + { + return quantity; + } + + public void setQuantity(Integer quantity) + { + this.quantity = quantity; + } + + public String getLocalizationKey() + { + return localizationKey; + } + + public void setLocalizationKey(String localizationKey) + { + this.localizationKey = localizationKey; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupRepeatingModifier_v4 that = (BackupRepeatingModifier_v4) o; + return Objects.equals(quantity, that.quantity) && Objects.equals(localizationKey, that.localizationKey); + } + + @Override + public int hashCode() + { + return Objects.hash(quantity, localizationKey); + } + + @Override + public String toString() + { + return "BackupRepeatingModifier_v4{" + + "quantity=" + quantity + + ", localizationKey='" + localizationKey + '\'' + + '}'; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupRepeatingOption_v4.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupRepeatingOption_v4.java new file mode 100644 index 0000000000000000000000000000000000000000..bc439b09c085d35b1b75fc6783b07ddb44047992 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupRepeatingOption_v4.java @@ -0,0 +1,77 @@ +package de.deadlocker8.budgetmaster.database.model.v4; + +import java.util.Objects; + +public class BackupRepeatingOption_v4 +{ + private String startDate; + private BackupRepeatingModifier_v4 modifier; + private BackupRepeatingEndOption_v4 endOption; + + public BackupRepeatingOption_v4() + { + // for GSON + } + + public BackupRepeatingOption_v4(String startDate, BackupRepeatingModifier_v4 modifier, BackupRepeatingEndOption_v4 endOption) + { + this.startDate = startDate; + this.modifier = modifier; + this.endOption = endOption; + } + + public String getStartDate() + { + return startDate; + } + + public void setStartDate(String startDate) + { + this.startDate = startDate; + } + + public BackupRepeatingModifier_v4 getModifier() + { + return modifier; + } + + public void setModifier(BackupRepeatingModifier_v4 modifier) + { + this.modifier = modifier; + } + + public BackupRepeatingEndOption_v4 getEndOption() + { + return endOption; + } + + public void setEndOption(BackupRepeatingEndOption_v4 endOption) + { + this.endOption = endOption; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupRepeatingOption_v4 that = (BackupRepeatingOption_v4) o; + return Objects.equals(startDate, that.startDate) && Objects.equals(modifier, that.modifier) && Objects.equals(endOption, that.endOption); + } + + @Override + public int hashCode() + { + return Objects.hash(startDate, modifier, endOption); + } + + @Override + public String toString() + { + return "BackupRepeatingOption_v4{" + + "startDate='" + startDate + '\'' + + ", modifier=" + modifier + + ", endOption=" + endOption + + '}'; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupTag_v4.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupTag_v4.java new file mode 100644 index 0000000000000000000000000000000000000000..72ca4933663354ceded8b02344e16a47cad3d097 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupTag_v4.java @@ -0,0 +1,51 @@ +package de.deadlocker8.budgetmaster.database.model.v4; + +import java.util.Objects; + +public class BackupTag_v4 +{ + private String name; + + public BackupTag_v4() + { + // for GSON + } + + public BackupTag_v4(String name) + { + this.name = name; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupTag_v4 that = (BackupTag_v4) o; + return Objects.equals(name, that.name); + } + + @Override + public int hashCode() + { + return Objects.hash(name); + } + + @Override + public String toString() + { + return "BackupTag_v4{" + + "name='" + name + '\'' + + '}'; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupTemplate_v4.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupTemplate_v4.java new file mode 100644 index 0000000000000000000000000000000000000000..75aa699855670a1e2bf8914b6406d27e3348774d --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupTemplate_v4.java @@ -0,0 +1,171 @@ +package de.deadlocker8.budgetmaster.database.model.v4; + +import de.deadlocker8.budgetmaster.database.model.Upgradeable; +import de.deadlocker8.budgetmaster.database.model.v5.BackupAccount_v5; +import de.deadlocker8.budgetmaster.database.model.v5.BackupCategory_v5; +import de.deadlocker8.budgetmaster.database.model.v5.BackupTemplate_v5; +import de.deadlocker8.budgetmaster.tags.Tag; + +import java.util.List; +import java.util.Objects; + +public class BackupTemplate_v4 implements BackupTransactionBase_v4, Upgradeable<BackupTemplate_v5> +{ + private String templateName; + private Integer amount; + private Boolean isExpenditure; + private BackupAccount_v4 account; + private BackupCategory_v4 category; + private String name; + private String description; + private List<BackupTag_v4> tags; + private BackupAccount_v4 transferAccount; + + public BackupTemplate_v4() + { + // for GSON + } + + public String getTemplateName() + { + return templateName; + } + + public void setTemplateName(String templateName) + { + this.templateName = templateName; + } + + public Integer getAmount() + { + return amount; + } + + public void setAmount(Integer amount) + { + this.amount = amount; + } + + public Boolean getExpenditure() + { + return isExpenditure; + } + + public void setExpenditure(Boolean expenditure) + { + isExpenditure = expenditure; + } + + public BackupAccount_v4 getAccount() + { + return account; + } + + public void setAccount(BackupAccount_v4 account) + { + this.account = account; + } + + public BackupCategory_v4 getCategory() + { + return category; + } + + public void setCategory(BackupCategory_v4 category) + { + this.category = category; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public List<BackupTag_v4> getTags() + { + return tags; + } + + public void setTags(List<BackupTag_v4> tags) + { + this.tags = tags; + } + + public BackupAccount_v4 getTransferAccount() + { + return transferAccount; + } + + public void setTransferAccount(BackupAccount_v4 transferAccount) + { + this.transferAccount = transferAccount; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupTemplate_v4 that = (BackupTemplate_v4) o; + return Objects.equals(templateName, that.templateName) && Objects.equals(amount, that.amount) && Objects.equals(isExpenditure, that.isExpenditure) && Objects.equals(account, that.account) && Objects.equals(category, that.category) && Objects.equals(name, that.name) && Objects.equals(description, that.description) && Objects.equals(tags, that.tags) && Objects.equals(transferAccount, that.transferAccount); + } + + @Override + public int hashCode() + { + return Objects.hash(templateName, amount, isExpenditure, account, category, name, description, tags, transferAccount); + } + + @Override + public String toString() + { + return "BackupTemplate_v4{templateName='" + templateName + '\'' + + ", amount=" + amount + + ", isExpenditure=" + isExpenditure + + ", account=" + account + + ", category=" + category + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + ", tags=" + tags + + ", transferAccount=" + transferAccount + + '}'; + } + + public BackupTemplate_v5 upgrade() + { + BackupAccount_v5 upgradedAccount = null; + if(account != null) + { + upgradedAccount = account.upgrade(); + } + + BackupCategory_v5 upgradedCategory = null; + if(category != null) + { + upgradedCategory = category.upgrade(); + } + + BackupAccount_v5 upgradedTransferAccount = null; + if(transferAccount != null) + { + upgradedTransferAccount = transferAccount.upgrade(); + } + + return new BackupTemplate_v5(templateName, amount, isExpenditure, upgradedAccount, upgradedCategory, name, description, null, tags, upgradedTransferAccount); + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupTransactionBase_v4.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupTransactionBase_v4.java new file mode 100644 index 0000000000000000000000000000000000000000..58274b0f45a0086895f90c936661ecd09b2729df --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupTransactionBase_v4.java @@ -0,0 +1,10 @@ +package de.deadlocker8.budgetmaster.database.model.v4; + +public interface BackupTransactionBase_v4 +{ + Integer getAmount(); + + Boolean getExpenditure(); + + void setExpenditure(Boolean isExpenditure); +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupTransaction_v4.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupTransaction_v4.java new file mode 100644 index 0000000000000000000000000000000000000000..8d6814c7ca01dbad48f6eb7631d1e0c5077ab22a --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v4/BackupTransaction_v4.java @@ -0,0 +1,174 @@ +package de.deadlocker8.budgetmaster.database.model.v4; + +import de.deadlocker8.budgetmaster.database.model.Upgradeable; +import de.deadlocker8.budgetmaster.database.model.v5.BackupAccount_v5; +import de.deadlocker8.budgetmaster.database.model.v5.BackupCategory_v5; +import de.deadlocker8.budgetmaster.database.model.v5.BackupTransaction_v5; +import de.deadlocker8.budgetmaster.tags.Tag; + +import java.util.List; +import java.util.Objects; + +public class BackupTransaction_v4 implements BackupTransactionBase_v4, Upgradeable<BackupTransaction_v5> +{ + private Integer amount; + private Boolean isExpenditure; + private String date; + private BackupAccount_v4 account; + private BackupCategory_v4 category; + private String name; + private String description; + private List<BackupTag_v4> tags; + private BackupRepeatingOption_v4 repeatingOption; + private BackupAccount_v4 transferAccount; + + public BackupTransaction_v4() + { + // for GSON + } + + public Integer getAmount() + { + return amount; + } + + public void setAmount(Integer amount) + { + this.amount = amount; + } + + public Boolean getExpenditure() + { + return isExpenditure; + } + + public void setExpenditure(Boolean expenditure) + { + isExpenditure = expenditure; + } + + public String getDate() + { + return date; + } + + public void setDate(String date) + { + this.date = date; + } + + public BackupAccount_v4 getAccount() + { + return account; + } + + public void setAccount(BackupAccount_v4 account) + { + this.account = account; + } + + public BackupCategory_v4 getCategory() + { + return category; + } + + public void setCategory(BackupCategory_v4 category) + { + this.category = category; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public List<BackupTag_v4> getTags() + { + return tags; + } + + public void setTags(List<BackupTag_v4> tags) + { + this.tags = tags; + } + + public BackupRepeatingOption_v4 getRepeatingOption() + { + return repeatingOption; + } + + public void setRepeatingOption(BackupRepeatingOption_v4 repeatingOption) + { + this.repeatingOption = repeatingOption; + } + + public BackupAccount_v4 getTransferAccount() + { + return transferAccount; + } + + public void setTransferAccount(BackupAccount_v4 transferAccount) + { + this.transferAccount = transferAccount; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupTransaction_v4 that = (BackupTransaction_v4) o; + return Objects.equals(amount, that.amount) && Objects.equals(isExpenditure, that.isExpenditure) && Objects.equals(date, that.date) && Objects.equals(account, that.account) && Objects.equals(category, that.category) && Objects.equals(name, that.name) && Objects.equals(description, that.description) && Objects.equals(tags, that.tags) && Objects.equals(repeatingOption, that.repeatingOption) && Objects.equals(transferAccount, that.transferAccount); + } + + @Override + public int hashCode() + { + return Objects.hash(amount, isExpenditure, date, account, category, name, description, tags, repeatingOption, transferAccount); + } + + @Override + public String toString() + { + return "BackupTransaction_v4{amount=" + amount + + ", isExpenditure=" + isExpenditure + + ", date=" + date + + ", account=" + account + + ", category=" + category + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + ", tags=" + tags + + ", repeatingOption=" + repeatingOption + + ", transferAccount=" + transferAccount + + '}'; + } + + public BackupTransaction_v5 upgrade() + { + BackupAccount_v5 upgradedAccount = account.upgrade(); + BackupCategory_v5 upgradedCategory = category.upgrade(); + + BackupAccount_v5 upgradedTransferAccount = null; + if(transferAccount != null) + { + upgradedTransferAccount = transferAccount.upgrade(); + } + + return new BackupTransaction_v5(amount, isExpenditure, date, upgradedAccount, upgradedCategory, name, description, tags, repeatingOption, upgradedTransferAccount); + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupAccount_v5.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupAccount_v5.java new file mode 100644 index 0000000000000000000000000000000000000000..2e1c80c3869eb6a78afd7069c2e1afad274cfbf6 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupAccount_v5.java @@ -0,0 +1,119 @@ +package de.deadlocker8.budgetmaster.database.model.v5; + +import de.deadlocker8.budgetmaster.accounts.AccountState; +import de.deadlocker8.budgetmaster.accounts.AccountType; +import de.deadlocker8.budgetmaster.database.model.Upgradeable; +import de.deadlocker8.budgetmaster.database.model.v6.BackupAccount_v6; + +import java.util.Objects; + +public class BackupAccount_v5 implements Upgradeable<BackupAccount_v6> +{ + private Integer ID; + private String name; + private AccountState accountState; + private AccountType type; + private BackupImage_v5 icon; + + public BackupAccount_v5() + { + // for GSON + } + + public BackupAccount_v5(Integer ID, String name, AccountState accountState, AccountType type, BackupImage_v5 icon) + { + this.ID = ID; + this.name = name; + this.accountState = accountState; + this.type = type; + this.icon = icon; + } + + public Integer getID() + { + return ID; + } + + public void setID(Integer ID) + { + this.ID = ID; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public AccountState getAccountState() + { + return accountState; + } + + public void setAccountState(AccountState accountState) + { + this.accountState = accountState; + } + + public AccountType getType() + { + return type; + } + + public void setType(AccountType type) + { + this.type = type; + } + + public BackupImage_v5 getIcon() + { + return icon; + } + + public void setIcon(BackupImage_v5 icon) + { + this.icon = icon; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupAccount_v5 that = (BackupAccount_v5) o; + return Objects.equals(ID, that.ID) && Objects.equals(name, that.name) && accountState == that.accountState && type == that.type && Objects.equals(icon, that.icon); + } + + @Override + public int hashCode() + { + return Objects.hash(ID, name, accountState, type, icon); + } + + @Override + public String toString() + { + return "BackupAccount_v5{" + + "ID=" + ID + + ", name='" + name + '\'' + + ", accountState=" + accountState + + ", type=" + type + + ", icon=" + icon + + '}'; + } + + public BackupAccount_v6 upgrade() + { + Integer iconID = null; + if(icon != null) + { + iconID = icon.getID(); + } + + return new BackupAccount_v6(ID, name, accountState, type, iconID); + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupCategory_v5.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupCategory_v5.java new file mode 100644 index 0000000000000000000000000000000000000000..44591eee0af5a1d7f1107c592ed321e70047480d --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupCategory_v5.java @@ -0,0 +1,105 @@ +package de.deadlocker8.budgetmaster.database.model.v5; + +import de.deadlocker8.budgetmaster.categories.CategoryType; + +import java.util.Objects; + +public class BackupCategory_v5 +{ + private Integer ID; + private String name; + private String color; + private CategoryType type; + private String icon; + + public BackupCategory_v5() + { + // for GSON + } + + public BackupCategory_v5(Integer ID, String name, String color, CategoryType type, String icon) + { + this.ID = ID; + this.name = name; + this.color = color; + this.type = type; + this.icon = icon; + } + + public Integer getID() + { + return ID; + } + + public void setID(Integer ID) + { + this.ID = ID; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getColor() + { + return color; + } + + public void setColor(String color) + { + this.color = color; + } + + public CategoryType getType() + { + return type; + } + + public void setType(CategoryType type) + { + this.type = type; + } + + public String getIcon() + { + return icon; + } + + public void setIcon(String icon) + { + this.icon = icon; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupCategory_v5 that = (BackupCategory_v5) o; + return Objects.equals(ID, that.ID) && Objects.equals(name, that.name) && Objects.equals(color, that.color) && type == that.type && Objects.equals(icon, that.icon); + } + + @Override + public int hashCode() + { + return Objects.hash(ID, name, color, type, icon); + } + + @Override + public String toString() + { + return "BackupCategory_v5{" + + "ID=" + ID + + ", name='" + name + '\'' + + ", color='" + color + '\'' + + ", type=" + type + + ", icon='" + icon + '\'' + + '}'; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupChart_v5.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupChart_v5.java new file mode 100644 index 0000000000000000000000000000000000000000..6b152774954df768bd840679c377fe5a2187f0c9 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupChart_v5.java @@ -0,0 +1,105 @@ +package de.deadlocker8.budgetmaster.database.model.v5; + +import de.deadlocker8.budgetmaster.charts.ChartType; + +import java.util.Objects; + +public class BackupChart_v5 +{ + private Integer ID; + private String name; + private String script; + private ChartType type; + private int version; + + public BackupChart_v5() + { + // for GSON + } + + public BackupChart_v5(Integer ID, String name, String script, ChartType type, int version) + { + this.ID = ID; + this.name = name; + this.script = script; + this.type = type; + this.version = version; + } + + public Integer getID() + { + return ID; + } + + public void setID(Integer ID) + { + this.ID = ID; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getScript() + { + return script; + } + + public void setScript(String script) + { + this.script = script; + } + + public ChartType getType() + { + return type; + } + + public void setType(ChartType type) + { + this.type = type; + } + + public int getVersion() + { + return version; + } + + public void setVersion(int version) + { + this.version = version; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupChart_v5 that = (BackupChart_v5) o; + return version == that.version && Objects.equals(ID, that.ID) && Objects.equals(name, that.name) && Objects.equals(script, that.script) && type == that.type; + } + + @Override + public int hashCode() + { + return Objects.hash(ID, name, script, type, version); + } + + @Override + public String toString() + { + return "BackupChart_v5{" + + "ID=" + ID + + ", name='" + name + '\'' + + ", script='" + script + '\'' + + ", type=" + type + + ", version=" + version + + '}'; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupDatabase_v5.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupDatabase_v5.java new file mode 100644 index 0000000000000000000000000000000000000000..e0fccca42657d82b41ef3a868f7db016d7f6afdc --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupDatabase_v5.java @@ -0,0 +1,125 @@ +package de.deadlocker8.budgetmaster.database.model.v5; + +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.v6.BackupDatabase_v6; + +import java.util.List; + +public class BackupDatabase_v5 implements BackupDatabase +{ + @SuppressWarnings("unused") + private final String TYPE = JSONIdentifier.BUDGETMASTER_DATABASE.toString(); + + @SuppressWarnings("FieldCanBeLocal") + private final int VERSION = 5; + + private List<BackupCategory_v5> categories; + private List<BackupAccount_v5> accounts; + private List<BackupTransaction_v5> transactions; + private List<BackupTemplate_v5> templates; + private List<BackupChart_v5> charts; + private List<BackupImage_v5> images; + + public BackupDatabase_v5() + { + // for GSON + } + + public BackupDatabase_v5(List<BackupCategory_v5> categories, List<BackupAccount_v5> accounts, List<BackupTransaction_v5> transactions, List<BackupTemplate_v5> templates, List<BackupChart_v5> charts, List<BackupImage_v5> images) + { + this.categories = categories; + this.accounts = accounts; + this.transactions = transactions; + this.templates = templates; + this.charts = charts; + this.images = images; + } + + public List<BackupCategory_v5> getCategories() + { + return categories; + } + + public void setCategories(List<BackupCategory_v5> categories) + { + this.categories = categories; + } + + public List<BackupAccount_v5> getAccounts() + { + return accounts; + } + + public void setAccounts(List<BackupAccount_v5> accounts) + { + this.accounts = accounts; + } + + public List<BackupTransaction_v5> getTransactions() + { + return transactions; + } + + public void setTransactions(List<BackupTransaction_v5> transactions) + { + this.transactions = transactions; + } + + public List<BackupTemplate_v5> getTemplates() + { + return templates; + } + + public void setTemplates(List<BackupTemplate_v5> 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 InternalDatabase convertToInternal() + { + throw new UnsupportedOperationException(); + } + + @Override + public int getVersion() + { + return VERSION; + } + + @Override + public BackupDatabase upgrade() + { + final BackupDatabase_v6 upgradedDatabase = new BackupDatabase_v6(); + + upgradedDatabase.setCategories(categories); + upgradedDatabase.setAccounts(upgradeItems(accounts)); + upgradedDatabase.setTransactions(upgradeItems(transactions)); + upgradedDatabase.setTemplates(upgradeItems(templates)); + upgradedDatabase.setCharts(charts); + upgradedDatabase.setImages(images); + + return upgradedDatabase; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupImage_v5.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupImage_v5.java new file mode 100644 index 0000000000000000000000000000000000000000..44517e9ed9c982de7ccfe0b71a51022ff47f5799 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupImage_v5.java @@ -0,0 +1,91 @@ +package de.deadlocker8.budgetmaster.database.model.v5; + +import de.deadlocker8.budgetmaster.images.ImageFileExtension; + +import java.util.Objects; + +public class BackupImage_v5 +{ + private Integer ID; + private Byte[] image; + private String fileName; + private ImageFileExtension fileExtension; + + public BackupImage_v5() + { + // for GSON + } + + public BackupImage_v5(Integer ID, Byte[] image, String fileName, ImageFileExtension fileExtension) + { + this.ID = ID; + this.image = image; + this.fileName = fileName; + this.fileExtension = fileExtension; + } + + public Integer getID() + { + return ID; + } + + public void setID(Integer ID) + { + this.ID = ID; + } + + public Byte[] getImage() + { + return image; + } + + public void setImage(Byte[] image) + { + this.image = image; + } + + public String getFileName() + { + return fileName; + } + + public void setFileName(String fileName) + { + this.fileName = fileName; + } + + public ImageFileExtension getFileExtension() + { + return fileExtension; + } + + public void setFileExtension(ImageFileExtension fileExtension) + { + this.fileExtension = fileExtension; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupImage_v5 that = (BackupImage_v5) o; + return Objects.equals(ID, that.ID) && Objects.equals(fileName, that.fileName) && fileExtension == that.fileExtension; + } + + @Override + public int hashCode() + { + return Objects.hash(ID, fileName, fileExtension); + } + + @Override + public String toString() + { + return "BackupImage_v5{" + + "ID=" + ID + + ", fileName='" + fileName + '\'' + + ", fileExtension=" + fileExtension + + '}'; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupTemplate_v5.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupTemplate_v5.java new file mode 100644 index 0000000000000000000000000000000000000000..2b846d174603ec3d11a354b143d22cbf6e915eab --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupTemplate_v5.java @@ -0,0 +1,202 @@ +package de.deadlocker8.budgetmaster.database.model.v5; + +import de.deadlocker8.budgetmaster.database.model.Upgradeable; +import de.deadlocker8.budgetmaster.database.model.v4.BackupTag_v4; +import de.deadlocker8.budgetmaster.database.model.v6.BackupTemplate_v6; + +import java.util.List; +import java.util.Objects; + +public class BackupTemplate_v5 implements Upgradeable<BackupTemplate_v6> +{ + private String templateName; + private Integer amount; + private Boolean isExpenditure; + private BackupAccount_v5 account; + private BackupCategory_v5 category; + private String name; + private String description; + private BackupImage_v5 icon; + private List<BackupTag_v4> tags; + private BackupAccount_v5 transferAccount; + + public BackupTemplate_v5() + { + // for GSON + } + + public BackupTemplate_v5(String templateName, Integer amount, Boolean isExpenditure, BackupAccount_v5 account, BackupCategory_v5 category, String name, String description, BackupImage_v5 icon, List<BackupTag_v4> tags, BackupAccount_v5 transferAccount) + { + this.templateName = templateName; + this.amount = amount; + this.isExpenditure = isExpenditure; + this.account = account; + this.category = category; + this.name = name; + this.description = description; + this.icon = icon; + this.tags = tags; + this.transferAccount = transferAccount; + } + + public String getTemplateName() + { + return templateName; + } + + public void setTemplateName(String templateName) + { + this.templateName = templateName; + } + + public Integer getAmount() + { + return amount; + } + + public void setAmount(Integer amount) + { + this.amount = amount; + } + + public Boolean getExpenditure() + { + return isExpenditure; + } + + public void setExpenditure(Boolean expenditure) + { + isExpenditure = expenditure; + } + + public BackupAccount_v5 getAccount() + { + return account; + } + + public void setAccount(BackupAccount_v5 account) + { + this.account = account; + } + + public BackupCategory_v5 getCategory() + { + return category; + } + + public void setCategory(BackupCategory_v5 category) + { + this.category = category; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public BackupImage_v5 getIcon() + { + return icon; + } + + public void setIcon(BackupImage_v5 icon) + { + this.icon = icon; + } + + public List<BackupTag_v4> getTags() + { + return tags; + } + + public void setTags(List<BackupTag_v4> tags) + { + this.tags = tags; + } + + public BackupAccount_v5 getTransferAccount() + { + return transferAccount; + } + + public void setTransferAccount(BackupAccount_v5 transferAccount) + { + this.transferAccount = transferAccount; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupTemplate_v5 that = (BackupTemplate_v5) o; + return Objects.equals(templateName, that.templateName) && Objects.equals(amount, that.amount) && Objects.equals(isExpenditure, that.isExpenditure) && Objects.equals(account, that.account) && Objects.equals(category, that.category) && Objects.equals(name, that.name) && Objects.equals(description, that.description) && Objects.equals(icon, that.icon) && Objects.equals(tags, that.tags) && Objects.equals(transferAccount, that.transferAccount); + } + + @Override + public int hashCode() + { + return Objects.hash(templateName, amount, isExpenditure, account, category, name, description, icon, tags, transferAccount); + } + + @Override + public String toString() + { + return "BackupTemplate_v5{templateName='" + templateName + '\'' + + ", amount=" + amount + + ", isExpenditure=" + isExpenditure + + ", account=" + account + + ", category=" + category + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + ", icon=" + icon + + ", tags=" + tags + + ", transferAccount=" + transferAccount + + '}'; + } + + @Override + public BackupTemplate_v6 upgrade() + { + Integer accountID = null; + if(account != null) + { + accountID = account.getID(); + } + + Integer categoryID = null; + if(category != null) + { + categoryID = category.getID(); + } + + Integer iconID = null; + if(icon != null) + { + iconID = icon.getID(); + } + + Integer transferAccountID = null; + if(transferAccount != null) + { + transferAccountID = transferAccount.getID(); + } + + return new BackupTemplate_v6(templateName, amount, isExpenditure, accountID, categoryID, name, description, iconID, tags, transferAccountID); + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupTransaction_v5.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupTransaction_v5.java new file mode 100644 index 0000000000000000000000000000000000000000..d6043623c58871f5697f132754824c6c3fe0bce6 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v5/BackupTransaction_v5.java @@ -0,0 +1,185 @@ +package de.deadlocker8.budgetmaster.database.model.v5; + +import de.deadlocker8.budgetmaster.database.model.Upgradeable; +import de.deadlocker8.budgetmaster.database.model.v4.BackupRepeatingOption_v4; +import de.deadlocker8.budgetmaster.database.model.v4.BackupTag_v4; +import de.deadlocker8.budgetmaster.database.model.v6.BackupTransaction_v6; + +import java.util.List; +import java.util.Objects; + +public class BackupTransaction_v5 implements Upgradeable<BackupTransaction_v6> +{ + private Integer amount; + private Boolean isExpenditure; + private String date; + private BackupAccount_v5 account; + private BackupCategory_v5 category; + private String name; + private String description; + private List<BackupTag_v4> tags; + private BackupRepeatingOption_v4 repeatingOption; + private BackupAccount_v5 transferAccount; + + public BackupTransaction_v5() + { + // for GSON + } + + public BackupTransaction_v5(Integer amount, Boolean isExpenditure, String date, BackupAccount_v5 account, BackupCategory_v5 category, String name, String description, List<BackupTag_v4> tags, BackupRepeatingOption_v4 repeatingOption, BackupAccount_v5 transferAccount) + { + this.amount = amount; + this.isExpenditure = isExpenditure; + this.date = date; + this.account = account; + this.category = category; + this.name = name; + this.description = description; + this.tags = tags; + this.repeatingOption = repeatingOption; + this.transferAccount = transferAccount; + } + + public Integer getAmount() + { + return amount; + } + + public void setAmount(Integer amount) + { + this.amount = amount; + } + + public Boolean getExpenditure() + { + return isExpenditure; + } + + public void setExpenditure(Boolean expenditure) + { + isExpenditure = expenditure; + } + + public String getDate() + { + return date; + } + + public void setDate(String date) + { + this.date = date; + } + + public BackupAccount_v5 getAccount() + { + return account; + } + + public void setAccount(BackupAccount_v5 account) + { + this.account = account; + } + + public BackupCategory_v5 getCategory() + { + return category; + } + + public void setCategory(BackupCategory_v5 category) + { + this.category = category; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public List<BackupTag_v4> getTags() + { + return tags; + } + + public void setTags(List<BackupTag_v4> tags) + { + this.tags = tags; + } + + public BackupRepeatingOption_v4 getRepeatingOption() + { + return repeatingOption; + } + + public void setRepeatingOption(BackupRepeatingOption_v4 repeatingOption) + { + this.repeatingOption = repeatingOption; + } + + public BackupAccount_v5 getTransferAccount() + { + return transferAccount; + } + + public void setTransferAccount(BackupAccount_v5 transferAccount) + { + this.transferAccount = transferAccount; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupTransaction_v5 that = (BackupTransaction_v5) o; + return Objects.equals(amount, that.amount) && Objects.equals(isExpenditure, that.isExpenditure) && Objects.equals(date, that.date) && Objects.equals(account, that.account) && Objects.equals(category, that.category) && Objects.equals(name, that.name) && Objects.equals(description, that.description) && Objects.equals(tags, that.tags) && Objects.equals(repeatingOption, that.repeatingOption) && Objects.equals(transferAccount, that.transferAccount); + } + + @Override + public int hashCode() + { + return Objects.hash(amount, isExpenditure, date, account, category, name, description, tags, repeatingOption, transferAccount); + } + + @Override + public String toString() + { + return "BackupTransaction_v5{amount=" + amount + + ", isExpenditure=" + isExpenditure + + ", date=" + date + + ", account=" + account + + ", category=" + category + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + ", tags=" + tags + + ", repeatingOption=" + repeatingOption + + ", transferAccount=" + transferAccount + + '}'; + } + + @Override + public BackupTransaction_v6 upgrade() + { + Integer transferAccountID = null; + if(transferAccount != null) + { + transferAccountID = transferAccount.getID(); + } + + return new BackupTransaction_v6(amount, isExpenditure, date, account.getID(), category.getID(), name, description, tags, repeatingOption, transferAccountID); + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v6/BackupAccount_v6.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v6/BackupAccount_v6.java new file mode 100644 index 0000000000000000000000000000000000000000..48b47bba4a64336445b1264b7640d5410ed6b45d --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v6/BackupAccount_v6.java @@ -0,0 +1,106 @@ +package de.deadlocker8.budgetmaster.database.model.v6; + +import de.deadlocker8.budgetmaster.accounts.AccountState; +import de.deadlocker8.budgetmaster.accounts.AccountType; + +import java.util.Objects; + +public class BackupAccount_v6 +{ + private Integer ID; + private String name; + private AccountState accountState; + private AccountType type; + private Integer iconID; + + public BackupAccount_v6() + { + // for GSON + } + + public BackupAccount_v6(Integer ID, String name, AccountState accountState, AccountType type, Integer iconID) + { + this.ID = ID; + this.name = name; + this.accountState = accountState; + this.type = type; + this.iconID = iconID; + } + + public Integer getID() + { + return ID; + } + + public void setID(Integer ID) + { + this.ID = ID; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public AccountState getAccountState() + { + return accountState; + } + + public void setAccountState(AccountState accountState) + { + this.accountState = accountState; + } + + public AccountType getType() + { + return type; + } + + public void setType(AccountType type) + { + this.type = type; + } + + public Integer getIconID() + { + return iconID; + } + + public void setIconID(Integer iconID) + { + this.iconID = iconID; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupAccount_v6 that = (BackupAccount_v6) o; + return Objects.equals(ID, that.ID) && Objects.equals(name, that.name) && accountState == that.accountState && type == that.type && Objects.equals(iconID, that.iconID); + } + + @Override + public int hashCode() + { + return Objects.hash(ID, name, accountState, type, iconID); + } + + @Override + public String toString() + { + return "BackupAccount_v6{" + + "ID=" + ID + + ", name='" + name + '\'' + + ", accountState=" + accountState + + ", type=" + type + + ", iconID=" + iconID + + '}'; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v6/BackupDatabase_v6.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v6/BackupDatabase_v6.java new file mode 100644 index 0000000000000000000000000000000000000000..6ce3d66c3e95586528571a8d73ae9c47d0912299 --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v6/BackupDatabase_v6.java @@ -0,0 +1,146 @@ +package de.deadlocker8.budgetmaster.database.model.v6; + +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.BackupCategory_v5; +import de.deadlocker8.budgetmaster.database.model.v5.BackupChart_v5; +import de.deadlocker8.budgetmaster.database.model.v5.BackupImage_v5; +import de.deadlocker8.budgetmaster.images.Image; +import de.deadlocker8.budgetmaster.templates.Template; +import de.deadlocker8.budgetmaster.transactions.Transaction; + +import java.util.List; + +public class BackupDatabase_v6 implements BackupDatabase +{ + @SuppressWarnings("unused") + private final String TYPE = JSONIdentifier.BUDGETMASTER_DATABASE.toString(); + + @SuppressWarnings("FieldCanBeLocal") + private final int VERSION = 6; + + private List<BackupCategory_v5> categories; + private List<BackupAccount_v6> accounts; + private List<BackupTransaction_v6> transactions; + private List<BackupTemplate_v6> templates; + private List<BackupChart_v5> charts; + private List<BackupImage_v5> images; + + public BackupDatabase_v6() + { + // for GSON + } + + public BackupDatabase_v6(List<BackupCategory_v5> categories, List<BackupAccount_v6> accounts, List<BackupTransaction_v6> transactions, List<BackupTemplate_v6> templates, List<BackupChart_v5> charts, List<BackupImage_v5> images) + { + this.categories = categories; + this.accounts = accounts; + this.transactions = transactions; + this.templates = templates; + this.charts = charts; + this.images = images; + } + + public List<BackupCategory_v5> getCategories() + { + return categories; + } + + public void setCategories(List<BackupCategory_v5> categories) + { + this.categories = categories; + } + + public List<BackupAccount_v6> getAccounts() + { + return accounts; + } + + public void setAccounts(List<BackupAccount_v6> accounts) + { + this.accounts = accounts; + } + + public List<BackupTransaction_v6> getTransactions() + { + return transactions; + } + + public void setTransactions(List<BackupTransaction_v6> transactions) + { + this.transactions = transactions; + } + + public List<BackupTemplate_v6> getTemplates() + { + return templates; + } + + public void setTemplates(List<BackupTemplate_v6> 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 InternalDatabase convertToInternal() + { + final List<Image> convertedImages = convertItemsToInternal(this.images, new ImageConverter()); + final List<Category> convertedCategories = convertItemsToInternal(categories, new CategoryConverter()); + final List<Account> convertedAccounts = convertItemsToInternal(accounts, new AccountConverter(convertedImages)); + final List<Transaction> convertedTransactions = convertItemsToInternal(this.transactions, new TransactionConverter(convertedCategories, convertedAccounts)); + final List<Template> convertedTemplates = convertItemsToInternal(this.templates, new TemplateConverter(convertedImages, convertedCategories, convertedAccounts)); + final List<Chart> convertedCharts = convertItemsToInternal(this.charts, new ChartConverter()); + + return new InternalDatabase(convertedCategories, convertedAccounts, convertedTransactions, convertedTemplates, convertedCharts, convertedImages); + } + + @Override + public int getVersion() + { + return VERSION; + } + + @Override + public BackupDatabase upgrade() + { + throw new UnsupportedOperationException(); + } + + public static BackupDatabase_v6 createFromInternalEntities(InternalDatabase database) + { + final BackupDatabase_v6 externalDatabase = new BackupDatabase_v6(); + + externalDatabase.setCategories(externalDatabase.convertItemsToExternal(database.getCategories(), new CategoryConverter())); + externalDatabase.setAccounts(externalDatabase.convertItemsToExternal(database.getAccounts(), new AccountConverter(null))); + externalDatabase.setTransactions(externalDatabase.convertItemsToExternal(database.getTransactions(), new TransactionConverter(null, null))); + externalDatabase.setTemplates(externalDatabase.convertItemsToExternal(database.getTemplates(), new TemplateConverter(null, null, null))); + externalDatabase.setCharts(externalDatabase.convertItemsToExternal(database.getCharts(), new ChartConverter())); + externalDatabase.setImages(externalDatabase.convertItemsToExternal(database.getImages(), new ImageConverter())); + + return externalDatabase; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v6/BackupTemplate_v6.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v6/BackupTemplate_v6.java new file mode 100644 index 0000000000000000000000000000000000000000..d36a35ab8107e7edead5afbd6f8ba81833ad99aa --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v6/BackupTemplate_v6.java @@ -0,0 +1,170 @@ +package de.deadlocker8.budgetmaster.database.model.v6; + +import de.deadlocker8.budgetmaster.database.model.v4.BackupTag_v4; + +import java.util.List; +import java.util.Objects; + +public class BackupTemplate_v6 +{ + private String templateName; + private Integer amount; + private Boolean isExpenditure; + private Integer accountID; + private Integer categoryID; + private String name; + private String description; + private Integer iconID; + private List<BackupTag_v4> tags; + private Integer transferAccountID; + + public BackupTemplate_v6() + { + // for GSON + } + + public BackupTemplate_v6(String templateName, Integer amount, Boolean isExpenditure, Integer accountID, Integer categoryID, String name, String description, Integer iconID, List<BackupTag_v4> tags, Integer transferAccountID) + { + this.templateName = templateName; + this.amount = amount; + this.isExpenditure = isExpenditure; + this.accountID = accountID; + this.categoryID = categoryID; + this.name = name; + this.description = description; + this.iconID = iconID; + this.tags = tags; + this.transferAccountID = transferAccountID; + } + + public String getTemplateName() + { + return templateName; + } + + public void setTemplateName(String templateName) + { + this.templateName = templateName; + } + + public Integer getAmount() + { + return amount; + } + + public void setAmount(Integer amount) + { + this.amount = amount; + } + + public Boolean getExpenditure() + { + return isExpenditure; + } + + public void setExpenditure(Boolean expenditure) + { + isExpenditure = expenditure; + } + + public Integer getAccountID() + { + return accountID; + } + + public void setAccountID(Integer accountID) + { + this.accountID = accountID; + } + + public Integer getCategoryID() + { + return categoryID; + } + + public void setCategoryID(Integer categoryID) + { + this.categoryID = categoryID; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public Integer getIconID() + { + return iconID; + } + + public void setIconID(Integer iconID) + { + this.iconID = iconID; + } + + public List<BackupTag_v4> getTags() + { + return tags; + } + + public void setTags(List<BackupTag_v4> tags) + { + this.tags = tags; + } + + public Integer getTransferAccountID() + { + return transferAccountID; + } + + public void setTransferAccountID(Integer transferAccountID) + { + this.transferAccountID = transferAccountID; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupTemplate_v6 that = (BackupTemplate_v6) o; + return Objects.equals(templateName, that.templateName) && Objects.equals(amount, that.amount) && Objects.equals(isExpenditure, that.isExpenditure) && Objects.equals(accountID, that.accountID) && Objects.equals(categoryID, that.categoryID) && Objects.equals(name, that.name) && Objects.equals(description, that.description) && Objects.equals(iconID, that.iconID) && Objects.equals(tags, that.tags) && Objects.equals(transferAccountID, that.transferAccountID); + } + + @Override + public int hashCode() + { + return Objects.hash(templateName, amount, isExpenditure, accountID, categoryID, name, description, iconID, tags, transferAccountID); + } + + @Override + public String toString() + { + return "BackupTemplate_v6{templateName='" + templateName + '\'' + + ", amount=" + amount + + ", isExpenditure=" + isExpenditure + + ", accountID=" + accountID + + ", categoryID=" + categoryID + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + ", iconID=" + iconID + + ", tags=" + tags + + ", transferAccountID=" + transferAccountID + + '}'; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/database/model/v6/BackupTransaction_v6.java b/src/main/java/de/deadlocker8/budgetmaster/database/model/v6/BackupTransaction_v6.java new file mode 100644 index 0000000000000000000000000000000000000000..14f46f7adc0d9bc78b4a7b44da52ab418c60322d --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/database/model/v6/BackupTransaction_v6.java @@ -0,0 +1,171 @@ +package de.deadlocker8.budgetmaster.database.model.v6; + +import de.deadlocker8.budgetmaster.database.model.v4.BackupRepeatingOption_v4; +import de.deadlocker8.budgetmaster.database.model.v4.BackupTag_v4; + +import java.util.List; +import java.util.Objects; + +public class BackupTransaction_v6 +{ + private Integer amount; + private Boolean isExpenditure; + private String date; + private Integer accountID; + private Integer categoryID; + private String name; + private String description; + private List<BackupTag_v4> tags; + private BackupRepeatingOption_v4 repeatingOption; + private Integer transferAccountID; + + public BackupTransaction_v6() + { + // for GSON + } + + public BackupTransaction_v6(Integer amount, Boolean isExpenditure, String date, Integer accountID, Integer categoryID, String name, String description, List<BackupTag_v4> tags, BackupRepeatingOption_v4 repeatingOption, Integer transferAccountID) + { + this.amount = amount; + this.isExpenditure = isExpenditure; + this.date = date; + this.accountID = accountID; + this.categoryID = categoryID; + this.name = name; + this.description = description; + this.tags = tags; + this.repeatingOption = repeatingOption; + this.transferAccountID = transferAccountID; + } + + public Integer getAmount() + { + return amount; + } + + public void setAmount(Integer amount) + { + this.amount = amount; + } + + public Boolean getExpenditure() + { + return isExpenditure; + } + + public void setExpenditure(Boolean expenditure) + { + isExpenditure = expenditure; + } + + public String getDate() + { + return date; + } + + public void setDate(String date) + { + this.date = date; + } + + public Integer getAccountID() + { + return accountID; + } + + public void setAccountID(Integer accountID) + { + this.accountID = accountID; + } + + public Integer getCategoryID() + { + return categoryID; + } + + public void setCategoryID(Integer categoryID) + { + this.categoryID = categoryID; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getDescription() + { + return description; + } + + public void setDescription(String description) + { + this.description = description; + } + + public List<BackupTag_v4> getTags() + { + return tags; + } + + public void setTags(List<BackupTag_v4> tags) + { + this.tags = tags; + } + + public BackupRepeatingOption_v4 getRepeatingOption() + { + return repeatingOption; + } + + public void setRepeatingOption(BackupRepeatingOption_v4 repeatingOption) + { + this.repeatingOption = repeatingOption; + } + + public Integer getTransferAccountID() + { + return transferAccountID; + } + + public void setTransferAccountID(Integer transferAccountID) + { + this.transferAccountID = transferAccountID; + } + + @Override + public boolean equals(Object o) + { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + BackupTransaction_v6 that = (BackupTransaction_v6) o; + return Objects.equals(amount, that.amount) && Objects.equals(isExpenditure, that.isExpenditure) && Objects.equals(date, that.date) && Objects.equals(accountID, that.accountID) && Objects.equals(categoryID, that.categoryID) && Objects.equals(name, that.name) && Objects.equals(description, that.description) && Objects.equals(tags, that.tags) && Objects.equals(repeatingOption, that.repeatingOption) && Objects.equals(transferAccountID, that.transferAccountID); + } + + @Override + public int hashCode() + { + return Objects.hash(amount, isExpenditure, date, accountID, categoryID, name, description, tags, repeatingOption, transferAccountID); + } + + @Override + public String toString() + { + return "BackupTransaction_v6{amount=" + amount + + ", isExpenditure=" + isExpenditure + + ", date=" + date + + ", accountID=" + accountID + + ", categoryID=" + categoryID + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + ", tags=" + tags + + ", repeatingOption=" + repeatingOption + + ", transferAccountID=" + transferAccountID + + '}'; + } +} diff --git a/src/main/java/de/deadlocker8/budgetmaster/images/Image.java b/src/main/java/de/deadlocker8/budgetmaster/images/Image.java index fdcdc2739b3c0e878af4b22a3c7ad42979ed9b35..5dfce63bdc876d0f37fbfd8ba4d577839fef0d06 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/images/Image.java +++ b/src/main/java/de/deadlocker8/budgetmaster/images/Image.java @@ -2,6 +2,7 @@ package de.deadlocker8.budgetmaster.images; import com.google.gson.annotations.Expose; import de.deadlocker8.budgetmaster.accounts.Account; +import de.deadlocker8.budgetmaster.utils.ProvidesID; import org.apache.commons.lang3.ArrayUtils; import org.apache.tomcat.util.codec.binary.Base64; @@ -12,7 +13,7 @@ import java.util.List; import java.util.Objects; @Entity -public class Image +public class Image implements ProvidesID { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/de/deadlocker8/budgetmaster/services/ImportService.java b/src/main/java/de/deadlocker8/budgetmaster/services/ImportService.java index 67ee1c9d14be4bf840f25f4702b65916a44cd3a2..a8671a0f3cacf463f01da4d878febae279ebd0c1 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/services/ImportService.java +++ b/src/main/java/de/deadlocker8/budgetmaster/services/ImportService.java @@ -6,7 +6,7 @@ import de.deadlocker8.budgetmaster.categories.CategoryRepository; import de.deadlocker8.budgetmaster.categories.CategoryType; import de.deadlocker8.budgetmaster.charts.Chart; import de.deadlocker8.budgetmaster.charts.ChartService; -import de.deadlocker8.budgetmaster.database.Database; +import de.deadlocker8.budgetmaster.database.InternalDatabase; import de.deadlocker8.budgetmaster.database.accountmatches.AccountMatch; import de.deadlocker8.budgetmaster.database.accountmatches.AccountMatchList; import de.deadlocker8.budgetmaster.images.Image; @@ -42,7 +42,7 @@ public class ImportService private final ImageService imageService; private final RepeatingTransactionUpdater repeatingTransactionUpdater; - private Database database; + private InternalDatabase database; private List<String> collectedErrorMessages; @Autowired @@ -58,7 +58,7 @@ public class ImportService this.repeatingTransactionUpdater = repeatingTransactionUpdater; } - public List<ImportResultItem> importDatabase(Database database, AccountMatchList accountMatchList, Boolean importTemplates, Boolean importCharts) + public List<ImportResultItem> importDatabase(InternalDatabase database, AccountMatchList accountMatchList, Boolean importTemplates, Boolean importCharts) { this.database = database; this.collectedErrorMessages = new ArrayList<>(); @@ -97,7 +97,7 @@ public class ImportService return importResultItems; } - public Database getDatabase() + public InternalDatabase getDatabase() { return database; } diff --git a/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsController.java b/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsController.java index b03c5b032d3284ee0337e09a368672f223e9899f..33440497e4d83a0cf8fcc5ca29f8e7137b6af3d3 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsController.java +++ b/src/main/java/de/deadlocker8/budgetmaster/settings/SettingsController.java @@ -5,12 +5,12 @@ import de.deadlocker8.budgetmaster.Build; import de.deadlocker8.budgetmaster.accounts.AccountService; import de.deadlocker8.budgetmaster.backup.*; import de.deadlocker8.budgetmaster.categories.CategoryService; -import de.deadlocker8.budgetmaster.categories.CategoryType; import de.deadlocker8.budgetmaster.controller.BaseController; -import de.deadlocker8.budgetmaster.database.Database; import de.deadlocker8.budgetmaster.database.DatabaseParser; import de.deadlocker8.budgetmaster.database.DatabaseService; +import de.deadlocker8.budgetmaster.database.InternalDatabase; import de.deadlocker8.budgetmaster.database.accountmatches.AccountMatchList; +import de.deadlocker8.budgetmaster.database.model.v6.BackupDatabase_v6; import de.deadlocker8.budgetmaster.services.ImportResultItem; import de.deadlocker8.budgetmaster.services.ImportService; import de.deadlocker8.budgetmaster.services.UpdateCheckService; @@ -219,7 +219,7 @@ public class SettingsController extends BaseController { LOGGER.debug("Exporting database..."); - final Database databaseForJsonSerialization = databaseService.getDatabaseForJsonSerialization(); + final BackupDatabase_v6 databaseForJsonSerialization = databaseService.getDatabaseForJsonSerialization(); String data = DatabaseService.GSON.toJson(databaseForJsonSerialization); byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8); @@ -291,8 +291,8 @@ public class SettingsController extends BaseController try { String jsonString = new String(file.getBytes(), StandardCharsets.UTF_8); - DatabaseParser importer = new DatabaseParser(jsonString, categoryService.findByType(CategoryType.NONE)); - Database database = importer.parseDatabaseFromJSON(); + DatabaseParser importer = new DatabaseParser(jsonString); + InternalDatabase database = importer.parseDatabaseFromJSON(); request.setAttribute("database", database, RequestAttributes.SCOPE_SESSION); return "redirect:/settings/database/import/step1"; @@ -338,7 +338,7 @@ public class SettingsController extends BaseController @PostMapping("/database/import/step3") public String importDatabase(WebRequest request, @ModelAttribute("Import") AccountMatchList accountMatchList, Model model) { - final Database database = (Database) request.getAttribute("database", RequestAttributes.SCOPE_SESSION); + final InternalDatabase database = (InternalDatabase) request.getAttribute("database", RequestAttributes.SCOPE_SESSION); request.removeAttribute("database", RequestAttributes.SCOPE_SESSION); final Boolean importTemplates = (Boolean) request.getAttribute("importTemplates", RequestAttributes.SCOPE_SESSION); diff --git a/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionController.java b/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionController.java index 0f95e0d69398536d2cb0850f8a890c9d500856af..2668621bb91f488237d2287a410be65ba6468a80 100644 --- a/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionController.java +++ b/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionController.java @@ -115,8 +115,15 @@ public class TransactionController extends BaseController } @GetMapping("/newTransaction/{type}") - public String newTransaction(Model model, @CookieValue("currentDate") String cookieDate, @PathVariable String type) + public String newTransaction(WebRequest request, Model model, @CookieValue("currentDate") String cookieDate, @PathVariable String type) { + final AccountState accountState = helpers.getCurrentAccount().getAccountState(); + if(accountState != AccountState.FULL_ACCESS) + { + WebRequestUtils.putNotification(request, new Notification(Localization.getString("notification.transaction.add.warning", Localization.getString(accountState.getLocalizationKey())), NotificationType.WARNING)); + return "redirect:/transactions"; + } + DateTime date = dateService.getDateTimeFromCookie(cookieDate); Transaction emptyTransaction = new Transaction(); emptyTransaction.setCategory(categoryService.findByType(CategoryType.NONE)); diff --git a/src/main/java/de/deadlocker8/budgetmaster/utils/ProvidesID.java b/src/main/java/de/deadlocker8/budgetmaster/utils/ProvidesID.java new file mode 100644 index 0000000000000000000000000000000000000000..783961088ae17a25321a68fbc4b99717609d88ab --- /dev/null +++ b/src/main/java/de/deadlocker8/budgetmaster/utils/ProvidesID.java @@ -0,0 +1,6 @@ +package de.deadlocker8.budgetmaster.utils; + +public interface ProvidesID +{ + Integer getID(); +} diff --git a/src/main/resources/languages/base_de.properties b/src/main/resources/languages/base_de.properties index 20d448619f49ab9815979fa9b0b365e9c2b374e1..b98a9810b3c8d8e3394ebc04d7530d43bfdf3599 100644 --- a/src/main/resources/languages/base_de.properties +++ b/src/main/resources/languages/base_de.properties @@ -18,7 +18,8 @@ errorpages.500=Ein interner Serverfehler ist aufgetreten. error.title.database.import=Importfehler error.text.database.import=Beim Importieren der Datei ist ein Fehler aufgetreten.<br>Details:<br>{0} error.database.import.invalid.json=Die hochgeladene JSON Datei ist ungültig. -error.database.import.unknown.version=Die hochgeladene JSON Datei enthält keine gültige Definition einerBudgetMaster Datenbank. +error.database.import.unknown.version=Die hochgeladene JSON Datei enthält keine gültige Definition einer BudgetMaster Datenbank. +error.database.import.version.too.old=Die hochgeladene JSON Datei ist zu alt. Version: {0} Mindestversion: {1} # TITLE title.incomes=Einnahmen @@ -150,6 +151,10 @@ upload.image.error.no.file=Fehler: Keine Datei für Upload angegeben upload.image.error.invalid.extension=Die Dateiendung "{0}" is nicht zugelassen für das Hochladen von Bildern delete.image.success=Erfolgreich gelöscht delete.image.error.not.existing=Fehler: Bild mit ID {0} existiert nicht +upload.image.headline=Bild hochladen +available.images=Verfügbare Bilder + +notification.transaction.add.warning=Konto mit Sichtbarkeit "{0}" erlaubt keine neuen Buchungen! # WARNING warning.text.account.delete=Das Konto "{0}" kann nicht gelöscht werden, da mindestens ein Konto existieren muss. Um dieses Konto zu löschen musst du zuerst ein neues anlegen. diff --git a/src/main/resources/languages/base_en.properties b/src/main/resources/languages/base_en.properties index fee073554594d79783d7f516fbe6c9f5ef183b53..5f2b3f655033105f947c3d47b1ad0022404f96fe 100644 --- a/src/main/resources/languages/base_en.properties +++ b/src/main/resources/languages/base_en.properties @@ -19,6 +19,8 @@ error.title.database.import=Import Error error.text.database.import=An error occurred while importing the file.<br>Details:<br>{0} error.database.import.invalid.json=The uploaded JSON File is invalid. error.database.import.unknown.version=The uploaded JSON File does not contain a valid BudgetMaster database definition. +error.database.import.version.too.old=The uploaded JSON File is too old. Version: {0} Minimum version: {1} + # TITLE title.incomes=Incomes @@ -150,6 +152,10 @@ upload.image.error.no.file=Error: No file provided for upload upload.image.error.invalid.extension=File extension "{0}" is not allowed for image upload delete.image.success=Successfully deleted delete.image.error.not.existing=Error: Image with ID {0} does not exist +upload.image.headline=Upload image +available.images=Available Images + +notification.transaction.add.warning=Account with visibility "{0}" does not allow new transactions! # WARNING warning.text.account.delete=The account "{0}" could not be deleted, because at least one account must exist at all time. You have to create a new account in order to delete this one. diff --git a/src/main/resources/languages/news_de.properties b/src/main/resources/languages/news_de.properties index e7c967912ef2b5fbf101d6ca7cc3edbdb4dab4ec..d07e783300435e0637ffbfddfc61bb1d179fe692 100644 --- a/src/main/resources/languages/news_de.properties +++ b/src/main/resources/languages/news_de.properties @@ -2,6 +2,12 @@ news.further.information=Weitere Informationen news.all.releases=Alle veröffentlichten und geplanten Versionen: news.detailed=Ausführliches Changelog (nur auf Englisch): +news.fix.backup.size.headline=Fix für Dateigröße des Backups +news.fix.backup.size.description=Größe der Backupdateien massiv optimiert. + +news.fix.readonly.accounts.headline=Fix für Konten mit Lesezugriff +news.fix.readonly.accounts.description=Verhindert das Anlegen neuer Buchungen für Konten mit der Sichtbarkeit "Lesezugriff". + news.designOffensive.headline=Die Designoffensive news.designOffensive.description=Wähle für Kategorien ein Icon aus einer vordefinierten Bibliothek oder lade für Konten und Vorlagen eigene Bilder als Icon hoch.<br>Kategorien können in der Buchungsübersicht jetzt auch als Quadrate statt Kreise dargestellt werden.<br>Das gesamte Design wurde verbessert, z.B. durch Icons an Überschriften und Formularfeldern, Benachrichtigungsbannern, uvm. diff --git a/src/main/resources/languages/news_en.properties b/src/main/resources/languages/news_en.properties index 695a1c10127cae4576656d3adee183d17abbf258..360a97e0cebff13aca8e4d91abdc1994ca33c598 100644 --- a/src/main/resources/languages/news_en.properties +++ b/src/main/resources/languages/news_en.properties @@ -2,6 +2,12 @@ news.further.information=Further information news.all.releases=All published and planned releases: news.detailed=More detailed changelog (english only): +news.fix.backup.size.headline=Fix for backup file size +news.fix.backup.size.description=Dramatically optimized the size of the backup files. + +news.fix.readonly.accounts.headline=Fix for read-only accounts +news.fix.readonly.accounts.description=Prevents the creation of new transactions for read-only accounts. + news.designOffensive.headline=The design offensive news.designOffensive.description=Choose from a set of pre-defined set of icons for categories or upload your own images for accounts and templates.<br>Category circles can now be displayed as squares.<br>Improved overall design by adding icons to headlines and form inputs, notification banners, etc. diff --git a/src/main/resources/templates/helpers/imageSelect.ftl b/src/main/resources/templates/helpers/imageSelect.ftl index f4cd497f1d5581703d292cdca4be71c7b439001a..4bef6d187593be485faf1f908d97050d6e2eee98 100644 --- a/src/main/resources/templates/helpers/imageSelect.ftl +++ b/src/main/resources/templates/helpers/imageSelect.ftl @@ -26,7 +26,7 @@ <div class="modal-content center-align"> <div class="row"> <div class="col s12"> - <div class="headline">Upload image</div> + <div class="headline">${locale.getString('upload.image.headline')}</div> </div> </div> @@ -38,7 +38,7 @@ <div class="row"> <div class="col s12"> - <div class="headline">Available images</div> + <div class="headline">${locale.getString('available.images')}</div> </div> </div> diff --git a/src/main/resources/templates/transactions/transactionsMacros.ftl b/src/main/resources/templates/transactions/transactionsMacros.ftl index 6ca95dbb1700c77c8bccfa12f34293774d393fa8..8fdaf57b20d71477352927cf8edc9b3b57752276 100644 --- a/src/main/resources/templates/transactions/transactionsMacros.ftl +++ b/src/main/resources/templates/transactions/transactionsMacros.ftl @@ -96,12 +96,18 @@ <#macro buttons isFilterActive> <div class="row hide-on-small-only valign-wrapper"> - <div class="col s6 right-align transactions-buttons-col"> - <@buttonNew "new-transaction-button-list new-transaction-button-list-large"/> - </div> - <div class="col s6 left-align"> - <@buttonFilter isFilterActive/> - </div> + <#if helpers.getCurrentAccount().getAccountState().name() == 'FULL_ACCESS'> + <div class="col s6 right-align transactions-buttons-col"> + <@buttonNew "new-transaction-button-list new-transaction-button-list-large" helpers.getCurrentAccount()/> + </div> + <div class="col s6 left-align"> + <@buttonFilter isFilterActive/> + </div> + <#else> + <div class="col s12 center-align"> + <@buttonFilter isFilterActive/> + </div> + </#if> </div> <div class="hide-on-med-and-up center-align"> @@ -112,13 +118,17 @@ </div> </div> <div class="col s12 transactions-buttons-col"> - <@buttonNew "new-transaction-button-list "/> + <@buttonNew "new-transaction-button-list " helpers.getCurrentAccount()/> </div> </div> </div> </#macro> -<#macro buttonNew listClasses> +<#macro buttonNew listClasses currentAccount> + <#if currentAccount.getAccountState().name() != 'FULL_ACCESS'> + <#return/> + </#if> + <div class="fixed-action-btn new-transaction-button"> <a class="btn-floating btn-large btn waves-effect waves-light background-blue" id="button-new-transaction"> <i class="material-icons left">add</i>${locale.getString("title.transaction.new.short")} diff --git a/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/AccountTest.java b/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/AccountTest.java index 53ead8513a3e1dc18ff38959180378396f8d2f59..0c2823b26545ed2ca28915d40b314b2eb7a9c9cd 100644 --- a/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/AccountTest.java +++ b/src/test/java/de/deadlocker8/budgetmaster/integration/selenium/AccountTest.java @@ -225,6 +225,25 @@ public class AccountTest assertThat(icons).isEmpty(); } + @Test + public void test_readOnly_preventNewTransaction() + { + TransactionTestHelper.selectGlobalAccountByName(driver, "read only account"); + + driver.get(helper.getUrl() + "/transactions"); + WebDriverWait wait = new WebDriverWait(driver, 5); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("modalFilterTrigger"))); + + assertThat(driver.findElements(By.id("button-new-transaction"))).isEmpty(); + + // try to open new transaction page + driver.get(helper.getUrl() + "/transactions/newTransaction/normal"); + wait = new WebDriverWait(driver, 5); + wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("modalFilterTrigger"))); + + assertThat(driver.findElement(By.cssSelector(".notification.background-yellow")).isDisplayed()).isTrue(); + } + public static void assertAccountColumns(List<WebElement> columns, boolean isDefaultIconVisible, boolean isDefaultIconSelected, AccountState expectedAccountState, String name) { // icons diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/backup/LocalGitBackupTaskTest.java b/src/test/java/de/deadlocker8/budgetmaster/unit/backup/LocalGitBackupTaskTest.java index f40b97f92bd7747e726f732dd946f489e83643b1..8699ea20c9fcb334f305195a569fd86295fda097 100644 --- a/src/test/java/de/deadlocker8/budgetmaster/unit/backup/LocalGitBackupTaskTest.java +++ b/src/test/java/de/deadlocker8/budgetmaster/unit/backup/LocalGitBackupTaskTest.java @@ -4,10 +4,10 @@ import de.deadlocker8.budgetmaster.backup.AutoBackupStrategy; import de.deadlocker8.budgetmaster.backup.BackupStatus; import de.deadlocker8.budgetmaster.backup.BackupTask; import de.deadlocker8.budgetmaster.backup.LocalGitBackupTask; -import de.deadlocker8.budgetmaster.categories.Category; import de.deadlocker8.budgetmaster.categories.CategoryType; -import de.deadlocker8.budgetmaster.database.Database; import de.deadlocker8.budgetmaster.database.DatabaseService; +import de.deadlocker8.budgetmaster.database.model.v5.BackupCategory_v5; +import de.deadlocker8.budgetmaster.database.model.v6.BackupDatabase_v6; import de.deadlocker8.budgetmaster.settings.Settings; import de.deadlocker8.budgetmaster.settings.SettingsService; import de.deadlocker8.budgetmaster.unit.helpers.Helpers; @@ -103,7 +103,7 @@ public class LocalGitBackupTaskTest final Path repositoryFolder = tempFolder.newFolder().toPath().resolve(".git"); - final Database database = new Database(); + final BackupDatabase_v6 database = new BackupDatabase_v6(); Mockito.when(databaseService.getDatabaseForJsonSerialization()).thenReturn(database); Mockito.doCallRealMethod().when(databaseService).exportDatabase(Mockito.any()); @@ -131,7 +131,7 @@ public class LocalGitBackupTaskTest final Path repositoryFolder = tempFolder.newFolder().toPath().resolve(".git"); - final Database database = new Database(); + final BackupDatabase_v6 database = new BackupDatabase_v6(); Mockito.when(databaseService.getDatabaseForJsonSerialization()).thenReturn(database); Mockito.doCallRealMethod().when(databaseService).exportDatabase(Mockito.any()); @@ -155,7 +155,7 @@ public class LocalGitBackupTaskTest final Path repositoryFolder = tempFolder.newFolder().toPath().resolve(".git"); - final Database database = new Database(); + final BackupDatabase_v6 database = new BackupDatabase_v6(); Mockito.when(databaseService.getDatabaseForJsonSerialization()).thenReturn(database); Mockito.doCallRealMethod().when(databaseService).exportDatabase(Mockito.any()); @@ -163,7 +163,7 @@ public class LocalGitBackupTaskTest localGitBackupTask.setGitFolder(repositoryFolder); localGitBackupTask.run(); - final Database databaseModified = new Database(List.of(new Category("myCategory", "#FF0000", CategoryType.CUSTOM)), List.of(), List.of(), List.of(), List.of(), List.of()); + final BackupDatabase_v6 databaseModified = new BackupDatabase_v6(List.of(new BackupCategory_v5(5, "myCategory", "#FF0000", CategoryType.CUSTOM, null)), List.of(), List.of(), List.of(), List.of(), List.of()); Mockito.when(databaseService.getDatabaseForJsonSerialization()).thenReturn(databaseModified); localGitBackupTask.run(); diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/backup/RemoteGitBackupTaskTest.java b/src/test/java/de/deadlocker8/budgetmaster/unit/backup/RemoteGitBackupTaskTest.java index d5978c4742a296f5b323fec325e98842fd23deb3..5b7cdedf96ff5a6d58c551a0fc5082bbb9f03f2e 100644 --- a/src/test/java/de/deadlocker8/budgetmaster/unit/backup/RemoteGitBackupTaskTest.java +++ b/src/test/java/de/deadlocker8/budgetmaster/unit/backup/RemoteGitBackupTaskTest.java @@ -1,10 +1,13 @@ package de.deadlocker8.budgetmaster.unit.backup; -import de.deadlocker8.budgetmaster.backup.*; -import de.deadlocker8.budgetmaster.categories.Category; +import de.deadlocker8.budgetmaster.backup.AutoBackupStrategy; +import de.deadlocker8.budgetmaster.backup.BackupStatus; +import de.deadlocker8.budgetmaster.backup.BackupTask; +import de.deadlocker8.budgetmaster.backup.RemoteGitBackupTask; import de.deadlocker8.budgetmaster.categories.CategoryType; -import de.deadlocker8.budgetmaster.database.Database; import de.deadlocker8.budgetmaster.database.DatabaseService; +import de.deadlocker8.budgetmaster.database.model.v5.BackupCategory_v5; +import de.deadlocker8.budgetmaster.database.model.v6.BackupDatabase_v6; import de.deadlocker8.budgetmaster.settings.Settings; import de.deadlocker8.budgetmaster.settings.SettingsService; import de.deadlocker8.budgetmaster.unit.helpers.Helpers; @@ -21,7 +24,6 @@ import org.mockito.Mockito; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.util.List; @@ -215,7 +217,7 @@ public class RemoteGitBackupTaskTest final RemoteGitBackupTask remoteGitBackupTask = createBackupTask(repositoryFolder, fakeServerFolder); remoteGitBackupTask.run(); - final Database databaseModified = new Database(List.of(new Category("myCategory", "#FF0000", CategoryType.CUSTOM)), List.of(), List.of(), List.of(), List.of(), List.of()); + final BackupDatabase_v6 databaseModified = new BackupDatabase_v6(List.of(new BackupCategory_v5(5, "myCategory", "#FF0000", CategoryType.CUSTOM, null)), List.of(), List.of(), List.of(), List.of(), List.of()); Mockito.when(databaseService.getDatabaseForJsonSerialization()).thenReturn(databaseModified); remoteGitBackupTask.run(); @@ -255,7 +257,7 @@ public class RemoteGitBackupTaskTest settings.setAutoBackupGitToken("0815"); Mockito.when(settingsService.getSettings()).thenReturn(settings); - final Database database = new Database(); + final BackupDatabase_v6 database = new BackupDatabase_v6(); Mockito.when(databaseService.getDatabaseForJsonSerialization()).thenReturn(database); Mockito.doCallRealMethod().when(databaseService).exportDatabase(Mockito.any()); diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseExportTest.java b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseExportTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3e0648db995343192961f9b61bec836d66f14c23 --- /dev/null +++ b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseExportTest.java @@ -0,0 +1,267 @@ +package de.deadlocker8.budgetmaster.unit.database; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import de.deadlocker8.budgetmaster.accounts.Account; +import de.deadlocker8.budgetmaster.accounts.AccountRepository; +import de.deadlocker8.budgetmaster.accounts.AccountService; +import de.deadlocker8.budgetmaster.accounts.AccountType; +import de.deadlocker8.budgetmaster.categories.Category; +import de.deadlocker8.budgetmaster.categories.CategoryService; +import de.deadlocker8.budgetmaster.categories.CategoryType; +import de.deadlocker8.budgetmaster.charts.Chart; +import de.deadlocker8.budgetmaster.charts.ChartRepository; +import de.deadlocker8.budgetmaster.charts.ChartService; +import de.deadlocker8.budgetmaster.charts.ChartType; +import de.deadlocker8.budgetmaster.database.DatabaseParser; +import de.deadlocker8.budgetmaster.database.DatabaseService; +import de.deadlocker8.budgetmaster.database.InternalDatabase; +import de.deadlocker8.budgetmaster.database.JSONIdentifier; +import de.deadlocker8.budgetmaster.images.Image; +import de.deadlocker8.budgetmaster.images.ImageFileExtension; +import de.deadlocker8.budgetmaster.images.ImageRepository; +import de.deadlocker8.budgetmaster.images.ImageService; +import de.deadlocker8.budgetmaster.repeating.RepeatingOption; +import de.deadlocker8.budgetmaster.repeating.endoption.RepeatingEndAfterXTimes; +import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierDays; +import de.deadlocker8.budgetmaster.settings.SettingsService; +import de.deadlocker8.budgetmaster.tags.Tag; +import de.deadlocker8.budgetmaster.tags.TagService; +import de.deadlocker8.budgetmaster.templates.Template; +import de.deadlocker8.budgetmaster.templates.TemplateRepository; +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.thecodelabs.utils.util.Localization; +import org.joda.time.DateTime; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringJUnit4ClassRunner.class) +public class DatabaseExportTest +{ + @Before + public void before() + { + Localization.setDelegate(new Localization.LocalizationDelegate() + { + @Override + public Locale getLocale() + { + return Locale.ENGLISH; + } + + @Override + public String getBaseResource() + { + return "languages/base"; + } + }); + Localization.load(); + } + + @Mock + private AccountService accountService; + + @Mock + private CategoryService categoryService; + + @Mock + private TransactionService transactionService; + + @Mock + private TagService tagService; + + @Mock + private TemplateService templateService; + + @Mock + private ChartService chartService; + + @Mock + private SettingsService settingsService; + + @Mock + private ImageService imageService; + + @InjectMocks + private DatabaseService databaseService; + + @Rule + public final TemporaryFolder tempFolder = new TemporaryFolder(); + + @Test + public void test_specialFields() throws IOException + { + // categories + Mockito.when(categoryService.getAllEntitiesAsc()).thenReturn(List.of()); + + // accounts + AccountRepository accountRepositoryMock = Mockito.mock(AccountRepository.class); + Mockito.when(accountRepositoryMock.findAll()).thenReturn(List.of()); + Mockito.when(accountService.getRepository()).thenReturn(accountRepositoryMock); + + // transactions + TransactionRepository transactionRepositoryMock = Mockito.mock(TransactionRepository.class); + Mockito.when(transactionRepositoryMock.findAll()).thenReturn(List.of()); + Mockito.when(transactionService.getRepository()).thenReturn(transactionRepositoryMock); + + // templates + TemplateRepository templateRepositoryMock = Mockito.mock(TemplateRepository.class); + Mockito.when(templateRepositoryMock.findAll()).thenReturn(List.of()); + Mockito.when(templateService.getRepository()).thenReturn(templateRepositoryMock); + + // charts + ChartRepository chartRepositoryMock = Mockito.mock(ChartRepository.class); + Mockito.when(chartRepositoryMock.findAllByType(Mockito.any())).thenReturn(List.of()); + Mockito.when(chartService.getRepository()).thenReturn(chartRepositoryMock); + + // images + ImageRepository imageRepositoryMock = Mockito.mock(ImageRepository.class); + Mockito.when(imageRepositoryMock.findAll()).thenReturn(List.of()); + Mockito.when(imageService.getRepository()).thenReturn(imageRepositoryMock); + + + // act + Path exportPath = tempFolder.newFile("exportTest.json").toPath(); + databaseService.exportDatabase(exportPath); + + + // assert + String fileContent = Files.readString(exportPath, StandardCharsets.UTF_8); + JsonObject root = JsonParser.parseString(fileContent).getAsJsonObject(); + + assertThat(root.get("TYPE").getAsString()).isEqualTo(JSONIdentifier.BUDGETMASTER_DATABASE.toString()); + assertThat(root.get("VERSION").getAsInt()).isEqualTo(DatabaseParser.LATEST_VERSION); + } + + @Test + public void test_exportDatabase() throws IOException + { + // categories + Category categoryNone = new Category("NONE", "#000000", CategoryType.NONE); + categoryNone.setID(1); + Category categoryCustom = new Category("my First Category", "#FF0000", CategoryType.CUSTOM); + categoryCustom.setID(2); + Mockito.when(categoryService.getAllEntitiesAsc()).thenReturn(List.of(categoryNone, categoryCustom)); + + // accounts + Account account1 = new Account("Source_Account_1", AccountType.CUSTOM); + account1.setID(2); + Account account2 = new Account("Source_Account_2", AccountType.CUSTOM); + account2.setID(3); + + AccountRepository accountRepositoryMock = Mockito.mock(AccountRepository.class); + Mockito.when(accountRepositoryMock.findAll()).thenReturn(List.of(account1, account2)); + Mockito.when(accountService.getRepository()).thenReturn(accountRepositoryMock); + + // tags + Tag tag1 = new Tag("Car"); + List<Tag> tags = new ArrayList<>(); + tags.add(tag1); + + // transactions + Transaction transaction1 = new Transaction(); + transaction1.setAccount(account1); + transaction1.setCategory(categoryNone); + transaction1.setName("ShouldGoInAccount_1"); + transaction1.setAmount(200); + transaction1.setIsExpenditure(false); + transaction1.setDate(new DateTime(2018, 10, 3, 12, 0, 0, 0)); + transaction1.setTags(tags); + + Transaction transaction2 = new Transaction(); + transaction2.setAccount(account2); + transaction2.setCategory(categoryCustom); + transaction2.setName("ImPartOfAccount_2"); + transaction2.setAmount(-525); + transaction2.setIsExpenditure(true); + DateTime transaction2Date = new DateTime(2018, 10, 3, 12, 0, 0, 0); + transaction2.setDate(transaction2Date); + transaction2.setTags(new ArrayList<>()); + RepeatingOption repeatingOption = new RepeatingOption(transaction2Date, + new RepeatingModifierDays(3), + new RepeatingEndAfterXTimes(3)); + transaction2.setRepeatingOption(repeatingOption); + + TransactionRepository transactionRepositoryMock = Mockito.mock(TransactionRepository.class); + Mockito.when(transactionRepositoryMock.findAll()).thenReturn(List.of(transaction1, transaction2)); + Mockito.when(transactionService.getRepository()).thenReturn(transactionRepositoryMock); + + // templates + Template template1 = new Template(); + template1.setTemplateName("MyTemplate"); + template1.setAmount(1500); + template1.setIsExpenditure(false); + template1.setAccount(account1); + template1.setName("Transaction from Template"); + List<Tag> tags2 = new ArrayList<>(); + tags2.add(tag1); + template1.setTags(tags2); + + Template template2 = new Template(); + template2.setTemplateName("MyTemplate2"); + template2.setTransferAccount(account2); + template2.setIsExpenditure(true); + template2.setTags(new ArrayList<>()); + + TemplateRepository templateRepositoryMock = Mockito.mock(TemplateRepository.class); + Mockito.when(templateRepositoryMock.findAll()).thenReturn(List.of(template1, template2)); + Mockito.when(templateService.getRepository()).thenReturn(templateRepositoryMock); + + // charts + Chart chart = new Chart(); + chart.setID(9); + chart.setName("The best chart"); + chart.setType(ChartType.CUSTOM); + chart.setVersion(7); + chart.setScript("/* 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"); + + ChartRepository chartRepositoryMock = Mockito.mock(ChartRepository.class); + Mockito.when(chartRepositoryMock.findAllByType(Mockito.any())).thenReturn(List.of(chart)); + Mockito.when(chartService.getRepository()).thenReturn(chartRepositoryMock); + + // images + final Image image = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); + image.setID(12); + + ImageRepository imageRepositoryMock = Mockito.mock(ImageRepository.class); + Mockito.when(imageRepositoryMock.findAll()).thenReturn(List.of(image)); + Mockito.when(imageService.getRepository()).thenReturn(imageRepositoryMock); + + + // act + Path exportPath = tempFolder.newFile("exportTest.json").toPath(); + databaseService.exportDatabase(exportPath); + + // assert + String fileContent = Files.readString(exportPath, StandardCharsets.UTF_8); + DatabaseParser importer = new DatabaseParser(fileContent); + InternalDatabase importedDatabase = importer.parseDatabaseFromJSON(); + + assertThat(importedDatabase.getCategories()).containsExactly(categoryNone, categoryCustom); + assertThat(importedDatabase.getAccounts()).containsExactly(account1, account2); + assertThat(importedDatabase.getTransactions()).containsExactly(transaction1, transaction2); + assertThat(importedDatabase.getTemplates()).containsExactly(template1, template2); + assertThat(importedDatabase.getCharts()).containsExactly(chart); + assertThat(importedDatabase.getImages()).containsExactly(image); + } +} diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParserTest.java b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParserTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d514bd46eecff44c4a4cdf7d235f0f4c9c79a340 --- /dev/null +++ b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParserTest.java @@ -0,0 +1,99 @@ +package de.deadlocker8.budgetmaster.unit.database; + +import de.deadlocker8.budgetmaster.database.InternalDatabase; +import de.deadlocker8.budgetmaster.database.DatabaseParser; +import de.thecodelabs.utils.util.Localization; +import de.thecodelabs.utils.util.Localization.LocalizationDelegate; +import de.thecodelabs.utils.util.localization.LocalizationMessageFormatter; +import de.thecodelabs.utils.util.localization.formatter.JavaMessageFormatter; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + + +public class DatabaseParserTest +{ + @Before + public void before() + { + Localization.setDelegate(new LocalizationDelegate() + { + @Override + public Locale getLocale() + { + return Locale.ENGLISH; + } + + @Override + public LocalizationMessageFormatter messageFormatter() + { + return new JavaMessageFormatter(); + } + + @Override + public String getBaseResource() + { + return "languages/base"; + } + }); + Localization.load(); + } + + @Test + public void test_v6() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser importer = new DatabaseParser(json); + final InternalDatabase database = importer.parseDatabaseFromJSON(); + assertThat(database.getTransactions()) + .hasSize(4); + } + + @Test + public void test_v5() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v5Test.json").toURI()))); + DatabaseParser importer = new DatabaseParser(json); + final InternalDatabase database = importer.parseDatabaseFromJSON(); + assertThat(database.getTransactions()) + .hasSize(4); + } + + @Test + public void test_v4() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v4Test.json").toURI()))); + DatabaseParser importer = new DatabaseParser(json); + final InternalDatabase database = importer.parseDatabaseFromJSON(); + assertThat(database.getTransactions()) + .hasSize(4); + } + + @Test + public void test_v3() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v3Test.json").toURI()))); + DatabaseParser importer = new DatabaseParser(json); + assertThatThrownBy(importer::parseDatabaseFromJSON) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("too old"); + } + + @Test + public void test_v2() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("LegacyParserTest.json").toURI()))); + DatabaseParser importer = new DatabaseParser(json); + assertThatThrownBy(importer::parseDatabaseFromJSON) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("too old"); + } +} \ No newline at end of file diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v3Test.java b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v3Test.java deleted file mode 100644 index 8c95337e1ed811dcab829af6cc24b44bb0911f41..0000000000000000000000000000000000000000 --- a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v3Test.java +++ /dev/null @@ -1,204 +0,0 @@ -package de.deadlocker8.budgetmaster.unit.database; - -import de.deadlocker8.budgetmaster.accounts.Account; -import de.deadlocker8.budgetmaster.accounts.AccountType; -import de.deadlocker8.budgetmaster.categories.Category; -import de.deadlocker8.budgetmaster.categories.CategoryType; -import de.deadlocker8.budgetmaster.database.Database; -import de.deadlocker8.budgetmaster.database.DatabaseParser_v3; -import de.deadlocker8.budgetmaster.repeating.RepeatingOption; -import de.deadlocker8.budgetmaster.repeating.endoption.RepeatingEndAfterXTimes; -import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierDays; -import de.deadlocker8.budgetmaster.tags.Tag; -import de.deadlocker8.budgetmaster.transactions.Transaction; -import de.thecodelabs.utils.util.Localization; -import de.thecodelabs.utils.util.Localization.LocalizationDelegate; -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; -import org.junit.Before; -import org.junit.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; - -public class DatabaseParser_v3Test -{ - @Before - public void before() - { - Localization.setDelegate(new LocalizationDelegate() - { - @Override - public Locale getLocale() - { - return Locale.ENGLISH; - } - - @Override - public String getBaseResource() - { - return "languages/base"; - } - }); - Localization.load(); - } - - @Test - public void test_Categories() - { - try - { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v3Test.json").toURI()))); - DatabaseParser_v3 importer = new DatabaseParser_v3(json); - Database database = importer.parseDatabaseFromJSON(); - - final Category categoryNone = new Category("Keine Kategorie", "#FFFFFF", CategoryType.NONE); - categoryNone.setID(1); - - final Category categoryRest = new Category("Übertrag", "#FFFF00", CategoryType.REST); - categoryRest.setID(2); - - final Category category3 = new Category("0815", "#ffcc00", CategoryType.CUSTOM); - category3.setID(3); - - assertThat(database.getCategories()).hasSize(3) - .containsExactlyInAnyOrder(categoryNone, categoryRest, category3); - } - catch(IOException | URISyntaxException e) - { - e.printStackTrace(); - } - } - - @Test - public void test_Accounts() - { - try - { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v3Test.json").toURI()))); - DatabaseParser_v3 importer = new DatabaseParser_v3(json); - Database database = importer.parseDatabaseFromJSON(); - - final Account expectedAccount1 = new Account("Placeholder", AccountType.ALL); - expectedAccount1.setID(1); - - final Account expectedAccount2 = new Account("Default", AccountType.CUSTOM); - expectedAccount2.setID(2); - - final Account expectedAccount3 = new Account("Second Account", AccountType.CUSTOM); - expectedAccount3.setID(3); - - assertThat(database.getAccounts()).hasSize(3) - .containsExactlyInAnyOrder(expectedAccount1, expectedAccount2, expectedAccount3); - } - catch(IOException | URISyntaxException e) - { - e.printStackTrace(); - } - } - - @Test - public void test_Transactions() - { - try - { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v3Test.json").toURI()))); - DatabaseParser_v3 importer = new DatabaseParser_v3(json); - Database database = importer.parseDatabaseFromJSON(); - - Account account1 = new Account("Default", AccountType.CUSTOM); - account1.setID(2); - - Account account2 = new Account("Second Account", AccountType.CUSTOM); - account2.setID(3); - - Category categoryNone = new Category("Keine Kategorie", "#FFFFFF", CategoryType.NONE); - categoryNone.setID(1); - - Category category3 = new Category("0815", "#ffcc00", CategoryType.CUSTOM); - category3.setID(3); - - Transaction normalTransaction_1 = new Transaction(); - normalTransaction_1.setAmount(35000); - normalTransaction_1.setDate(DateTime.parse("2018-03-13", DateTimeFormat.forPattern("yyyy-MM-dd"))); - normalTransaction_1.setCategory(categoryNone); - normalTransaction_1.setName("Income"); - normalTransaction_1.setDescription("Lorem Ipsum"); - normalTransaction_1.setTags(new ArrayList<>()); - normalTransaction_1.setAccount(account1); - - Transaction normalTransaction_2 = new Transaction(); - normalTransaction_2.setAmount(-2000); - normalTransaction_2.setDate(DateTime.parse("2018-06-15", DateTimeFormat.forPattern("yyyy-MM-dd"))); - normalTransaction_2.setName("Simple"); - normalTransaction_2.setDescription(""); - normalTransaction_2.setAccount(account2); - normalTransaction_2.setCategory(category3); - - List<Tag> tags = new ArrayList<>(); - Tag tag = new Tag("0815"); - tag.setID(1); - tags.add(tag); - normalTransaction_2.setTags(tags); - - Transaction repeatingTransaction_1 = new Transaction(); - repeatingTransaction_1.setAmount(-12300); - DateTime repeatingTransactionDate_1 = DateTime.parse("2018-03-13", DateTimeFormat.forPattern("yyyy-MM-dd")); - repeatingTransaction_1.setDate(repeatingTransactionDate_1); - repeatingTransaction_1.setCategory(categoryNone); - repeatingTransaction_1.setName("Test"); - repeatingTransaction_1.setDescription(""); - repeatingTransaction_1.setAccount(account1); - RepeatingOption repeatingOption_1 = new RepeatingOption(); - repeatingOption_1.setModifier(new RepeatingModifierDays(10)); - repeatingOption_1.setStartDate(repeatingTransactionDate_1); - repeatingOption_1.setEndOption(new RepeatingEndAfterXTimes(2)); - repeatingTransaction_1.setRepeatingOption(repeatingOption_1); - repeatingTransaction_1.setTags(new ArrayList<>()); - - Transaction repeatingTransaction_2 = new Transaction(); - repeatingTransaction_2.setAmount(-12300); - DateTime repeatingTransactionDate_2 = DateTime.parse("2018-03-23", DateTimeFormat.forPattern("yyyy-MM-dd")); - repeatingTransaction_2.setDate(repeatingTransactionDate_2); - repeatingTransaction_2.setCategory(categoryNone); - repeatingTransaction_2.setName("Test"); - repeatingTransaction_2.setDescription(""); - repeatingTransaction_2.setAccount(account1); - RepeatingOption repeatingOption_2 = new RepeatingOption(); - repeatingOption_2.setModifier(new RepeatingModifierDays(10)); - repeatingOption_2.setStartDate(repeatingTransactionDate_2); - repeatingOption_2.setEndOption(new RepeatingEndAfterXTimes(2)); - repeatingTransaction_2.setRepeatingOption(repeatingOption_2); - repeatingTransaction_2.setTags(new ArrayList<>()); - - Transaction transferTransaction = new Transaction(); - transferTransaction.setAmount(-250); - transferTransaction.setDate(DateTime.parse("2018-06-15", DateTimeFormat.forPattern("yyyy-MM-dd"))); - transferTransaction.setName("Transfer"); - transferTransaction.setDescription(""); - transferTransaction.setAccount(account2); - transferTransaction.setTransferAccount(account1); - transferTransaction.setCategory(category3); - transferTransaction.setTags(new ArrayList<>()); - - assertThat(database.getTransactions()).hasSize(6) - .contains(normalTransaction_1, - normalTransaction_2, - repeatingTransaction_1, - repeatingTransaction_2, - transferTransaction); - - } - catch(IOException | URISyntaxException e) - { - e.printStackTrace(); - } - } -} diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v4Test.java b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v4Test.java index f4d4084101ca9d1dc7884d6945d3eb4361ffcc02..bd0b3a64fa42906942fb1ece72d06cca846729de 100644 --- a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v4Test.java +++ b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v4Test.java @@ -1,21 +1,14 @@ package de.deadlocker8.budgetmaster.unit.database; -import de.deadlocker8.budgetmaster.accounts.Account; import de.deadlocker8.budgetmaster.accounts.AccountType; -import de.deadlocker8.budgetmaster.categories.Category; import de.deadlocker8.budgetmaster.categories.CategoryType; -import de.deadlocker8.budgetmaster.database.Database; import de.deadlocker8.budgetmaster.database.DatabaseParser_v4; -import de.deadlocker8.budgetmaster.repeating.RepeatingOption; +import de.deadlocker8.budgetmaster.database.model.v4.*; import de.deadlocker8.budgetmaster.repeating.endoption.RepeatingEndAfterXTimes; 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.thecodelabs.utils.util.Localization; import de.thecodelabs.utils.util.Localization.LocalizationDelegate; -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; import org.junit.Before; import org.junit.Test; @@ -27,7 +20,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.*; public class DatabaseParser_v4Test @@ -58,17 +51,12 @@ public class DatabaseParser_v4Test try { String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v4Test.json").toURI()))); - DatabaseParser_v4 importer = new DatabaseParser_v4(json); - Database database = importer.parseDatabaseFromJSON(); + DatabaseParser_v4 parser = new DatabaseParser_v4(json); + BackupDatabase_v4 database = parser.parseDatabaseFromJSON(); - final Category categoryNone = new Category("Keine Kategorie", "#FFFFFF", CategoryType.NONE); - categoryNone.setID(1); - - final Category categoryRest = new Category("Übertrag", "#FFFF00", CategoryType.REST); - categoryRest.setID(2); - - final Category category3 = new Category("0815", "#ffcc00", CategoryType.CUSTOM); - category3.setID(3); + final BackupCategory_v4 categoryNone = new BackupCategory_v4(1, "Keine Kategorie", "#FFFFFF", CategoryType.NONE); + final BackupCategory_v4 categoryRest = new BackupCategory_v4(2, "Übertrag", "#FFFF00", CategoryType.REST); + final BackupCategory_v4 category3 = new BackupCategory_v4(3, "0815", "#ffcc00", CategoryType.CUSTOM); assertThat(database.getCategories()).hasSize(3) .contains(categoryNone, categoryRest, category3); @@ -85,8 +73,8 @@ public class DatabaseParser_v4Test try { String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v4Test.json").toURI()))); - DatabaseParser_v4 importer = new DatabaseParser_v4(json); - Database database = importer.parseDatabaseFromJSON(); + DatabaseParser_v4 parser = new DatabaseParser_v4(json); + BackupDatabase_v4 database = parser.parseDatabaseFromJSON(); assertThat(database.getAccounts()).hasSize(3); assertThat(database.getAccounts().get(0)).hasFieldOrPropertyWithValue("name", "Placeholder"); @@ -105,94 +93,73 @@ public class DatabaseParser_v4Test try { String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v4Test.json").toURI()))); - DatabaseParser_v4 importer = new DatabaseParser_v4(json); - Database database = importer.parseDatabaseFromJSON(); - - Account account1 = new Account("Default", AccountType.CUSTOM); - account1.setID(2); + DatabaseParser_v4 parser = new DatabaseParser_v4(json); + BackupDatabase_v4 database = parser.parseDatabaseFromJSON(); - Account account2 = new Account("Second Account", AccountType.CUSTOM); - account2.setID(3); + BackupAccount_v4 account1 = new BackupAccount_v4(2, "Default", AccountType.CUSTOM); + BackupAccount_v4 account2 = new BackupAccount_v4(3, "Second Account", AccountType.CUSTOM); - Category categoryNone = new Category("Keine Kategorie", "#FFFFFF", CategoryType.NONE); - categoryNone.setID(1); + BackupCategory_v4 categoryNone = new BackupCategory_v4(1, "Keine Kategorie", "#FFFFFF", CategoryType.NONE); + BackupCategory_v4 category3 = new BackupCategory_v4(3, "0815", "#ffcc00", CategoryType.CUSTOM); - Category category3 = new Category("0815", "#ffcc00", CategoryType.CUSTOM); - category3.setID(3); - - Transaction normalTransaction_1 = new Transaction(); + BackupTransaction_v4 normalTransaction_1 = new BackupTransaction_v4(); normalTransaction_1.setAmount(35000); - normalTransaction_1.setDate(DateTime.parse("2018-03-13", DateTimeFormat.forPattern("yyyy-MM-dd"))); + normalTransaction_1.setDate("2018-03-13"); normalTransaction_1.setCategory(categoryNone); normalTransaction_1.setName("Income"); normalTransaction_1.setDescription("Lorem Ipsum"); normalTransaction_1.setTags(new ArrayList<>()); normalTransaction_1.setAccount(account1); - normalTransaction_1.setIsExpenditure(false); + normalTransaction_1.setExpenditure(false); - Transaction normalTransaction_2 = new Transaction(); + BackupTransaction_v4 normalTransaction_2 = new BackupTransaction_v4(); normalTransaction_2.setAmount(-2000); - normalTransaction_2.setDate(DateTime.parse("2018-06-15", DateTimeFormat.forPattern("yyyy-MM-dd"))); + normalTransaction_2.setDate("2018-06-15"); normalTransaction_2.setName("Simple"); normalTransaction_2.setDescription(""); normalTransaction_2.setAccount(account2); normalTransaction_2.setCategory(category3); - normalTransaction_2.setIsExpenditure(true); + normalTransaction_2.setExpenditure(true); - List<Tag> tags = new ArrayList<>(); - Tag tag = new Tag("0815"); - tag.setID(1); + List<BackupTag_v4> tags = new ArrayList<>(); + BackupTag_v4 tag = new BackupTag_v4("0815"); tags.add(tag); normalTransaction_2.setTags(tags); - Transaction repeatingTransaction_1 = new Transaction(); + BackupTransaction_v4 repeatingTransaction_1 = new BackupTransaction_v4(); repeatingTransaction_1.setAmount(-12300); - DateTime repeatingTransactionDate_1 = DateTime.parse("2018-03-13", DateTimeFormat.forPattern("yyyy-MM-dd")); + String repeatingTransactionDate_1 = "2018-03-13"; repeatingTransaction_1.setDate(repeatingTransactionDate_1); repeatingTransaction_1.setCategory(categoryNone); repeatingTransaction_1.setName("Test"); repeatingTransaction_1.setDescription(""); repeatingTransaction_1.setAccount(account1); - RepeatingOption repeatingOption_1 = new RepeatingOption(); - repeatingOption_1.setModifier(new RepeatingModifierDays(10)); + BackupRepeatingOption_v4 repeatingOption_1 = new BackupRepeatingOption_v4(); + repeatingOption_1.setModifier(new BackupRepeatingModifier_v4(10, new RepeatingModifierDays(10).getLocalizationKey())); repeatingOption_1.setStartDate(repeatingTransactionDate_1); - repeatingOption_1.setEndOption(new RepeatingEndAfterXTimes(2)); + BackupRepeatingEndOption_v4 repeatingEndOption = new BackupRepeatingEndOption_v4(); + repeatingEndOption.setTimes(2); + repeatingEndOption.setLocalizationKey(new RepeatingEndAfterXTimes(10).getLocalizationKey()); + repeatingOption_1.setEndOption(repeatingEndOption); repeatingTransaction_1.setRepeatingOption(repeatingOption_1); repeatingTransaction_1.setTags(new ArrayList<>()); - repeatingTransaction_1.setIsExpenditure(true); - - Transaction repeatingTransaction_2 = new Transaction(); - repeatingTransaction_2.setAmount(-12300); - DateTime repeatingTransactionDate_2 = DateTime.parse("2018-03-23", DateTimeFormat.forPattern("yyyy-MM-dd")); - repeatingTransaction_2.setDate(repeatingTransactionDate_2); - repeatingTransaction_2.setCategory(categoryNone); - repeatingTransaction_2.setName("Test"); - repeatingTransaction_2.setDescription(""); - repeatingTransaction_2.setAccount(account1); - RepeatingOption repeatingOption_2 = new RepeatingOption(); - repeatingOption_2.setModifier(new RepeatingModifierDays(10)); - repeatingOption_2.setStartDate(repeatingTransactionDate_2); - repeatingOption_2.setEndOption(new RepeatingEndAfterXTimes(2)); - repeatingTransaction_2.setRepeatingOption(repeatingOption_2); - repeatingTransaction_2.setTags(new ArrayList<>()); - repeatingTransaction_2.setIsExpenditure(true); - - Transaction transferTransaction = new Transaction(); + repeatingTransaction_1.setExpenditure(true); + + BackupTransaction_v4 transferTransaction = new BackupTransaction_v4(); transferTransaction.setAmount(-250); - transferTransaction.setDate(DateTime.parse("2018-06-15", DateTimeFormat.forPattern("yyyy-MM-dd"))); + transferTransaction.setDate("2018-06-15"); transferTransaction.setName("Transfer"); transferTransaction.setDescription(""); transferTransaction.setAccount(account2); transferTransaction.setTransferAccount(account1); transferTransaction.setCategory(category3); transferTransaction.setTags(new ArrayList<>()); - transferTransaction.setIsExpenditure(true); + transferTransaction.setExpenditure(true); - assertThat(database.getTransactions()).hasSize(6) + assertThat(database.getTransactions()).hasSize(4) .contains(normalTransaction_1, normalTransaction_2, repeatingTransaction_1, - repeatingTransaction_2, transferTransaction); } @@ -208,42 +175,35 @@ public class DatabaseParser_v4Test try { String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v4Test.json").toURI()))); - DatabaseParser_v4 importer = new DatabaseParser_v4(json); - Database database = importer.parseDatabaseFromJSON(); - - Account account1 = new Account("Default", AccountType.CUSTOM); - account1.setID(2); + DatabaseParser_v4 parser = new DatabaseParser_v4(json); + BackupDatabase_v4 database = parser.parseDatabaseFromJSON(); - Account account2 = new Account("Second Account", AccountType.CUSTOM); - account2.setID(3); + BackupAccount_v4 account1 = new BackupAccount_v4(2, "Default", AccountType.CUSTOM); + BackupAccount_v4 account2 = new BackupAccount_v4(3, "Second Account", AccountType.CUSTOM); - Category categoryNone = new Category("Keine Kategorie", "#FFFFFF", CategoryType.NONE); - categoryNone.setID(1); + BackupCategory_v4 categoryNone = new BackupCategory_v4(1, "Keine Kategorie", "#FFFFFF", CategoryType.NONE); + BackupCategory_v4 category3 = new BackupCategory_v4(3, "0815", "#ffcc00", CategoryType.CUSTOM); - Category category3 = new Category("0815", "#ffcc00", CategoryType.CUSTOM); - category3.setID(3); - - Template normalTemplate = new Template(); + BackupTemplate_v4 normalTemplate = new BackupTemplate_v4(); normalTemplate.setAmount(1500); normalTemplate.setName("Income"); normalTemplate.setTemplateName("My Simple Template"); normalTemplate.setDescription("Lorem Ipsum"); normalTemplate.setAccount(account1); normalTemplate.setCategory(categoryNone); - normalTemplate.setIsExpenditure(false); + normalTemplate.setExpenditure(false); - List<Tag> tags = new ArrayList<>(); - Tag tag = new Tag("0815"); - tag.setID(1); + List<BackupTag_v4> tags = new ArrayList<>(); + BackupTag_v4 tag = new BackupTag_v4("0815"); tags.add(tag); normalTemplate.setTags(tags); - Template minimalTemplate = new Template(); + BackupTemplate_v4 minimalTemplate = new BackupTemplate_v4(); minimalTemplate.setTemplateName("My Minimal Template"); minimalTemplate.setTags(new ArrayList<>()); - minimalTemplate.setIsExpenditure(true); + minimalTemplate.setExpenditure(true); - Template transferTemplate = new Template(); + BackupTemplate_v4 transferTemplate = new BackupTemplate_v4(); transferTemplate.setTemplateName("My Transfer Template"); transferTemplate.setAmount(-35000); transferTemplate.setAccount(account2); @@ -252,7 +212,7 @@ public class DatabaseParser_v4Test transferTemplate.setDescription("Lorem Ipsum"); transferTemplate.setCategory(category3); transferTemplate.setTags(tags); - transferTemplate.setIsExpenditure(true); + transferTemplate.setExpenditure(true); assertThat(database.getTemplates()).hasSize(3) .contains(normalTemplate, minimalTemplate, transferTemplate); @@ -263,4 +223,15 @@ public class DatabaseParser_v4Test e.printStackTrace(); } } + + @Test + public void test_convertToInternalShouldFail() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v4Test.json").toURI()))); + DatabaseParser_v4 parser = new DatabaseParser_v4(json); + BackupDatabase_v4 database = parser.parseDatabaseFromJSON(); + + assertThatThrownBy(database::convertToInternal) + .isInstanceOf(UnsupportedOperationException.class); + } } \ No newline at end of file diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v5Test.java b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v5Test.java index 17bcb1a09ce80a93912c6f1e93c92f7be7cf8498..962e4f50f94768a3a673495d362b1d4fad10f585 100644 --- a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v5Test.java +++ b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v5Test.java @@ -1,16 +1,16 @@ package de.deadlocker8.budgetmaster.unit.database; -import de.deadlocker8.budgetmaster.accounts.Account; +import de.deadlocker8.budgetmaster.accounts.AccountState; import de.deadlocker8.budgetmaster.accounts.AccountType; -import de.deadlocker8.budgetmaster.categories.Category; import de.deadlocker8.budgetmaster.categories.CategoryType; -import de.deadlocker8.budgetmaster.charts.Chart; import de.deadlocker8.budgetmaster.charts.ChartType; -import de.deadlocker8.budgetmaster.database.Database; +import de.deadlocker8.budgetmaster.database.DatabaseParser_v4; import de.deadlocker8.budgetmaster.database.DatabaseParser_v5; -import de.deadlocker8.budgetmaster.images.Image; +import de.deadlocker8.budgetmaster.database.model.v4.*; +import de.deadlocker8.budgetmaster.database.model.v5.*; import de.deadlocker8.budgetmaster.images.ImageFileExtension; -import de.deadlocker8.budgetmaster.templates.Template; +import de.deadlocker8.budgetmaster.repeating.endoption.RepeatingEndAfterXTimes; +import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierDays; import de.thecodelabs.utils.util.Localization; import de.thecodelabs.utils.util.Localization.LocalizationDelegate; import org.junit.Before; @@ -19,13 +19,13 @@ import org.junit.Test; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Arrays; +import java.util.ArrayList; import java.util.List; import java.util.Locale; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; public class DatabaseParser_v5Test @@ -56,11 +56,10 @@ public class DatabaseParser_v5Test try { String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v5Test.json").toURI()))); - DatabaseParser_v5 importer = new DatabaseParser_v5(json); - Database database = importer.parseDatabaseFromJSON(); + DatabaseParser_v5 parser = new DatabaseParser_v5(json); + BackupDatabase_v5 database = parser.parseDatabaseFromJSON(); - 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); - chart.setID(9); + 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); @@ -77,11 +76,10 @@ public class DatabaseParser_v5Test try { String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v5Test.json").toURI()))); - DatabaseParser_v5 importer = new DatabaseParser_v5(json); - Database database = importer.parseDatabaseFromJSON(); + DatabaseParser_v5 parser = new DatabaseParser_v5(json); + BackupDatabase_v5 database = parser.parseDatabaseFromJSON(); - final Category category = new Category("0815", "#ffcc00", CategoryType.CUSTOM, "fas fa-icons"); - category.setID(3); + final BackupCategory_v5 category = new BackupCategory_v5(3, "0815", "#ffcc00", CategoryType.CUSTOM, "fas fa-icons"); assertThat(database.getCategories()).hasSize(3) .contains(category); @@ -98,13 +96,11 @@ public class DatabaseParser_v5Test try { String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v5Test.json").toURI()))); - DatabaseParser_v5 importer = new DatabaseParser_v5(json); - Database database = importer.parseDatabaseFromJSON(); + DatabaseParser_v5 parser = new DatabaseParser_v5(json); + BackupDatabase_v5 database = parser.parseDatabaseFromJSON(); - final Image accountImage = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); - accountImage.setID(1); - final Account account = new Account("Second Account", AccountType.CUSTOM, accountImage); - account.setID(3); + final BackupImage_v5 accountImage = new BackupImage_v5(1, new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); + final BackupAccount_v5 account = new BackupAccount_v5(3, "Second Account", AccountState.FULL_ACCESS, AccountType.CUSTOM, accountImage); assertThat(database.getAccounts()).hasSize(3) .contains(account); @@ -124,11 +120,8 @@ public class DatabaseParser_v5Test try { String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v5Test.json").toURI()))); - DatabaseParser_v5 importer = new DatabaseParser_v5(json); - Database database = importer.parseDatabaseFromJSON(); - - final Image image = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); - image.setID(1); + DatabaseParser_v5 parser = new DatabaseParser_v5(json); + BackupDatabase_v5 database = parser.parseDatabaseFromJSON(); assertThat(database.getImages()).hasSize(1); assertThat(database.getImages().get(0)).hasFieldOrPropertyWithValue("fileExtension", ImageFileExtension.PNG); @@ -148,14 +141,14 @@ public class DatabaseParser_v5Test try { String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v5Test.json").toURI()))); - DatabaseParser_v5 importer = new DatabaseParser_v5(json); - Database database = importer.parseDatabaseFromJSON(); + DatabaseParser_v5 parser = new DatabaseParser_v5(json); + BackupDatabase_v5 database = parser.parseDatabaseFromJSON(); + + BackupImage_v5 templateImage = new BackupImage_v5(1, new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); - final Image templateImage = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); - templateImage.setID(1); - final Template template = new Template(); + BackupTemplate_v5 template = new BackupTemplate_v5(); template.setTemplateName("Template with icon"); - template.setIsExpenditure(true); + template.setExpenditure(true); template.setIcon(templateImage); template.setTags(List.of()); @@ -170,4 +163,101 @@ public class DatabaseParser_v5Test e.printStackTrace(); } } + + @Test + public void test_Transactions() + { + try + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v5Test.json").toURI()))); + DatabaseParser_v5 parser = new DatabaseParser_v5(json); + BackupDatabase_v5 database = parser.parseDatabaseFromJSON(); + + BackupAccount_v5 account1 = new BackupAccount_v5(2, "Default", AccountState.FULL_ACCESS, AccountType.CUSTOM, null); + + BackupImage_v5 image = new BackupImage_v5(1, new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); + + BackupAccount_v5 account2 = new BackupAccount_v5(3, "Second Account", AccountState.FULL_ACCESS, AccountType.CUSTOM, image); + + BackupCategory_v5 categoryNone = new BackupCategory_v5(1, "Keine Kategorie", "#FFFFFF", CategoryType.NONE, null); + + BackupCategory_v5 category3 = new BackupCategory_v5(3, "0815", "#ffcc00", CategoryType.CUSTOM, "fas fa-icons"); + + BackupTransaction_v5 normalTransaction_1 = new BackupTransaction_v5(); + normalTransaction_1.setAmount(35000); + normalTransaction_1.setDate("2018-03-13"); + normalTransaction_1.setCategory(categoryNone); + normalTransaction_1.setName("Income"); + normalTransaction_1.setDescription("Lorem Ipsum"); + normalTransaction_1.setTags(new ArrayList<>()); + normalTransaction_1.setAccount(account1); + normalTransaction_1.setExpenditure(false); + + BackupTransaction_v5 normalTransaction_2 = new BackupTransaction_v5(); + normalTransaction_2.setAmount(-2000); + normalTransaction_2.setDate("2018-06-15"); + normalTransaction_2.setName("Simple"); + normalTransaction_2.setDescription(""); + normalTransaction_2.setAccount(account2); + normalTransaction_2.setCategory(category3); + 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_v5 repeatingTransaction_1 = new BackupTransaction_v5(); + repeatingTransaction_1.setAmount(-12300); + String repeatingTransaction_1Date = "2018-03-13"; + repeatingTransaction_1.setDate(repeatingTransaction_1Date); + repeatingTransaction_1.setCategory(categoryNone); + repeatingTransaction_1.setName("Test"); + repeatingTransaction_1.setDescription(""); + repeatingTransaction_1.setAccount(account1); + 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_v5 transferTransaction = new BackupTransaction_v5(); + transferTransaction.setAmount(-250); + transferTransaction.setDate("2018-06-15"); + transferTransaction.setName("Transfer"); + transferTransaction.setDescription(""); + transferTransaction.setAccount(account2); + transferTransaction.setTransferAccount(account1); + transferTransaction.setCategory(category3); + transferTransaction.setTags(new ArrayList<>()); + transferTransaction.setExpenditure(true); + + assertThat(database.getTransactions()).hasSize(4) + .contains(normalTransaction_1, + normalTransaction_2, + repeatingTransaction_1, + transferTransaction); + + } + catch(IOException | URISyntaxException e) + { + e.printStackTrace(); + } + } + @Test + public void test_convertToInternalShouldFail() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v5Test.json").toURI()))); + DatabaseParser_v5 parser = new DatabaseParser_v5(json); + BackupDatabase_v5 database = parser.parseDatabaseFromJSON(); + + assertThatThrownBy(database::convertToInternal) + .isInstanceOf(UnsupportedOperationException.class); + } + } \ No newline at end of file diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v6Test.java b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v6Test.java new file mode 100644 index 0000000000000000000000000000000000000000..22cfef0df591dc2b13da0cb6787b21d7a70e5e47 --- /dev/null +++ b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v6Test.java @@ -0,0 +1,200 @@ +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_v6; +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.BackupCategory_v5; +import de.deadlocker8.budgetmaster.database.model.v5.BackupChart_v5; +import de.deadlocker8.budgetmaster.database.model.v6.BackupAccount_v6; +import de.deadlocker8.budgetmaster.database.model.v6.BackupDatabase_v6; +import de.deadlocker8.budgetmaster.database.model.v6.BackupTemplate_v6; +import de.deadlocker8.budgetmaster.database.model.v6.BackupTransaction_v6; +import de.deadlocker8.budgetmaster.images.ImageFileExtension; +import de.deadlocker8.budgetmaster.repeating.endoption.RepeatingEndAfterXTimes; +import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierDays; +import de.thecodelabs.utils.util.Localization; +import de.thecodelabs.utils.util.Localization.LocalizationDelegate; +import org.junit.Before; +import org.junit.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; + + +public class DatabaseParser_v6Test +{ + @Before + public void before() + { + Localization.setDelegate(new LocalizationDelegate() + { + @Override + public Locale getLocale() + { + return Locale.ENGLISH; + } + + @Override + public String getBaseResource() + { + return "languages/base"; + } + }); + Localization.load(); + } + + @Test + public void test_Charts() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser_v6 parser = new DatabaseParser_v6(json); + BackupDatabase_v6 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 + public void test_Categories() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser_v6 parser = new DatabaseParser_v6(json); + BackupDatabase_v6 database = parser.parseDatabaseFromJSON(); + + final BackupCategory_v5 category = new BackupCategory_v5(3, "0815", "#ffcc00", CategoryType.CUSTOM, "fas fa-icons"); + + assertThat(database.getCategories()).hasSize(3) + .contains(category); + } + + @Test + public void test_Accounts() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser_v6 parser = new DatabaseParser_v6(json); + BackupDatabase_v6 database = parser.parseDatabaseFromJSON(); + + final BackupAccount_v6 account = new BackupAccount_v6(3, "Second Account", AccountState.FULL_ACCESS, AccountType.CUSTOM, 1); + + assertThat(database.getAccounts()).hasSize(3) + .contains(account); + assertThat(database.getAccounts().get(2).getIconID()) + .isOne(); + } + + @Test + public void test_Images() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser_v6 parser = new DatabaseParser_v6(json); + BackupDatabase_v6 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 + public void test_Templates() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser_v6 parser = new DatabaseParser_v6(json); + BackupDatabase_v6 database = parser.parseDatabaseFromJSON(); + + BackupTemplate_v6 template = new BackupTemplate_v6(); + template.setTemplateName("Template with icon"); + template.setExpenditure(true); + template.setIconID(1); + template.setTags(List.of()); + + assertThat(database.getTemplates()).hasSize(4) + .contains(template); + assertThat(database.getTemplates().get(3).getIconID()) + .isOne(); + } + + @Test + public void test_Transactions() throws URISyntaxException, IOException + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser_v6 parser = new DatabaseParser_v6(json); + BackupDatabase_v6 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); + + assertThat(database.getTransactions()).hasSize(4) + .contains(normalTransaction_1, + normalTransaction_2, + repeatingTransaction_1, + transferTransaction); + } +} \ No newline at end of file diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v6_convertToInternalTest.java b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v6_convertToInternalTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4328d68b7f38408ffe39f66f06f41ef63d4d977e --- /dev/null +++ b/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseParser_v6_convertToInternalTest.java @@ -0,0 +1,276 @@ +package de.deadlocker8.budgetmaster.unit.database; + +import de.deadlocker8.budgetmaster.accounts.Account; +import de.deadlocker8.budgetmaster.accounts.AccountType; +import de.deadlocker8.budgetmaster.categories.Category; +import de.deadlocker8.budgetmaster.categories.CategoryType; +import de.deadlocker8.budgetmaster.charts.Chart; +import de.deadlocker8.budgetmaster.charts.ChartType; +import de.deadlocker8.budgetmaster.database.DatabaseParser_v6; +import de.deadlocker8.budgetmaster.database.InternalDatabase; +import de.deadlocker8.budgetmaster.images.Image; +import de.deadlocker8.budgetmaster.images.ImageFileExtension; +import de.deadlocker8.budgetmaster.repeating.RepeatingOption; +import de.deadlocker8.budgetmaster.repeating.endoption.RepeatingEndAfterXTimes; +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.thecodelabs.utils.util.Localization; +import de.thecodelabs.utils.util.Localization.LocalizationDelegate; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.junit.Before; +import org.junit.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; + + +public class DatabaseParser_v6_convertToInternalTest +{ + @Before + public void before() + { + Localization.setDelegate(new LocalizationDelegate() + { + @Override + public Locale getLocale() + { + return Locale.ENGLISH; + } + + @Override + public String getBaseResource() + { + return "languages/base"; + } + }); + Localization.load(); + } + + @Test + public void test_Charts() + { + try + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser_v6 importer = new DatabaseParser_v6(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); + chart.setID(9); + + assertThat(database.getCharts()).hasSize(1) + .contains(chart); + } + catch(IOException | URISyntaxException e) + { + e.printStackTrace(); + } + } + + @Test + public void test_Categories() + { + try + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser_v6 importer = new DatabaseParser_v6(json); + InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); + + final Category category = new Category("0815", "#ffcc00", CategoryType.CUSTOM, "fas fa-icons"); + category.setID(3); + + assertThat(database.getCategories()).hasSize(3) + .contains(category); + } + catch(IOException | URISyntaxException e) + { + e.printStackTrace(); + } + } + + @Test + public void test_Accounts() + { + try + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser_v6 importer = new DatabaseParser_v6(json); + InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); + + final Image accountImage = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); + accountImage.setID(1); + final Account account = new Account("Second Account", AccountType.CUSTOM, accountImage); + account.setID(3); + + assertThat(database.getAccounts()).hasSize(3) + .contains(account); + assertThat(database.getAccounts().get(2).getIcon().getImage()) + .isNotNull() + .hasSizeGreaterThan(1); + } + catch(IOException | URISyntaxException e) + { + e.printStackTrace(); + } + } + + @Test + public void test_Images() + { + try + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser_v6 importer = new DatabaseParser_v6(json); + InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); + + final Image image = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); + image.setID(1); + + assertThat(database.getImages()).hasSize(1); + assertThat(database.getImages().get(0)).hasFieldOrPropertyWithValue("fileExtension", ImageFileExtension.PNG); + assertThat(database.getImages().get(0).getImage()) + .isNotNull() + .hasSizeGreaterThan(1); + } + catch(IOException | URISyntaxException e) + { + e.printStackTrace(); + } + } + + @Test + public void test_Templates() + { + try + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser_v6 importer = new DatabaseParser_v6(json); + InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); + + final Image templateImage = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); + templateImage.setID(1); + final Template template = new Template(); + template.setTemplateName("Template with icon"); + template.setIsExpenditure(true); + template.setIcon(templateImage); + template.setTags(List.of()); + + assertThat(database.getTemplates()).hasSize(4) + .contains(template); + assertThat(database.getTemplates().get(3).getIcon().getImage()) + .isNotNull() + .hasSizeGreaterThan(1); + } + catch(IOException | URISyntaxException e) + { + e.printStackTrace(); + } + } + + @Test + public void test_Transactions() + { + try + { + String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("DatabaseParser_v6Test.json").toURI()))); + DatabaseParser_v6 importer = new DatabaseParser_v6(json); + InternalDatabase database = importer.parseDatabaseFromJSON().convertToInternal(); + + Account account1 = new Account("Default", AccountType.CUSTOM); + account1.setID(2); + + Image image = new Image(new Byte[0], "awesomeIcon.png", ImageFileExtension.PNG); + image.setID(1); + + Account account2 = new Account("Second Account", AccountType.CUSTOM); + account2.setIcon(image); + account2.setID(3); + + Category categoryNone = new Category("Keine Kategorie", "#FFFFFF", CategoryType.NONE); + categoryNone.setID(1); + + Category category3 = new Category("0815", "#ffcc00", CategoryType.CUSTOM); + category3.setIcon("fas fa-icons"); + category3.setID(3); + + Transaction normalTransaction_1 = new Transaction(); + normalTransaction_1.setAmount(35000); + DateTime normalTransactionDate = DateTime.parse("2018-03-13", DateTimeFormat.forPattern("yyyy-MM-dd")); + normalTransactionDate = normalTransactionDate.withHourOfDay(12).withMinuteOfHour(0).withSecondOfMinute(0); + normalTransaction_1.setDate(normalTransactionDate); + normalTransaction_1.setCategory(categoryNone); + normalTransaction_1.setName("Income"); + normalTransaction_1.setDescription("Lorem Ipsum"); + normalTransaction_1.setTags(new ArrayList<>()); + normalTransaction_1.setAccount(account1); + normalTransaction_1.setIsExpenditure(false); + + Transaction normalTransaction_2 = new Transaction(); + normalTransaction_2.setAmount(-2000); + DateTime normalTransaction_2Date = DateTime.parse("2018-06-15", DateTimeFormat.forPattern("yyyy-MM-dd")); + normalTransaction_2Date = normalTransaction_2Date.withHourOfDay(12).withMinuteOfHour(0).withSecondOfMinute(0); + normalTransaction_2.setDate(normalTransaction_2Date); + normalTransaction_2.setName("Simple"); + normalTransaction_2.setDescription(""); + normalTransaction_2.setAccount(account2); + normalTransaction_2.setCategory(category3); + normalTransaction_2.setIsExpenditure(true); + + List<Tag> tags = new ArrayList<>(); + Tag tag = new Tag("0815"); + tags.add(tag); + normalTransaction_2.setTags(tags); + + Transaction repeatingTransaction_1 = new Transaction(); + repeatingTransaction_1.setAmount(-12300); + DateTime repeatingTransaction_1Date = DateTime.parse("2018-03-13", DateTimeFormat.forPattern("yyyy-MM-dd")); + repeatingTransaction_1Date = repeatingTransaction_1Date.withHourOfDay(12).withMinuteOfHour(0).withSecondOfMinute(0); + repeatingTransaction_1.setDate(repeatingTransaction_1Date); + repeatingTransaction_1.setCategory(categoryNone); + repeatingTransaction_1.setName("Test"); + repeatingTransaction_1.setDescription(""); + repeatingTransaction_1.setAccount(account1); + RepeatingOption repeatingOption_1 = new RepeatingOption(); + repeatingOption_1.setModifier(new RepeatingModifierDays(10)); + repeatingOption_1.setStartDate(repeatingTransaction_1Date); + repeatingOption_1.setEndOption(new RepeatingEndAfterXTimes(2)); + repeatingTransaction_1.setRepeatingOption(repeatingOption_1); + repeatingTransaction_1.setTags(new ArrayList<>()); + repeatingTransaction_1.setIsExpenditure(true); + + Transaction transferTransaction = new Transaction(); + transferTransaction.setAmount(-250); + DateTime transferTransactionDate = DateTime.parse("2018-06-15", DateTimeFormat.forPattern("yyyy-MM-dd")); + transferTransactionDate = transferTransactionDate.withHourOfDay(12).withMinuteOfHour(0).withSecondOfMinute(0); + transferTransaction.setDate(transferTransactionDate); + transferTransaction.setName("Transfer"); + transferTransaction.setDescription(""); + transferTransaction.setAccount(account2); + transferTransaction.setTransferAccount(account1); + transferTransaction.setCategory(category3); + transferTransaction.setTags(new ArrayList<>()); + transferTransaction.setIsExpenditure(true); + + assertThat(database.getTransactions()).hasSize(4) + .contains(normalTransaction_1, + normalTransaction_2, + repeatingTransaction_1, + transferTransaction); + + } + catch(IOException | URISyntaxException e) + { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseImportTest.java b/src/test/java/de/deadlocker8/budgetmaster/unit/database/ImportServiceTest.java similarity index 95% rename from src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseImportTest.java rename to src/test/java/de/deadlocker8/budgetmaster/unit/database/ImportServiceTest.java index 157aced05cf12a4a3c62a946a3217da1ad330b92..287d7d00561f36a8f1b8458ac7068fe3b05bbcbb 100644 --- a/src/test/java/de/deadlocker8/budgetmaster/unit/database/DatabaseImportTest.java +++ b/src/test/java/de/deadlocker8/budgetmaster/unit/database/ImportServiceTest.java @@ -9,7 +9,7 @@ import de.deadlocker8.budgetmaster.charts.Chart; import de.deadlocker8.budgetmaster.charts.ChartRepository; import de.deadlocker8.budgetmaster.charts.ChartService; import de.deadlocker8.budgetmaster.charts.ChartType; -import de.deadlocker8.budgetmaster.database.Database; +import de.deadlocker8.budgetmaster.database.InternalDatabase; import de.deadlocker8.budgetmaster.database.accountmatches.AccountMatch; import de.deadlocker8.budgetmaster.database.accountmatches.AccountMatchList; import de.deadlocker8.budgetmaster.images.Image; @@ -41,7 +41,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringJUnit4ClassRunner.class) -public class DatabaseImportTest +public class ImportServiceTest { @Mock private CategoryRepository categoryRepository; @@ -424,7 +424,7 @@ public class DatabaseImportTest chart.setScript("/* 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"); // database - Database database = new Database(new ArrayList<>(), accounts, transactions, templates, List.of(chart), List.of()); + InternalDatabase database = new InternalDatabase(new ArrayList<>(), accounts, transactions, templates, List.of(chart), List.of()); // account matches AccountMatch match1 = new AccountMatch(sourceAccount1); @@ -476,7 +476,7 @@ public class DatabaseImportTest Mockito.when(chartService.getRepository()).thenReturn(chartRepositoryMock); importService.importDatabase(database, accountMatchList, true, true); - Database databaseResult = importService.getDatabase(); + InternalDatabase databaseResult = importService.getDatabase(); // assert assertThat(databaseResult.getTransactions()) @@ -502,7 +502,7 @@ public class DatabaseImportTest chart.setScript("/* 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"); // database - Database database = new Database(List.of(), List.of(), List.of(), List.of(), List.of(chart), List.of()); + InternalDatabase database = new InternalDatabase(List.of(), List.of(), List.of(), List.of(), List.of(chart), List.of()); // act int highestUsedID = 22; @@ -511,7 +511,7 @@ public class DatabaseImportTest Mockito.when(chartService.getRepository()).thenReturn(chartRepositoryMock); importService.importDatabase(database, new AccountMatchList(List.of()), true, true); - Database databaseResult = importService.getDatabase(); + InternalDatabase databaseResult = importService.getDatabase(); // assert assertThat(databaseResult.getCharts().get(0)) @@ -552,7 +552,7 @@ public class DatabaseImportTest Mockito.when(imageService.getRepository()).thenReturn(imageRepositoryMock); Mockito.when(imageRepositoryMock.save(Mockito.any())).thenReturn(newImage); - Database database = new Database(List.of(), List.of(), List.of(), List.of(), List.of(), List.of(image)); + InternalDatabase database = new InternalDatabase(List.of(), List.of(), List.of(), List.of(), List.of(), List.of(image)); importService.importDatabase(database, new AccountMatchList(List.of()), true, true); Image expectedImage = new Image(image.getImage(), image.getFileName(), image.getFileExtension()); @@ -572,7 +572,7 @@ public class DatabaseImportTest Mockito.when(imageService.getRepository()).thenReturn(imageRepositoryMock); Mockito.when(imageRepositoryMock.save(Mockito.any())).thenReturn(newImage); - Database database = new Database(List.of(), List.of(), List.of(), List.of(), List.of(), List.of(image)); + InternalDatabase database = new InternalDatabase(List.of(), List.of(), List.of(), List.of(), List.of(), List.of(image)); importService.importDatabase(database, new AccountMatchList(List.of()), true, true); Image expectedImage = new Image(image.getImage(), image.getFileName(), image.getFileExtension()); @@ -619,7 +619,7 @@ public class DatabaseImportTest template.setTags(new ArrayList<>()); // database - Database database = new Database(List.of(), List.of(), List.of(), List.of(template), List.of(), List.of()); + InternalDatabase database = new InternalDatabase(List.of(), List.of(), List.of(), List.of(template), List.of(), List.of()); // act importService.importDatabase(database, new AccountMatchList(List.of()), false, true); @@ -638,7 +638,7 @@ public class DatabaseImportTest chart.setVersion(7); // database - Database database = new Database(List.of(), List.of(), List.of(), List.of(), List.of(chart), List.of()); + InternalDatabase database = new InternalDatabase(List.of(), List.of(), List.of(), List.of(), List.of(chart), List.of()); Mockito.when(chartService.getHighestUsedID()).thenReturn(8); final ChartRepository chartRepositoryMock = Mockito.mock(ChartRepository.class); @@ -664,7 +664,7 @@ public class DatabaseImportTest Mockito.when(categoryRepository.findByNameAndColorAndType(Mockito.eq("Category1"), Mockito.any(), Mockito.any())).thenThrow(new NullPointerException()); Mockito.when(categoryRepository.findByNameAndColorAndType(Mockito.eq("Category2"), Mockito.any(), Mockito.any())).thenReturn(category2); - Database database = new Database(List.of(category1, category2), List.of(), List.of(), List.of(), List.of(), List.of()); + InternalDatabase database = new InternalDatabase(List.of(category1, category2), List.of(), List.of(), List.of(), List.of(), List.of()); final List<ImportResultItem> importResultItems = importService.importDatabase(database, new AccountMatchList(List.of()), false, false); assertThat(importResultItems).hasSize(6) diff --git a/src/test/java/de/deadlocker8/budgetmaster/unit/database/LegacyParserTest.java b/src/test/java/de/deadlocker8/budgetmaster/unit/database/LegacyParserTest.java deleted file mode 100644 index 6a9027c1ea5694146dc074f4cb639ebd0e462f7e..0000000000000000000000000000000000000000 --- a/src/test/java/de/deadlocker8/budgetmaster/unit/database/LegacyParserTest.java +++ /dev/null @@ -1,157 +0,0 @@ -package de.deadlocker8.budgetmaster.unit.database; - -import de.deadlocker8.budgetmaster.accounts.Account; -import de.deadlocker8.budgetmaster.accounts.AccountType; -import de.deadlocker8.budgetmaster.categories.Category; -import de.deadlocker8.budgetmaster.categories.CategoryType; -import de.deadlocker8.budgetmaster.database.Database; -import de.deadlocker8.budgetmaster.database.legacy.LegacyParser; -import de.deadlocker8.budgetmaster.repeating.RepeatingOption; -import de.deadlocker8.budgetmaster.repeating.endoption.RepeatingEndDate; -import de.deadlocker8.budgetmaster.repeating.endoption.RepeatingEndNever; -import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierDays; -import de.deadlocker8.budgetmaster.repeating.modifier.RepeatingModifierMonths; -import de.deadlocker8.budgetmaster.tags.Tag; -import de.deadlocker8.budgetmaster.transactions.Transaction; -import org.joda.time.DateTime; -import org.joda.time.format.DateTimeFormat; -import org.junit.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 static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -public class LegacyParserTest -{ - private static final Category categoryNone = new Category("NONE", "#CCCCCC", CategoryType.NONE); - - @Test - public void test_Categories() - { - try - { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("LegacyParserTest.json").toURI()))); - - LegacyParser importer = new LegacyParser(json, categoryNone); - Database database = importer.parseDatabaseFromJSON(); - - assertEquals(2, database.getCategories().size()); - Category category3 = new Category("Salary", "#4CD964", CategoryType.CUSTOM); - category3.setID(3); - assertTrue(database.getCategories().contains(category3)); - - Category category4 = new Category("Stuff", "#9B59B6", CategoryType.CUSTOM); - category4.setID(4); - assertTrue(database.getCategories().contains(category4)); - } - catch(IOException | URISyntaxException e) - { - e.printStackTrace(); - } - } - - @Test - public void test_Accounts() - { - try - { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("LegacyParserTest.json").toURI()))); - LegacyParser importer = new LegacyParser(json, categoryNone); - Database database = importer.parseDatabaseFromJSON(); - - assertEquals(1, database.getAccounts().size()); - assertEquals("LEGACY_IMPORT", database.getAccounts().get(0).getName()); - } - catch(IOException | URISyntaxException e) - { - e.printStackTrace(); - } - } - - @Test - public void test_Payments() - { - try - { - String json = new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("LegacyParserTest.json").toURI()))); - Account account = new Account("LEGACY_IMPORT", AccountType.CUSTOM); - - List<Tag> tags = new ArrayList<>(); - tags.add(new Tag("0815")); - - Category category3 = new Category("Salary", "#4CD964", CategoryType.CUSTOM); - category3.setID(3); - - Category category4 = new Category("Stuff", "#9B59B6", CategoryType.CUSTOM); - category4.setID(4); - - LegacyParser importer = new LegacyParser(json, categoryNone); - Database database = importer.parseDatabaseFromJSON(); - - assertEquals(4, database.getTransactions().size()); - - Transaction normalTransaction_1 = new Transaction(); - normalTransaction_1.setAmount(-2323); - normalTransaction_1.setDate(DateTime.parse("2018-01-21", DateTimeFormat.forPattern("yyyy-MM-dd"))); - normalTransaction_1.setCategory(category4); - normalTransaction_1.setName("Fuel"); - normalTransaction_1.setDescription("Lorem Ipsum"); - normalTransaction_1.setTags(tags); - normalTransaction_1.setAccount(account); - assertTrue(database.getTransactions().contains(normalTransaction_1)); - - Transaction normalTransaction_2 = new Transaction(); - normalTransaction_2.setAmount(100); - normalTransaction_2.setDate(DateTime.parse("2018-01-01", DateTimeFormat.forPattern("yyyy-MM-dd"))); - normalTransaction_2.setName("no category"); - normalTransaction_2.setDescription(""); - normalTransaction_2.setAccount(account); - normalTransaction_2.setCategory(categoryNone); - normalTransaction_2.setTags(new ArrayList<>()); - assertTrue(database.getTransactions().contains(normalTransaction_2)); - - Transaction repeatingTransaction_1 = new Transaction(); - repeatingTransaction_1.setAmount(500000); - DateTime repeatingTransactionDate_1 = DateTime.parse("2017-03-01", DateTimeFormat.forPattern("yyyy-MM-dd")); - repeatingTransaction_1.setDate(repeatingTransactionDate_1); - repeatingTransaction_1.setCategory(category3); - repeatingTransaction_1.setName("Salary"); - repeatingTransaction_1.setDescription("Monthly cash"); - repeatingTransaction_1.setAccount(account); - RepeatingOption repeatingOption_1 = new RepeatingOption(); - repeatingOption_1.setModifier(new RepeatingModifierMonths(1)); - repeatingOption_1.setStartDate(repeatingTransactionDate_1); - repeatingOption_1.setEndOption(new RepeatingEndNever()); - repeatingTransaction_1.setRepeatingOption(repeatingOption_1); - repeatingTransaction_1.setTags(tags); - assertTrue(database.getTransactions().contains(repeatingTransaction_1)); - - Transaction repeatingTransaction_2 = new Transaction(); - repeatingTransaction_2.setAmount(-2500); - DateTime repeatingTransactionDate_2 = DateTime.parse("2017-03-15", DateTimeFormat.forPattern("yyyy-MM-dd")); - repeatingTransaction_2.setDate(repeatingTransactionDate_2); - repeatingTransaction_2.setCategory(category4); - repeatingTransaction_2.setName("Rent"); - repeatingTransaction_2.setDescription("Repeating every 7 days"); - repeatingTransaction_2.setAccount(account); - RepeatingOption repeatingOption_2= new RepeatingOption(); - repeatingOption_2.setModifier(new RepeatingModifierDays(7)); - repeatingOption_2.setStartDate(repeatingTransactionDate_2); - repeatingOption_2.setEndOption(new RepeatingEndDate(DateTime.parse("2017-06-15", DateTimeFormat.forPattern("yyyy-MM-dd")))); - repeatingTransaction_2.setDate(repeatingTransactionDate_2); - repeatingTransaction_2.setRepeatingOption(repeatingOption_2); - repeatingTransaction_2.setTags(new ArrayList<>()); - assertTrue(database.getTransactions().contains(repeatingTransaction_2)); - } - catch(IOException | URISyntaxException e) - { - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/src/test/resources/DatabaseParser_v4Test.json b/src/test/resources/DatabaseParser_v4Test.json index 045f7d329df060b639551fa21293194a1e861360..c05ebe607388d72e197fc60e35cc4ce8d7404693 100644 --- a/src/test/resources/DatabaseParser_v4Test.json +++ b/src/test/resources/DatabaseParser_v4Test.json @@ -43,9 +43,11 @@ "ID": 5, "amount": 35000, "date": "2018-03-13", + "isExpenditure": false, "account": { "ID": 2, - "name": "Default" + "name": "Default", + "type": "CUSTOM" }, "category": { "ID": 1, @@ -63,7 +65,8 @@ "date": "2018-06-15", "account": { "ID": 3, - "name": "Second Account" + "name": "Second Account", + "type": "CUSTOM" }, "category": { "ID": 3, @@ -86,71 +89,8 @@ "date": "2018-03-13", "account": { "ID": 2, - "name": "Default" - }, - "category": { - "ID": 1, - "name": "Keine Kategorie", - "color": "#FFFFFF", - "type": "NONE" - }, - "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": 14, - "amount": -12300, - "date": "2018-03-23", - "account": { - "ID": 2, - "name": "Default" - }, - "category": { - "ID": 1, - "name": "Keine Kategorie", - "color": "#FFFFFF", - "type": "NONE" - }, - "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": 15, - "amount": -12300, - "date": "2018-04-02", - "account": { - "ID": 2, - "name": "Default" + "name": "Default", + "type": "CUSTOM" }, "category": { "ID": 1, @@ -182,7 +122,8 @@ "date": "2018-06-15", "account": { "ID": 3, - "name": "Second Account" + "name": "Second Account", + "type": "CUSTOM" }, "category": { "ID": 3, @@ -206,7 +147,8 @@ "amount": 1500, "account": { "ID": 2, - "name": "Default" + "name": "Default", + "type": "CUSTOM" }, "category": { "ID": 1, @@ -234,7 +176,8 @@ "amount": -35000, "account": { "ID": 3, - "name": "Second Account" + "name": "Second Account", + "type": "CUSTOM" }, "category": { "ID": 3, diff --git a/src/test/resources/DatabaseParser_v5Test.json b/src/test/resources/DatabaseParser_v5Test.json index a5d6d334e60045f69b924b72ad0a6e28e1cdf447..c75ebdf6bdd29508967c7e18ca4d8390231171ba 100644 --- a/src/test/resources/DatabaseParser_v5Test.json +++ b/src/test/resources/DatabaseParser_v5Test.json @@ -26,16 +26,19 @@ { "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", "icon": { "ID": 1, @@ -3165,10 +3168,13 @@ { "ID": 5, "amount": 35000, + "isExpenditure": false, "date": "2018-03-13", "account": { "ID": 2, - "name": "Default" + "name": "Default", + "accountState": "FULL_ACCESS", + "type": "CUSTOM" }, "category": { "ID": 1, @@ -3183,10 +3189,3135 @@ { "ID": 12, "amount": -2000, + "isExpenditure": true, "date": "2018-06-15", "account": { "ID": 3, - "name": "Second Account" + "name": "Second Account", + "accountState": "FULL_ACCESS", + "type": "CUSTOM", + "icon": { + "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" + } }, "category": { "ID": 3, @@ -3207,74 +6338,13 @@ { "ID": 13, "amount": -12300, + "isExpenditure": true, "date": "2018-03-13", "account": { "ID": 2, - "name": "Default" - }, - "category": { - "ID": 1, - "name": "Keine Kategorie", - "color": "#FFFFFF", - "type": "NONE" - }, - "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": 14, - "amount": -12300, - "date": "2018-03-23", - "account": { - "ID": 2, - "name": "Default" - }, - "category": { - "ID": 1, - "name": "Keine Kategorie", - "color": "#FFFFFF", - "type": "NONE" - }, - "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": 15, - "amount": -12300, - "date": "2018-04-02", - "account": { - "ID": 2, - "name": "Default" + "name": "Default", + "accountState": "FULL_ACCESS", + "type": "CUSTOM" }, "category": { "ID": 1, @@ -3303,10 +6373,3135 @@ { "ID": 16, "amount": -250, + "isExpenditure": true, "date": "2018-06-15", "account": { "ID": 3, - "name": "Second Account" + "name": "Second Account", + "accountState": "FULL_ACCESS", + "type": "CUSTOM", + "icon": { + "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" + } }, "category": { "ID": 3, @@ -3321,6 +9516,7 @@ "transferAccount": { "ID": 2, "name": "Default", + "accountState": "FULL_ACCESS", "type": "CUSTOM" } } @@ -3331,7 +9527,9 @@ "amount": 1500, "account": { "ID": 2, - "name": "Default" + "name": "Default", + "accountState": "FULL_ACCESS", + "type": "CUSTOM" }, "category": { "ID": 1, @@ -3359,7 +9557,3131 @@ "amount": -35000, "account": { "ID": 3, - "name": "Second Account" + "name": "Second Account", + "accountState": "FULL_ACCESS", + "type": "CUSTOM", + "icon": { + "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" + } }, "category": { "ID": 3, @@ -3380,6 +12702,7 @@ "transferAccount": { "ID": 2, "name": "Default", + "accountState": "FULL_ACCESS", "type": "CUSTOM" } }, @@ -3387,6 +12710,7 @@ "ID": 8, "templateName": "Template with icon", "tags": [], + "isExpenditure": true, "icon": { "ID": 1, "image": [ diff --git a/src/test/resources/DatabaseParser_v6Test.json b/src/test/resources/DatabaseParser_v6Test.json new file mode 100644 index 0000000000000000000000000000000000000000..fe9c3bae8ddc33de4e583074b57509147a4da2d1 --- /dev/null +++ b/src/test/resources/DatabaseParser_v6Test.json @@ -0,0 +1,3288 @@ +{ + "TYPE": "BUDGETMASTER_DATABASE", + "VERSION": 6, + "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", + "icon": "fas fa-icons" + } + ], + "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", + "iconID": 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 + } + ], + "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": [], + "iconID": 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" + } + ] +} \ No newline at end of file