@Test public void shouldRecursivelyDeleteAccount() { Account account = new Account("Parent"); Account account2 = new Account("Child"); account2.setParentUID(account.getUID()); Transaction transaction = new Transaction("Random"); account2.addTransaction(transaction); Split split = new Split(Money.getZeroInstance(), account.getUID()); transaction.addSplit(split); transaction.addSplit(split.createPair(account2.getUID())); mAccountsDbAdapter.addRecord(account); mAccountsDbAdapter.addRecord(account2); assertThat(mAccountsDbAdapter.getRecordsCount()).isEqualTo(3); assertThat(mTransactionsDbAdapter.getRecordsCount()).isEqualTo(1); assertThat(mSplitsDbAdapter.getRecordsCount()).isEqualTo(2); boolean result = mAccountsDbAdapter.recursiveDeleteAccount(mAccountsDbAdapter.getID(account.getUID())); assertThat(result).isTrue(); assertThat(mAccountsDbAdapter.getRecordsCount()).isEqualTo(1); // the root account assertThat(mTransactionsDbAdapter.getRecordsCount()).isZero(); assertThat(mSplitsDbAdapter.getRecordsCount()).isZero(); }
@Test public void deletingTransactionsShouldDeleteSplits() { Transaction transaction = new Transaction(""); Split split = new Split(Money.getZeroInstance(), alphaAccount.getUID()); transaction.addSplit(split); mTransactionsDbAdapter.addRecord(transaction); assertThat(mSplitsDbAdapter.getSplitsForTransaction(transaction.getUID())).hasSize(1); mTransactionsDbAdapter.deleteRecord(transaction.getUID()); assertThat(mSplitsDbAdapter.getSplitsForTransaction(transaction.getUID())).hasSize(0); }
private void init(@Nullable SQLiteDatabase db) { if (db == null) { mAccountsDbAdapter = AccountsDbAdapter.getInstance(); mTransactionsDbAdapter = TransactionsDbAdapter.getInstance(); mScheduledActionsDbAdapter = ScheduledActionDbAdapter.getInstance(); mCommoditiesDbAdapter = CommoditiesDbAdapter.getInstance(); mPricesDbAdapter = PricesDbAdapter.getInstance(); } else { mTransactionsDbAdapter = new TransactionsDbAdapter(db, new SplitsDbAdapter(db)); mAccountsDbAdapter = new AccountsDbAdapter(db, mTransactionsDbAdapter); mScheduledActionsDbAdapter = new ScheduledActionDbAdapter(db); mCommoditiesDbAdapter = new CommoditiesDbAdapter(db); mPricesDbAdapter = new PricesDbAdapter(db); } mContent = new StringBuilder(); mAccountList = new ArrayList<>(); mAccountMap = new HashMap<>(); mTransactionList = new ArrayList<>(); mScheduledActionsList = new ArrayList<>(); mTemplatAccountList = new ArrayList<>(); mTemplateTransactions = new ArrayList<>(); mTemplateAccountToTransactionMap = new HashMap<>(); mAutoBalanceSplits = new ArrayList<>(); mPriceList = new ArrayList<>(); }
@Before public void setUp() throws Exception { mSplitsDbAdapter = SplitsDbAdapter.getInstance(); mTransactionsDbAdapter = TransactionsDbAdapter.getInstance(); mAccountsDbAdapter = AccountsDbAdapter.getInstance(); }
@Test public void shouldClearAllTablesWhenDeletingAllAccounts() { Account account = new Account("Test"); Transaction transaction = new Transaction("Test description"); Split split = new Split(Money.getZeroInstance(), account.getUID()); transaction.addSplit(split); Account account2 = new Account("Transfer account"); transaction.addSplit(split.createPair(account2.getUID())); mAccountsDbAdapter.addRecord(account); mAccountsDbAdapter.addRecord(account2); ScheduledAction scheduledAction = new ScheduledAction(ScheduledAction.ActionType.BACKUP); scheduledAction.setActionUID("Test-uid"); ScheduledActionDbAdapter scheduledActionDbAdapter = ScheduledActionDbAdapter.getInstance(); scheduledActionDbAdapter.addRecord(scheduledAction); mAccountsDbAdapter.deleteAllRecords(); assertThat(mAccountsDbAdapter.getRecordsCount()).isZero(); assertThat(mTransactionsDbAdapter.getRecordsCount()).isZero(); assertThat(mSplitsDbAdapter.getRecordsCount()).isZero(); assertThat(scheduledActionDbAdapter.getRecordsCount()).isZero(); }
@Test public void shouldAddAccountsToDatabase() { Account account1 = new Account("AlphaAccount"); Account account2 = new Account("BetaAccount"); Transaction transaction = new Transaction("MyTransaction"); Split split = new Split(Money.getZeroInstance(), account1.getUID()); transaction.addSplit(split); transaction.addSplit(split.createPair(account2.getUID())); account1.addTransaction(transaction); account2.addTransaction(transaction); mAccountsDbAdapter.addRecord(account1); mAccountsDbAdapter.addRecord(account2); Account firstAccount = mAccountsDbAdapter.getRecord(account1.getUID()); assertThat(firstAccount).isNotNull(); assertThat(firstAccount.getUID()).isEqualTo(account1.getUID()); assertThat(firstAccount.getFullName()).isEqualTo(account1.getFullName()); Account secondAccount = mAccountsDbAdapter.getRecord(account2.getUID()); assertThat(secondAccount).isNotNull(); assertThat(secondAccount.getUID()).isEqualTo(account2.getUID()); assertThat(mTransactionsDbAdapter.getRecordsCount()).isEqualTo(1); }
@Test public void shouldBalanceTransactionsOnSave() { Transaction transaction = new Transaction("Auto balance"); Split split = new Split( new Money(BigDecimal.TEN, Currency.getInstance(Money.DEFAULT_CURRENCY_CODE)), alphaAccount.getUID()); transaction.addSplit(split); mTransactionsDbAdapter.addRecord(transaction); Transaction trn = mTransactionsDbAdapter.getRecord(transaction.getUID()); assertThat(trn.getSplits()).hasSize(2); String imbalanceAccountUID = mAccountsDbAdapter.getImbalanceAccountUID( Currency.getInstance(Money.DEFAULT_CURRENCY_CODE)); assertThat(trn.getSplits()).extracting("mAccountUID").contains(imbalanceAccountUID); }
@Test public void testComputeBalance() { Transaction transaction = new Transaction("Compute"); Money firstSplitAmount = new Money("4.99", DEFAULT_CURRENCY.getCurrencyCode()); Split split = new Split(firstSplitAmount, alphaAccount.getUID()); transaction.addSplit(split); Money secondSplitAmount = new Money("3.50", DEFAULT_CURRENCY.getCurrencyCode()); split = new Split(secondSplitAmount, bravoAccount.getUID()); transaction.addSplit(split); mTransactionsDbAdapter.addRecord(transaction); // balance is negated because the CASH account has inverse normal balance transaction = mTransactionsDbAdapter.getRecord(transaction.getUID()); Money savedBalance = transaction.getBalance(alphaAccount.getUID()); assertThat(savedBalance).isEqualTo(firstSplitAmount.negate()); savedBalance = transaction.getBalance(bravoAccount.getUID()); assertThat(savedBalance.getNumerator()).isEqualTo(secondSplitAmount.negate().getNumerator()); assertThat(savedBalance.getCurrency()).isEqualTo(secondSplitAmount.getCurrency()); }
@Test public void testTransactionsAreTimeSorted() { Transaction t1 = new Transaction("T800"); t1.setTime(System.currentTimeMillis() - 10000); Split split = new Split(Money.getZeroInstance(), alphaAccount.getUID()); t1.addSplit(split); t1.addSplit(split.createPair(bravoAccount.getUID())); Transaction t2 = new Transaction("T1000"); t2.setTime(System.currentTimeMillis()); Split split2 = new Split(new Money("23.50"), bravoAccount.getUID()); t2.addSplit(split2); t2.addSplit(split2.createPair(alphaAccount.getUID())); mTransactionsDbAdapter.addRecord(t1); mTransactionsDbAdapter.addRecord(t2); List<Transaction> transactionsList = mTransactionsDbAdapter.getAllTransactionsForAccount(alphaAccount.getUID()); assertThat(transactionsList).contains(t2, Index.atIndex(0)); assertThat(transactionsList).contains(t1, Index.atIndex(1)); }
@Before public void setUp() throws Exception { mSplitsDbAdapter = SplitsDbAdapter.getInstance(); mTransactionsDbAdapter = TransactionsDbAdapter.getInstance(); mAccountsDbAdapter = AccountsDbAdapter.getInstance(); alphaAccount = new Account(ALPHA_ACCOUNT_NAME); bravoAccount = new Account(BRAVO_ACCOUNT_NAME); mAccountsDbAdapter.addRecord(bravoAccount); mAccountsDbAdapter.addRecord(alphaAccount); mTestSplit = new Split(new Money(BigDecimal.TEN, DEFAULT_CURRENCY), alphaAccount.getUID()); }
/** Tests the foreign key constraint "ON DELETE CASCADE" between accounts and splits */ @Test public void shouldDeleteSplitsWhenAccountDeleted() { Account first = new Account(ALPHA_ACCOUNT_NAME); first.setUID(ALPHA_ACCOUNT_NAME); Account second = new Account(BRAVO_ACCOUNT_NAME); second.setUID(BRAVO_ACCOUNT_NAME); mAccountsDbAdapter.addRecord(second); mAccountsDbAdapter.addRecord(first); Transaction transaction = new Transaction("TestTrn"); Split split = new Split(Money.getZeroInstance(), ALPHA_ACCOUNT_NAME); transaction.addSplit(split); transaction.addSplit(split.createPair(BRAVO_ACCOUNT_NAME)); mTransactionsDbAdapter.addRecord(transaction); mAccountsDbAdapter.deleteRecord(ALPHA_ACCOUNT_NAME); Transaction trxn = mTransactionsDbAdapter.getRecord(transaction.getUID()); assertThat(trxn.getSplits().size()).isEqualTo(1); assertThat(trxn.getSplits().get(0).getAccountUID()).isEqualTo(BRAVO_ACCOUNT_NAME); }
@Override public void onReceive(Context context, Intent intent) { Log.i("TransactionRecorder", "Received transaction recording intent"); Bundle args = intent.getExtras(); String name = args.getString(Intent.EXTRA_TITLE); String note = args.getString(Intent.EXTRA_TEXT); BigDecimal amountBigDecimal = (BigDecimal) args.getSerializable(Transaction.EXTRA_AMOUNT); String currencyCode = args.getString(Account.EXTRA_CURRENCY_CODE); if (currencyCode == null) currencyCode = Money.DEFAULT_CURRENCY_CODE; String accountUID = args.getString(Transaction.EXTRA_ACCOUNT_UID); if (accountUID == null) // if no account was assigned, throw an exception throw new IllegalArgumentException("No account specified for the transaction"); String doubleAccountUID = args.getString(Transaction.EXTRA_DOUBLE_ACCOUNT_UID); if (doubleAccountUID == null || doubleAccountUID.length() == 0) doubleAccountUID = QifHelper.getImbalanceAccountName(Currency.getInstance(Money.DEFAULT_CURRENCY_CODE)); Transaction.TransactionType type = Transaction.TransactionType.valueOf(args.getString(Transaction.EXTRA_TRANSACTION_TYPE)); Money amount = new Money(amountBigDecimal, Currency.getInstance(currencyCode)); Transaction transaction = new Transaction(amount, name); transaction.setTime(System.currentTimeMillis()); transaction.setDescription(note); transaction.setAccountUID(accountUID); transaction.setDoubleEntryAccountUID(doubleAccountUID); transaction.setTransactionType(type); TransactionsDbAdapter transacionsDbAdapter = new TransactionsDbAdapter(context); transacionsDbAdapter.addTransaction(transaction); WidgetConfigurationActivity.updateAllWidgets(context); transacionsDbAdapter.close(); }
@Test public void shouldAddTransactionsAndSplitsWhenAddingAccounts() { Account account = new Account("Test"); mAccountsDbAdapter.addRecord(account); Transaction transaction = new Transaction("Test description"); Split split = new Split(Money.getZeroInstance(), account.getUID()); transaction.addSplit(split); Account account1 = new Account("Transfer account"); transaction.addSplit(split.createPair(account1.getUID())); account1.addTransaction(transaction); mAccountsDbAdapter.addRecord(account1); assertThat(mTransactionsDbAdapter.getRecordsCount()).isEqualTo(1); assertThat(mSplitsDbAdapter.getRecordsCount()).isEqualTo(2); assertThat(mAccountsDbAdapter.getRecordsCount()) .isEqualTo(3); // ROOT account automatically added }
@Test public void shouldComputeAccountBalanceCorrectly() { Account account = new Account("Test", Commodity.USD); account.setAccountType(AccountType.ASSET); // debit normal account balance Account transferAcct = new Account("Transfer"); mAccountsDbAdapter.addRecord(account); mAccountsDbAdapter.addRecord(transferAcct); Transaction transaction = new Transaction("Test description"); mTransactionsDbAdapter.addRecord(transaction); Split split = new Split(new Money(BigDecimal.TEN, Commodity.USD), account.getUID()); split.setTransactionUID(transaction.getUID()); split.setType(TransactionType.DEBIT); mSplitsDbAdapter.addRecord(split); split = new Split(new Money("4.99", "USD"), account.getUID()); split.setTransactionUID(transaction.getUID()); split.setType(TransactionType.DEBIT); mSplitsDbAdapter.addRecord(split); split = new Split(new Money("1.19", "USD"), account.getUID()); split.setTransactionUID(transaction.getUID()); split.setType(TransactionType.CREDIT); mSplitsDbAdapter.addRecord(split); split = new Split(new Money("3.49", "EUR"), account.getUID()); split.setTransactionUID(transaction.getUID()); split.setType(TransactionType.DEBIT); mSplitsDbAdapter.addRecord(split); split = new Split(new Money("8.39", "USD"), transferAcct.getUID()); split.setTransactionUID(transaction.getUID()); mSplitsDbAdapter.addRecord(split); // balance computation ignores the currency of the split Money balance = mAccountsDbAdapter.getAccountBalance(account.getUID()); Money expectedBalance = new Money("17.29", "USD"); // EUR splits should be ignored assertThat(balance).isEqualTo(expectedBalance); }
@Override public void endDocument() throws SAXException { super.endDocument(); HashMap<String, String> mapFullName = new HashMap<>(mAccountList.size()); HashMap<String, Account> mapImbalanceAccount = new HashMap<>(); // The XML has no ROOT, create one if (mRootAccount == null) { mRootAccount = new Account("ROOT"); mRootAccount.setAccountType(AccountType.ROOT); mAccountList.add(mRootAccount); mAccountMap.put(mRootAccount.getUID(), mRootAccount); } String imbalancePrefix = AccountsDbAdapter.getImbalanceAccountPrefix(); // Add all account without a parent to ROOT, and collect top level imbalance accounts for (Account account : mAccountList) { mapFullName.put(account.getUID(), null); boolean topLevel = false; if (account.getParentUID() == null && account.getAccountType() != AccountType.ROOT) { account.setParentUID(mRootAccount.getUID()); topLevel = true; } if (topLevel || (mRootAccount.getUID().equals(account.getParentUID()))) { if (account.getName().startsWith(imbalancePrefix)) { mapImbalanceAccount.put(account.getName().substring(imbalancePrefix.length()), account); } } } // Set the account for created balancing splits to correct imbalance accounts for (Split split : mAutoBalanceSplits) { String currencyCode = split.getAccountUID(); Account imbAccount = mapImbalanceAccount.get(currencyCode); if (imbAccount == null) { imbAccount = new Account(imbalancePrefix + currencyCode, Currency.getInstance(currencyCode)); imbAccount.setParentUID(mRootAccount.getUID()); imbAccount.setAccountType(AccountType.BANK); mapImbalanceAccount.put(currencyCode, imbAccount); mAccountList.add(imbAccount); } split.setAccountUID(imbAccount.getUID()); } java.util.Stack<Account> stack = new Stack<>(); for (Account account : mAccountList) { if (mapFullName.get(account.getUID()) != null) { continue; } stack.push(account); String parentAccountFullName; while (!stack.isEmpty()) { Account acc = stack.peek(); if (acc.getAccountType() == AccountType.ROOT) { // ROOT_ACCOUNT_FULL_NAME should ensure ROOT always sorts first mapFullName.put(acc.getUID(), AccountsDbAdapter.ROOT_ACCOUNT_FULL_NAME); stack.pop(); continue; } String parentUID = acc.getParentUID(); Account parentAccount = mAccountMap.get(parentUID); // ROOT account will be added if not exist, so now anly ROOT // has an empty parent if (parentAccount.getAccountType() == AccountType.ROOT) { // top level account, full name is the same as its name mapFullName.put(acc.getUID(), acc.getName()); stack.pop(); continue; } parentAccountFullName = mapFullName.get(parentUID); if (parentAccountFullName == null) { // non-top-level account, parent full name still unknown stack.push(parentAccount); continue; } mapFullName.put( acc.getUID(), parentAccountFullName + AccountsDbAdapter.ACCOUNT_NAME_SEPARATOR + acc.getName()); stack.pop(); } } for (Account account : mAccountList) { account.setFullName(mapFullName.get(account.getUID())); } long startTime = System.nanoTime(); mAccountsDbAdapter.beginTransaction(); Log.d(getClass().getSimpleName(), "bulk insert starts"); try { Log.d(getClass().getSimpleName(), "before clean up db"); mAccountsDbAdapter.deleteAllRecords(); Log.d( getClass().getSimpleName(), String.format("deb clean up done %d ns", System.nanoTime() - startTime)); long nAccounts = mAccountsDbAdapter.bulkAddRecords(mAccountList); Log.d("Handler:", String.format("%d accounts inserted", nAccounts)); // We need to add scheduled actions first because there is a foreign key constraint on // transactions // which are generated from scheduled actions (we do auto-create some transactions during // import) long nSchedActions = mScheduledActionsDbAdapter.bulkAddRecords(mScheduledActionsList); Log.d("Handler:", String.format("%d scheduled actions inserted", nSchedActions)); long nTempTransactions = mTransactionsDbAdapter.bulkAddRecords(mTemplateTransactions); Log.d("Handler:", String.format("%d template transactions inserted", nTempTransactions)); long nTransactions = mTransactionsDbAdapter.bulkAddRecords(mTransactionList); Log.d("Handler:", String.format("%d transactions inserted", nTransactions)); long nPrices = mPricesDbAdapter.bulkAddRecords(mPriceList); Log.d(getClass().getSimpleName(), String.format("%d prices inserted", nPrices)); long endTime = System.nanoTime(); Log.d(getClass().getSimpleName(), String.format("bulk insert time: %d", endTime - startTime)); mAccountsDbAdapter.setTransactionSuccessful(); } finally { mAccountsDbAdapter.endTransaction(); } }
/** * Serializes {@link ScheduledAction}s from the database to XML * * @param xmlSerializer XML serializer * @throws IOException */ private void exportScheduledTransactions(XmlSerializer xmlSerializer) throws IOException { // for now we will export only scheduled transactions to XML Cursor cursor = mScheduledActionDbAdapter.fetchAllRecords( ScheduledActionEntry.COLUMN_TYPE + "=?", new String[] {ScheduledAction.ActionType.TRANSACTION.name()}); while (cursor.moveToNext()) { String actionUID = cursor.getString(cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_ACTION_UID)); Account accountUID = mTransactionToTemplateAccountMap.get(actionUID); if (accountUID == null) // if the action UID does not belong to a transaction we've seen before, skip it continue; xmlSerializer.startTag(null, GncXmlHelper.TAG_SCHEDULED_ACTION); xmlSerializer.attribute(null, GncXmlHelper.ATTR_KEY_VERSION, GncXmlHelper.BOOK_VERSION); xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_ID); String nameUID = accountUID.getName(); xmlSerializer.attribute(null, GncXmlHelper.ATTR_KEY_TYPE, GncXmlHelper.ATTR_VALUE_GUID); xmlSerializer.text(nameUID); xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_ID); xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_NAME); ScheduledAction.ActionType actionType = ScheduledAction.ActionType.valueOf( cursor.getString(cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_TYPE))); if (actionType == ScheduledAction.ActionType.TRANSACTION) { String description = TransactionsDbAdapter.getInstance() .getAttribute(actionUID, TransactionEntry.COLUMN_DESCRIPTION); xmlSerializer.text(description); } else { xmlSerializer.text(actionType.name()); } xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_NAME); xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_ENABLED); boolean enabled = cursor.getShort(cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_ENABLED)) > 0; xmlSerializer.text(enabled ? "y" : "n"); xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_ENABLED); xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_AUTO_CREATE); xmlSerializer.text("n"); // we do not want transactions auto-created on the desktop. xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_AUTO_CREATE); xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_AUTO_CREATE_NOTIFY); xmlSerializer.text( "n"); // TODO: if we ever support notifying before creating a scheduled transaction, then // update this xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_AUTO_CREATE_NOTIFY); xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_ADVANCE_CREATE_DAYS); xmlSerializer.text("0"); xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_ADVANCE_CREATE_DAYS); xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_ADVANCE_REMIND_DAYS); xmlSerializer.text("0"); xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_ADVANCE_REMIND_DAYS); xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_INSTANCE_COUNT); String scheduledActionUID = cursor.getString(cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_UID)); long instanceCount = mScheduledActionDbAdapter.getActionInstanceCount(scheduledActionUID); xmlSerializer.text(Long.toString(instanceCount)); xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_INSTANCE_COUNT); // start date String createdTimestamp = cursor.getString(cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_CREATED_AT)); long scheduleStartTime = Timestamp.valueOf(createdTimestamp).getTime(); serializeDate(xmlSerializer, GncXmlHelper.TAG_SX_START, scheduleStartTime); long lastRunTime = cursor.getLong(cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_LAST_RUN)); if (lastRunTime > 0) { serializeDate(xmlSerializer, GncXmlHelper.TAG_SX_LAST, lastRunTime); } long endTime = cursor.getLong(cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_END_TIME)); if (endTime > 0) { // end date serializeDate(xmlSerializer, GncXmlHelper.TAG_SX_END, endTime); } else { // add number of occurrences int totalFrequency = cursor.getInt( cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_TOTAL_FREQUENCY)); xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_NUM_OCCUR); xmlSerializer.text(Integer.toString(totalFrequency)); xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_NUM_OCCUR); // remaining occurrences int executionCount = cursor.getInt( cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_EXECUTION_COUNT)); xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_REM_OCCUR); xmlSerializer.text(Integer.toString(totalFrequency - executionCount)); xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_REM_OCCUR); } String tag = cursor.getString(cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_TAG)); if (tag != null && !tag.isEmpty()) { xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_TAG); xmlSerializer.text(tag); xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_TAG); } xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_TEMPL_ACCOUNT); xmlSerializer.attribute(null, GncXmlHelper.ATTR_KEY_TYPE, GncXmlHelper.ATTR_VALUE_GUID); xmlSerializer.text(accountUID.getUID()); xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_TEMPL_ACCOUNT); xmlSerializer.startTag(null, GncXmlHelper.TAG_SX_SCHEDULE); xmlSerializer.startTag(null, GncXmlHelper.TAG_RECURRENCE); xmlSerializer.attribute(null, GncXmlHelper.ATTR_KEY_VERSION, GncXmlHelper.RECURRENCE_VERSION); long period = cursor.getLong(cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_PERIOD)); PeriodType periodType = ScheduledAction.getPeriodType(period); xmlSerializer.startTag(null, GncXmlHelper.TAG_RX_MULT); xmlSerializer.text(String.valueOf(periodType.getMultiplier())); xmlSerializer.endTag(null, GncXmlHelper.TAG_RX_MULT); xmlSerializer.startTag(null, GncXmlHelper.TAG_RX_PERIOD_TYPE); xmlSerializer.text(periodType.name().toLowerCase()); xmlSerializer.endTag(null, GncXmlHelper.TAG_RX_PERIOD_TYPE); long recurrenceStartTime = cursor.getLong(cursor.getColumnIndexOrThrow(ScheduledActionEntry.COLUMN_START_TIME)); serializeDate(xmlSerializer, GncXmlHelper.TAG_RX_START, recurrenceStartTime); xmlSerializer.endTag(null, GncXmlHelper.TAG_RECURRENCE); xmlSerializer.endTag(null, GncXmlHelper.TAG_SX_SCHEDULE); xmlSerializer.endTag(null, GncXmlHelper.TAG_SCHEDULED_ACTION); } }