1515 */
1616package org .gnucash .android .test .unit .service ;
1717
18+ import android .content .ContentValues ;
1819import android .database .sqlite .SQLiteDatabase ;
19- import android .support .annotation .NonNull ;
2020
2121import org .gnucash .android .BuildConfig ;
2222import org .gnucash .android .R ;
2323import org .gnucash .android .app .GnuCashApplication ;
24+ import org .gnucash .android .db .DatabaseSchema ;
2425import org .gnucash .android .db .adapter .AccountsDbAdapter ;
2526import org .gnucash .android .db .adapter .BooksDbAdapter ;
2627import org .gnucash .android .db .adapter .CommoditiesDbAdapter ;
3940import org .gnucash .android .model .ScheduledAction ;
4041import org .gnucash .android .model .Split ;
4142import org .gnucash .android .model .Transaction ;
43+ import org .gnucash .android .model .TransactionType ;
4244import org .gnucash .android .service .ScheduledActionService ;
4345import org .gnucash .android .test .unit .testutil .GnucashTestRunner ;
4446import org .gnucash .android .test .unit .testutil .ShadowCrashlytics ;
4547import org .gnucash .android .test .unit .testutil .ShadowUserVoice ;
48+ import org .gnucash .android .util .TimestampHelper ;
4649import org .joda .time .DateTime ;
4750import org .joda .time .LocalDateTime ;
4851import org .joda .time .Weeks ;
5760import java .io .File ;
5861import java .io .IOException ;
5962import java .math .BigDecimal ;
63+ import java .sql .Timestamp ;
6064import java .util .ArrayList ;
6165import java .util .List ;
6266
@@ -79,6 +83,7 @@ public class ScheduledActionServiceTest {
7983 private static Account mTransferAccount = new Account ("Transfer Account" );
8084
8185 private static Transaction mTemplateTransaction ;
86+ private TransactionsDbAdapter mTransactionsDbAdapter ;
8287
8388 public void createAccounts (){
8489 try {
@@ -117,9 +122,8 @@ public void setUp(){
117122 accountsDbAdapter .addRecord (mBaseAccount );
118123 accountsDbAdapter .addRecord (mTransferAccount );
119124
120- TransactionsDbAdapter transactionsDbAdapter = TransactionsDbAdapter .getInstance ();
121- transactionsDbAdapter .addRecord (mTemplateTransaction , DatabaseAdapter .UpdateMethod .insert );
122-
125+ mTransactionsDbAdapter = TransactionsDbAdapter .getInstance ();
126+ mTransactionsDbAdapter .addRecord (mTemplateTransaction , DatabaseAdapter .UpdateMethod .insert );
123127 }
124128
125129 @ Test
@@ -363,6 +367,103 @@ public void scheduledBackups_shouldNotRunBeforeNextScheduledExecution(){
363367 assertThat (backupFolder .listFiles ()).hasSize (0 );
364368 }
365369
370+ /**
371+ * Tests that an scheduled backup doesn't include transactions added or modified
372+ * previous to the last run.
373+ */
374+ @ Test
375+ public void scheduledBackups_shouldNotIncludeTransactionsPreviousToTheLastRun () {
376+ ScheduledAction scheduledBackup = new ScheduledAction (ScheduledAction .ActionType .BACKUP );
377+ scheduledBackup .setStartTime (LocalDateTime .now ().minusDays (15 ).toDate ().getTime ());
378+ scheduledBackup .setLastRun (LocalDateTime .now ().minusDays (8 ).toDate ().getTime ());
379+ long previousLastRun = scheduledBackup .getLastRunTime ();
380+ scheduledBackup .setExecutionCount (1 );
381+ scheduledBackup .setRecurrence (PeriodType .WEEK , 1 );
382+ ExportParams backupParams = new ExportParams (ExportFormat .QIF );
383+ backupParams .setExportTarget (ExportParams .ExportTarget .SD_CARD );
384+ backupParams .setExportStartTime (new Timestamp (scheduledBackup .getStartTime ()));
385+ scheduledBackup .setTag (backupParams .toCsv ());
386+
387+ // Create a transaction with a modified date previous to the last run
388+ Transaction transaction = new Transaction ("Tandoori express" );
389+ Split split = new Split (new Money ("10" , Commodity .DEFAULT_COMMODITY .getCurrencyCode ()),
390+ mBaseAccount .getUID ());
391+ split .setType (TransactionType .DEBIT );
392+ transaction .addSplit (split );
393+ transaction .addSplit (split .createPair (mTransferAccount .getUID ()));
394+ mTransactionsDbAdapter .addRecord (transaction );
395+ // We set the date directly in the database as the corresponding field
396+ // is ignored when the object is stored. It's set through a trigger instead.
397+ setTransactionInDbModifiedTimestamp (transaction .getUID (),
398+ new Timestamp (LocalDateTime .now ().minusDays (9 ).toDate ().getTime ()));
399+
400+ File backupFolder = new File (
401+ Exporter .getExportFolderPath (BooksDbAdapter .getInstance ().getActiveBookUID ()));
402+ assertThat (backupFolder ).exists ();
403+ assertThat (backupFolder .listFiles ()).isEmpty ();
404+
405+ List <ScheduledAction > actions = new ArrayList <>();
406+ actions .add (scheduledBackup );
407+ ScheduledActionService .processScheduledActions (actions , mDb );
408+
409+ assertThat (scheduledBackup .getExecutionCount ()).isEqualTo (2 );
410+ assertThat (scheduledBackup .getLastRunTime ()).isGreaterThan (previousLastRun );
411+ assertThat (backupFolder .listFiles ()).hasSize (0 );
412+ }
413+
414+ /**
415+ * Sets the transaction modified timestamp directly in the database.
416+ *
417+ * @param transactionUID UID of the transaction to set the modified timestamp.
418+ * @param timestamp new modified timestamp.
419+ */
420+ private void setTransactionInDbModifiedTimestamp (String transactionUID , Timestamp timestamp ) {
421+ ContentValues values = new ContentValues ();
422+ values .put (DatabaseSchema .TransactionEntry .COLUMN_MODIFIED_AT ,
423+ TimestampHelper .getUtcStringFromTimestamp (timestamp ));
424+ mTransactionsDbAdapter .updateTransaction (values , "uid = ?" ,
425+ new String []{transactionUID });
426+ }
427+
428+ /**
429+ * Tests that an scheduled backup includes transactions added or modified
430+ * after the last run.
431+ */
432+ @ Test
433+ public void scheduledBackups_shouldIncludeTransactionsAfterTheLastRun () {
434+ ScheduledAction scheduledBackup = new ScheduledAction (ScheduledAction .ActionType .BACKUP );
435+ scheduledBackup .setStartTime (LocalDateTime .now ().minusDays (15 ).toDate ().getTime ());
436+ scheduledBackup .setLastRun (LocalDateTime .now ().minusDays (8 ).toDate ().getTime ());
437+ long previousLastRun = scheduledBackup .getLastRunTime ();
438+ scheduledBackup .setExecutionCount (1 );
439+ scheduledBackup .setRecurrence (PeriodType .WEEK , 1 );
440+ ExportParams backupParams = new ExportParams (ExportFormat .QIF );
441+ backupParams .setExportTarget (ExportParams .ExportTarget .SD_CARD );
442+ backupParams .setExportStartTime (new Timestamp (scheduledBackup .getStartTime ()));
443+ scheduledBackup .setTag (backupParams .toCsv ());
444+
445+ Transaction transaction = new Transaction ("Orient palace" );
446+ Split split = new Split (new Money ("10" , Commodity .DEFAULT_COMMODITY .getCurrencyCode ()),
447+ mBaseAccount .getUID ());
448+ split .setType (TransactionType .DEBIT );
449+ transaction .addSplit (split );
450+ transaction .addSplit (split .createPair (mTransferAccount .getUID ()));
451+ mTransactionsDbAdapter .addRecord (transaction );
452+
453+ File backupFolder = new File (
454+ Exporter .getExportFolderPath (BooksDbAdapter .getInstance ().getActiveBookUID ()));
455+ assertThat (backupFolder ).exists ();
456+ assertThat (backupFolder .listFiles ()).isEmpty ();
457+
458+ List <ScheduledAction > actions = new ArrayList <>();
459+ actions .add (scheduledBackup );
460+ ScheduledActionService .processScheduledActions (actions , mDb );
461+
462+ assertThat (scheduledBackup .getExecutionCount ()).isEqualTo (2 );
463+ assertThat (scheduledBackup .getLastRunTime ()).isGreaterThan (previousLastRun );
464+ assertThat (backupFolder .listFiles ()).hasSize (1 );
465+ }
466+
366467 @ After
367468 public void tearDown (){
368469 TransactionsDbAdapter .getInstance ().deleteAllRecords ();
0 commit comments