diff --git a/assets/translations/en.json b/assets/translations/en.json index 86d29131..e43bfc9f 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -506,6 +506,9 @@ "noPendingChanges": "No pending changes", "failedChanges": "Failed changes", "noFailedChanges": "No failed changes", + "needsAttention": "Needs attention", + "noQuarantinedChanges": "Nothing needs attention", + "quarantinedHint": "These changes keep being rejected and won't retry automatically. Fix the underlying data, then retry — or discard them.", "dismiss": "Dismiss", "categorySalary": "Salary", "categorySalaryDesc": "Regular employment income", diff --git a/drift_schemas/default/drift_schema_v8.json b/drift_schemas/default/drift_schema_v8.json new file mode 100644 index 00000000..a6baf6fb --- /dev/null +++ b/drift_schemas/default/drift_schema_v8.json @@ -0,0 +1 @@ +{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":true},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"wallets","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"client_id","getter_name":"clientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"rev","getter_name":"rev","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":"const CustomExpression('\\'1\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_synced_at","getter_name":"lastSyncedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const WalletTypeConverter()","dart_type_name":"WalletType"}},{"name":"balance","getter_name":"balance","moor_type":"double","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0.0')","default_client_dart":null,"dsl_features":[]},{"name":"currency","getter_name":"currency","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"stats","getter_name":"stats","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const WalletStatsConverter()","dart_type_name":"WalletStats"}},{"name":"icon","getter_name":"icon","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const MediaConverter()","dart_type_name":"Media"}}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["client_id"]}},{"id":1,"references":[],"type":"table","data":{"name":"parties","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"client_id","getter_name":"clientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"rev","getter_name":"rev","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":"const CustomExpression('\\'1\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_synced_at","getter_name":"lastSyncedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"icon","getter_name":"icon","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const MediaConverter()","dart_type_name":"Media"}},{"name":"type","getter_name":"type","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const PartyTypeConverter()","dart_type_name":"PartyType"}}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["client_id"]}},{"id":2,"references":[],"type":"table","data":{"name":"groups","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"client_id","getter_name":"clientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"rev","getter_name":"rev","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":"const CustomExpression('\\'1\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_synced_at","getter_name":"lastSyncedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"icon","getter_name":"icon","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const MediaConverter()","dart_type_name":"Media"}}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["client_id"]}},{"id":3,"references":[0,1,2],"type":"table","data":{"name":"transactions","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"client_id","getter_name":"clientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"rev","getter_name":"rev","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":"const CustomExpression('\\'1\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_synced_at","getter_name":"lastSyncedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"amount","getter_name":"amount","moor_type":"double","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(TransactionType.values)","dart_type_name":"TransactionType"}},{"name":"intent","getter_name":"intent","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'regular\\'')","default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"datetime","getter_name":"datetime","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"party_id","getter_name":"partyId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"wallet_id","getter_name":"walletId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"group_id","getter_name":"groupId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"wallet_client_id","getter_name":"walletClientId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES wallets (client_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES wallets (client_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"wallets","column":"client_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"party_client_id","getter_name":"partyClientId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES parties (client_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES parties (client_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"parties","column":"client_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"group_client_id","getter_name":"groupClientId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES \"groups\" (client_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES \"groups\" (client_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"groups","column":"client_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"transfer_id","getter_name":"transferId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"transfer_client_id","getter_name":"transferClientId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_refund","getter_name":"isRefund","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_refund\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_refund\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"refund_of_transaction_id","getter_name":"refundOfTransactionId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"recurrence_period","getter_name":"recurrencePeriod","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"recurrence_interval","getter_name":"recurrenceInterval","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"recurrence_ends_at","getter_name":"recurrenceEndsAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"recurrence_next_scheduled_at","getter_name":"recurrenceNextScheduledAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["client_id"]}},{"id":4,"references":[],"type":"table","data":{"name":"categories","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"client_id","getter_name":"clientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"rev","getter_name":"rev","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":"const CustomExpression('\\'1\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_synced_at","getter_name":"lastSyncedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"slug","getter_name":"slug","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(TransactionType.values)","dart_type_name":"TransactionType"}},{"name":"icon","getter_name":"icon","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const MediaConverter()","dart_type_name":"Media"}}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["client_id"]}},{"id":5,"references":[],"type":"table","data":{"name":"configs","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"client_id","getter_name":"clientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"rev","getter_name":"rev","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":"const CustomExpression('\\'1\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_synced_at","getter_name":"lastSyncedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"key","getter_name":"key","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(ConfigType.values)","dart_type_name":"ConfigType"}},{"name":"value","getter_name":"value","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const ConfigValueConverter()","dart_type_name":"dynamic"}}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["client_id"]}},{"id":6,"references":[],"type":"table","data":{"name":"users","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"email","getter_name":"email","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"first_name","getter_name":"firstName","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_name","getter_name":"lastName","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"username","getter_name":"username","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"phone","getter_name":"phone","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"avatar","getter_name":"avatar","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["id"]}},{"id":7,"references":[],"type":"table","data":{"name":"local_changes","was_declared_in_moor":false,"columns":[{"name":"entity_type","getter_name":"entityType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"entity_id","getter_name":"entityId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"entity_rev","getter_name":"entityRev","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"deleted","getter_name":"deleted","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"deleted\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"deleted\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"data","getter_name":"data","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const JsonMapConverter()","dart_type_name":"Map"}},{"name":"create_at","getter_name":"createAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"concluded","getter_name":"concluded","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"concluded\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"concluded\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"concluded_moment","getter_name":"concludedMoment","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"error","getter_name":"error","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"dismissed","getter_name":"dismissed","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"dismissed\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"dismissed\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"attempt_count","getter_name":"attemptCount","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"quarantined_at","getter_name":"quarantinedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["entity_id","entity_type"]}},{"id":8,"references":[],"type":"table","data":{"name":"sync_metadata","was_declared_in_moor":false,"columns":[{"name":"entity_type","getter_name":"entityType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_synced_at","getter_name":"lastSyncedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["entity_type"]}},{"id":9,"references":[4],"type":"table","data":{"name":"categorizables","was_declared_in_moor":false,"columns":[{"name":"categorizable_id","getter_name":"categorizableId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"categorizable_type","getter_name":"categorizableType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(CategorizableType.values)","dart_type_name":"CategorizableType"}},{"name":"category_client_id","getter_name":"categoryClientId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES categories (client_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES categories (client_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"categories","column":"client_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["categorizable_id","categorizable_type","category_client_id"]}},{"id":10,"references":[],"type":"table","data":{"name":"notifications","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"client_id","getter_name":"clientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"rev","getter_name":"rev","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":"const CustomExpression('\\'1\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_synced_at","getter_name":"lastSyncedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(NotificationType.values)","dart_type_name":"NotificationType"}},{"name":"title","getter_name":"title","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"body","getter_name":"body","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"data","getter_name":"data","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const JsonMapConverter()","dart_type_name":"Map"}},{"name":"read_at","getter_name":"readAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["client_id"]}},{"id":11,"references":[],"type":"table","data":{"name":"media_files","was_declared_in_moor":false,"columns":[{"name":"path","getter_name":"path","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"id","getter_name":"id","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"fileable_type","getter_name":"fileableType","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"fileable_id","getter_name":"fileableId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"local_fileable_type","getter_name":"localFileableType","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"local_fileable_id","getter_name":"localFileableId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["path"]}},{"id":12,"references":[0,3],"type":"table","data":{"name":"transfers","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"client_id","getter_name":"clientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"rev","getter_name":"rev","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":"const CustomExpression('\\'1\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_synced_at","getter_name":"lastSyncedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"amount","getter_name":"amount","moor_type":"double","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"from_wallet_id","getter_name":"fromWalletId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"to_wallet_id","getter_name":"toWalletId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"from_wallet_client_id","getter_name":"fromWalletClientId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES wallets (client_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES wallets (client_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"wallets","column":"client_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"to_wallet_client_id","getter_name":"toWalletClientId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES wallets (client_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES wallets (client_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"wallets","column":"client_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"exchange_rate","getter_name":"exchangeRate","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"datetime","getter_name":"datetime","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"expense_transaction_client_id","getter_name":"expenseTransactionClientId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES transactions (client_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES transactions (client_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"transactions","column":"client_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"income_transaction_client_id","getter_name":"incomeTransactionClientId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES transactions (client_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES transactions (client_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"transactions","column":"client_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["client_id"]}},{"id":13,"references":[],"type":"table","data":{"name":"budgets","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"client_id","getter_name":"clientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"rev","getter_name":"rev","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":"const CustomExpression('\\'1\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_synced_at","getter_name":"lastSyncedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"slug","getter_name":"slug","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"amount","getter_name":"amount","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const StringToDoubleConverter()","dart_type_name":"double"}},{"name":"currency","getter_name":"currency","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"period_type","getter_name":"periodType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(BudgetPeriodType.values)","dart_type_name":"BudgetPeriodType"}},{"name":"start_date","getter_name":"startDate","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"end_date","getter_name":"endDate","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"rollover_enabled","getter_name":"rolloverEnabled","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"rollover_enabled\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"rollover_enabled\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"threshold_percent","getter_name":"thresholdPercent","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('80')","default_client_dart":null,"dsl_features":[]},{"name":"forecast_alerts_enabled","getter_name":"forecastAlertsEnabled","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"forecast_alerts_enabled\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"forecast_alerts_enabled\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"is_active","getter_name":"isActive","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_active\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_active\" IN (0, 1))"},"default_dart":"const CustomExpression('1')","default_client_dart":null,"dsl_features":[]},{"name":"owner_type","getter_name":"ownerType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'user\\'')","default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"progress","getter_name":"progress","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const BudgetProgressJsonConverter()","dart_type_name":"BudgetProgressEntity"}}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["client_id"]}},{"id":14,"references":[13],"type":"table","data":{"name":"budget_targets","was_declared_in_moor":false,"columns":[{"name":"budget_client_id","getter_name":"budgetClientId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES budgets (client_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES budgets (client_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"budgets","column":"client_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"target_type","getter_name":"targetType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(BudgetTargetType.values)","dart_type_name":"BudgetTargetType"}},{"name":"target_client_id","getter_name":"targetClientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["budget_client_id","target_type","target_client_id"]}},{"id":15,"references":[13],"type":"table","data":{"name":"budget_period_states","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"client_id","getter_name":"clientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"rev","getter_name":"rev","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":"const CustomExpression('\\'1\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_synced_at","getter_name":"lastSyncedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"budget_client_id","getter_name":"budgetClientId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES budgets (client_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES budgets (client_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"budgets","column":"client_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"period_start","getter_name":"periodStart","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"period_end","getter_name":"periodEnd","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"net_spent","getter_name":"netSpent","moor_type":"double","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0.0')","default_client_dart":null,"dsl_features":[]},{"name":"rollover_in","getter_name":"rolloverIn","moor_type":"double","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0.0')","default_client_dart":null,"dsl_features":[]},{"name":"rollover_out","getter_name":"rolloverOut","moor_type":"double","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0.0')","default_client_dart":null,"dsl_features":[]},{"name":"closed_at","getter_name":"closedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["client_id"]}},{"id":16,"references":[],"type":"table","data":{"name":"holdings","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"symbol","getter_name":"symbol","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"quantity","getter_name":"quantity","moor_type":"double","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0.0')","default_client_dart":null,"dsl_features":[]},{"name":"currency","getter_name":"currency","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"unit_price","getter_name":"unitPrice","moor_type":"double","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0.0')","default_client_dart":null,"dsl_features":[]},{"name":"value","getter_name":"value","moor_type":"double","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0.0')","default_client_dart":null,"dsl_features":[]},{"name":"price_source","getter_name":"priceSource","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'manual\\'')","default_client_dart":null,"dsl_features":[]},{"name":"provider","getter_name":"provider","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"external_ref","getter_name":"externalRef","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_priced_at","getter_name":"lastPricedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["id"]}},{"id":17,"references":[],"type":"table","data":{"name":"financial_position_cache","was_declared_in_moor":false,"columns":[{"name":"cache_key","getter_name":"cacheKey","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"payload","getter_name":"payload","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"currency","getter_name":"currency","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"fetched_at","getter_name":"fetchedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["cache_key"]}},{"id":18,"references":[],"type":"table","data":{"name":"reminders","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"UNIQUE","dialectAwareDefaultConstraints":{"sqlite":"UNIQUE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unique"]},{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"client_id","getter_name":"clientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"rev","getter_name":"rev","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":"const CustomExpression('\\'1\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_synced_at","getter_name":"lastSyncedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"title","getter_name":"title","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'custom\\'')","default_client_dart":null,"dsl_features":[]},{"name":"trigger_at","getter_name":"triggerAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"due_at","getter_name":"dueAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"repeat_rule","getter_name":"repeatRule","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"timezone","getter_name":"timezone","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"status","getter_name":"status","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'active\\'')","default_client_dart":null,"dsl_features":[]},{"name":"priority","getter_name":"priority","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"snoozed_until","getter_name":"snoozedUntil","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_triggered_at","getter_name":"lastTriggeredAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"next_trigger_at","getter_name":"nextTriggerAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["client_id"]}},{"id":19,"references":[],"type":"table","data":{"name":"deferred_remote_items","was_declared_in_moor":false,"columns":[{"name":"entity_type","getter_name":"entityType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"client_id","getter_name":"clientId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"data","getter_name":"data","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"parked_at","getter_name":"parkedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["entity_type","client_id"]}}]} \ No newline at end of file diff --git a/lib/core/sync/sync_database.dart b/lib/core/sync/sync_database.dart index ae76d20b..8daef8c5 100644 --- a/lib/core/sync/sync_database.dart +++ b/lib/core/sync/sync_database.dart @@ -13,7 +13,10 @@ class SynchAppDatabase extends DriftSynchronizer { required super.requestAuthorizationService, required super.logger, super.crashReporter, - }); + }) : super( + cursorRewind: const Duration(seconds: 1), + classifyFailure: restFailureClassifier, + ); final _syncStateController = StreamController.broadcast(); diff --git a/lib/core/utils/date_util.dart b/lib/core/utils/date_util.dart index 997ef24f..f14be996 100644 --- a/lib/core/utils/date_util.dart +++ b/lib/core/utils/date_util.dart @@ -1,13 +1,5 @@ -import 'package:easy_localization/easy_localization.dart'; - -DateTime _formatServerIsoDateTime(DateTime now) { - final formatted = DateFormat("yyyy-MM-dd'T'HH:mm:ss.mmm'Z'").format(now); - final dateTime = DateTime.parse(formatted); - return dateTime; -} - -String formatServerIsoDateTimeString(DateTime utcDateTime) { - return _formatServerIsoDateTime(utcDateTime).toIso8601String(); +String formatServerIsoDateTimeString(DateTime dateTime) { + return dateTime.toUtc().toIso8601String(); } DateTime getNewFormattedUtcDateTime() { diff --git a/lib/data/database/app_database.dart b/lib/data/database/app_database.dart index 12ab7863..7dad9a0c 100644 --- a/lib/data/database/app_database.dart +++ b/lib/data/database/app_database.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:io'; import 'package:drift/drift.dart'; @@ -18,6 +19,7 @@ import 'package:trakli/data/database/tables/budgets.dart'; import 'package:trakli/data/database/tables/categories.dart'; import 'package:trakli/data/database/tables/categorizables.dart'; import 'package:trakli/data/database/tables/configs.dart'; +import 'package:trakli/data/database/tables/deferred_remote_items.dart'; import 'package:trakli/data/database/tables/financial_position_cache.dart'; import 'package:trakli/data/database/tables/groups.dart'; import 'package:trakli/data/database/tables/holdings.dart'; @@ -63,6 +65,7 @@ part 'app_database.g.dart'; Holdings, FinancialPositionCache, Reminders, + DeferredRemoteItems, ]) class AppDatabase extends _$AppDatabase with SynchronizerDb { final Set typeHandlers; @@ -74,7 +77,7 @@ class AppDatabase extends _$AppDatabase with SynchronizerDb { super(executor ?? _openConnection()); @override - int get schemaVersion => 7; + int get schemaVersion => 8; @override MigrationStrategy get migration { @@ -96,12 +99,49 @@ class AppDatabase extends _$AppDatabase with SynchronizerDb { }); } + /// Failed changes are retried automatically once this much time has passed + /// since the last attempt; a successful retry deletes the row. + /// Base delay before the first retry of a failed change. Each further + /// failed attempt doubles the wait ([retryBackoff]). + static const failedChangeRetryDelay = Duration(minutes: 1); + + /// Upper bound on the exponential retry backoff. + static const failedChangeRetryCap = Duration(hours: 1); + + /// Backoff before retrying a change that has failed [attemptCount] times: + /// base doubles per attempt, capped at [failedChangeRetryCap]. + static Duration retryBackoff(int attemptCount) { + if (attemptCount <= 1) return failedChangeRetryDelay; + final shift = attemptCount - 1; + // Cap the exponent itself, not just the final duration: on Dart + // compiled to JS, bitwise shifts truncate to 32 bits, so a large shift + // can wrap negative before the cap check below ever runs. 6 is already + // past the point where the multiplication exceeds the cap. + final safeShift = shift > 6 ? 6 : shift; + final ms = failedChangeRetryDelay.inMilliseconds * (1 << safeShift); + return ms >= failedChangeRetryCap.inMilliseconds + ? failedChangeRetryCap + : Duration(milliseconds: ms); + } + @override Future> getPendingLocalChanges() async { - final rows = - await (select(localChanges)..where((lc) => lc.error.isNull())).get(); + final now = DateTime.now(); + // Quarantined and dismissed changes never retry, so both are excluded + // in SQL. The remaining rows are filtered by their per-row exponential + // backoff below (not expressible in SQL). + final rows = await (select(localChanges) + ..where((lc) => + lc.quarantinedAt.isNull() & lc.dismissed.equals(false))) + .get(); return rows + .where((row) { + if (row.error == null) return true; // never failed + final concluded = row.concludedMoment; + if (concluded == null) return true; + return now.isAfter(concluded.add(retryBackoff(row.attemptCount))); + }) .map((row) => PendingLocalChange( entityType: row.entityType, entityId: row.entityId, @@ -113,6 +153,8 @@ class AppDatabase extends _$AppDatabase with SynchronizerDb { concludedMoment: row.concludedMoment, error: row.error, dismissed: row.dismissed, + attemptCount: row.attemptCount, + quarantinedAt: row.quarantinedAt, )) .toList(); } @@ -122,6 +164,22 @@ class AppDatabase extends _$AppDatabase with SynchronizerDb { await delete(localChanges).go(); } + /// True while transaction or transfer changes are still waiting to sync — + /// server /stats cannot include them yet. Dismissed and quarantined + /// changes don't count: dismissed changes never sync, and quarantined + /// ones won't sync without a user retry, so neither should hold reports + /// on "local estimate" indefinitely. + Future hasPendingTransactionChanges() async { + final row = await (select(localChanges) + ..where((lc) => + lc.entityType.isIn(const ['transaction', 'transfer']) & + lc.dismissed.equals(false) & + lc.quarantinedAt.isNull()) + ..limit(1)) + .getSingleOrNull(); + return row != null; + } + Future> getCategoriesForTransaction( String transactionId, CategorizableType sourceType) async { final query = select(categories).join([ @@ -150,15 +208,22 @@ class AppDatabase extends _$AppDatabase with SynchronizerDb { @override Future concludeLocalChange(PendingLocalChange localChange, - {Object? error, bool persistedToRemote = false}) async { + {Object? error, + bool persistedToRemote = false, + bool quarantine = false}) async { if (error != null) { await (update(localChanges) - ..where((lc) => lc.entityId.equals(localChange.entityId))) + ..where((lc) => + lc.entityType.equals(localChange.entityType) & + lc.entityId.equals(localChange.entityId))) .write( LocalChangesCompanion( concludedMoment: Value(DateTime.now()), error: Value(error.toString()), concluded: const Value(true), + attemptCount: Value(localChange.attemptCount + 1), + quarantinedAt: + quarantine ? Value(DateTime.now()) : const Value.absent(), ), ); } @@ -189,6 +254,8 @@ class AppDatabase extends _$AppDatabase with SynchronizerDb { concludedMoment: Value(pendingLocalChange.concludedMoment), error: Value(pendingLocalChange.error), deleted: Value(pendingLocalChange.deleted), + attemptCount: Value(pendingLocalChange.attemptCount), + quarantinedAt: Value(pendingLocalChange.quarantinedAt), ); await into(localChanges).insert( @@ -273,6 +340,43 @@ class AppDatabase extends _$AppDatabase with SynchronizerDb { ); } + @override + Future parkRemoteItem(ParkedRemoteItem item) async { + await deferredRemoteItems.insertOne( + DeferredRemoteItemsCompanion.insert( + entityType: item.entityType, + clientId: item.clientId, + data: jsonEncode(item.data), + parkedAt: Value(item.parkedAt ?? DateTime.now().toUtc()), + ), + mode: InsertMode.insertOrReplace, + ); + } + + @override + Future> getParkedRemoteItems( + String entityType) async { + final rows = await (select(deferredRemoteItems) + ..where((t) => t.entityType.equals(entityType))) + .get(); + return rows + .map((row) => ParkedRemoteItem( + entityType: row.entityType, + clientId: row.clientId, + data: jsonDecode(row.data) as Map, + parkedAt: row.parkedAt, + )) + .toList(growable: false); + } + + @override + Future unparkRemoteItem(String entityType, String clientId) async { + await (delete(deferredRemoteItems) + ..where((t) => + t.entityType.equals(entityType) & t.clientId.equals(clientId))) + .go(); + } + @override Future clearDatabase() async { await users.deleteAll(); @@ -343,5 +447,17 @@ extension Migrations on GeneratedDatabase { // Reminders await m.createTable(schema.reminders); }, + from7To8: (Migrator m, Schema8 schema) async { + // Parking store for down-synced items with unmet local + // dependencies (SyncTypeHandler.shouldPersistLocal). + await m.createTable(schema.deferredRemoteItems); + + // Failure classification: retry accounting + quarantine for + // permanently failed local changes. + await m.addColumn( + schema.localChanges, schema.localChanges.attemptCount); + await m.addColumn( + schema.localChanges, schema.localChanges.quarantinedAt); + }, ); } diff --git a/lib/data/database/app_database.g.dart b/lib/data/database/app_database.g.dart index 200d1ba1..aa62ff0d 100644 --- a/lib/data/database/app_database.g.dart +++ b/lib/data/database/app_database.g.dart @@ -4230,6 +4230,16 @@ class $LocalChangesTable extends LocalChanges defaultConstraints: GeneratedColumn.constraintIsAlways('CHECK ("dismissed" IN (0, 1))')); @override + late final GeneratedColumn attemptCount = GeneratedColumn( + 'attempt_count', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const Constant(0)); + @override + late final GeneratedColumn quarantinedAt = + GeneratedColumn('quarantined_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override List get $columns => [ entityType, entityId, @@ -4240,7 +4250,9 @@ class $LocalChangesTable extends LocalChanges concluded, concludedMoment, error, - dismissed + dismissed, + attemptCount, + quarantinedAt ]; @override String get aliasedName => _alias ?? actualTableName; @@ -4274,6 +4286,10 @@ class $LocalChangesTable extends LocalChanges .read(DriftSqlType.string, data['${effectivePrefix}error']), dismissed: attachedDatabase.typeMapping .read(DriftSqlType.bool, data['${effectivePrefix}dismissed'])!, + attemptCount: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}attempt_count'])!, + quarantinedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}quarantined_at']), ); } @@ -4297,6 +4313,8 @@ class LocalChange extends DataClass implements Insertable { final DateTime? concludedMoment; final String? error; final bool dismissed; + final int attemptCount; + final DateTime? quarantinedAt; const LocalChange( {required this.entityType, required this.entityId, @@ -4307,7 +4325,9 @@ class LocalChange extends DataClass implements Insertable { required this.concluded, this.concludedMoment, this.error, - required this.dismissed}); + required this.dismissed, + required this.attemptCount, + this.quarantinedAt}); @override Map toColumns(bool nullToAbsent) { final map = {}; @@ -4328,6 +4348,10 @@ class LocalChange extends DataClass implements Insertable { map['error'] = Variable(error); } map['dismissed'] = Variable(dismissed); + map['attempt_count'] = Variable(attemptCount); + if (!nullToAbsent || quarantinedAt != null) { + map['quarantined_at'] = Variable(quarantinedAt); + } return map; } @@ -4346,6 +4370,10 @@ class LocalChange extends DataClass implements Insertable { error: error == null && nullToAbsent ? const Value.absent() : Value(error), dismissed: Value(dismissed), + attemptCount: Value(attemptCount), + quarantinedAt: quarantinedAt == null && nullToAbsent + ? const Value.absent() + : Value(quarantinedAt), ); } @@ -4363,6 +4391,8 @@ class LocalChange extends DataClass implements Insertable { concludedMoment: serializer.fromJson(json['concludedMoment']), error: serializer.fromJson(json['error']), dismissed: serializer.fromJson(json['dismissed']), + attemptCount: serializer.fromJson(json['attemptCount']), + quarantinedAt: serializer.fromJson(json['quarantinedAt']), ); } @override @@ -4379,6 +4409,8 @@ class LocalChange extends DataClass implements Insertable { 'concludedMoment': serializer.toJson(concludedMoment), 'error': serializer.toJson(error), 'dismissed': serializer.toJson(dismissed), + 'attemptCount': serializer.toJson(attemptCount), + 'quarantinedAt': serializer.toJson(quarantinedAt), }; } @@ -4392,7 +4424,9 @@ class LocalChange extends DataClass implements Insertable { bool? concluded, Value concludedMoment = const Value.absent(), Value error = const Value.absent(), - bool? dismissed}) => + bool? dismissed, + int? attemptCount, + Value quarantinedAt = const Value.absent()}) => LocalChange( entityType: entityType ?? this.entityType, entityId: entityId ?? this.entityId, @@ -4406,6 +4440,9 @@ class LocalChange extends DataClass implements Insertable { : this.concludedMoment, error: error.present ? error.value : this.error, dismissed: dismissed ?? this.dismissed, + attemptCount: attemptCount ?? this.attemptCount, + quarantinedAt: + quarantinedAt.present ? quarantinedAt.value : this.quarantinedAt, ); LocalChange copyWithCompanion(LocalChangesCompanion data) { return LocalChange( @@ -4422,6 +4459,12 @@ class LocalChange extends DataClass implements Insertable { : this.concludedMoment, error: data.error.present ? data.error.value : this.error, dismissed: data.dismissed.present ? data.dismissed.value : this.dismissed, + attemptCount: data.attemptCount.present + ? data.attemptCount.value + : this.attemptCount, + quarantinedAt: data.quarantinedAt.present + ? data.quarantinedAt.value + : this.quarantinedAt, ); } @@ -4437,14 +4480,27 @@ class LocalChange extends DataClass implements Insertable { ..write('concluded: $concluded, ') ..write('concludedMoment: $concludedMoment, ') ..write('error: $error, ') - ..write('dismissed: $dismissed') + ..write('dismissed: $dismissed, ') + ..write('attemptCount: $attemptCount, ') + ..write('quarantinedAt: $quarantinedAt') ..write(')')) .toString(); } @override - int get hashCode => Object.hash(entityType, entityId, entityRev, deleted, - data, createAt, concluded, concludedMoment, error, dismissed); + int get hashCode => Object.hash( + entityType, + entityId, + entityRev, + deleted, + data, + createAt, + concluded, + concludedMoment, + error, + dismissed, + attemptCount, + quarantinedAt); @override bool operator ==(Object other) => identical(this, other) || @@ -4458,7 +4514,9 @@ class LocalChange extends DataClass implements Insertable { other.concluded == this.concluded && other.concludedMoment == this.concludedMoment && other.error == this.error && - other.dismissed == this.dismissed); + other.dismissed == this.dismissed && + other.attemptCount == this.attemptCount && + other.quarantinedAt == this.quarantinedAt); } class LocalChangesCompanion extends UpdateCompanion { @@ -4472,6 +4530,8 @@ class LocalChangesCompanion extends UpdateCompanion { final Value concludedMoment; final Value error; final Value dismissed; + final Value attemptCount; + final Value quarantinedAt; final Value rowid; const LocalChangesCompanion({ this.entityType = const Value.absent(), @@ -4484,6 +4544,8 @@ class LocalChangesCompanion extends UpdateCompanion { this.concludedMoment = const Value.absent(), this.error = const Value.absent(), this.dismissed = const Value.absent(), + this.attemptCount = const Value.absent(), + this.quarantinedAt = const Value.absent(), this.rowid = const Value.absent(), }); LocalChangesCompanion.insert({ @@ -4497,6 +4559,8 @@ class LocalChangesCompanion extends UpdateCompanion { this.concludedMoment = const Value.absent(), this.error = const Value.absent(), required bool dismissed, + this.attemptCount = const Value.absent(), + this.quarantinedAt = const Value.absent(), this.rowid = const Value.absent(), }) : entityType = Value(entityType), entityId = Value(entityId), @@ -4517,6 +4581,8 @@ class LocalChangesCompanion extends UpdateCompanion { Expression? concludedMoment, Expression? error, Expression? dismissed, + Expression? attemptCount, + Expression? quarantinedAt, Expression? rowid, }) { return RawValuesInsertable({ @@ -4530,6 +4596,8 @@ class LocalChangesCompanion extends UpdateCompanion { if (concludedMoment != null) 'concluded_moment': concludedMoment, if (error != null) 'error': error, if (dismissed != null) 'dismissed': dismissed, + if (attemptCount != null) 'attempt_count': attemptCount, + if (quarantinedAt != null) 'quarantined_at': quarantinedAt, if (rowid != null) 'rowid': rowid, }); } @@ -4545,6 +4613,8 @@ class LocalChangesCompanion extends UpdateCompanion { Value? concludedMoment, Value? error, Value? dismissed, + Value? attemptCount, + Value? quarantinedAt, Value? rowid}) { return LocalChangesCompanion( entityType: entityType ?? this.entityType, @@ -4557,6 +4627,8 @@ class LocalChangesCompanion extends UpdateCompanion { concludedMoment: concludedMoment ?? this.concludedMoment, error: error ?? this.error, dismissed: dismissed ?? this.dismissed, + attemptCount: attemptCount ?? this.attemptCount, + quarantinedAt: quarantinedAt ?? this.quarantinedAt, rowid: rowid ?? this.rowid, ); } @@ -4595,6 +4667,12 @@ class LocalChangesCompanion extends UpdateCompanion { if (dismissed.present) { map['dismissed'] = Variable(dismissed.value); } + if (attemptCount.present) { + map['attempt_count'] = Variable(attemptCount.value); + } + if (quarantinedAt.present) { + map['quarantined_at'] = Variable(quarantinedAt.value); + } if (rowid.present) { map['rowid'] = Variable(rowid.value); } @@ -4614,6 +4692,8 @@ class LocalChangesCompanion extends UpdateCompanion { ..write('concludedMoment: $concludedMoment, ') ..write('error: $error, ') ..write('dismissed: $dismissed, ') + ..write('attemptCount: $attemptCount, ') + ..write('quarantinedAt: $quarantinedAt, ') ..write('rowid: $rowid') ..write(')')) .toString(); @@ -10025,6 +10105,244 @@ class RemindersCompanion extends UpdateCompanion { } } +class $DeferredRemoteItemsTable extends DeferredRemoteItems + with TableInfo<$DeferredRemoteItemsTable, DeferredRemoteItem> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $DeferredRemoteItemsTable(this.attachedDatabase, [this._alias]); + @override + late final GeneratedColumn entityType = GeneratedColumn( + 'entity_type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + late final GeneratedColumn data = GeneratedColumn( + 'data', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + late final GeneratedColumn parkedAt = GeneratedColumn( + 'parked_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + List get $columns => [entityType, clientId, data, parkedAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'deferred_remote_items'; + @override + Set get $primaryKey => {entityType, clientId}; + @override + DeferredRemoteItem map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return DeferredRemoteItem( + entityType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}entity_type'])!, + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + data: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}data'])!, + parkedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}parked_at'])!, + ); + } + + @override + $DeferredRemoteItemsTable createAlias(String alias) { + return $DeferredRemoteItemsTable(attachedDatabase, alias); + } +} + +class DeferredRemoteItem extends DataClass + implements Insertable { + final String entityType; + final String clientId; + + /// Marshalled entity payload (JSON). + final String data; + final DateTime parkedAt; + const DeferredRemoteItem( + {required this.entityType, + required this.clientId, + required this.data, + required this.parkedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['entity_type'] = Variable(entityType); + map['client_id'] = Variable(clientId); + map['data'] = Variable(data); + map['parked_at'] = Variable(parkedAt); + return map; + } + + DeferredRemoteItemsCompanion toCompanion(bool nullToAbsent) { + return DeferredRemoteItemsCompanion( + entityType: Value(entityType), + clientId: Value(clientId), + data: Value(data), + parkedAt: Value(parkedAt), + ); + } + + factory DeferredRemoteItem.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return DeferredRemoteItem( + entityType: serializer.fromJson(json['entityType']), + clientId: serializer.fromJson(json['clientId']), + data: serializer.fromJson(json['data']), + parkedAt: serializer.fromJson(json['parkedAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'entityType': serializer.toJson(entityType), + 'clientId': serializer.toJson(clientId), + 'data': serializer.toJson(data), + 'parkedAt': serializer.toJson(parkedAt), + }; + } + + DeferredRemoteItem copyWith( + {String? entityType, + String? clientId, + String? data, + DateTime? parkedAt}) => + DeferredRemoteItem( + entityType: entityType ?? this.entityType, + clientId: clientId ?? this.clientId, + data: data ?? this.data, + parkedAt: parkedAt ?? this.parkedAt, + ); + DeferredRemoteItem copyWithCompanion(DeferredRemoteItemsCompanion data) { + return DeferredRemoteItem( + entityType: + data.entityType.present ? data.entityType.value : this.entityType, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + data: data.data.present ? data.data.value : this.data, + parkedAt: data.parkedAt.present ? data.parkedAt.value : this.parkedAt, + ); + } + + @override + String toString() { + return (StringBuffer('DeferredRemoteItem(') + ..write('entityType: $entityType, ') + ..write('clientId: $clientId, ') + ..write('data: $data, ') + ..write('parkedAt: $parkedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(entityType, clientId, data, parkedAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is DeferredRemoteItem && + other.entityType == this.entityType && + other.clientId == this.clientId && + other.data == this.data && + other.parkedAt == this.parkedAt); +} + +class DeferredRemoteItemsCompanion extends UpdateCompanion { + final Value entityType; + final Value clientId; + final Value data; + final Value parkedAt; + final Value rowid; + const DeferredRemoteItemsCompanion({ + this.entityType = const Value.absent(), + this.clientId = const Value.absent(), + this.data = const Value.absent(), + this.parkedAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + DeferredRemoteItemsCompanion.insert({ + required String entityType, + required String clientId, + required String data, + this.parkedAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : entityType = Value(entityType), + clientId = Value(clientId), + data = Value(data); + static Insertable custom({ + Expression? entityType, + Expression? clientId, + Expression? data, + Expression? parkedAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (entityType != null) 'entity_type': entityType, + if (clientId != null) 'client_id': clientId, + if (data != null) 'data': data, + if (parkedAt != null) 'parked_at': parkedAt, + if (rowid != null) 'rowid': rowid, + }); + } + + DeferredRemoteItemsCompanion copyWith( + {Value? entityType, + Value? clientId, + Value? data, + Value? parkedAt, + Value? rowid}) { + return DeferredRemoteItemsCompanion( + entityType: entityType ?? this.entityType, + clientId: clientId ?? this.clientId, + data: data ?? this.data, + parkedAt: parkedAt ?? this.parkedAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (entityType.present) { + map['entity_type'] = Variable(entityType.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (data.present) { + map['data'] = Variable(data.value); + } + if (parkedAt.present) { + map['parked_at'] = Variable(parkedAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('DeferredRemoteItemsCompanion(') + ..write('entityType: $entityType, ') + ..write('clientId: $clientId, ') + ..write('data: $data, ') + ..write('parkedAt: $parkedAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + abstract class _$AppDatabase extends GeneratedDatabase { _$AppDatabase(QueryExecutor e) : super(e); $AppDatabaseManager get managers => $AppDatabaseManager(this); @@ -10049,6 +10367,8 @@ abstract class _$AppDatabase extends GeneratedDatabase { late final $FinancialPositionCacheTable financialPositionCache = $FinancialPositionCacheTable(this); late final $RemindersTable reminders = $RemindersTable(this); + late final $DeferredRemoteItemsTable deferredRemoteItems = + $DeferredRemoteItemsTable(this); @override Iterable> get allTables => allSchemaEntities.whereType>(); @@ -10072,7 +10392,8 @@ abstract class _$AppDatabase extends GeneratedDatabase { budgetPeriodStates, holdings, financialPositionCache, - reminders + reminders, + deferredRemoteItems ]; @override DriftDatabaseOptions get options => @@ -12845,6 +13166,8 @@ typedef $$LocalChangesTableCreateCompanionBuilder = LocalChangesCompanion Value concludedMoment, Value error, required bool dismissed, + Value attemptCount, + Value quarantinedAt, Value rowid, }); typedef $$LocalChangesTableUpdateCompanionBuilder = LocalChangesCompanion @@ -12859,6 +13182,8 @@ typedef $$LocalChangesTableUpdateCompanionBuilder = LocalChangesCompanion Value concludedMoment, Value error, Value dismissed, + Value attemptCount, + Value quarantinedAt, Value rowid, }); @@ -12904,6 +13229,12 @@ class $$LocalChangesTableFilterComposer ColumnFilters get dismissed => $composableBuilder( column: $table.dismissed, builder: (column) => ColumnFilters(column)); + + ColumnFilters get attemptCount => $composableBuilder( + column: $table.attemptCount, builder: (column) => ColumnFilters(column)); + + ColumnFilters get quarantinedAt => $composableBuilder( + column: $table.quarantinedAt, builder: (column) => ColumnFilters(column)); } class $$LocalChangesTableOrderingComposer @@ -12945,6 +13276,14 @@ class $$LocalChangesTableOrderingComposer ColumnOrderings get dismissed => $composableBuilder( column: $table.dismissed, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get attemptCount => $composableBuilder( + column: $table.attemptCount, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get quarantinedAt => $composableBuilder( + column: $table.quarantinedAt, + builder: (column) => ColumnOrderings(column)); } class $$LocalChangesTableAnnotationComposer @@ -12985,6 +13324,12 @@ class $$LocalChangesTableAnnotationComposer GeneratedColumn get dismissed => $composableBuilder(column: $table.dismissed, builder: (column) => column); + + GeneratedColumn get attemptCount => $composableBuilder( + column: $table.attemptCount, builder: (column) => column); + + GeneratedColumn get quarantinedAt => $composableBuilder( + column: $table.quarantinedAt, builder: (column) => column); } class $$LocalChangesTableTableManager extends RootTableManager< @@ -13023,6 +13368,8 @@ class $$LocalChangesTableTableManager extends RootTableManager< Value concludedMoment = const Value.absent(), Value error = const Value.absent(), Value dismissed = const Value.absent(), + Value attemptCount = const Value.absent(), + Value quarantinedAt = const Value.absent(), Value rowid = const Value.absent(), }) => LocalChangesCompanion( @@ -13036,6 +13383,8 @@ class $$LocalChangesTableTableManager extends RootTableManager< concludedMoment: concludedMoment, error: error, dismissed: dismissed, + attemptCount: attemptCount, + quarantinedAt: quarantinedAt, rowid: rowid, ), createCompanionCallback: ({ @@ -13049,6 +13398,8 @@ class $$LocalChangesTableTableManager extends RootTableManager< Value concludedMoment = const Value.absent(), Value error = const Value.absent(), required bool dismissed, + Value attemptCount = const Value.absent(), + Value quarantinedAt = const Value.absent(), Value rowid = const Value.absent(), }) => LocalChangesCompanion.insert( @@ -13062,6 +13413,8 @@ class $$LocalChangesTableTableManager extends RootTableManager< concludedMoment: concludedMoment, error: error, dismissed: dismissed, + attemptCount: attemptCount, + quarantinedAt: quarantinedAt, rowid: rowid, ), withReferenceMapper: (p0) => p0 @@ -16811,6 +17164,169 @@ typedef $$RemindersTableProcessedTableManager = ProcessedTableManager< (Reminder, BaseReferences<_$AppDatabase, $RemindersTable, Reminder>), Reminder, PrefetchHooks Function()>; +typedef $$DeferredRemoteItemsTableCreateCompanionBuilder + = DeferredRemoteItemsCompanion Function({ + required String entityType, + required String clientId, + required String data, + Value parkedAt, + Value rowid, +}); +typedef $$DeferredRemoteItemsTableUpdateCompanionBuilder + = DeferredRemoteItemsCompanion Function({ + Value entityType, + Value clientId, + Value data, + Value parkedAt, + Value rowid, +}); + +class $$DeferredRemoteItemsTableFilterComposer + extends Composer<_$AppDatabase, $DeferredRemoteItemsTable> { + $$DeferredRemoteItemsTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get entityType => $composableBuilder( + column: $table.entityType, builder: (column) => ColumnFilters(column)); + + ColumnFilters get clientId => $composableBuilder( + column: $table.clientId, builder: (column) => ColumnFilters(column)); + + ColumnFilters get data => $composableBuilder( + column: $table.data, builder: (column) => ColumnFilters(column)); + + ColumnFilters get parkedAt => $composableBuilder( + column: $table.parkedAt, builder: (column) => ColumnFilters(column)); +} + +class $$DeferredRemoteItemsTableOrderingComposer + extends Composer<_$AppDatabase, $DeferredRemoteItemsTable> { + $$DeferredRemoteItemsTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get entityType => $composableBuilder( + column: $table.entityType, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get clientId => $composableBuilder( + column: $table.clientId, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get data => $composableBuilder( + column: $table.data, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get parkedAt => $composableBuilder( + column: $table.parkedAt, builder: (column) => ColumnOrderings(column)); +} + +class $$DeferredRemoteItemsTableAnnotationComposer + extends Composer<_$AppDatabase, $DeferredRemoteItemsTable> { + $$DeferredRemoteItemsTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get entityType => $composableBuilder( + column: $table.entityType, builder: (column) => column); + + GeneratedColumn get clientId => + $composableBuilder(column: $table.clientId, builder: (column) => column); + + GeneratedColumn get data => + $composableBuilder(column: $table.data, builder: (column) => column); + + GeneratedColumn get parkedAt => + $composableBuilder(column: $table.parkedAt, builder: (column) => column); +} + +class $$DeferredRemoteItemsTableTableManager extends RootTableManager< + _$AppDatabase, + $DeferredRemoteItemsTable, + DeferredRemoteItem, + $$DeferredRemoteItemsTableFilterComposer, + $$DeferredRemoteItemsTableOrderingComposer, + $$DeferredRemoteItemsTableAnnotationComposer, + $$DeferredRemoteItemsTableCreateCompanionBuilder, + $$DeferredRemoteItemsTableUpdateCompanionBuilder, + ( + DeferredRemoteItem, + BaseReferences<_$AppDatabase, $DeferredRemoteItemsTable, + DeferredRemoteItem> + ), + DeferredRemoteItem, + PrefetchHooks Function()> { + $$DeferredRemoteItemsTableTableManager( + _$AppDatabase db, $DeferredRemoteItemsTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$DeferredRemoteItemsTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$DeferredRemoteItemsTableOrderingComposer( + $db: db, $table: table), + createComputedFieldComposer: () => + $$DeferredRemoteItemsTableAnnotationComposer( + $db: db, $table: table), + updateCompanionCallback: ({ + Value entityType = const Value.absent(), + Value clientId = const Value.absent(), + Value data = const Value.absent(), + Value parkedAt = const Value.absent(), + Value rowid = const Value.absent(), + }) => + DeferredRemoteItemsCompanion( + entityType: entityType, + clientId: clientId, + data: data, + parkedAt: parkedAt, + rowid: rowid, + ), + createCompanionCallback: ({ + required String entityType, + required String clientId, + required String data, + Value parkedAt = const Value.absent(), + Value rowid = const Value.absent(), + }) => + DeferredRemoteItemsCompanion.insert( + entityType: entityType, + clientId: clientId, + data: data, + parkedAt: parkedAt, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$DeferredRemoteItemsTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $DeferredRemoteItemsTable, + DeferredRemoteItem, + $$DeferredRemoteItemsTableFilterComposer, + $$DeferredRemoteItemsTableOrderingComposer, + $$DeferredRemoteItemsTableAnnotationComposer, + $$DeferredRemoteItemsTableCreateCompanionBuilder, + $$DeferredRemoteItemsTableUpdateCompanionBuilder, + ( + DeferredRemoteItem, + BaseReferences<_$AppDatabase, $DeferredRemoteItemsTable, + DeferredRemoteItem> + ), + DeferredRemoteItem, + PrefetchHooks Function()>; class $AppDatabaseManager { final _$AppDatabase _db; @@ -16854,4 +17370,6 @@ class $AppDatabaseManager { _db, _db.financialPositionCache); $$RemindersTableTableManager get reminders => $$RemindersTableTableManager(_db, _db.reminders); + $$DeferredRemoteItemsTableTableManager get deferredRemoteItems => + $$DeferredRemoteItemsTableTableManager(_db, _db.deferredRemoteItems); } diff --git a/lib/data/database/app_database.steps.dart b/lib/data/database/app_database.steps.dart index 63c9a45b..cf751724 100644 --- a/lib/data/database/app_database.steps.dart +++ b/lib/data/database/app_database.steps.dart @@ -3392,6 +3392,582 @@ i1.GeneratedColumn _column_116(String aliasedName) => i1.GeneratedColumn _column_117(String aliasedName) => i1.GeneratedColumn('next_trigger_at', aliasedName, true, type: i1.DriftSqlType.dateTime); + +final class Schema8 extends i0.VersionedSchema { + Schema8({required super.database}) : super(version: 8); + @override + late final List entities = [ + wallets, + parties, + groups, + transactions, + categories, + configs, + users, + localChanges, + syncMetadata, + categorizables, + notifications, + mediaFiles, + transfers, + budgets, + budgetTargets, + budgetPeriodStates, + holdings, + financialPositionCache, + reminders, + deferredRemoteItems, + ]; + late final Shape0 wallets = Shape0( + source: i0.VersionedTable( + entityName: 'wallets', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(client_id)', + ], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + _column_4, + _column_5, + _column_6, + _column_7, + _column_8, + _column_9, + _column_10, + _column_11, + _column_12, + _column_13, + _column_14, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape1 parties = Shape1( + source: i0.VersionedTable( + entityName: 'parties', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(client_id)', + ], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + _column_4, + _column_5, + _column_6, + _column_7, + _column_8, + _column_12, + _column_14, + _column_15, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape2 groups = Shape2( + source: i0.VersionedTable( + entityName: 'groups', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(client_id)', + ], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + _column_4, + _column_5, + _column_6, + _column_7, + _column_8, + _column_12, + _column_14, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape20 transactions = Shape20( + source: i0.VersionedTable( + entityName: 'transactions', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(client_id)', + ], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + _column_4, + _column_5, + _column_6, + _column_7, + _column_16, + _column_9, + _column_89, + _column_12, + _column_17, + _column_18, + _column_19, + _column_20, + _column_21, + _column_22, + _column_23, + _column_59, + _column_60, + _column_102, + _column_103, + _column_104, + _column_105, + _column_106, + _column_107, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape4 categories = Shape4( + source: i0.VersionedTable( + entityName: 'categories', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(client_id)', + ], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + _column_4, + _column_5, + _column_6, + _column_7, + _column_24, + _column_25, + _column_12, + _column_9, + _column_14, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape5 configs = Shape5( + source: i0.VersionedTable( + entityName: 'configs', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(client_id)', + ], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + _column_4, + _column_5, + _column_6, + _column_7, + _column_26, + _column_9, + _column_27, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape6 users = Shape6( + source: i0.VersionedTable( + entityName: 'users', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(id)', + ], + columns: [ + _column_28, + _column_29, + _column_30, + _column_31, + _column_32, + _column_33, + _column_34, + _column_35, + _column_36, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape22 localChanges = Shape22( + source: i0.VersionedTable( + entityName: 'local_changes', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(entity_id, entity_type)', + ], + columns: [ + _column_37, + _column_38, + _column_39, + _column_40, + _column_41, + _column_42, + _column_43, + _column_44, + _column_45, + _column_46, + _column_118, + _column_119, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape8 syncMetadata = Shape8( + source: i0.VersionedTable( + entityName: 'sync_metadata', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(entity_type)', + ], + columns: [ + _column_37, + _column_7, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape9 categorizables = Shape9( + source: i0.VersionedTable( + entityName: 'categorizables', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(categorizable_id, categorizable_type, category_client_id)', + ], + columns: [ + _column_47, + _column_48, + _column_49, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape10 notifications = Shape10( + source: i0.VersionedTable( + entityName: 'notifications', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(client_id)', + ], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + _column_4, + _column_5, + _column_6, + _column_7, + _column_9, + _column_50, + _column_51, + _column_41, + _column_52, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape11 mediaFiles = Shape11( + source: i0.VersionedTable( + entityName: 'media_files', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(path)', + ], + columns: [ + _column_53, + _column_54, + _column_15, + _column_55, + _column_56, + _column_57, + _column_58, + _column_35, + _column_36, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape13 transfers = Shape13( + source: i0.VersionedTable( + entityName: 'transfers', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(client_id)', + ], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + _column_4, + _column_5, + _column_6, + _column_7, + _column_16, + _column_61, + _column_62, + _column_63, + _column_64, + _column_65, + _column_66, + _column_67, + _column_68, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape14 budgets = Shape14( + source: i0.VersionedTable( + entityName: 'budgets', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(client_id)', + ], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + _column_4, + _column_5, + _column_6, + _column_7, + _column_8, + _column_25, + _column_12, + _column_69, + _column_11, + _column_70, + _column_71, + _column_72, + _column_73, + _column_74, + _column_75, + _column_76, + _column_77, + _column_78, + _column_79, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape15 budgetTargets = Shape15( + source: i0.VersionedTable( + entityName: 'budget_targets', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(budget_client_id, target_type, target_client_id)', + ], + columns: [ + _column_80, + _column_81, + _column_82, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape16 budgetPeriodStates = Shape16( + source: i0.VersionedTable( + entityName: 'budget_period_states', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(client_id)', + ], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + _column_4, + _column_5, + _column_6, + _column_7, + _column_80, + _column_83, + _column_84, + _column_85, + _column_86, + _column_87, + _column_88, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape18 holdings = Shape18( + source: i0.VersionedTable( + entityName: 'holdings', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(id)', + ], + columns: [ + _column_28, + _column_8, + _column_90, + _column_91, + _column_11, + _column_92, + _column_93, + _column_94, + _column_95, + _column_96, + _column_97, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape19 financialPositionCache = Shape19( + source: i0.VersionedTable( + entityName: 'financial_position_cache', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(cache_key)', + ], + columns: [ + _column_98, + _column_99, + _column_100, + _column_101, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape21 reminders = Shape21( + source: i0.VersionedTable( + entityName: 'reminders', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(client_id)', + ], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + _column_4, + _column_5, + _column_6, + _column_7, + _column_50, + _column_12, + _column_108, + _column_109, + _column_110, + _column_111, + _column_112, + _column_113, + _column_114, + _column_115, + _column_116, + _column_117, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape23 deferredRemoteItems = Shape23( + source: i0.VersionedTable( + entityName: 'deferred_remote_items', + withoutRowId: false, + isStrict: false, + tableConstraints: [ + 'PRIMARY KEY(entity_type, client_id)', + ], + columns: [ + _column_37, + _column_120, + _column_41, + _column_121, + ], + attachedDatabase: database, + ), + alias: null); +} + +class Shape22 extends i0.VersionedTable { + Shape22({required super.source, required super.alias}) : super.aliased(); + i1.GeneratedColumn get entityType => + columnsByName['entity_type']! as i1.GeneratedColumn; + i1.GeneratedColumn get entityId => + columnsByName['entity_id']! as i1.GeneratedColumn; + i1.GeneratedColumn get entityRev => + columnsByName['entity_rev']! as i1.GeneratedColumn; + i1.GeneratedColumn get deleted => + columnsByName['deleted']! as i1.GeneratedColumn; + i1.GeneratedColumn get data => + columnsByName['data']! as i1.GeneratedColumn; + i1.GeneratedColumn get createAt => + columnsByName['create_at']! as i1.GeneratedColumn; + i1.GeneratedColumn get concluded => + columnsByName['concluded']! as i1.GeneratedColumn; + i1.GeneratedColumn get concludedMoment => + columnsByName['concluded_moment']! as i1.GeneratedColumn; + i1.GeneratedColumn get error => + columnsByName['error']! as i1.GeneratedColumn; + i1.GeneratedColumn get dismissed => + columnsByName['dismissed']! as i1.GeneratedColumn; + i1.GeneratedColumn get attemptCount => + columnsByName['attempt_count']! as i1.GeneratedColumn; + i1.GeneratedColumn get quarantinedAt => + columnsByName['quarantined_at']! as i1.GeneratedColumn; +} + +i1.GeneratedColumn _column_118(String aliasedName) => + i1.GeneratedColumn('attempt_count', aliasedName, false, + type: i1.DriftSqlType.int, defaultValue: const CustomExpression('0')); +i1.GeneratedColumn _column_119(String aliasedName) => + i1.GeneratedColumn('quarantined_at', aliasedName, true, + type: i1.DriftSqlType.dateTime); + +class Shape23 extends i0.VersionedTable { + Shape23({required super.source, required super.alias}) : super.aliased(); + i1.GeneratedColumn get entityType => + columnsByName['entity_type']! as i1.GeneratedColumn; + i1.GeneratedColumn get clientId => + columnsByName['client_id']! as i1.GeneratedColumn; + i1.GeneratedColumn get data => + columnsByName['data']! as i1.GeneratedColumn; + i1.GeneratedColumn get parkedAt => + columnsByName['parked_at']! as i1.GeneratedColumn; +} + +i1.GeneratedColumn _column_120(String aliasedName) => + i1.GeneratedColumn('client_id', aliasedName, false, + type: i1.DriftSqlType.string); +i1.GeneratedColumn _column_121(String aliasedName) => + i1.GeneratedColumn('parked_at', aliasedName, false, + type: i1.DriftSqlType.dateTime, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); i0.MigrationStepWithVersion migrationSteps({ required Future Function(i1.Migrator m, Schema2 schema) from1To2, required Future Function(i1.Migrator m, Schema3 schema) from2To3, @@ -3399,6 +3975,7 @@ i0.MigrationStepWithVersion migrationSteps({ required Future Function(i1.Migrator m, Schema5 schema) from4To5, required Future Function(i1.Migrator m, Schema6 schema) from5To6, required Future Function(i1.Migrator m, Schema7 schema) from6To7, + required Future Function(i1.Migrator m, Schema8 schema) from7To8, }) { return (currentVersion, database) async { switch (currentVersion) { @@ -3432,6 +4009,11 @@ i0.MigrationStepWithVersion migrationSteps({ final migrator = i1.Migrator(database, schema); await from6To7(migrator, schema); return 7; + case 7: + final schema = Schema8(database: database); + final migrator = i1.Migrator(database, schema); + await from7To8(migrator, schema); + return 8; default: throw ArgumentError.value('Unknown migration from $currentVersion'); } @@ -3445,6 +4027,7 @@ i1.OnUpgrade stepByStep({ required Future Function(i1.Migrator m, Schema5 schema) from4To5, required Future Function(i1.Migrator m, Schema6 schema) from5To6, required Future Function(i1.Migrator m, Schema7 schema) from6To7, + required Future Function(i1.Migrator m, Schema8 schema) from7To8, }) => i0.VersionedSchema.stepByStepHelper( step: migrationSteps( @@ -3454,4 +4037,5 @@ i1.OnUpgrade stepByStep({ from4To5: from4To5, from5To6: from5To6, from6To7: from6To7, + from7To8: from7To8, )); diff --git a/lib/data/database/tables/deferred_remote_items.dart b/lib/data/database/tables/deferred_remote_items.dart new file mode 100644 index 00000000..166320fc --- /dev/null +++ b/lib/data/database/tables/deferred_remote_items.dart @@ -0,0 +1,16 @@ +import 'package:drift/drift.dart'; + +/// Down-synced entities whose local dependencies were not met at persist +/// time (SyncTypeHandler.shouldPersistLocal). Retried each sync cycle. +class DeferredRemoteItems extends Table { + TextColumn get entityType => text()(); + TextColumn get clientId => text()(); + + /// Marshalled entity payload (JSON). + TextColumn get data => text()(); + + DateTimeColumn get parkedAt => dateTime().withDefault(currentDateAndTime)(); + + @override + Set get primaryKey => {entityType, clientId}; +} diff --git a/lib/data/database/tables/local_changes.dart b/lib/data/database/tables/local_changes.dart index a2b6359b..48caf009 100644 --- a/lib/data/database/tables/local_changes.dart +++ b/lib/data/database/tables/local_changes.dart @@ -14,6 +14,8 @@ class LocalChanges extends Table { DateTimeColumn get concludedMoment => dateTime().nullable()(); TextColumn get error => text().nullable()(); BoolColumn get dismissed => boolean()(); + IntColumn get attemptCount => integer().withDefault(const Constant(0))(); + DateTimeColumn get quarantinedAt => dateTime().nullable()(); @override Set get primaryKey => {entityId, entityType}; diff --git a/lib/data/datasources/budget/budget_remote_datasource.dart b/lib/data/datasources/budget/budget_remote_datasource.dart index 051a47cd..9738e1f8 100644 --- a/lib/data/datasources/budget/budget_remote_datasource.dart +++ b/lib/data/datasources/budget/budget_remote_datasource.dart @@ -16,6 +16,11 @@ abstract class BudgetRemoteDataSource { Future getBudget(int id); Future insertBudget(BudgetCompleteDto dto); Future updateBudget(BudgetCompleteDto dto); + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }); Future deleteBudget(int id); Future closeBudgetPeriod(int id); Future> getAllPeriodStates({ @@ -102,6 +107,22 @@ class BudgetRemoteDataSourceImpl implements BudgetRemoteDataSource { ); } + @override + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }) async { + final response = await dio.put('budgets/$id', data: { + 'client_id': clientId, + 'updated_at': formatServerIsoDateTimeString(updatedAt), + }); + final apiResponse = ApiResponse.fromJson(response.data); + return BudgetCompleteDto.fromServerJson( + apiResponse.data as Map, + ); + } + @override Future deleteBudget(int id) async { await dio.delete('budgets/$id'); diff --git a/lib/data/datasources/category/category_remote_datasource.dart b/lib/data/datasources/category/category_remote_datasource.dart index 66dc0eeb..9809ad2b 100644 --- a/lib/data/datasources/category/category_remote_datasource.dart +++ b/lib/data/datasources/category/category_remote_datasource.dart @@ -12,6 +12,11 @@ abstract class CategoryRemoteDataSource { Future getCategory(int id); Future insertCategory(Category category); Future updateCategory(Category category); + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }); Future deleteCategory(int id); } @@ -119,6 +124,20 @@ class CategoryRemoteDataSourceImpl implements CategoryRemoteDataSource { return Category.fromJson(apiResponse.data); } + @override + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }) async { + final response = await dio.put('categories/$id', data: { + 'client_id': clientId, + 'updated_at': formatServerIsoDateTimeString(updatedAt), + }); + final apiResponse = ApiResponse.fromJson(response.data); + return Category.fromJson(apiResponse.data); + } + @override Future deleteCategory(int id) async { await dio.delete('categories/$id'); diff --git a/lib/data/datasources/group/group_remote_datasource.dart b/lib/data/datasources/group/group_remote_datasource.dart index e0f05471..4ad3559a 100644 --- a/lib/data/datasources/group/group_remote_datasource.dart +++ b/lib/data/datasources/group/group_remote_datasource.dart @@ -11,6 +11,11 @@ abstract class GroupRemoteDataSource { Future getGroup(int id); Future insertGroup(Group group); Future updateGroup(Group group); + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }); Future deleteGroup(int int); /// Updates multiple groups with new client IDs in a single request @@ -102,6 +107,20 @@ class GroupRemoteDataSourceImpl implements GroupRemoteDataSource { return Group.fromJson(apiResponse.data as Map); } + @override + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }) async { + final response = await dio.put('groups/$id', data: { + 'client_id': clientId, + 'updated_at': formatServerIsoDateTimeString(updatedAt), + }); + final apiResponse = ApiResponse.fromJson(response.data); + return Group.fromJson(apiResponse.data as Map); + } + @override Future deleteGroup(int id) async { await dio.delete('groups/$id'); diff --git a/lib/data/datasources/party/party_remote_datasource.dart b/lib/data/datasources/party/party_remote_datasource.dart index 59e1c777..3fc4e5ab 100644 --- a/lib/data/datasources/party/party_remote_datasource.dart +++ b/lib/data/datasources/party/party_remote_datasource.dart @@ -12,6 +12,11 @@ abstract class PartyRemoteDataSource { Future getParty(int id); Future insertParty(Party party); Future updateParty(Party party); + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }); Future deleteParty(int id); } @@ -115,6 +120,20 @@ class PartyRemoteDataSourceImpl implements PartyRemoteDataSource { return Party.fromJson(apiResponse.data); } + @override + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }) async { + final response = await dio.put('parties/$id', data: { + 'client_id': clientId, + 'updated_at': formatServerIsoDateTimeString(updatedAt), + }); + final apiResponse = ApiResponse.fromJson(response.data); + return Party.fromJson(apiResponse.data); + } + @override Future deleteParty(int id) async { await dio.delete('parties/$id'); diff --git a/lib/data/datasources/reminder/reminder_remote_datasource.dart b/lib/data/datasources/reminder/reminder_remote_datasource.dart index a9a29171..58498cfb 100644 --- a/lib/data/datasources/reminder/reminder_remote_datasource.dart +++ b/lib/data/datasources/reminder/reminder_remote_datasource.dart @@ -14,6 +14,11 @@ abstract class ReminderRemoteDataSource { Future getReminder(int id); Future insertReminder(Reminder reminder); Future updateReminder(Reminder reminder); + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }); Future deleteReminder(int id); Future snoozeReminder(int id, DateTime until); Future pauseReminder(int id); @@ -106,6 +111,20 @@ class ReminderRemoteDataSourceImpl implements ReminderRemoteDataSource { return Reminder.fromJson(apiResponse.data); } + @override + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }) async { + final response = await dio.put('reminders/$id', data: { + 'client_id': clientId, + 'updated_at': formatServerIsoDateTimeString(updatedAt), + }); + final apiResponse = ApiResponse.fromJson(response.data); + return Reminder.fromJson(apiResponse.data); + } + @override Future deleteReminder(int id) async { await dio.delete('reminders/$id'); diff --git a/lib/data/datasources/stats/dto/report_stats_dto.dart b/lib/data/datasources/stats/dto/report_stats_dto.dart new file mode 100644 index 00000000..a87a9f45 --- /dev/null +++ b/lib/data/datasources/stats/dto/report_stats_dto.dart @@ -0,0 +1,83 @@ +double _asDouble(dynamic v) { + if (v == null) return 0; + if (v is num) return v.toDouble(); + return double.tryParse(v.toString()) ?? 0; +} + +class ReportStatsCategory { + final String name; + final double amount; + final double percentage; + + const ReportStatsCategory({ + required this.name, + required this.amount, + required this.percentage, + }); + + factory ReportStatsCategory.fromJson(Map json) { + return ReportStatsCategory( + name: json['name']?.toString() ?? '', + amount: _asDouble(json['amount']), + percentage: _asDouble(json['percentage']), + ); + } +} + +/// Subset of GET /stats consumed by the Reports screen. Amounts arrive +/// already converted to the account's primary currency server-side. +class ReportStatsDto { + final double totalIncome; + final double totalExpenses; + final double netCashFlow; + + /// Fraction (0..1); the server reports a percent. + final double savingsRate; + final List expenseCategories; + final List incomeCategories; + + /// True when amounts in a currency with no exchange rate were excluded, + /// so totals are understated for [unconvertedCurrencies]. + final bool partial; + final List unconvertedCurrencies; + + const ReportStatsDto({ + required this.totalIncome, + required this.totalExpenses, + required this.netCashFlow, + required this.savingsRate, + required this.expenseCategories, + required this.incomeCategories, + required this.partial, + required this.unconvertedCurrencies, + }); + + factory ReportStatsDto.fromJson(Map json) { + final overview = + (json['overview'] as Map?)?.cast() ?? const {}; + final charts = + (json['charts'] as Map?)?.cast() ?? const {}; + + List categories(dynamic list) => list is List + ? list + .whereType() + .map((e) => + ReportStatsCategory.fromJson(e.cast())) + .toList() + : const []; + + return ReportStatsDto( + totalIncome: _asDouble(overview['total_income']), + totalExpenses: _asDouble(overview['total_expenses']), + netCashFlow: _asDouble(overview['net_cash_flow']), + savingsRate: _asDouble(overview['savings_rate']) / 100, + expenseCategories: categories(charts['category_spending']), + incomeCategories: categories(charts['income_sources']), + partial: json['partial'] == true, + unconvertedCurrencies: (json['unconverted_currencies'] as List?) + ?.map((e) => e.toString()) + .toList() ?? + const [], + ); + } +} diff --git a/lib/data/datasources/stats/stats_remote_datasource.dart b/lib/data/datasources/stats/stats_remote_datasource.dart index edbfaf2e..9bb8c09a 100644 --- a/lib/data/datasources/stats/stats_remote_datasource.dart +++ b/lib/data/datasources/stats/stats_remote_datasource.dart @@ -1,12 +1,19 @@ import 'package:dio/dio.dart'; import 'package:injectable/injectable.dart'; +import 'package:intl/intl.dart'; import 'package:trakli/data/datasources/core/api_response.dart'; import 'package:trakli/data/datasources/stats/dto/financial_position_dto.dart'; +import 'package:trakli/data/datasources/stats/dto/report_stats_dto.dart'; import 'package:trakli/presentation/utils/enums.dart'; abstract class StatsRemoteDataSource { Future getFinancialPosition( FinancialPositionPreset preset); + + Future getReportStats({ + required DateTime start, + required DateTime end, + }); } @Injectable(as: StatsRemoteDataSource) @@ -32,4 +39,23 @@ class StatsRemoteDataSourceImpl implements StatsRemoteDataSource { position['partial'] = data['partial'] ?? position['partial'] ?? false; return FinancialPositionDto.fromJson(position); } + + @override + Future getReportStats({ + required DateTime start, + required DateTime end, + }) async { + final response = await dio.get( + 'stats', + queryParameters: { + 'start_date': _ymd(start), + 'end_date': _ymd(end), + }, + ); + final apiResponse = ApiResponse.fromJson(response.data); + return ReportStatsDto.fromJson( + (apiResponse.data as Map).cast()); + } + + String _ymd(DateTime d) => DateFormat('yyyy-MM-dd').format(d); } diff --git a/lib/data/datasources/transaction/dto/transaction_complete_dto.dart b/lib/data/datasources/transaction/dto/transaction_complete_dto.dart index 48906b86..6b2d05ed 100644 --- a/lib/data/datasources/transaction/dto/transaction_complete_dto.dart +++ b/lib/data/datasources/transaction/dto/transaction_complete_dto.dart @@ -4,6 +4,7 @@ import 'package:trakli/data/database/app_database.dart'; import 'package:trakli/data/datasources/media_file/dto/media_file_dto.dart'; import 'package:trakli/data/datasources/transaction/dto/transaction_dto.dart'; import 'package:trakli/data/datasources/wallet/dtos/wallet_dto.dart'; +import 'package:trakli/presentation/utils/enums.dart'; part 'transaction_complete_dto.freezed.dart'; part 'transaction_complete_dto.g.dart'; @@ -31,7 +32,12 @@ class TransactionConverter @override Transaction fromJson(Map json) { - return Transaction.fromJson(json); + return Transaction.fromJson({ + ...json, + 'intent': json['intent'] ?? TransactionIntent.regular.serverKey, + // Snapshots queued by pre-v7 builds lack the refund flag. + 'is_refund': json['is_refund'] ?? false, + }); } @override diff --git a/lib/data/datasources/transaction/mock_transaction_remote_datasource.dart b/lib/data/datasources/transaction/mock_transaction_remote_datasource.dart index 3bbc1497..ce6c98f1 100644 --- a/lib/data/datasources/transaction/mock_transaction_remote_datasource.dart +++ b/lib/data/datasources/transaction/mock_transaction_remote_datasource.dart @@ -50,6 +50,22 @@ class MockTransactionRemoteDataSource implements TransactionRemoteDataSource { }); } + @override + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }) async { + return _simulateDelay(() async { + final index = + _transactions.indexWhere((t) => t.transaction.id == id); + if (index == -1) { + throw Exception('Transaction not found'); + } + return _transactions[index]; + }); + } + @override Future deleteTransaction(int id) async { await _simulateDelay(() async { diff --git a/lib/data/datasources/transaction/transaction_remote_datasource.dart b/lib/data/datasources/transaction/transaction_remote_datasource.dart index bfb63009..6fb54878 100644 --- a/lib/data/datasources/transaction/transaction_remote_datasource.dart +++ b/lib/data/datasources/transaction/transaction_remote_datasource.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:dio/dio.dart'; +import 'package:trakli/core/utils/date_util.dart'; import 'package:injectable/injectable.dart'; import 'package:trakli/data/database/app_database.dart'; import 'package:trakli/data/datasources/core/api_response.dart'; @@ -22,6 +23,12 @@ abstract class TransactionRemoteDataSource { Future updateTransaction( TransactionCompleteDto transaction); + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }); + Future deleteTransaction(int id); Future addMediaToTransaction( @@ -160,6 +167,22 @@ class TransactionRemoteDataSourceImpl implements TransactionRemoteDataSource { apiResponse.data as Map); } + @override + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }) async { + final response = await dio.put('transactions/$id', data: { + 'client_id': clientId, + 'updated_at': formatServerIsoDateTimeString(updatedAt), + }); + final apiResponse = + ApiResponse.fromJson(response.data as Map); + return TransactionCompleteDto.fromServerJson( + apiResponse.data as Map); + } + @override Future deleteTransaction(int id) async { await dio.delete('transactions/$id'); diff --git a/lib/data/datasources/transfer/dto/transfer_dto.dart b/lib/data/datasources/transfer/dto/transfer_dto.dart index e8d089a8..a4e9d451 100644 --- a/lib/data/datasources/transfer/dto/transfer_dto.dart +++ b/lib/data/datasources/transfer/dto/transfer_dto.dart @@ -41,6 +41,26 @@ class TransferDto with _$TransferDto { factory TransferDto.fromJson(Map json) => _$TransferDtoFromJson(json); + factory TransferDto.fromTransfer(Transfer transfer) => TransferDto( + id: transfer.id, + userId: transfer.userId, + clientId: transfer.clientId, + rev: transfer.rev, + createdAt: transfer.createdAt, + updatedAt: transfer.updatedAt, + deletedAt: transfer.deletedAt, + lastSyncedAt: transfer.lastSyncedAt, + amount: transfer.amount, + fromWalletId: transfer.fromWalletId, + toWalletId: transfer.toWalletId, + fromWalletClientId: transfer.fromWalletClientId, + toWalletClientId: transfer.toWalletClientId, + exchangeRate: transfer.exchangeRate, + datetime: transfer.datetime, + expenseTransactionClientId: transfer.expenseTransactionClientId, + incomeTransactionClientId: transfer.incomeTransactionClientId, + ); + Transfer toTransfer() => Transfer( id: id, userId: userId, diff --git a/lib/data/datasources/transfer/transfer_remote_datasource.dart b/lib/data/datasources/transfer/transfer_remote_datasource.dart index 9f901655..29115bba 100644 --- a/lib/data/datasources/transfer/transfer_remote_datasource.dart +++ b/lib/data/datasources/transfer/transfer_remote_datasource.dart @@ -20,6 +20,11 @@ abstract class TransferRemoteDataSource { Future getTransfer(int id); Future insertTransfer(Transfer transfer); Future updateTransfer(Transfer transfer); + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }); Future deleteTransfer(int id); } @@ -112,6 +117,21 @@ class TransferRemoteDataSourceImpl implements TransferRemoteDataSource { .toTransfer(); } + @override + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }) async { + final response = await dio.put('transfers/$id', data: { + 'client_id': clientId, + 'updated_at': formatServerIsoDateTimeString(updatedAt), + }); + final apiResponse = ApiResponse.fromJson(response.data); + return TransferDto.fromJson(apiResponse.data as Map) + .toTransfer(); + } + @override Future deleteTransfer(int id) async { await dio.delete('transfers/$id'); diff --git a/lib/data/datasources/wallet/wallet_remote_datasource.dart b/lib/data/datasources/wallet/wallet_remote_datasource.dart index d1c67407..49c7aa4d 100644 --- a/lib/data/datasources/wallet/wallet_remote_datasource.dart +++ b/lib/data/datasources/wallet/wallet_remote_datasource.dart @@ -11,6 +11,11 @@ abstract class WalletRemoteDataSource { Future getWallet(int id); Future insertWallet(Wallet wallet); Future updateWallet(Wallet wallet); + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }); Future deleteWallet(int id); } @@ -116,6 +121,20 @@ class WalletRemoteDataSourceImpl implements WalletRemoteDataSource { return WalletDto.fromJson(apiResponse.data).toModel(); } + @override + Future claimClientId({ + required int id, + required String clientId, + required DateTime updatedAt, + }) async { + final response = await dio.put('wallets/$id', data: { + 'client_id': clientId, + 'updated_at': formatServerIsoDateTimeString(updatedAt), + }); + final apiResponse = ApiResponse.fromJson(response.data); + return WalletDto.fromJson(apiResponse.data).toModel(); + } + @override Future deleteWallet(int id) async { await dio.delete('wallets/$id'); diff --git a/lib/data/services/budget/budget_progress_recomputer.dart b/lib/data/services/budget/budget_progress_recomputer.dart index 81c0aeb5..eb9801e5 100644 --- a/lib/data/services/budget/budget_progress_recomputer.dart +++ b/lib/data/services/budget/budget_progress_recomputer.dart @@ -129,6 +129,7 @@ class BudgetProgressRecomputer { amount: t.amount, datetime: t.datetime, transferId: t.transferId, + transferClientId: t.transferClientId, walletClientId: t.walletClientId, walletCurrency: currencyByWallet[t.walletClientId], groupClientId: t.groupClientId, diff --git a/lib/data/services/budget/compute_local_progress.dart b/lib/data/services/budget/compute_local_progress.dart index f93f542d..fd994dc0 100644 --- a/lib/data/services/budget/compute_local_progress.dart +++ b/lib/data/services/budget/compute_local_progress.dart @@ -8,6 +8,7 @@ class BudgetTxnInput { final double amount; final DateTime? datetime; final int? transferId; + final String? transferClientId; final String walletClientId; final String? walletCurrency; final String? groupClientId; @@ -18,6 +19,7 @@ class BudgetTxnInput { required this.amount, required this.datetime, required this.transferId, + this.transferClientId, required this.walletClientId, required this.walletCurrency, required this.groupClientId, @@ -52,7 +54,9 @@ BudgetProgressEntity computeLocalProgress({ double grossSpent = 0; for (final t in txns) { - if (t.transferId != null) continue; + if (t.transferId != null || (t.transferClientId?.isNotEmpty ?? false)) { + continue; + } if (t.type != TransactionType.expense) continue; final dt = t.datetime; if (dt == null) continue; diff --git a/lib/data/sync/budget_period_state_sync_handler.dart b/lib/data/sync/budget_period_state_sync_handler.dart index 87a24e6b..28249500 100644 --- a/lib/data/sync/budget_period_state_sync_handler.dart +++ b/lib/data/sync/budget_period_state_sync_handler.dart @@ -37,6 +37,10 @@ class BudgetPeriodStateSyncHandler @override DateTime? getLastSyncedAt(BudgetPeriodStateDto entity) => entity.lastSyncedAt; + @override + DateTime? getCursorTimestamp(BudgetPeriodStateDto entity) => + entity.updatedAt ?? entity.lastSyncedAt; + @override Future unmarshal( Map entityJson) async { diff --git a/lib/data/sync/budget_sync_handler.dart b/lib/data/sync/budget_sync_handler.dart index 1b7ac905..6ffbf922 100644 --- a/lib/data/sync/budget_sync_handler.dart +++ b/lib/data/sync/budget_sync_handler.dart @@ -41,6 +41,10 @@ class BudgetSyncHandler DateTime? getLastSyncedAt(BudgetCompleteDto entity) => entity.budget.lastSyncedAt; + @override + DateTime? getCursorTimestamp(BudgetCompleteDto entity) => + entity.budget.updatedAt; + @override Future unmarshal(Map entityJson) async { return BudgetCompleteDto.fromServerJson(entityJson); @@ -70,6 +74,15 @@ class BudgetSyncHandler return remoteDataSource.getBudget(id); } + @override + Future claimClientId(BudgetCompleteDto entity) { + return remoteDataSource.claimClientId( + id: entity.budget.id!, + clientId: entity.budget.clientId, + updatedAt: entity.budget.updatedAt, + ); + } + @override Future restPutRemote(BudgetCompleteDto entity) async { if (entity.budget.id == null) { diff --git a/lib/data/sync/category_sync_handler.dart b/lib/data/sync/category_sync_handler.dart index 7b0f4d4e..e6c85567 100644 --- a/lib/data/sync/category_sync_handler.dart +++ b/lib/data/sync/category_sync_handler.dart @@ -57,6 +57,15 @@ class CategorySyncHandler extends SyncTypeHandler return await remoteDataSource.getCategory(id); } + @override + Future claimClientId(Category entity) { + return remoteDataSource.claimClientId( + id: entity.id!, + clientId: entity.clientId, + updatedAt: entity.updatedAt, + ); + } + @override Future restPutRemote(Category entity) async { if (entity.id == null) { @@ -186,4 +195,7 @@ class CategorySyncHandler extends SyncTypeHandler @override DateTime? getLastSyncedAt(Category entity) => entity.lastSyncedAt; + + @override + DateTime? getCursorTimestamp(Category entity) => entity.updatedAt; } diff --git a/lib/data/sync/config_sync_handler.dart b/lib/data/sync/config_sync_handler.dart index fb1814bf..c0697ace 100644 --- a/lib/data/sync/config_sync_handler.dart +++ b/lib/data/sync/config_sync_handler.dart @@ -180,5 +180,8 @@ class ConfigSyncHandler extends SyncTypeHandler @override DateTime? getLastSyncedAt(Config entity) => entity.lastSyncedAt; + + @override + DateTime? getCursorTimestamp(Config entity) => entity.updatedAt; } diff --git a/lib/data/sync/group_sync_handler.dart b/lib/data/sync/group_sync_handler.dart index 2f63c9e1..17fc983e 100644 --- a/lib/data/sync/group_sync_handler.dart +++ b/lib/data/sync/group_sync_handler.dart @@ -57,6 +57,15 @@ class GroupSyncHandler extends SyncTypeHandler return await remoteDataSource.getGroup(id); } + @override + Future claimClientId(Group entity) { + return remoteDataSource.claimClientId( + id: entity.id!, + clientId: entity.clientId, + updatedAt: entity.updatedAt, + ); + } + @override Future restPutRemote(Group entity) async { if (entity.id == null) { @@ -195,4 +204,7 @@ class GroupSyncHandler extends SyncTypeHandler @override DateTime? getLastSyncedAt(Group entity) => entity.lastSyncedAt; + + @override + DateTime? getCursorTimestamp(Group entity) => entity.updatedAt; } diff --git a/lib/data/sync/notification_sync_handler.dart b/lib/data/sync/notification_sync_handler.dart index 5a926941..c99311b4 100644 --- a/lib/data/sync/notification_sync_handler.dart +++ b/lib/data/sync/notification_sync_handler.dart @@ -171,4 +171,7 @@ class NotificationSyncHandler extends SyncTypeHandler @override DateTime? getLastSyncedAt(Notification entity) => entity.lastSyncedAt; + + @override + DateTime? getCursorTimestamp(Notification entity) => entity.updatedAt; } diff --git a/lib/data/sync/party_sync_handler.dart b/lib/data/sync/party_sync_handler.dart index 4da18c61..20f928fe 100644 --- a/lib/data/sync/party_sync_handler.dart +++ b/lib/data/sync/party_sync_handler.dart @@ -50,6 +50,15 @@ class PartySyncHandler extends SyncTypeHandler ); } + @override + Future claimClientId(Party entity) { + return remoteDataSource.claimClientId( + id: entity.id!, + clientId: entity.clientId, + updatedAt: entity.updatedAt, + ); + } + @override Future restPutRemote(Party entity) async { if (entity.id == null) { @@ -149,4 +158,7 @@ class PartySyncHandler extends SyncTypeHandler @override DateTime? getLastSyncedAt(Party entity) => entity.lastSyncedAt; + + @override + DateTime? getCursorTimestamp(Party entity) => entity.updatedAt; } diff --git a/lib/data/sync/reminder_sync_handler.dart b/lib/data/sync/reminder_sync_handler.dart index 9a169227..a0e7c588 100644 --- a/lib/data/sync/reminder_sync_handler.dart +++ b/lib/data/sync/reminder_sync_handler.dart @@ -46,6 +46,15 @@ class ReminderSyncHandler extends SyncTypeHandler ); } + @override + Future claimClientId(Reminder entity) { + return remoteDataSource.claimClientId( + id: entity.id!, + clientId: entity.clientId, + updatedAt: entity.updatedAt, + ); + } + @override Future restPutRemote(Reminder entity) async { if (entity.id == null) { @@ -123,4 +132,7 @@ class ReminderSyncHandler extends SyncTypeHandler @override DateTime? getLastSyncedAt(Reminder entity) => entity.lastSyncedAt; + + @override + DateTime? getCursorTimestamp(Reminder entity) => entity.updatedAt; } diff --git a/lib/data/sync/transaction_sync_handler.dart b/lib/data/sync/transaction_sync_handler.dart index 8157a087..8c3a7d3f 100644 --- a/lib/data/sync/transaction_sync_handler.dart +++ b/lib/data/sync/transaction_sync_handler.dart @@ -127,6 +127,16 @@ class TransactionSyncHandler } } + @override + Future claimClientId( + TransactionCompleteDto entity) { + return remoteDataSource.claimClientId( + id: entity.transaction.id!, + clientId: entity.transaction.clientId, + updatedAt: entity.transaction.updatedAt, + ); + } + @override Future restGetRemote(int id) async { return await remoteDataSource.getTransaction(id); @@ -392,4 +402,8 @@ class TransactionSyncHandler @override DateTime? getLastSyncedAt(TransactionCompleteDto entity) => entity.transaction.lastSyncedAt; + + @override + DateTime? getCursorTimestamp(TransactionCompleteDto entity) => + entity.transaction.updatedAt; } diff --git a/lib/data/sync/transfer_sync_handler.dart b/lib/data/sync/transfer_sync_handler.dart index d67b2a16..3230523c 100644 --- a/lib/data/sync/transfer_sync_handler.dart +++ b/lib/data/sync/transfer_sync_handler.dart @@ -35,12 +35,17 @@ class TransferSyncHandler extends SyncTypeHandler @override Future unmarshal(Map entityJson) async { - return TransferDto.fromJson(entityJson).toTransfer(); + // Snapshots queued by older builds used the API request shape + // (toServerJson), which lacks these DTO fields. + final json = Map.from(entityJson); + json['client_generated_id'] ??= json['client_id']; + json['updated_at'] ??= json['created_at']; + return TransferDto.fromJson(json).toTransfer(); } @override Map marshal(Transfer entity) { - return toServerJson(entity); + return TransferDto.fromTransfer(entity).toJson(); } @override @@ -72,6 +77,22 @@ class TransferSyncHandler extends SyncTypeHandler return true; } + @override + Future shouldPersistLocal(Transfer entity) async { + if (entity.deletedAt != null) return true; + + for (final legClientId in [ + entity.expenseTransactionClientId, + entity.incomeTransactionClientId, + ]) { + if (legClientId == null || legClientId.isEmpty) continue; + final txn = await transactionLocalDataSource + .getTransactionByClientId(legClientId); + if (txn == null) return false; + } + return true; + } + @override Future> restGetAllRemote({ bool? noClientId, @@ -108,6 +129,17 @@ class TransferSyncHandler extends SyncTypeHandler return result; } + @override + Future claimClientId(Transfer entity) async { + final result = await remoteDataSource.claimClientId( + id: entity.id!, + clientId: entity.clientId, + updatedAt: entity.updatedAt, + ); + await upsertLocal(result); + return result; + } + @override Future restDeleteRemote(Transfer entity) async { if (entity.id != null) { @@ -128,6 +160,10 @@ class TransferSyncHandler extends SyncTypeHandler @override Future upsertAllLocal(List list) async { for (final entity in list) { + if (entity.clientId.isEmpty) { + continue; + } + if (entity.deletedAt != null) { await table.deleteWhere((t) => t.clientId.equals(entity.clientId)); } else { @@ -184,4 +220,7 @@ class TransferSyncHandler extends SyncTypeHandler @override DateTime? getLastSyncedAt(Transfer entity) => entity.lastSyncedAt; + + @override + DateTime? getCursorTimestamp(Transfer entity) => entity.updatedAt; } diff --git a/lib/data/sync/wallet_sync_handler.dart b/lib/data/sync/wallet_sync_handler.dart index 6a361acc..139ebb47 100644 --- a/lib/data/sync/wallet_sync_handler.dart +++ b/lib/data/sync/wallet_sync_handler.dart @@ -40,6 +40,15 @@ class WalletSyncHandler extends SyncTypeHandler return await remoteDataSource.getWallet(id); } + @override + Future claimClientId(Wallet entity) { + return remoteDataSource.claimClientId( + id: entity.id!, + clientId: entity.clientId, + updatedAt: entity.updatedAt, + ); + } + @override Future restPutRemote(Wallet entity) async { if (entity.id == null) { @@ -178,4 +187,7 @@ class WalletSyncHandler extends SyncTypeHandler @override DateTime? getLastSyncedAt(Wallet entity) => entity.lastSyncedAt; + + @override + DateTime? getCursorTimestamp(Wallet entity) => entity.updatedAt; } diff --git a/lib/di/injection.config.dart b/lib/di/injection.config.dart index 91bc4d60..c4524215 100644 --- a/lib/di/injection.config.dart +++ b/lib/di/injection.config.dart @@ -901,14 +901,14 @@ _i174.GetIt $initGetIt( () => _i163.DeleteTransactionUseCase(gh<_i118.TransactionRepository>())); gh.factory<_i973.ListenToTransactionsUseCase>(() => _i973.ListenToTransactionsUseCase(gh<_i118.TransactionRepository>())); - gh.factory<_i241.UpdateTransactionUseCase>( - () => _i241.UpdateTransactionUseCase(gh<_i118.TransactionRepository>())); - gh.factory<_i947.GetAllTransactionsUseCase>( - () => _i947.GetAllTransactionsUseCase(gh<_i118.TransactionRepository>())); gh.factory<_i322.UnmarkTransactionRefundUseCase>(() => _i322.UnmarkTransactionRefundUseCase(gh<_i118.TransactionRepository>())); + gh.factory<_i241.UpdateTransactionUseCase>( + () => _i241.UpdateTransactionUseCase(gh<_i118.TransactionRepository>())); gh.factory<_i468.MarkTransactionRefundUseCase>(() => _i468.MarkTransactionRefundUseCase(gh<_i118.TransactionRepository>())); + gh.factory<_i947.GetAllTransactionsUseCase>( + () => _i947.GetAllTransactionsUseCase(gh<_i118.TransactionRepository>())); gh.lazySingleton>>( () => syncModule.provideSyncTypeHandlers( gh<_i463.CategorySyncHandler>(), diff --git a/lib/domain/entities/transaction_entity.dart b/lib/domain/entities/transaction_entity.dart index 3d385cf4..1ca6095c 100644 --- a/lib/domain/entities/transaction_entity.dart +++ b/lib/domain/entities/transaction_entity.dart @@ -34,3 +34,10 @@ class TransactionEntity with _$TransactionEntity { factory TransactionEntity.fromJson(Map json) => _$TransactionEntityFromJson(json); } + +extension TransactionTransferLeg on TransactionEntity { + /// True for either leg of a wallet-to-wallet transfer, synced + /// ([transferId]) or not yet synced ([transferClientId]). + bool get isTransferLeg => + transferId != null || (transferClientId?.isNotEmpty ?? false); +} diff --git a/lib/gen/translations/codegen_loader.g.dart b/lib/gen/translations/codegen_loader.g.dart index 22203a64..ad229e0e 100644 --- a/lib/gen/translations/codegen_loader.g.dart +++ b/lib/gen/translations/codegen_loader.g.dart @@ -510,6 +510,9 @@ abstract class LocaleKeys { static const noPendingChanges = 'noPendingChanges'; static const failedChanges = 'failedChanges'; static const noFailedChanges = 'noFailedChanges'; + static const needsAttention = 'needsAttention'; + static const noQuarantinedChanges = 'noQuarantinedChanges'; + static const quarantinedHint = 'quarantinedHint'; static const dismiss = 'dismiss'; static const categorySalary = 'categorySalary'; static const categorySalaryDesc = 'categorySalaryDesc'; diff --git a/lib/presentation/ai_chat/widgets/proposed_action_card.dart b/lib/presentation/ai_chat/widgets/proposed_action_card.dart index 0e38d575..bcc405b5 100644 --- a/lib/presentation/ai_chat/widgets/proposed_action_card.dart +++ b/lib/presentation/ai_chat/widgets/proposed_action_card.dart @@ -1,15 +1,20 @@ import 'dart:async'; +import 'package:collection/collection.dart'; import 'package:currency_picker/currency_picker.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:trakli/data/datasources/ai/dto/chat_blocks_dto.dart'; +import 'package:trakli/domain/entities/category_entity.dart'; +import 'package:trakli/domain/entities/party_entity.dart'; +import 'package:trakli/domain/entities/wallet_entity.dart'; import 'package:trakli/gen/translations/codegen_loader.g.dart'; import 'package:trakli/presentation/ai_chat/cubit/ai_chat_cubit.dart'; import 'package:trakli/presentation/category/cubit/category_cubit.dart'; import 'package:trakli/presentation/parties/cubit/party_cubit.dart'; +import 'package:trakli/presentation/utils/custom_dropdown_search.dart'; import 'package:trakli/presentation/utils/design_tokens.dart'; import 'package:trakli/presentation/utils/enums.dart'; import 'package:trakli/presentation/wallets/cubit/wallet_cubit.dart'; @@ -30,7 +35,9 @@ class ProposedActionCardState extends State { void initState() { super.initState(); for (final f in widget.block.fields) { - _edited[f.key] = f is CategoriesActionField ? f.initialIds : f.value; + _edited[f.key] = f is CategoriesActionField + ? (f.initialIds.isEmpty ? const [] : [f.initialIds.first]) + : f.value; } } @@ -172,17 +179,6 @@ class ProposedActionCardState extends State { } Widget _field(AppTones tones, ActionField f) { - if (f is CategoriesActionField) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(f.label, - style: TextStyle(color: tones.textMuted, fontSize: 12.sp)), - SizedBox(height: 6.h), - _categoryChips(tones, f), - ], - ); - } return Row( children: [ Expanded( @@ -232,19 +228,22 @@ class ProposedActionCardState extends State { ); } + Color _accent(AppTones tones) => + widget.block.risk == 'high' ? tones.accentWarm : tones.brand.deep; + /// Wallet type (bank / cash / credit_card / mobile) as a dropdown. Widget _walletTypeInput(AppTones tones, WalletTypeActionField f) { final current = _edited[f.key]?.toString(); - return _dropdown( - value: - WalletType.values.any((w) => w.serverKey == current) ? current : null, - items: WalletType.values - .map((w) => DropdownMenuItem( - value: w.serverKey, - child: Text(w.customName, style: TextStyle(fontSize: 12.sp)), - )) - .toList(), - onChanged: (v) => setState(() => _edited[f.key] = v), + return CustomDropdownSearch( + label: "", + accentColor: _accent(tones), + selectedItem: + WalletType.values.firstWhereOrNull((w) => w.serverKey == current), + showSearchBox: false, + items: (filter, infiniteScrollProps) => WalletType.values, + itemAsString: (w) => w.customName, + onChanged: (v) => setState(() => _edited[f.key] = v?.serverKey), + compareFn: (i1, i2) => i1 == i2, ); } @@ -256,56 +255,65 @@ class ProposedActionCardState extends State { final PartyRefActionField x => _partyDropdown(tones, x), final NumberActionField x => _numberInput(tones, x), final DateTimeActionField x => _datetimeField(tones, x), - final CategoriesActionField x => _categoryChips(tones, x), + final CategoriesActionField x => _categoryDropdown(tones, x), final TextActionField x => _textInput(tones, x), }; - Widget _enumDropdown(AppTones tones, EnumActionField f) => _dropdown( - value: _edited[f.key]?.toString(), - items: f.options - .map((o) => DropdownMenuItem( - value: o, - child: Text(_cap(o), style: TextStyle(fontSize: 12.sp)), - )) - .toList(), + Widget _enumDropdown(AppTones tones, EnumActionField f) => + CustomDropdownSearch( + label: "", + accentColor: _accent(tones), + selectedItem: f.options.contains(_edited[f.key]?.toString()) + ? _edited[f.key].toString() + : null, + showSearchBox: false, + items: (filter, infiniteScrollProps) => f.options, + itemAsString: _cap, onChanged: (v) => setState(() => _edited[f.key] = v), + compareFn: (i1, i2) => i1 == i2, ); Widget _walletDropdown(AppTones tones, WalletRefActionField f) { - final wallets = - context.watch().state.wallets.where((w) => w.id != null); - return _dropdown( - value: _edited[f.key] is num ? (_edited[f.key] as num).toInt() : null, - items: wallets - .map((w) => DropdownMenuItem( - value: w.id!, - child: Text(w.name, - style: TextStyle(fontSize: 12.sp), - overflow: TextOverflow.ellipsis), - )) - .toList(), - onChanged: (v) => setState(() => _edited[f.key] = v), + final wallets = context + .watch() + .state + .wallets + .where((w) => w.id != null) + .toList(); + final currentId = + _edited[f.key] is num ? (_edited[f.key] as num).toInt() : null; + return CustomDropdownSearch( + label: "", + accentColor: _accent(tones), + selectedItem: wallets.firstWhereOrNull((w) => w.id == currentId), + showSearchBox: false, + items: (filter, infiniteScrollProps) => wallets, + itemAsString: (w) => w.name, + onChanged: (v) => setState(() => _edited[f.key] = v?.id), + compareFn: (i1, i2) => i1.clientId == i2.clientId, ); } Widget _partyDropdown(AppTones tones, PartyRefActionField f) { - final parties = - context.watch().state.parties.where((p) => p.id != null); - return _dropdown( - value: _edited[f.key] is num ? (_edited[f.key] as num).toInt() : null, - items: [ - DropdownMenuItem( - value: null, - child: Text(LocaleKeys.none.tr(), style: TextStyle(fontSize: 12.sp)), - ), - ...parties.map((p) => DropdownMenuItem( - value: p.id!, - child: Text(p.name, - style: TextStyle(fontSize: 12.sp), - overflow: TextOverflow.ellipsis), - )), - ], - onChanged: (v) => setState(() => _edited[f.key] = v), + final parties = context + .watch() + .state + .parties + .where((p) => p.id != null) + .toList(); + final currentId = + _edited[f.key] is num ? (_edited[f.key] as num).toInt() : null; + return CustomDropdownSearch( + label: "", + accentColor: _accent(tones), + selectedItem: parties.firstWhereOrNull((p) => p.id == currentId), + showClearButton: true, + items: (filter, infiniteScrollProps) => parties, + itemAsString: (p) => p.name, + onChanged: (v) => setState(() => _edited[f.key] = v?.id), + compareFn: (i1, i2) => i1.clientId == i2.clientId, + filterFn: (p, filter) => + p.name.toLowerCase().contains(filter.toLowerCase()), ); } @@ -324,35 +332,30 @@ class ProposedActionCardState extends State { onChanged: (v) => _edited[f.key] = v, ); - Widget _categoryChips(AppTones tones, CategoriesActionField f) { - final selected = (_edited[f.key] as List?)?.cast() ?? []; + /// Single category as a dropdown; stored as a one-element list so the + /// overrides payload shape stays unchanged. + Widget _categoryDropdown(AppTones tones, CategoriesActionField f) { + final selected = (_edited[f.key] as List?)?.cast() ?? const []; final categories = context .watch() .state .categories .where((c) => c.id != null) .toList(); - return Wrap( - spacing: 6.w, - runSpacing: 6.h, - children: categories.map((c) { - final isSel = selected.contains(c.id); - return FilterChip( - label: Text(c.name, style: TextStyle(fontSize: 11.sp)), - selected: isSel, - onSelected: (v) { - setState(() { - final list = List.from(selected); - if (v) { - list.add(c.id!); - } else { - list.remove(c.id); - } - _edited[f.key] = list; - }); - }, - ); - }).toList(), + return CustomDropdownSearch( + label: "", + accentColor: _accent(tones), + selectedItem: selected.isEmpty + ? null + : categories.firstWhereOrNull((c) => c.id == selected.first), + showClearButton: true, + items: (filter, infiniteScrollProps) => categories, + itemAsString: (c) => c.name, + onChanged: (v) => setState(() => + _edited[f.key] = v?.id == null ? const [] : [v!.id!]), + compareFn: (i1, i2) => i1.clientId == i2.clientId, + filterFn: (c, filter) => + c.name.toLowerCase().contains(filter.toLowerCase()), ); } @@ -401,31 +404,6 @@ class ProposedActionCardState extends State { ); } - Widget _dropdown({ - required T? value, - required List> items, - required ValueChanged onChanged, - }) { - final tones = context.tones; - final safeValue = items.any((it) => it.value == value) ? value : null; - return Container( - padding: EdgeInsets.symmetric(horizontal: 10.w), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8.r), - border: Border.all(color: tones.borderLight), - ), - child: DropdownButton( - value: safeValue, - isExpanded: true, - isDense: true, - underline: const SizedBox.shrink(), - style: TextStyle(fontSize: 12.sp, color: tones.textPrimary), - items: items, - onChanged: onChanged, - ), - ); - } - InputDecoration _inputDecoration(AppTones tones) => InputDecoration( isDense: true, contentPadding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 8.h), diff --git a/lib/presentation/statistics/cubit/report_stats_cubit.dart b/lib/presentation/statistics/cubit/report_stats_cubit.dart new file mode 100644 index 00000000..344f47a1 --- /dev/null +++ b/lib/presentation/statistics/cubit/report_stats_cubit.dart @@ -0,0 +1,99 @@ +import 'dart:async'; + +import 'package:drift_sync_core/drift_sync_core.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:trakli/core/services/auth_service.dart'; +import 'package:trakli/data/database/app_database.dart'; +import 'package:trakli/data/datasources/stats/dto/report_stats_dto.dart'; +import 'package:trakli/data/datasources/stats/stats_remote_datasource.dart'; + +class ReportStatsState { + /// Server stats applied for [periodDays]; null means the screen renders + /// its locally computed numbers. + final ReportStatsDto? stats; + final int periodDays; + final bool isLoading; + + /// True when the user has no account, so local numbers are the only truth. + final bool isLocalOnly; + + /// True when server stats were withheld because unsynced transactions + /// would be missing from them. + final bool deferredForPendingSync; + + const ReportStatsState({ + this.stats, + this.periodDays = 90, + this.isLoading = false, + this.isLocalOnly = false, + this.deferredForPendingSync = false, + }); +} + +/// Fetches server /stats for the Reports screen so totals and category +/// breakdowns match web. Local numbers win while the user is signed out, +/// while transactions are waiting to sync, or when the fetch fails; a +/// completed sync run triggers a refetch. +class ReportStatsCubit extends Cubit { + final StatsRemoteDataSource _remote; + final AuthService _authService; + final AppDatabase _db; + StreamSubscription? _syncSubscription; + int _loadId = 0; + + ReportStatsCubit({ + required StatsRemoteDataSource remote, + required AuthService authService, + required AppDatabase db, + Stream? syncStream, + }) : _remote = remote, + _authService = authService, + _db = db, + super(const ReportStatsState()) { + _syncSubscription = syncStream?.listen((syncState) { + if (!syncState.isSynchronizing) load(state.periodDays); + }); + } + + Future load(int periodDays) async { + final id = ++_loadId; + emit(ReportStatsState( + stats: periodDays == state.periodDays ? state.stats : null, + periodDays: periodDays, + isLoading: true, + )); + + if (!await _authService.isAuthenticated()) { + if (id != _loadId) return; + emit(ReportStatsState(periodDays: periodDays, isLocalOnly: true)); + return; + } + + if (await _db.hasPendingTransactionChanges()) { + if (id != _loadId) return; + emit(ReportStatsState( + periodDays: periodDays, deferredForPendingSync: true)); + return; + } + + try { + final now = DateTime.now(); + final today = DateTime(now.year, now.month, now.day); + final stats = await _remote.getReportStats( + start: today.subtract(Duration(days: periodDays - 1)), + end: today, + ); + if (id != _loadId) return; + emit(ReportStatsState(stats: stats, periodDays: periodDays)); + } catch (_) { + if (id != _loadId) return; + emit(ReportStatsState(periodDays: periodDays)); + } + } + + @override + Future close() async { + await _syncSubscription?.cancel(); + return super.close(); + } +} diff --git a/lib/presentation/statistics/month_in_review/month_in_review_data.dart b/lib/presentation/statistics/month_in_review/month_in_review_data.dart index 0add9909..8421fde6 100644 --- a/lib/presentation/statistics/month_in_review/month_in_review_data.dart +++ b/lib/presentation/statistics/month_in_review/month_in_review_data.dart @@ -1,4 +1,5 @@ import 'package:trakli/domain/entities/transaction_complete_entity.dart'; +import 'package:trakli/domain/entities/transaction_entity.dart'; import 'package:trakli/presentation/utils/enums.dart'; class TopByName { @@ -47,12 +48,9 @@ class MonthInReviewData { }); } -/// Computes a recap for the most recent month that actually has activity. -/// If [offsetMonths] is 0 (default), the function walks back from "now" and -/// picks the first month where there is at least one transaction — so the -/// card never shows "No activity yet" for an account that only logged -/// transactions in earlier months. A positive [offsetMonths] anchors to -/// that many months before now (used for "previous month" comparisons). +/// Computes a recap for the month [offsetMonths] before the current one +/// (0 = the current month), matching the web recap. Transfer legs are +/// excluded; returns null when the target month has no activity. MonthInReviewData? buildMonthInReview( List transactions, { int offsetMonths = 0, @@ -60,37 +58,14 @@ MonthInReviewData? buildMonthInReview( if (transactions.isEmpty) return null; final now = DateTime.now(); - late final DateTime target; - - if (offsetMonths != 0) { - target = DateTime(now.year, now.month - offsetMonths, 1); - } else { - DateTime? candidate; - for (var i = 0; i < 24; i++) { - final probe = DateTime(now.year, now.month - i, 1); - final hasAny = transactions.any((t) => - t.transaction.datetime.year == probe.year && - t.transaction.datetime.month == probe.month); - if (hasAny) { - candidate = probe; - break; - } - } - if (candidate == null) { - final latest = transactions - .map((t) => t.transaction.datetime) - .reduce((a, b) => a.isAfter(b) ? a : b); - candidate = DateTime(latest.year, latest.month, 1); - } - target = candidate; - } + final target = DateTime(now.year, now.month - offsetMonths, 1); final monthEnd = DateTime(target.year, target.month + 1, 0); bool sameMonth(DateTime d) => d.year == target.year && d.month == target.month; final inMonth = transactions.where((t) { - return sameMonth(t.transaction.datetime); + return !t.transaction.isTransferLeg && sameMonth(t.transaction.datetime); }).toList(); double income = 0; diff --git a/lib/presentation/statistics/reports/report_data.dart b/lib/presentation/statistics/reports/report_data.dart index aee5f8ac..41bd2f19 100644 --- a/lib/presentation/statistics/reports/report_data.dart +++ b/lib/presentation/statistics/reports/report_data.dart @@ -1,4 +1,5 @@ import 'package:trakli/domain/entities/transaction_complete_entity.dart'; +import 'package:trakli/domain/entities/transaction_entity.dart'; import 'package:trakli/presentation/utils/enums.dart'; /// Mobile port of the daily/monthly bucket types in `useReportData.ts`. @@ -109,6 +110,8 @@ ReportData buildReportData( double totalExpense = 0; for (final t in transactions) { + // Transfer legs aren't income or spending; web and /stats exclude them. + if (t.transaction.isTransferLeg) continue; final day = _startOfDay(t.transaction.datetime); if (day.isBefore(start) || day.isAfter(end)) continue; diff --git a/lib/presentation/statistics/reports/reports_screen.dart b/lib/presentation/statistics/reports/reports_screen.dart index f8ed1313..75a82673 100644 --- a/lib/presentation/statistics/reports/reports_screen.dart +++ b/lib/presentation/statistics/reports/reports_screen.dart @@ -1,7 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:trakli/core/services/auth_service.dart'; +import 'package:trakli/core/sync/sync_database.dart'; import 'package:trakli/core/utils/currency_formater.dart'; +import 'package:trakli/data/database/app_database.dart'; +import 'package:trakli/data/datasources/stats/stats_remote_datasource.dart'; +import 'package:trakli/di/injection.dart'; +import 'package:trakli/presentation/statistics/cubit/report_stats_cubit.dart'; import 'package:trakli/presentation/statistics/month_in_review/month_in_review_data.dart'; import 'package:trakli/presentation/statistics/month_in_review/month_in_review_screen.dart'; import 'package:trakli/presentation/statistics/reports/charts/calendar_heatmap.dart'; @@ -21,8 +27,11 @@ import 'package:trakli/presentation/utils/design_tokens.dart'; /// - Hero KPIs /// - Tabbed cashflow / breakdown / activity charts /// -/// The screen reads transactions from TransactionCubit and computes the -/// report bundle locally, mirroring the web's `useReportData` composable. +/// Totals and category breakdowns come from server /stats when available +/// (matching web); daily-granularity charts and the recap are computed from +/// local transactions, exactly as the web's `useReportData` does. Local +/// numbers win while signed out, offline, or while transactions are still +/// waiting to sync. class ReportsScreen extends StatefulWidget { const ReportsScreen({super.key}); @@ -49,62 +58,147 @@ class _ReportsScreenState extends State @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - final data = buildReportData( - state.transactions, - periodDays: _periodDays, - ); - final recap = buildMonthInReview(state.transactions); - - return Scaffold( - appBar: const PageAppBar(title: 'Reports'), - body: SingleChildScrollView( - padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - MonthInReviewCard( - data: recap, - onTap: recap == null - ? null - : () => MonthInReviewScreen.show(context, recap), - ), - SizedBox(height: 16.h), - _PeriodChips( - selected: _periodDays, - onChange: (v) => setState(() => _periodDays = v), - ), - SizedBox(height: 16.h), - _KpiGrid(totals: data.totals), - SizedBox(height: 16.h), - _SectionCard( - title: 'Cashflow', - subtitle: 'Income vs expense across the period', - child: CashflowChart(daily: data.daily), - ), - SizedBox(height: 16.h), - _TabbedCard( - controller: _tabs, - tabs: const [ - _TabSpec(label: 'Categories', icon: Icons.donut_small), - _TabSpec(label: 'Daily', icon: Icons.calendar_view_day), - _TabSpec(label: 'Calendar', icon: Icons.grid_on), - _TabSpec(label: 'Ratios', icon: Icons.percent), - ], - children: [ - _BreakdownTab(data: data), - _DailyTab(data: data), - _CalendarTab(data: data), - _RatiosTab(totals: data.totals), - ], + return BlocProvider( + create: (_) => ReportStatsCubit( + remote: getIt(), + authService: getIt(), + db: getIt(), + syncStream: getIt().syncStateStream, + )..load(_periodDays), + child: BlocBuilder( + builder: (context, state) { + return BlocBuilder( + builder: (context, statsState) { + final data = buildReportData( + state.transactions, + periodDays: _periodDays, + ); + final recap = buildMonthInReview(state.transactions); + + final server = statsState.stats; + final totals = server == null + ? data.totals + : ReportTotals( + income: server.totalIncome, + expense: server.totalExpenses, + net: server.netCashFlow, + savingsRate: server.savingsRate, + expenseRatio: server.totalIncome > 0 + ? server.totalExpenses / server.totalIncome + : 0, + daysInPeriod: _periodDays, + ); + final expenseCategories = server == null + ? data.expenseCategories + : [ + for (final c in server.expenseCategories) + CategoryAggregate( + name: c.name, + amount: c.amount, + percentage: c.percentage, + ), + ]; + + return Scaffold( + appBar: const PageAppBar(title: 'Reports'), + body: SingleChildScrollView( + padding: + EdgeInsets.symmetric(horizontal: 16.w, vertical: 16.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + MonthInReviewCard( + data: recap, + onTap: recap == null + ? null + : () => MonthInReviewScreen.show(context, recap), + ), + SizedBox(height: 16.h), + _PeriodChips( + selected: _periodDays, + onChange: (v) { + setState(() => _periodDays = v); + context.read().load(v); + }, + ), + SizedBox(height: 16.h), + _StatsSourceNote(statsState: statsState), + _KpiGrid(totals: totals), + SizedBox(height: 16.h), + _SectionCard( + title: 'Cashflow', + subtitle: 'Income vs expense across the period', + child: CashflowChart(daily: data.daily), + ), + SizedBox(height: 16.h), + _TabbedCard( + controller: _tabs, + tabs: const [ + _TabSpec( + label: 'Categories', icon: Icons.donut_small), + _TabSpec( + label: 'Daily', icon: Icons.calendar_view_day), + _TabSpec(label: 'Calendar', icon: Icons.grid_on), + _TabSpec(label: 'Ratios', icon: Icons.percent), + ], + children: [ + _BreakdownTab(categories: expenseCategories), + _DailyTab(data: data), + _CalendarTab(data: data), + _RatiosTab(totals: totals), + ], + ), + SizedBox(height: 24.h), + ], + ), ), - SizedBox(height: 24.h), - ], + ); + }, + ); + }, + ), + ); + } +} + +/// One-line note under the period chips when the numbers aren't plain +/// server truth: local estimate (signed in but no server stats yet) or +/// partial conversion. Signed-out users see nothing — local is their truth. +class _StatsSourceNote extends StatelessWidget { + final ReportStatsState statsState; + + const _StatsSourceNote({required this.statsState}); + + @override + Widget build(BuildContext context) { + final tones = context.tones; + final server = statsState.stats; + + String? note; + if (server != null && server.partial) { + note = + 'Totals exclude ${server.unconvertedCurrencies.join(', ')} (no exchange rate)'; + } else if (server == null && !statsState.isLocalOnly) { + note = statsState.deferredForPendingSync + ? 'Local estimate — sync pending' + : 'Local estimate'; + } + if (note == null) return const SizedBox.shrink(); + + return Padding( + padding: EdgeInsets.only(bottom: 8.h), + child: Row( + children: [ + Icon(Icons.info_outline, size: 13.sp, color: tones.textMuted), + SizedBox(width: 6.w), + Expanded( + child: Text( + note, + style: TextStyle(fontSize: 11.sp, color: tones.textMuted), ), ), - ); - }, + ], + ), ); } } @@ -485,9 +579,9 @@ class _TabChip extends StatelessWidget { } class _BreakdownTab extends StatelessWidget { - final ReportData data; + final List categories; - const _BreakdownTab({required this.data}); + const _BreakdownTab({required this.categories}); @override Widget build(BuildContext context) { @@ -495,13 +589,13 @@ class _BreakdownTab extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ CategoryDonut( - categories: data.expenseCategories, + categories: categories, palette: expensePalette, centerLabel: 'Expense', ), SizedBox(height: 16.h), CategoryRanking( - categories: data.expenseCategories, + categories: categories, palette: expensePalette, ), ], diff --git a/lib/presentation/sync_history_screen.dart b/lib/presentation/sync_history_screen.dart index ab1a667b..7c016593 100644 --- a/lib/presentation/sync_history_screen.dart +++ b/lib/presentation/sync_history_screen.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:drift/drift.dart' hide Column; import 'package:drift_sync_core/drift_sync_core.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -23,6 +25,7 @@ class _SyncHistoryScreenState extends State { List _syncMetadata = []; List _pendingChanges = []; List _failedChanges = []; + List _quarantinedChanges = []; bool _isLoading = true; bool _isSyncing = false; @@ -48,14 +51,23 @@ class _SyncHistoryScreenState extends State { final metadata = await _db.getLocalSyncMetadataList(); final allChanges = await _db.select(_db.localChanges).get(); - final pending = allChanges.where((c) => c.error == null).toList(); - final failed = allChanges.where((c) => c.error != null).toList(); + // Quarantined changes are permanently failed and never retry + // automatically; keep them out of the transient "failed" bucket. + final pending = allChanges + .where((c) => c.error == null && c.quarantinedAt == null) + .toList(); + final failed = allChanges + .where((c) => c.error != null && c.quarantinedAt == null) + .toList(); + final quarantined = + allChanges.where((c) => c.quarantinedAt != null).toList(); if (mounted) { setState(() { _syncMetadata = metadata; _pendingChanges = pending; _failedChanges = failed; + _quarantinedChanges = quarantined; _isLoading = false; }); } @@ -79,21 +91,28 @@ class _SyncHistoryScreenState extends State { } } - Future _dismissFailedChange(LocalChange change) async { - await (_db.delete(_db.localChanges) + Future _retryFailedChange(LocalChange change) async { + await (_db.update(_db.localChanges) ..where((lc) => lc.entityType.equals(change.entityType) & lc.entityId.equals(change.entityId))) - .go(); + .write(const LocalChangesCompanion(error: Value(null))); _loadData(); + _triggerSync(); } - Future _retryFailedChange(LocalChange change) async { + /// Un-quarantine: clear the error, lift quarantine, and reset the attempt + /// counter so the change re-enters the normal retry path immediately. + Future _retryQuarantinedChange(LocalChange change) async { await (_db.update(_db.localChanges) ..where((lc) => lc.entityType.equals(change.entityType) & lc.entityId.equals(change.entityId))) - .write(const LocalChangesCompanion(error: Value(null))); + .write(const LocalChangesCompanion( + error: Value(null), + quarantinedAt: Value(null), + attemptCount: Value(0), + )); _loadData(); _triggerSync(); } @@ -130,25 +149,33 @@ class _SyncHistoryScreenState extends State { ), body: _isLoading ? const Center(child: CircularProgressIndicator()) - : RefreshIndicator( - onRefresh: _loadData, - child: SingleChildScrollView( - physics: const AlwaysScrollableScrollPhysics(), - padding: EdgeInsets.symmetric( - horizontal: 16.w, - vertical: 16.h, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildSyncButton(), - SizedBox(height: 24.h), - _buildSyncStatusSection(), - SizedBox(height: 24.h), - _buildPendingChangesSection(), - SizedBox(height: 24.h), - _buildFailedChangesSection(), - ], + : SafeArea( + child: RefreshIndicator( + onRefresh: _loadData, + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + padding: EdgeInsets.only( + left: 16.w, + right: 16.w, + top: 16.h, + bottom: 32.h, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildSyncButton(), + SizedBox(height: 24.h), + _buildSyncStatusSection(), + SizedBox(height: 24.h), + if (_quarantinedChanges.isNotEmpty) ...[ + _buildQuarantinedSection(), + SizedBox(height: 24.h), + ], + _buildPendingChangesSection(), + SizedBox(height: 24.h), + _buildFailedChangesSection(), + ], + ), ), ), ), @@ -318,6 +345,152 @@ class _SyncHistoryScreenState extends State { ); } + /// Full error text plus the queued request payload, so validation + /// failures show exactly what the server received. + void _showChangeDetails(LocalChange change) { + final payload = const JsonEncoder.withIndent(' ').convert(change.data); + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(_getEntityTypeDisplayName(change.entityType)), + content: SizedBox( + width: double.maxFinite, + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + if (change.error != null) ...[ + SelectableText( + change.error!, + style: TextStyle(fontSize: 12.sp, color: Colors.red[700]), + ), + SizedBox(height: 12.h), + ], + Container( + width: double.infinity, + padding: EdgeInsets.all(8.r), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: BorderRadius.circular(8.r), + ), + child: SelectableText( + payload, + style: TextStyle(fontSize: 11.sp, fontFamily: 'monospace'), + ), + ), + ], + ), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text(LocaleKeys.done.tr()), + ), + ], + ), + ); + } + + Widget _buildQuarantinedSection() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(Icons.report_problem, size: 18.sp, color: Colors.orange[800]), + SizedBox(width: 6.w), + Text( + LocaleKeys.needsAttention.tr(), + style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold), + ), + SizedBox(width: 8.w), + Container( + padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 2.h), + decoration: BoxDecoration( + color: Colors.orange.withValues(alpha: 0.2), + borderRadius: BorderRadius.circular(12.r), + ), + child: Text( + _quarantinedChanges.length.toString(), + style: TextStyle( + fontSize: 12.sp, + fontWeight: FontWeight.bold, + color: Colors.orange[800], + ), + ), + ), + ], + ), + SizedBox(height: 4.h), + Text( + LocaleKeys.quarantinedHint.tr(), + style: TextStyle(fontSize: 11.sp, color: Colors.grey[600]), + ), + SizedBox(height: 8.h), + Card( + child: ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: _quarantinedChanges.length, + separatorBuilder: (_, __) => const Divider(height: 1), + itemBuilder: (context, index) { + final change = _quarantinedChanges[index]; + return ListTile( + dense: true, + leading: Icon(Icons.report_problem, + size: 20.sp, color: Colors.orange[800]), + title: Text( + _getEntityTypeDisplayName(change.entityType), + style: TextStyle(fontSize: 14.sp), + ), + subtitle: Text( + change.error ?? '', + style: TextStyle(fontSize: 11.sp, color: Colors.orange[900]), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + trailing: PopupMenuButton( + icon: Icon(Icons.more_vert, size: 20.sp), + onSelected: (value) { + if (value == 'retry') { + _retryQuarantinedChange(change); + } else if (value == 'details') { + _showChangeDetails(change); + } + }, + itemBuilder: (context) => [ + const PopupMenuItem( + value: 'details', + child: Row( + children: [ + Icon(Icons.info_outline, size: 18), + SizedBox(width: 8), + Text('View details'), + ], + ), + ), + PopupMenuItem( + value: 'retry', + child: Row( + children: [ + const Icon(Icons.refresh, size: 18), + SizedBox(width: 8.w), + Text(LocaleKeys.retry.tr()), + ], + ), + ), + ], + ), + ); + }, + ), + ), + ], + ); + } + Widget _buildFailedChangesSection() { return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -397,28 +570,28 @@ class _SyncHistoryScreenState extends State { onSelected: (value) { if (value == 'retry') { _retryFailedChange(change); - } else if (value == 'dismiss') { - _dismissFailedChange(change); + } else if (value == 'details') { + _showChangeDetails(change); } }, itemBuilder: (context) => [ - PopupMenuItem( - value: 'retry', + const PopupMenuItem( + value: 'details', child: Row( children: [ - const Icon(Icons.refresh, size: 18), - SizedBox(width: 8.w), - Text(LocaleKeys.retry.tr()), + Icon(Icons.info_outline, size: 18), + SizedBox(width: 8), + Text('View details'), ], ), ), PopupMenuItem( - value: 'dismiss', + value: 'retry', child: Row( children: [ - const Icon(Icons.close, size: 18), + const Icon(Icons.refresh, size: 18), SizedBox(width: 8.w), - Text(LocaleKeys.dismiss.tr()), + Text(LocaleKeys.retry.tr()), ], ), ), diff --git a/lib/presentation/transactions/add_transaction_form_compact_layout.dart b/lib/presentation/transactions/add_transaction_form_compact_layout.dart index 8d52c16d..5f0e544f 100644 --- a/lib/presentation/transactions/add_transaction_form_compact_layout.dart +++ b/lib/presentation/transactions/add_transaction_form_compact_layout.dart @@ -478,11 +478,10 @@ class _AddTransactionFormCompactLayoutState }, onSelected: (value) { setState(() { - debugPrint(value.name); _selectedParty = value; }); }, - // selectedItem: _selectedCategory, + initialValue: _selectedParty, ); }, ), @@ -527,11 +526,10 @@ class _AddTransactionFormCompactLayoutState }, onSelected: (value) { setState(() { - debugPrint(value.name); _selectedCategory = value; }); }, - // selectedItem: _selectedCategory, + initialValue: _selectedCategory, ); }, ), diff --git a/lib/presentation/transactions/transaction_intent_selector.dart b/lib/presentation/transactions/transaction_intent_selector.dart index 5bf08954..fd9ca55b 100644 --- a/lib/presentation/transactions/transaction_intent_selector.dart +++ b/lib/presentation/transactions/transaction_intent_selector.dart @@ -2,11 +2,12 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:trakli/gen/translations/codegen_loader.g.dart'; +import 'package:trakli/presentation/utils/custom_dropdown_search.dart'; import 'package:trakli/presentation/utils/enums.dart'; -/// Contextual intent picker shown in the add/edit transaction form. Offers the -/// intents valid for the given [type] (regular first), mirroring the web -/// `TransactionForm` intent pills. +/// Contextual intent picker shown in the add/edit transaction form. Offers +/// the intents valid for the given [type] (regular first) in the same +/// dropdown used for parties, without the search box. class TransactionIntentSelector extends StatelessWidget { final TransactionType type; final TransactionIntent selected; @@ -24,6 +25,7 @@ class TransactionIntentSelector extends StatelessWidget { @override Widget build(BuildContext context) { final options = TransactionIntent.optionsFor(type); + final value = options.contains(selected) ? selected : options.first; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -34,30 +36,17 @@ class TransactionIntentSelector extends StatelessWidget { ), ), SizedBox(height: 8.h), - Wrap( - spacing: 8.w, - runSpacing: 8.h, - children: options.map((intent) { - final isSelected = intent == selected; - return ChoiceChip( - label: Text(intent.label.tr()), - selected: isSelected, - showCheckmark: false, - onSelected: (_) => onChanged(intent), - selectedColor: accentColor.withValues(alpha: 0.15), - labelStyle: TextStyle( - fontSize: 13.sp, - color: isSelected - ? accentColor - : Theme.of(context).textTheme.bodyMedium?.color, - fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400, - ), - side: BorderSide( - color: - isSelected ? accentColor : Theme.of(context).dividerColor, - ), - ); - }).toList(), + CustomDropdownSearch( + label: "", + accentColor: accentColor, + selectedItem: value, + showSearchBox: false, + items: (filter, infiniteScrollProps) => options, + itemAsString: (intent) => intent.label.tr(), + onChanged: (intent) { + if (intent != null) onChanged(intent); + }, + compareFn: (i1, i2) => i1 == i2, ), ], ); diff --git a/lib/presentation/utils/custom_dropdown_search.dart b/lib/presentation/utils/custom_dropdown_search.dart index 62f81a2d..7abb13df 100644 --- a/lib/presentation/utils/custom_dropdown_search.dart +++ b/lib/presentation/utils/custom_dropdown_search.dart @@ -17,6 +17,7 @@ class CustomDropdownSearch extends StatelessWidget { final Color accentColor; final T? selectedItem; final bool showSearchBox; + final bool showClearButton; const CustomDropdownSearch({ super.key, @@ -30,6 +31,7 @@ class CustomDropdownSearch extends StatelessWidget { this.validator, this.selectedItem, this.showSearchBox = true, + this.showClearButton = false, }); @override @@ -43,6 +45,9 @@ class CustomDropdownSearch extends StatelessWidget { validator: validator, onChanged: onChanged, selectedItem: selectedItem, + suffixProps: DropdownSuffixProps( + clearButtonProps: ClearButtonProps(isVisible: showClearButton), + ), popupProps: PopupProps.menu( searchFieldProps: TextFieldProps( decoration: InputDecoration( @@ -73,17 +78,21 @@ class CustomDropdownSearch extends StatelessWidget { ), decoratorProps: DropDownDecoratorProps( decoration: InputDecoration( - contentPadding: EdgeInsets.only(top: 16.h), - prefixIcon: Padding( - padding: const EdgeInsets.all(12), - child: SvgPicture.asset( - Assets.images.searchSpecial, - colorFilter: ColorFilter.mode( - accentColor, - BlendMode.srcIn, - ), - ), - ), + contentPadding: showSearchBox + ? EdgeInsets.only(top: 16.h) + : EdgeInsets.only(top: 16.h, left: 12.w), + prefixIcon: !showSearchBox + ? null + : Padding( + padding: const EdgeInsets.all(12), + child: SvgPicture.asset( + Assets.images.searchSpecial, + colorFilter: ColorFilter.mode( + accentColor, + BlendMode.srcIn, + ), + ), + ), suffixIcon: Padding( padding: const EdgeInsets.all(12), child: SvgPicture.asset( diff --git a/lib/presentation/utils/forms/add_transaction_form.dart b/lib/presentation/utils/forms/add_transaction_form.dart index 114e80a6..a2192d32 100644 --- a/lib/presentation/utils/forms/add_transaction_form.dart +++ b/lib/presentation/utils/forms/add_transaction_form.dart @@ -153,6 +153,14 @@ class _AddTransactionFormState extends State // Set currency from wallet currency = selectedWallet!.currency; } + + if (widget.transactionCompleteEntity?.party != null) { + selectedParty = widget.transactionCompleteEntity!.party; + } + + if (widget.transactionCompleteEntity!.categories.isNotEmpty) { + selectedCategory = widget.transactionCompleteEntity!.categories.first; + } } else { date = DateTime.now(); dateController.text = dateFormat.format(date); @@ -176,10 +184,6 @@ class _AddTransactionFormState extends State currency = defaultWallet.currency; } } - - if (widget.transactionCompleteEntity?.party != null) { - selectedParty = widget.transactionCompleteEntity!.party; - } } if (widget.transactionCompleteEntity != null) { WidgetsBinding.instance.addPostFrameCallback((_) { @@ -568,7 +572,7 @@ class _AddTransactionFormState extends State child: BlocBuilder( builder: (context, state) { //Category by transaction type - final searchCategories = state.categories + final typeCategories = state.categories .where((element) => element.type == widget.transactionType) .toList(); @@ -578,11 +582,7 @@ class _AddTransactionFormState extends State accentColor: widget.accentColor, selectedItem: selectedCategory, items: (filter, infiniteScrollProps) { - return searchCategories - .where((CategoryEntity el) => el.name - .toLowerCase() - .contains(filter.toLowerCase())) - .toList(); + return typeCategories; }, itemAsString: (item) => item.name, onChanged: (value) { @@ -591,11 +591,9 @@ class _AddTransactionFormState extends State }); }, compareFn: (i1, i2) => i1.clientId == i2.clientId, - filterFn: (el, filter) { - return el.name.toLowerCase().contains( - filter.toLowerCase(), - ); - }, + filterFn: (el, filter) => el.name + .toLowerCase() + .contains(filter.toLowerCase()), validator: (value) => value == null ? LocaleKeys.categoryIsRequired.tr() : null, diff --git a/pubspec.lock b/pubspec.lock index e7fd4ced..12ed0e58 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -429,8 +429,8 @@ packages: dependency: "direct main" description: path: "packages/drift_sync_core" - ref: "drift_sync_core-v0.2.1" - resolved-ref: "9ae0f78ad61c3ef9a9e6ff4bce26222fa6324d7e" + ref: "drift_sync_core-v0.3.0" + resolved-ref: "0aa018599a40da32e07a1f7a6fa4e92db94ac525" url: "https://github.com/whilesmartflutter/drift_sync.git" source: git version: "0.2.0" @@ -2126,7 +2126,7 @@ packages: source: hosted version: "1.0.1" web_socket_channel: - dependency: transitive + dependency: "direct main" description: name: web_socket_channel sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 diff --git a/pubspec.yaml b/pubspec.yaml index 4cef9e39..8cfda4c2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -55,6 +55,7 @@ dependencies: sqflite: ^2.4.2 path: ^1.9.1 dio: ^5.8.0+1 + web_socket_channel: ^3.0.3 http: ^1.3.0 json_annotation: ^4.9.0 drift_db_viewer: ^2.1.0 @@ -64,7 +65,7 @@ dependencies: drift_sync_core: git: url: https://github.com/whilesmartflutter/drift_sync.git - ref: drift_sync_core-v0.2.1 + ref: drift_sync_core-v0.3.0 path: packages/drift_sync_core drift_sync_flutter: git: diff --git a/test/drift/default/generated/schema.dart b/test/drift/default/generated/schema.dart index 87de9194..746206e4 100644 --- a/test/drift/default/generated/schema.dart +++ b/test/drift/default/generated/schema.dart @@ -10,6 +10,7 @@ import 'schema_v4.dart' as v4; import 'schema_v5.dart' as v5; import 'schema_v6.dart' as v6; import 'schema_v7.dart' as v7; +import 'schema_v8.dart' as v8; class GeneratedHelper implements SchemaInstantiationHelper { @override @@ -29,10 +30,12 @@ class GeneratedHelper implements SchemaInstantiationHelper { return v6.DatabaseAtV6(db); case 7: return v7.DatabaseAtV7(db); + case 8: + return v8.DatabaseAtV8(db); default: throw MissingSchemaException(version, versions); } } - static const versions = const [1, 2, 3, 4, 5, 6, 7]; + static const versions = const [1, 2, 3, 4, 5, 6, 7, 8]; } diff --git a/test/drift/default/generated/schema_v8.dart b/test/drift/default/generated/schema_v8.dart new file mode 100644 index 00000000..6654d23c --- /dev/null +++ b/test/drift/default/generated/schema_v8.dart @@ -0,0 +1,9954 @@ +// dart format width=80 +// GENERATED CODE, DO NOT EDIT BY HAND. +// ignore_for_file: type=lint +import 'package:drift/drift.dart'; + +class Wallets extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Wallets(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\'')); + late final GeneratedColumn rev = GeneratedColumn( + 'rev', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'1\'')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn lastSyncedAt = GeneratedColumn( + 'last_synced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn balance = GeneratedColumn( + 'balance', aliasedName, false, + type: DriftSqlType.double, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0.0')); + late final GeneratedColumn currency = GeneratedColumn( + 'currency', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn description = GeneratedColumn( + 'description', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn stats = GeneratedColumn( + 'stats', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn icon = GeneratedColumn( + 'icon', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + @override + List get $columns => [ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + name, + type, + balance, + currency, + description, + stats, + icon + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'wallets'; + @override + Set get $primaryKey => {clientId}; + @override + WalletsData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return WalletsData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id']), + userId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}user_id']), + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + rev: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}rev']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + deletedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}deleted_at']), + lastSyncedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_synced_at']), + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + balance: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}balance'])!, + currency: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}currency'])!, + description: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}description']), + stats: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}stats']), + icon: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}icon']), + ); + } + + @override + Wallets createAlias(String alias) { + return Wallets(attachedDatabase, alias); + } +} + +class WalletsData extends DataClass implements Insertable { + final int? id; + final int? userId; + final String clientId; + final String? rev; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final DateTime? lastSyncedAt; + final String name; + final String type; + final double balance; + final String currency; + final String? description; + final String? stats; + final String? icon; + const WalletsData( + {this.id, + this.userId, + required this.clientId, + this.rev, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + this.lastSyncedAt, + required this.name, + required this.type, + required this.balance, + required this.currency, + this.description, + this.stats, + this.icon}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + map['client_id'] = Variable(clientId); + if (!nullToAbsent || rev != null) { + map['rev'] = Variable(rev); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || lastSyncedAt != null) { + map['last_synced_at'] = Variable(lastSyncedAt); + } + map['name'] = Variable(name); + map['type'] = Variable(type); + map['balance'] = Variable(balance); + map['currency'] = Variable(currency); + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + if (!nullToAbsent || stats != null) { + map['stats'] = Variable(stats); + } + if (!nullToAbsent || icon != null) { + map['icon'] = Variable(icon); + } + return map; + } + + WalletsCompanion toCompanion(bool nullToAbsent) { + return WalletsCompanion( + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + userId: + userId == null && nullToAbsent ? const Value.absent() : Value(userId), + clientId: Value(clientId), + rev: rev == null && nullToAbsent ? const Value.absent() : Value(rev), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: deletedAt == null && nullToAbsent + ? const Value.absent() + : Value(deletedAt), + lastSyncedAt: lastSyncedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastSyncedAt), + name: Value(name), + type: Value(type), + balance: Value(balance), + currency: Value(currency), + description: description == null && nullToAbsent + ? const Value.absent() + : Value(description), + stats: + stats == null && nullToAbsent ? const Value.absent() : Value(stats), + icon: icon == null && nullToAbsent ? const Value.absent() : Value(icon), + ); + } + + factory WalletsData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return WalletsData( + id: serializer.fromJson(json['id']), + userId: serializer.fromJson(json['userId']), + clientId: serializer.fromJson(json['clientId']), + rev: serializer.fromJson(json['rev']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + lastSyncedAt: serializer.fromJson(json['lastSyncedAt']), + name: serializer.fromJson(json['name']), + type: serializer.fromJson(json['type']), + balance: serializer.fromJson(json['balance']), + currency: serializer.fromJson(json['currency']), + description: serializer.fromJson(json['description']), + stats: serializer.fromJson(json['stats']), + icon: serializer.fromJson(json['icon']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'userId': serializer.toJson(userId), + 'clientId': serializer.toJson(clientId), + 'rev': serializer.toJson(rev), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'lastSyncedAt': serializer.toJson(lastSyncedAt), + 'name': serializer.toJson(name), + 'type': serializer.toJson(type), + 'balance': serializer.toJson(balance), + 'currency': serializer.toJson(currency), + 'description': serializer.toJson(description), + 'stats': serializer.toJson(stats), + 'icon': serializer.toJson(icon), + }; + } + + WalletsData copyWith( + {Value id = const Value.absent(), + Value userId = const Value.absent(), + String? clientId, + Value rev = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + Value lastSyncedAt = const Value.absent(), + String? name, + String? type, + double? balance, + String? currency, + Value description = const Value.absent(), + Value stats = const Value.absent(), + Value icon = const Value.absent()}) => + WalletsData( + id: id.present ? id.value : this.id, + userId: userId.present ? userId.value : this.userId, + clientId: clientId ?? this.clientId, + rev: rev.present ? rev.value : this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + lastSyncedAt: + lastSyncedAt.present ? lastSyncedAt.value : this.lastSyncedAt, + name: name ?? this.name, + type: type ?? this.type, + balance: balance ?? this.balance, + currency: currency ?? this.currency, + description: description.present ? description.value : this.description, + stats: stats.present ? stats.value : this.stats, + icon: icon.present ? icon.value : this.icon, + ); + WalletsData copyWithCompanion(WalletsCompanion data) { + return WalletsData( + id: data.id.present ? data.id.value : this.id, + userId: data.userId.present ? data.userId.value : this.userId, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + rev: data.rev.present ? data.rev.value : this.rev, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + lastSyncedAt: data.lastSyncedAt.present + ? data.lastSyncedAt.value + : this.lastSyncedAt, + name: data.name.present ? data.name.value : this.name, + type: data.type.present ? data.type.value : this.type, + balance: data.balance.present ? data.balance.value : this.balance, + currency: data.currency.present ? data.currency.value : this.currency, + description: + data.description.present ? data.description.value : this.description, + stats: data.stats.present ? data.stats.value : this.stats, + icon: data.icon.present ? data.icon.value : this.icon, + ); + } + + @override + String toString() { + return (StringBuffer('WalletsData(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('balance: $balance, ') + ..write('currency: $currency, ') + ..write('description: $description, ') + ..write('stats: $stats, ') + ..write('icon: $icon') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + name, + type, + balance, + currency, + description, + stats, + icon); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is WalletsData && + other.id == this.id && + other.userId == this.userId && + other.clientId == this.clientId && + other.rev == this.rev && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.lastSyncedAt == this.lastSyncedAt && + other.name == this.name && + other.type == this.type && + other.balance == this.balance && + other.currency == this.currency && + other.description == this.description && + other.stats == this.stats && + other.icon == this.icon); +} + +class WalletsCompanion extends UpdateCompanion { + final Value id; + final Value userId; + final Value clientId; + final Value rev; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value lastSyncedAt; + final Value name; + final Value type; + final Value balance; + final Value currency; + final Value description; + final Value stats; + final Value icon; + final Value rowid; + const WalletsCompanion({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + this.name = const Value.absent(), + this.type = const Value.absent(), + this.balance = const Value.absent(), + this.currency = const Value.absent(), + this.description = const Value.absent(), + this.stats = const Value.absent(), + this.icon = const Value.absent(), + this.rowid = const Value.absent(), + }); + WalletsCompanion.insert({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + required String name, + required String type, + this.balance = const Value.absent(), + required String currency, + this.description = const Value.absent(), + this.stats = const Value.absent(), + this.icon = const Value.absent(), + this.rowid = const Value.absent(), + }) : name = Value(name), + type = Value(type), + currency = Value(currency); + static Insertable custom({ + Expression? id, + Expression? userId, + Expression? clientId, + Expression? rev, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? lastSyncedAt, + Expression? name, + Expression? type, + Expression? balance, + Expression? currency, + Expression? description, + Expression? stats, + Expression? icon, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (userId != null) 'user_id': userId, + if (clientId != null) 'client_id': clientId, + if (rev != null) 'rev': rev, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (lastSyncedAt != null) 'last_synced_at': lastSyncedAt, + if (name != null) 'name': name, + if (type != null) 'type': type, + if (balance != null) 'balance': balance, + if (currency != null) 'currency': currency, + if (description != null) 'description': description, + if (stats != null) 'stats': stats, + if (icon != null) 'icon': icon, + if (rowid != null) 'rowid': rowid, + }); + } + + WalletsCompanion copyWith( + {Value? id, + Value? userId, + Value? clientId, + Value? rev, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? lastSyncedAt, + Value? name, + Value? type, + Value? balance, + Value? currency, + Value? description, + Value? stats, + Value? icon, + Value? rowid}) { + return WalletsCompanion( + id: id ?? this.id, + userId: userId ?? this.userId, + clientId: clientId ?? this.clientId, + rev: rev ?? this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt, + name: name ?? this.name, + type: type ?? this.type, + balance: balance ?? this.balance, + currency: currency ?? this.currency, + description: description ?? this.description, + stats: stats ?? this.stats, + icon: icon ?? this.icon, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (rev.present) { + map['rev'] = Variable(rev.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (lastSyncedAt.present) { + map['last_synced_at'] = Variable(lastSyncedAt.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (balance.present) { + map['balance'] = Variable(balance.value); + } + if (currency.present) { + map['currency'] = Variable(currency.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (stats.present) { + map['stats'] = Variable(stats.value); + } + if (icon.present) { + map['icon'] = Variable(icon.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('WalletsCompanion(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('balance: $balance, ') + ..write('currency: $currency, ') + ..write('description: $description, ') + ..write('stats: $stats, ') + ..write('icon: $icon, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Parties extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Parties(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\'')); + late final GeneratedColumn rev = GeneratedColumn( + 'rev', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'1\'')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn lastSyncedAt = GeneratedColumn( + 'last_synced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn description = GeneratedColumn( + 'description', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn icon = GeneratedColumn( + 'icon', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + @override + List get $columns => [ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + name, + description, + icon, + type + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'parties'; + @override + Set get $primaryKey => {clientId}; + @override + PartiesData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PartiesData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id']), + userId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}user_id']), + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + rev: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}rev']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + deletedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}deleted_at']), + lastSyncedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_synced_at']), + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + description: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}description']), + icon: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}icon']), + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type']), + ); + } + + @override + Parties createAlias(String alias) { + return Parties(attachedDatabase, alias); + } +} + +class PartiesData extends DataClass implements Insertable { + final int? id; + final int? userId; + final String clientId; + final String? rev; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final DateTime? lastSyncedAt; + final String name; + final String? description; + final String? icon; + final String? type; + const PartiesData( + {this.id, + this.userId, + required this.clientId, + this.rev, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + this.lastSyncedAt, + required this.name, + this.description, + this.icon, + this.type}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + map['client_id'] = Variable(clientId); + if (!nullToAbsent || rev != null) { + map['rev'] = Variable(rev); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || lastSyncedAt != null) { + map['last_synced_at'] = Variable(lastSyncedAt); + } + map['name'] = Variable(name); + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + if (!nullToAbsent || icon != null) { + map['icon'] = Variable(icon); + } + if (!nullToAbsent || type != null) { + map['type'] = Variable(type); + } + return map; + } + + PartiesCompanion toCompanion(bool nullToAbsent) { + return PartiesCompanion( + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + userId: + userId == null && nullToAbsent ? const Value.absent() : Value(userId), + clientId: Value(clientId), + rev: rev == null && nullToAbsent ? const Value.absent() : Value(rev), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: deletedAt == null && nullToAbsent + ? const Value.absent() + : Value(deletedAt), + lastSyncedAt: lastSyncedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastSyncedAt), + name: Value(name), + description: description == null && nullToAbsent + ? const Value.absent() + : Value(description), + icon: icon == null && nullToAbsent ? const Value.absent() : Value(icon), + type: type == null && nullToAbsent ? const Value.absent() : Value(type), + ); + } + + factory PartiesData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PartiesData( + id: serializer.fromJson(json['id']), + userId: serializer.fromJson(json['userId']), + clientId: serializer.fromJson(json['clientId']), + rev: serializer.fromJson(json['rev']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + lastSyncedAt: serializer.fromJson(json['lastSyncedAt']), + name: serializer.fromJson(json['name']), + description: serializer.fromJson(json['description']), + icon: serializer.fromJson(json['icon']), + type: serializer.fromJson(json['type']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'userId': serializer.toJson(userId), + 'clientId': serializer.toJson(clientId), + 'rev': serializer.toJson(rev), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'lastSyncedAt': serializer.toJson(lastSyncedAt), + 'name': serializer.toJson(name), + 'description': serializer.toJson(description), + 'icon': serializer.toJson(icon), + 'type': serializer.toJson(type), + }; + } + + PartiesData copyWith( + {Value id = const Value.absent(), + Value userId = const Value.absent(), + String? clientId, + Value rev = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + Value lastSyncedAt = const Value.absent(), + String? name, + Value description = const Value.absent(), + Value icon = const Value.absent(), + Value type = const Value.absent()}) => + PartiesData( + id: id.present ? id.value : this.id, + userId: userId.present ? userId.value : this.userId, + clientId: clientId ?? this.clientId, + rev: rev.present ? rev.value : this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + lastSyncedAt: + lastSyncedAt.present ? lastSyncedAt.value : this.lastSyncedAt, + name: name ?? this.name, + description: description.present ? description.value : this.description, + icon: icon.present ? icon.value : this.icon, + type: type.present ? type.value : this.type, + ); + PartiesData copyWithCompanion(PartiesCompanion data) { + return PartiesData( + id: data.id.present ? data.id.value : this.id, + userId: data.userId.present ? data.userId.value : this.userId, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + rev: data.rev.present ? data.rev.value : this.rev, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + lastSyncedAt: data.lastSyncedAt.present + ? data.lastSyncedAt.value + : this.lastSyncedAt, + name: data.name.present ? data.name.value : this.name, + description: + data.description.present ? data.description.value : this.description, + icon: data.icon.present ? data.icon.value : this.icon, + type: data.type.present ? data.type.value : this.type, + ); + } + + @override + String toString() { + return (StringBuffer('PartiesData(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('icon: $icon, ') + ..write('type: $type') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, userId, clientId, rev, createdAt, + updatedAt, deletedAt, lastSyncedAt, name, description, icon, type); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PartiesData && + other.id == this.id && + other.userId == this.userId && + other.clientId == this.clientId && + other.rev == this.rev && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.lastSyncedAt == this.lastSyncedAt && + other.name == this.name && + other.description == this.description && + other.icon == this.icon && + other.type == this.type); +} + +class PartiesCompanion extends UpdateCompanion { + final Value id; + final Value userId; + final Value clientId; + final Value rev; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value lastSyncedAt; + final Value name; + final Value description; + final Value icon; + final Value type; + final Value rowid; + const PartiesCompanion({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + this.name = const Value.absent(), + this.description = const Value.absent(), + this.icon = const Value.absent(), + this.type = const Value.absent(), + this.rowid = const Value.absent(), + }); + PartiesCompanion.insert({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + required String name, + this.description = const Value.absent(), + this.icon = const Value.absent(), + this.type = const Value.absent(), + this.rowid = const Value.absent(), + }) : name = Value(name); + static Insertable custom({ + Expression? id, + Expression? userId, + Expression? clientId, + Expression? rev, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? lastSyncedAt, + Expression? name, + Expression? description, + Expression? icon, + Expression? type, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (userId != null) 'user_id': userId, + if (clientId != null) 'client_id': clientId, + if (rev != null) 'rev': rev, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (lastSyncedAt != null) 'last_synced_at': lastSyncedAt, + if (name != null) 'name': name, + if (description != null) 'description': description, + if (icon != null) 'icon': icon, + if (type != null) 'type': type, + if (rowid != null) 'rowid': rowid, + }); + } + + PartiesCompanion copyWith( + {Value? id, + Value? userId, + Value? clientId, + Value? rev, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? lastSyncedAt, + Value? name, + Value? description, + Value? icon, + Value? type, + Value? rowid}) { + return PartiesCompanion( + id: id ?? this.id, + userId: userId ?? this.userId, + clientId: clientId ?? this.clientId, + rev: rev ?? this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt, + name: name ?? this.name, + description: description ?? this.description, + icon: icon ?? this.icon, + type: type ?? this.type, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (rev.present) { + map['rev'] = Variable(rev.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (lastSyncedAt.present) { + map['last_synced_at'] = Variable(lastSyncedAt.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (icon.present) { + map['icon'] = Variable(icon.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PartiesCompanion(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('icon: $icon, ') + ..write('type: $type, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Groups extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Groups(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\'')); + late final GeneratedColumn rev = GeneratedColumn( + 'rev', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'1\'')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn lastSyncedAt = GeneratedColumn( + 'last_synced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn description = GeneratedColumn( + 'description', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn icon = GeneratedColumn( + 'icon', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + @override + List get $columns => [ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + name, + description, + icon + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'groups'; + @override + Set get $primaryKey => {clientId}; + @override + GroupsData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return GroupsData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id']), + userId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}user_id']), + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + rev: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}rev']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + deletedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}deleted_at']), + lastSyncedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_synced_at']), + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + description: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}description']), + icon: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}icon']), + ); + } + + @override + Groups createAlias(String alias) { + return Groups(attachedDatabase, alias); + } +} + +class GroupsData extends DataClass implements Insertable { + final int? id; + final int? userId; + final String clientId; + final String? rev; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final DateTime? lastSyncedAt; + final String name; + final String? description; + final String? icon; + const GroupsData( + {this.id, + this.userId, + required this.clientId, + this.rev, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + this.lastSyncedAt, + required this.name, + this.description, + this.icon}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + map['client_id'] = Variable(clientId); + if (!nullToAbsent || rev != null) { + map['rev'] = Variable(rev); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || lastSyncedAt != null) { + map['last_synced_at'] = Variable(lastSyncedAt); + } + map['name'] = Variable(name); + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + if (!nullToAbsent || icon != null) { + map['icon'] = Variable(icon); + } + return map; + } + + GroupsCompanion toCompanion(bool nullToAbsent) { + return GroupsCompanion( + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + userId: + userId == null && nullToAbsent ? const Value.absent() : Value(userId), + clientId: Value(clientId), + rev: rev == null && nullToAbsent ? const Value.absent() : Value(rev), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: deletedAt == null && nullToAbsent + ? const Value.absent() + : Value(deletedAt), + lastSyncedAt: lastSyncedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastSyncedAt), + name: Value(name), + description: description == null && nullToAbsent + ? const Value.absent() + : Value(description), + icon: icon == null && nullToAbsent ? const Value.absent() : Value(icon), + ); + } + + factory GroupsData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return GroupsData( + id: serializer.fromJson(json['id']), + userId: serializer.fromJson(json['userId']), + clientId: serializer.fromJson(json['clientId']), + rev: serializer.fromJson(json['rev']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + lastSyncedAt: serializer.fromJson(json['lastSyncedAt']), + name: serializer.fromJson(json['name']), + description: serializer.fromJson(json['description']), + icon: serializer.fromJson(json['icon']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'userId': serializer.toJson(userId), + 'clientId': serializer.toJson(clientId), + 'rev': serializer.toJson(rev), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'lastSyncedAt': serializer.toJson(lastSyncedAt), + 'name': serializer.toJson(name), + 'description': serializer.toJson(description), + 'icon': serializer.toJson(icon), + }; + } + + GroupsData copyWith( + {Value id = const Value.absent(), + Value userId = const Value.absent(), + String? clientId, + Value rev = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + Value lastSyncedAt = const Value.absent(), + String? name, + Value description = const Value.absent(), + Value icon = const Value.absent()}) => + GroupsData( + id: id.present ? id.value : this.id, + userId: userId.present ? userId.value : this.userId, + clientId: clientId ?? this.clientId, + rev: rev.present ? rev.value : this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + lastSyncedAt: + lastSyncedAt.present ? lastSyncedAt.value : this.lastSyncedAt, + name: name ?? this.name, + description: description.present ? description.value : this.description, + icon: icon.present ? icon.value : this.icon, + ); + GroupsData copyWithCompanion(GroupsCompanion data) { + return GroupsData( + id: data.id.present ? data.id.value : this.id, + userId: data.userId.present ? data.userId.value : this.userId, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + rev: data.rev.present ? data.rev.value : this.rev, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + lastSyncedAt: data.lastSyncedAt.present + ? data.lastSyncedAt.value + : this.lastSyncedAt, + name: data.name.present ? data.name.value : this.name, + description: + data.description.present ? data.description.value : this.description, + icon: data.icon.present ? data.icon.value : this.icon, + ); + } + + @override + String toString() { + return (StringBuffer('GroupsData(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('icon: $icon') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, userId, clientId, rev, createdAt, + updatedAt, deletedAt, lastSyncedAt, name, description, icon); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is GroupsData && + other.id == this.id && + other.userId == this.userId && + other.clientId == this.clientId && + other.rev == this.rev && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.lastSyncedAt == this.lastSyncedAt && + other.name == this.name && + other.description == this.description && + other.icon == this.icon); +} + +class GroupsCompanion extends UpdateCompanion { + final Value id; + final Value userId; + final Value clientId; + final Value rev; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value lastSyncedAt; + final Value name; + final Value description; + final Value icon; + final Value rowid; + const GroupsCompanion({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + this.name = const Value.absent(), + this.description = const Value.absent(), + this.icon = const Value.absent(), + this.rowid = const Value.absent(), + }); + GroupsCompanion.insert({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + required String name, + this.description = const Value.absent(), + this.icon = const Value.absent(), + this.rowid = const Value.absent(), + }) : name = Value(name); + static Insertable custom({ + Expression? id, + Expression? userId, + Expression? clientId, + Expression? rev, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? lastSyncedAt, + Expression? name, + Expression? description, + Expression? icon, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (userId != null) 'user_id': userId, + if (clientId != null) 'client_id': clientId, + if (rev != null) 'rev': rev, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (lastSyncedAt != null) 'last_synced_at': lastSyncedAt, + if (name != null) 'name': name, + if (description != null) 'description': description, + if (icon != null) 'icon': icon, + if (rowid != null) 'rowid': rowid, + }); + } + + GroupsCompanion copyWith( + {Value? id, + Value? userId, + Value? clientId, + Value? rev, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? lastSyncedAt, + Value? name, + Value? description, + Value? icon, + Value? rowid}) { + return GroupsCompanion( + id: id ?? this.id, + userId: userId ?? this.userId, + clientId: clientId ?? this.clientId, + rev: rev ?? this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt, + name: name ?? this.name, + description: description ?? this.description, + icon: icon ?? this.icon, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (rev.present) { + map['rev'] = Variable(rev.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (lastSyncedAt.present) { + map['last_synced_at'] = Variable(lastSyncedAt.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (icon.present) { + map['icon'] = Variable(icon.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('GroupsCompanion(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('icon: $icon, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Transactions extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Transactions(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\'')); + late final GeneratedColumn rev = GeneratedColumn( + 'rev', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'1\'')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn lastSyncedAt = GeneratedColumn( + 'last_synced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn amount = GeneratedColumn( + 'amount', aliasedName, false, + type: DriftSqlType.double, requiredDuringInsert: true); + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn intent = GeneratedColumn( + 'intent', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'regular\'')); + late final GeneratedColumn description = GeneratedColumn( + 'description', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn datetime = GeneratedColumn( + 'datetime', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn partyId = GeneratedColumn( + 'party_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn walletId = GeneratedColumn( + 'wallet_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn groupId = GeneratedColumn( + 'group_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn walletClientId = GeneratedColumn( + 'wallet_client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES wallets (client_id)')); + late final GeneratedColumn partyClientId = GeneratedColumn( + 'party_client_id', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES parties (client_id)')); + late final GeneratedColumn groupClientId = GeneratedColumn( + 'group_client_id', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES "groups" (client_id)')); + late final GeneratedColumn transferId = GeneratedColumn( + 'transfer_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn transferClientId = GeneratedColumn( + 'transfer_client_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn isRefund = GeneratedColumn( + 'is_refund', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("is_refund" IN (0, 1))'), + defaultValue: const CustomExpression('0')); + late final GeneratedColumn refundOfTransactionId = GeneratedColumn( + 'refund_of_transaction_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn recurrencePeriod = GeneratedColumn( + 'recurrence_period', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn recurrenceInterval = GeneratedColumn( + 'recurrence_interval', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn recurrenceEndsAt = + GeneratedColumn('recurrence_ends_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn recurrenceNextScheduledAt = + GeneratedColumn( + 'recurrence_next_scheduled_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + amount, + type, + intent, + description, + datetime, + partyId, + walletId, + groupId, + walletClientId, + partyClientId, + groupClientId, + transferId, + transferClientId, + isRefund, + refundOfTransactionId, + recurrencePeriod, + recurrenceInterval, + recurrenceEndsAt, + recurrenceNextScheduledAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'transactions'; + @override + Set get $primaryKey => {clientId}; + @override + TransactionsData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return TransactionsData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id']), + userId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}user_id']), + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + rev: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}rev']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + deletedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}deleted_at']), + lastSyncedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_synced_at']), + amount: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}amount'])!, + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + intent: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}intent'])!, + description: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}description']), + datetime: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}datetime']), + partyId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}party_id']), + walletId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}wallet_id']), + groupId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}group_id']), + walletClientId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}wallet_client_id'])!, + partyClientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}party_client_id']), + groupClientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}group_client_id']), + transferId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}transfer_id']), + transferClientId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}transfer_client_id']), + isRefund: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}is_refund'])!, + refundOfTransactionId: attachedDatabase.typeMapping.read( + DriftSqlType.int, data['${effectivePrefix}refund_of_transaction_id']), + recurrencePeriod: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}recurrence_period']), + recurrenceInterval: attachedDatabase.typeMapping.read( + DriftSqlType.int, data['${effectivePrefix}recurrence_interval']), + recurrenceEndsAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}recurrence_ends_at']), + recurrenceNextScheduledAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}recurrence_next_scheduled_at']), + ); + } + + @override + Transactions createAlias(String alias) { + return Transactions(attachedDatabase, alias); + } +} + +class TransactionsData extends DataClass + implements Insertable { + final int? id; + final int? userId; + final String clientId; + final String? rev; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final DateTime? lastSyncedAt; + final double amount; + final String type; + final String intent; + final String? description; + final DateTime? datetime; + final int? partyId; + final int? walletId; + final int? groupId; + final String walletClientId; + final String? partyClientId; + final String? groupClientId; + final int? transferId; + final String? transferClientId; + final bool isRefund; + final int? refundOfTransactionId; + final String? recurrencePeriod; + final int? recurrenceInterval; + final DateTime? recurrenceEndsAt; + final DateTime? recurrenceNextScheduledAt; + const TransactionsData( + {this.id, + this.userId, + required this.clientId, + this.rev, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + this.lastSyncedAt, + required this.amount, + required this.type, + required this.intent, + this.description, + this.datetime, + this.partyId, + this.walletId, + this.groupId, + required this.walletClientId, + this.partyClientId, + this.groupClientId, + this.transferId, + this.transferClientId, + required this.isRefund, + this.refundOfTransactionId, + this.recurrencePeriod, + this.recurrenceInterval, + this.recurrenceEndsAt, + this.recurrenceNextScheduledAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + map['client_id'] = Variable(clientId); + if (!nullToAbsent || rev != null) { + map['rev'] = Variable(rev); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || lastSyncedAt != null) { + map['last_synced_at'] = Variable(lastSyncedAt); + } + map['amount'] = Variable(amount); + map['type'] = Variable(type); + map['intent'] = Variable(intent); + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + if (!nullToAbsent || datetime != null) { + map['datetime'] = Variable(datetime); + } + if (!nullToAbsent || partyId != null) { + map['party_id'] = Variable(partyId); + } + if (!nullToAbsent || walletId != null) { + map['wallet_id'] = Variable(walletId); + } + if (!nullToAbsent || groupId != null) { + map['group_id'] = Variable(groupId); + } + map['wallet_client_id'] = Variable(walletClientId); + if (!nullToAbsent || partyClientId != null) { + map['party_client_id'] = Variable(partyClientId); + } + if (!nullToAbsent || groupClientId != null) { + map['group_client_id'] = Variable(groupClientId); + } + if (!nullToAbsent || transferId != null) { + map['transfer_id'] = Variable(transferId); + } + if (!nullToAbsent || transferClientId != null) { + map['transfer_client_id'] = Variable(transferClientId); + } + map['is_refund'] = Variable(isRefund); + if (!nullToAbsent || refundOfTransactionId != null) { + map['refund_of_transaction_id'] = Variable(refundOfTransactionId); + } + if (!nullToAbsent || recurrencePeriod != null) { + map['recurrence_period'] = Variable(recurrencePeriod); + } + if (!nullToAbsent || recurrenceInterval != null) { + map['recurrence_interval'] = Variable(recurrenceInterval); + } + if (!nullToAbsent || recurrenceEndsAt != null) { + map['recurrence_ends_at'] = Variable(recurrenceEndsAt); + } + if (!nullToAbsent || recurrenceNextScheduledAt != null) { + map['recurrence_next_scheduled_at'] = + Variable(recurrenceNextScheduledAt); + } + return map; + } + + TransactionsCompanion toCompanion(bool nullToAbsent) { + return TransactionsCompanion( + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + userId: + userId == null && nullToAbsent ? const Value.absent() : Value(userId), + clientId: Value(clientId), + rev: rev == null && nullToAbsent ? const Value.absent() : Value(rev), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: deletedAt == null && nullToAbsent + ? const Value.absent() + : Value(deletedAt), + lastSyncedAt: lastSyncedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastSyncedAt), + amount: Value(amount), + type: Value(type), + intent: Value(intent), + description: description == null && nullToAbsent + ? const Value.absent() + : Value(description), + datetime: datetime == null && nullToAbsent + ? const Value.absent() + : Value(datetime), + partyId: partyId == null && nullToAbsent + ? const Value.absent() + : Value(partyId), + walletId: walletId == null && nullToAbsent + ? const Value.absent() + : Value(walletId), + groupId: groupId == null && nullToAbsent + ? const Value.absent() + : Value(groupId), + walletClientId: Value(walletClientId), + partyClientId: partyClientId == null && nullToAbsent + ? const Value.absent() + : Value(partyClientId), + groupClientId: groupClientId == null && nullToAbsent + ? const Value.absent() + : Value(groupClientId), + transferId: transferId == null && nullToAbsent + ? const Value.absent() + : Value(transferId), + transferClientId: transferClientId == null && nullToAbsent + ? const Value.absent() + : Value(transferClientId), + isRefund: Value(isRefund), + refundOfTransactionId: refundOfTransactionId == null && nullToAbsent + ? const Value.absent() + : Value(refundOfTransactionId), + recurrencePeriod: recurrencePeriod == null && nullToAbsent + ? const Value.absent() + : Value(recurrencePeriod), + recurrenceInterval: recurrenceInterval == null && nullToAbsent + ? const Value.absent() + : Value(recurrenceInterval), + recurrenceEndsAt: recurrenceEndsAt == null && nullToAbsent + ? const Value.absent() + : Value(recurrenceEndsAt), + recurrenceNextScheduledAt: + recurrenceNextScheduledAt == null && nullToAbsent + ? const Value.absent() + : Value(recurrenceNextScheduledAt), + ); + } + + factory TransactionsData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return TransactionsData( + id: serializer.fromJson(json['id']), + userId: serializer.fromJson(json['userId']), + clientId: serializer.fromJson(json['clientId']), + rev: serializer.fromJson(json['rev']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + lastSyncedAt: serializer.fromJson(json['lastSyncedAt']), + amount: serializer.fromJson(json['amount']), + type: serializer.fromJson(json['type']), + intent: serializer.fromJson(json['intent']), + description: serializer.fromJson(json['description']), + datetime: serializer.fromJson(json['datetime']), + partyId: serializer.fromJson(json['partyId']), + walletId: serializer.fromJson(json['walletId']), + groupId: serializer.fromJson(json['groupId']), + walletClientId: serializer.fromJson(json['walletClientId']), + partyClientId: serializer.fromJson(json['partyClientId']), + groupClientId: serializer.fromJson(json['groupClientId']), + transferId: serializer.fromJson(json['transferId']), + transferClientId: serializer.fromJson(json['transferClientId']), + isRefund: serializer.fromJson(json['isRefund']), + refundOfTransactionId: + serializer.fromJson(json['refundOfTransactionId']), + recurrencePeriod: serializer.fromJson(json['recurrencePeriod']), + recurrenceInterval: serializer.fromJson(json['recurrenceInterval']), + recurrenceEndsAt: + serializer.fromJson(json['recurrenceEndsAt']), + recurrenceNextScheduledAt: + serializer.fromJson(json['recurrenceNextScheduledAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'userId': serializer.toJson(userId), + 'clientId': serializer.toJson(clientId), + 'rev': serializer.toJson(rev), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'lastSyncedAt': serializer.toJson(lastSyncedAt), + 'amount': serializer.toJson(amount), + 'type': serializer.toJson(type), + 'intent': serializer.toJson(intent), + 'description': serializer.toJson(description), + 'datetime': serializer.toJson(datetime), + 'partyId': serializer.toJson(partyId), + 'walletId': serializer.toJson(walletId), + 'groupId': serializer.toJson(groupId), + 'walletClientId': serializer.toJson(walletClientId), + 'partyClientId': serializer.toJson(partyClientId), + 'groupClientId': serializer.toJson(groupClientId), + 'transferId': serializer.toJson(transferId), + 'transferClientId': serializer.toJson(transferClientId), + 'isRefund': serializer.toJson(isRefund), + 'refundOfTransactionId': serializer.toJson(refundOfTransactionId), + 'recurrencePeriod': serializer.toJson(recurrencePeriod), + 'recurrenceInterval': serializer.toJson(recurrenceInterval), + 'recurrenceEndsAt': serializer.toJson(recurrenceEndsAt), + 'recurrenceNextScheduledAt': + serializer.toJson(recurrenceNextScheduledAt), + }; + } + + TransactionsData copyWith( + {Value id = const Value.absent(), + Value userId = const Value.absent(), + String? clientId, + Value rev = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + Value lastSyncedAt = const Value.absent(), + double? amount, + String? type, + String? intent, + Value description = const Value.absent(), + Value datetime = const Value.absent(), + Value partyId = const Value.absent(), + Value walletId = const Value.absent(), + Value groupId = const Value.absent(), + String? walletClientId, + Value partyClientId = const Value.absent(), + Value groupClientId = const Value.absent(), + Value transferId = const Value.absent(), + Value transferClientId = const Value.absent(), + bool? isRefund, + Value refundOfTransactionId = const Value.absent(), + Value recurrencePeriod = const Value.absent(), + Value recurrenceInterval = const Value.absent(), + Value recurrenceEndsAt = const Value.absent(), + Value recurrenceNextScheduledAt = const Value.absent()}) => + TransactionsData( + id: id.present ? id.value : this.id, + userId: userId.present ? userId.value : this.userId, + clientId: clientId ?? this.clientId, + rev: rev.present ? rev.value : this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + lastSyncedAt: + lastSyncedAt.present ? lastSyncedAt.value : this.lastSyncedAt, + amount: amount ?? this.amount, + type: type ?? this.type, + intent: intent ?? this.intent, + description: description.present ? description.value : this.description, + datetime: datetime.present ? datetime.value : this.datetime, + partyId: partyId.present ? partyId.value : this.partyId, + walletId: walletId.present ? walletId.value : this.walletId, + groupId: groupId.present ? groupId.value : this.groupId, + walletClientId: walletClientId ?? this.walletClientId, + partyClientId: + partyClientId.present ? partyClientId.value : this.partyClientId, + groupClientId: + groupClientId.present ? groupClientId.value : this.groupClientId, + transferId: transferId.present ? transferId.value : this.transferId, + transferClientId: transferClientId.present + ? transferClientId.value + : this.transferClientId, + isRefund: isRefund ?? this.isRefund, + refundOfTransactionId: refundOfTransactionId.present + ? refundOfTransactionId.value + : this.refundOfTransactionId, + recurrencePeriod: recurrencePeriod.present + ? recurrencePeriod.value + : this.recurrencePeriod, + recurrenceInterval: recurrenceInterval.present + ? recurrenceInterval.value + : this.recurrenceInterval, + recurrenceEndsAt: recurrenceEndsAt.present + ? recurrenceEndsAt.value + : this.recurrenceEndsAt, + recurrenceNextScheduledAt: recurrenceNextScheduledAt.present + ? recurrenceNextScheduledAt.value + : this.recurrenceNextScheduledAt, + ); + TransactionsData copyWithCompanion(TransactionsCompanion data) { + return TransactionsData( + id: data.id.present ? data.id.value : this.id, + userId: data.userId.present ? data.userId.value : this.userId, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + rev: data.rev.present ? data.rev.value : this.rev, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + lastSyncedAt: data.lastSyncedAt.present + ? data.lastSyncedAt.value + : this.lastSyncedAt, + amount: data.amount.present ? data.amount.value : this.amount, + type: data.type.present ? data.type.value : this.type, + intent: data.intent.present ? data.intent.value : this.intent, + description: + data.description.present ? data.description.value : this.description, + datetime: data.datetime.present ? data.datetime.value : this.datetime, + partyId: data.partyId.present ? data.partyId.value : this.partyId, + walletId: data.walletId.present ? data.walletId.value : this.walletId, + groupId: data.groupId.present ? data.groupId.value : this.groupId, + walletClientId: data.walletClientId.present + ? data.walletClientId.value + : this.walletClientId, + partyClientId: data.partyClientId.present + ? data.partyClientId.value + : this.partyClientId, + groupClientId: data.groupClientId.present + ? data.groupClientId.value + : this.groupClientId, + transferId: + data.transferId.present ? data.transferId.value : this.transferId, + transferClientId: data.transferClientId.present + ? data.transferClientId.value + : this.transferClientId, + isRefund: data.isRefund.present ? data.isRefund.value : this.isRefund, + refundOfTransactionId: data.refundOfTransactionId.present + ? data.refundOfTransactionId.value + : this.refundOfTransactionId, + recurrencePeriod: data.recurrencePeriod.present + ? data.recurrencePeriod.value + : this.recurrencePeriod, + recurrenceInterval: data.recurrenceInterval.present + ? data.recurrenceInterval.value + : this.recurrenceInterval, + recurrenceEndsAt: data.recurrenceEndsAt.present + ? data.recurrenceEndsAt.value + : this.recurrenceEndsAt, + recurrenceNextScheduledAt: data.recurrenceNextScheduledAt.present + ? data.recurrenceNextScheduledAt.value + : this.recurrenceNextScheduledAt, + ); + } + + @override + String toString() { + return (StringBuffer('TransactionsData(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('amount: $amount, ') + ..write('type: $type, ') + ..write('intent: $intent, ') + ..write('description: $description, ') + ..write('datetime: $datetime, ') + ..write('partyId: $partyId, ') + ..write('walletId: $walletId, ') + ..write('groupId: $groupId, ') + ..write('walletClientId: $walletClientId, ') + ..write('partyClientId: $partyClientId, ') + ..write('groupClientId: $groupClientId, ') + ..write('transferId: $transferId, ') + ..write('transferClientId: $transferClientId, ') + ..write('isRefund: $isRefund, ') + ..write('refundOfTransactionId: $refundOfTransactionId, ') + ..write('recurrencePeriod: $recurrencePeriod, ') + ..write('recurrenceInterval: $recurrenceInterval, ') + ..write('recurrenceEndsAt: $recurrenceEndsAt, ') + ..write('recurrenceNextScheduledAt: $recurrenceNextScheduledAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hashAll([ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + amount, + type, + intent, + description, + datetime, + partyId, + walletId, + groupId, + walletClientId, + partyClientId, + groupClientId, + transferId, + transferClientId, + isRefund, + refundOfTransactionId, + recurrencePeriod, + recurrenceInterval, + recurrenceEndsAt, + recurrenceNextScheduledAt + ]); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is TransactionsData && + other.id == this.id && + other.userId == this.userId && + other.clientId == this.clientId && + other.rev == this.rev && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.lastSyncedAt == this.lastSyncedAt && + other.amount == this.amount && + other.type == this.type && + other.intent == this.intent && + other.description == this.description && + other.datetime == this.datetime && + other.partyId == this.partyId && + other.walletId == this.walletId && + other.groupId == this.groupId && + other.walletClientId == this.walletClientId && + other.partyClientId == this.partyClientId && + other.groupClientId == this.groupClientId && + other.transferId == this.transferId && + other.transferClientId == this.transferClientId && + other.isRefund == this.isRefund && + other.refundOfTransactionId == this.refundOfTransactionId && + other.recurrencePeriod == this.recurrencePeriod && + other.recurrenceInterval == this.recurrenceInterval && + other.recurrenceEndsAt == this.recurrenceEndsAt && + other.recurrenceNextScheduledAt == this.recurrenceNextScheduledAt); +} + +class TransactionsCompanion extends UpdateCompanion { + final Value id; + final Value userId; + final Value clientId; + final Value rev; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value lastSyncedAt; + final Value amount; + final Value type; + final Value intent; + final Value description; + final Value datetime; + final Value partyId; + final Value walletId; + final Value groupId; + final Value walletClientId; + final Value partyClientId; + final Value groupClientId; + final Value transferId; + final Value transferClientId; + final Value isRefund; + final Value refundOfTransactionId; + final Value recurrencePeriod; + final Value recurrenceInterval; + final Value recurrenceEndsAt; + final Value recurrenceNextScheduledAt; + final Value rowid; + const TransactionsCompanion({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + this.amount = const Value.absent(), + this.type = const Value.absent(), + this.intent = const Value.absent(), + this.description = const Value.absent(), + this.datetime = const Value.absent(), + this.partyId = const Value.absent(), + this.walletId = const Value.absent(), + this.groupId = const Value.absent(), + this.walletClientId = const Value.absent(), + this.partyClientId = const Value.absent(), + this.groupClientId = const Value.absent(), + this.transferId = const Value.absent(), + this.transferClientId = const Value.absent(), + this.isRefund = const Value.absent(), + this.refundOfTransactionId = const Value.absent(), + this.recurrencePeriod = const Value.absent(), + this.recurrenceInterval = const Value.absent(), + this.recurrenceEndsAt = const Value.absent(), + this.recurrenceNextScheduledAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + TransactionsCompanion.insert({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + required double amount, + required String type, + this.intent = const Value.absent(), + this.description = const Value.absent(), + this.datetime = const Value.absent(), + this.partyId = const Value.absent(), + this.walletId = const Value.absent(), + this.groupId = const Value.absent(), + required String walletClientId, + this.partyClientId = const Value.absent(), + this.groupClientId = const Value.absent(), + this.transferId = const Value.absent(), + this.transferClientId = const Value.absent(), + this.isRefund = const Value.absent(), + this.refundOfTransactionId = const Value.absent(), + this.recurrencePeriod = const Value.absent(), + this.recurrenceInterval = const Value.absent(), + this.recurrenceEndsAt = const Value.absent(), + this.recurrenceNextScheduledAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : amount = Value(amount), + type = Value(type), + walletClientId = Value(walletClientId); + static Insertable custom({ + Expression? id, + Expression? userId, + Expression? clientId, + Expression? rev, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? lastSyncedAt, + Expression? amount, + Expression? type, + Expression? intent, + Expression? description, + Expression? datetime, + Expression? partyId, + Expression? walletId, + Expression? groupId, + Expression? walletClientId, + Expression? partyClientId, + Expression? groupClientId, + Expression? transferId, + Expression? transferClientId, + Expression? isRefund, + Expression? refundOfTransactionId, + Expression? recurrencePeriod, + Expression? recurrenceInterval, + Expression? recurrenceEndsAt, + Expression? recurrenceNextScheduledAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (userId != null) 'user_id': userId, + if (clientId != null) 'client_id': clientId, + if (rev != null) 'rev': rev, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (lastSyncedAt != null) 'last_synced_at': lastSyncedAt, + if (amount != null) 'amount': amount, + if (type != null) 'type': type, + if (intent != null) 'intent': intent, + if (description != null) 'description': description, + if (datetime != null) 'datetime': datetime, + if (partyId != null) 'party_id': partyId, + if (walletId != null) 'wallet_id': walletId, + if (groupId != null) 'group_id': groupId, + if (walletClientId != null) 'wallet_client_id': walletClientId, + if (partyClientId != null) 'party_client_id': partyClientId, + if (groupClientId != null) 'group_client_id': groupClientId, + if (transferId != null) 'transfer_id': transferId, + if (transferClientId != null) 'transfer_client_id': transferClientId, + if (isRefund != null) 'is_refund': isRefund, + if (refundOfTransactionId != null) + 'refund_of_transaction_id': refundOfTransactionId, + if (recurrencePeriod != null) 'recurrence_period': recurrencePeriod, + if (recurrenceInterval != null) 'recurrence_interval': recurrenceInterval, + if (recurrenceEndsAt != null) 'recurrence_ends_at': recurrenceEndsAt, + if (recurrenceNextScheduledAt != null) + 'recurrence_next_scheduled_at': recurrenceNextScheduledAt, + if (rowid != null) 'rowid': rowid, + }); + } + + TransactionsCompanion copyWith( + {Value? id, + Value? userId, + Value? clientId, + Value? rev, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? lastSyncedAt, + Value? amount, + Value? type, + Value? intent, + Value? description, + Value? datetime, + Value? partyId, + Value? walletId, + Value? groupId, + Value? walletClientId, + Value? partyClientId, + Value? groupClientId, + Value? transferId, + Value? transferClientId, + Value? isRefund, + Value? refundOfTransactionId, + Value? recurrencePeriod, + Value? recurrenceInterval, + Value? recurrenceEndsAt, + Value? recurrenceNextScheduledAt, + Value? rowid}) { + return TransactionsCompanion( + id: id ?? this.id, + userId: userId ?? this.userId, + clientId: clientId ?? this.clientId, + rev: rev ?? this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt, + amount: amount ?? this.amount, + type: type ?? this.type, + intent: intent ?? this.intent, + description: description ?? this.description, + datetime: datetime ?? this.datetime, + partyId: partyId ?? this.partyId, + walletId: walletId ?? this.walletId, + groupId: groupId ?? this.groupId, + walletClientId: walletClientId ?? this.walletClientId, + partyClientId: partyClientId ?? this.partyClientId, + groupClientId: groupClientId ?? this.groupClientId, + transferId: transferId ?? this.transferId, + transferClientId: transferClientId ?? this.transferClientId, + isRefund: isRefund ?? this.isRefund, + refundOfTransactionId: + refundOfTransactionId ?? this.refundOfTransactionId, + recurrencePeriod: recurrencePeriod ?? this.recurrencePeriod, + recurrenceInterval: recurrenceInterval ?? this.recurrenceInterval, + recurrenceEndsAt: recurrenceEndsAt ?? this.recurrenceEndsAt, + recurrenceNextScheduledAt: + recurrenceNextScheduledAt ?? this.recurrenceNextScheduledAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (rev.present) { + map['rev'] = Variable(rev.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (lastSyncedAt.present) { + map['last_synced_at'] = Variable(lastSyncedAt.value); + } + if (amount.present) { + map['amount'] = Variable(amount.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (intent.present) { + map['intent'] = Variable(intent.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (datetime.present) { + map['datetime'] = Variable(datetime.value); + } + if (partyId.present) { + map['party_id'] = Variable(partyId.value); + } + if (walletId.present) { + map['wallet_id'] = Variable(walletId.value); + } + if (groupId.present) { + map['group_id'] = Variable(groupId.value); + } + if (walletClientId.present) { + map['wallet_client_id'] = Variable(walletClientId.value); + } + if (partyClientId.present) { + map['party_client_id'] = Variable(partyClientId.value); + } + if (groupClientId.present) { + map['group_client_id'] = Variable(groupClientId.value); + } + if (transferId.present) { + map['transfer_id'] = Variable(transferId.value); + } + if (transferClientId.present) { + map['transfer_client_id'] = Variable(transferClientId.value); + } + if (isRefund.present) { + map['is_refund'] = Variable(isRefund.value); + } + if (refundOfTransactionId.present) { + map['refund_of_transaction_id'] = + Variable(refundOfTransactionId.value); + } + if (recurrencePeriod.present) { + map['recurrence_period'] = Variable(recurrencePeriod.value); + } + if (recurrenceInterval.present) { + map['recurrence_interval'] = Variable(recurrenceInterval.value); + } + if (recurrenceEndsAt.present) { + map['recurrence_ends_at'] = Variable(recurrenceEndsAt.value); + } + if (recurrenceNextScheduledAt.present) { + map['recurrence_next_scheduled_at'] = + Variable(recurrenceNextScheduledAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('TransactionsCompanion(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('amount: $amount, ') + ..write('type: $type, ') + ..write('intent: $intent, ') + ..write('description: $description, ') + ..write('datetime: $datetime, ') + ..write('partyId: $partyId, ') + ..write('walletId: $walletId, ') + ..write('groupId: $groupId, ') + ..write('walletClientId: $walletClientId, ') + ..write('partyClientId: $partyClientId, ') + ..write('groupClientId: $groupClientId, ') + ..write('transferId: $transferId, ') + ..write('transferClientId: $transferClientId, ') + ..write('isRefund: $isRefund, ') + ..write('refundOfTransactionId: $refundOfTransactionId, ') + ..write('recurrencePeriod: $recurrencePeriod, ') + ..write('recurrenceInterval: $recurrenceInterval, ') + ..write('recurrenceEndsAt: $recurrenceEndsAt, ') + ..write('recurrenceNextScheduledAt: $recurrenceNextScheduledAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Categories extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Categories(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\'')); + late final GeneratedColumn rev = GeneratedColumn( + 'rev', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'1\'')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn lastSyncedAt = GeneratedColumn( + 'last_synced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn slug = GeneratedColumn( + 'slug', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn description = GeneratedColumn( + 'description', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn icon = GeneratedColumn( + 'icon', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + @override + List get $columns => [ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + name, + slug, + description, + type, + icon + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'categories'; + @override + Set get $primaryKey => {clientId}; + @override + CategoriesData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return CategoriesData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id']), + userId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}user_id']), + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + rev: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}rev']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + deletedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}deleted_at']), + lastSyncedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_synced_at']), + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + slug: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}slug'])!, + description: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}description']), + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + icon: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}icon']), + ); + } + + @override + Categories createAlias(String alias) { + return Categories(attachedDatabase, alias); + } +} + +class CategoriesData extends DataClass implements Insertable { + final int? id; + final int? userId; + final String clientId; + final String? rev; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final DateTime? lastSyncedAt; + final String name; + final String slug; + final String? description; + final String type; + final String? icon; + const CategoriesData( + {this.id, + this.userId, + required this.clientId, + this.rev, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + this.lastSyncedAt, + required this.name, + required this.slug, + this.description, + required this.type, + this.icon}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + map['client_id'] = Variable(clientId); + if (!nullToAbsent || rev != null) { + map['rev'] = Variable(rev); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || lastSyncedAt != null) { + map['last_synced_at'] = Variable(lastSyncedAt); + } + map['name'] = Variable(name); + map['slug'] = Variable(slug); + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + map['type'] = Variable(type); + if (!nullToAbsent || icon != null) { + map['icon'] = Variable(icon); + } + return map; + } + + CategoriesCompanion toCompanion(bool nullToAbsent) { + return CategoriesCompanion( + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + userId: + userId == null && nullToAbsent ? const Value.absent() : Value(userId), + clientId: Value(clientId), + rev: rev == null && nullToAbsent ? const Value.absent() : Value(rev), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: deletedAt == null && nullToAbsent + ? const Value.absent() + : Value(deletedAt), + lastSyncedAt: lastSyncedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastSyncedAt), + name: Value(name), + slug: Value(slug), + description: description == null && nullToAbsent + ? const Value.absent() + : Value(description), + type: Value(type), + icon: icon == null && nullToAbsent ? const Value.absent() : Value(icon), + ); + } + + factory CategoriesData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return CategoriesData( + id: serializer.fromJson(json['id']), + userId: serializer.fromJson(json['userId']), + clientId: serializer.fromJson(json['clientId']), + rev: serializer.fromJson(json['rev']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + lastSyncedAt: serializer.fromJson(json['lastSyncedAt']), + name: serializer.fromJson(json['name']), + slug: serializer.fromJson(json['slug']), + description: serializer.fromJson(json['description']), + type: serializer.fromJson(json['type']), + icon: serializer.fromJson(json['icon']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'userId': serializer.toJson(userId), + 'clientId': serializer.toJson(clientId), + 'rev': serializer.toJson(rev), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'lastSyncedAt': serializer.toJson(lastSyncedAt), + 'name': serializer.toJson(name), + 'slug': serializer.toJson(slug), + 'description': serializer.toJson(description), + 'type': serializer.toJson(type), + 'icon': serializer.toJson(icon), + }; + } + + CategoriesData copyWith( + {Value id = const Value.absent(), + Value userId = const Value.absent(), + String? clientId, + Value rev = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + Value lastSyncedAt = const Value.absent(), + String? name, + String? slug, + Value description = const Value.absent(), + String? type, + Value icon = const Value.absent()}) => + CategoriesData( + id: id.present ? id.value : this.id, + userId: userId.present ? userId.value : this.userId, + clientId: clientId ?? this.clientId, + rev: rev.present ? rev.value : this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + lastSyncedAt: + lastSyncedAt.present ? lastSyncedAt.value : this.lastSyncedAt, + name: name ?? this.name, + slug: slug ?? this.slug, + description: description.present ? description.value : this.description, + type: type ?? this.type, + icon: icon.present ? icon.value : this.icon, + ); + CategoriesData copyWithCompanion(CategoriesCompanion data) { + return CategoriesData( + id: data.id.present ? data.id.value : this.id, + userId: data.userId.present ? data.userId.value : this.userId, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + rev: data.rev.present ? data.rev.value : this.rev, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + lastSyncedAt: data.lastSyncedAt.present + ? data.lastSyncedAt.value + : this.lastSyncedAt, + name: data.name.present ? data.name.value : this.name, + slug: data.slug.present ? data.slug.value : this.slug, + description: + data.description.present ? data.description.value : this.description, + type: data.type.present ? data.type.value : this.type, + icon: data.icon.present ? data.icon.value : this.icon, + ); + } + + @override + String toString() { + return (StringBuffer('CategoriesData(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('name: $name, ') + ..write('slug: $slug, ') + ..write('description: $description, ') + ..write('type: $type, ') + ..write('icon: $icon') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, userId, clientId, rev, createdAt, + updatedAt, deletedAt, lastSyncedAt, name, slug, description, type, icon); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is CategoriesData && + other.id == this.id && + other.userId == this.userId && + other.clientId == this.clientId && + other.rev == this.rev && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.lastSyncedAt == this.lastSyncedAt && + other.name == this.name && + other.slug == this.slug && + other.description == this.description && + other.type == this.type && + other.icon == this.icon); +} + +class CategoriesCompanion extends UpdateCompanion { + final Value id; + final Value userId; + final Value clientId; + final Value rev; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value lastSyncedAt; + final Value name; + final Value slug; + final Value description; + final Value type; + final Value icon; + final Value rowid; + const CategoriesCompanion({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + this.name = const Value.absent(), + this.slug = const Value.absent(), + this.description = const Value.absent(), + this.type = const Value.absent(), + this.icon = const Value.absent(), + this.rowid = const Value.absent(), + }); + CategoriesCompanion.insert({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + required String name, + required String slug, + this.description = const Value.absent(), + required String type, + this.icon = const Value.absent(), + this.rowid = const Value.absent(), + }) : name = Value(name), + slug = Value(slug), + type = Value(type); + static Insertable custom({ + Expression? id, + Expression? userId, + Expression? clientId, + Expression? rev, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? lastSyncedAt, + Expression? name, + Expression? slug, + Expression? description, + Expression? type, + Expression? icon, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (userId != null) 'user_id': userId, + if (clientId != null) 'client_id': clientId, + if (rev != null) 'rev': rev, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (lastSyncedAt != null) 'last_synced_at': lastSyncedAt, + if (name != null) 'name': name, + if (slug != null) 'slug': slug, + if (description != null) 'description': description, + if (type != null) 'type': type, + if (icon != null) 'icon': icon, + if (rowid != null) 'rowid': rowid, + }); + } + + CategoriesCompanion copyWith( + {Value? id, + Value? userId, + Value? clientId, + Value? rev, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? lastSyncedAt, + Value? name, + Value? slug, + Value? description, + Value? type, + Value? icon, + Value? rowid}) { + return CategoriesCompanion( + id: id ?? this.id, + userId: userId ?? this.userId, + clientId: clientId ?? this.clientId, + rev: rev ?? this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt, + name: name ?? this.name, + slug: slug ?? this.slug, + description: description ?? this.description, + type: type ?? this.type, + icon: icon ?? this.icon, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (rev.present) { + map['rev'] = Variable(rev.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (lastSyncedAt.present) { + map['last_synced_at'] = Variable(lastSyncedAt.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (slug.present) { + map['slug'] = Variable(slug.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (icon.present) { + map['icon'] = Variable(icon.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('CategoriesCompanion(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('name: $name, ') + ..write('slug: $slug, ') + ..write('description: $description, ') + ..write('type: $type, ') + ..write('icon: $icon, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Configs extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Configs(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\'')); + late final GeneratedColumn rev = GeneratedColumn( + 'rev', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'1\'')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn lastSyncedAt = GeneratedColumn( + 'last_synced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn key = GeneratedColumn( + 'key', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn value = GeneratedColumn( + 'value', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => [ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + key, + type, + value + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'configs'; + @override + Set get $primaryKey => {clientId}; + @override + ConfigsData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return ConfigsData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id']), + userId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}user_id']), + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + rev: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}rev']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + deletedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}deleted_at']), + lastSyncedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_synced_at']), + key: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}key'])!, + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + value: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}value'])!, + ); + } + + @override + Configs createAlias(String alias) { + return Configs(attachedDatabase, alias); + } +} + +class ConfigsData extends DataClass implements Insertable { + final int? id; + final int? userId; + final String clientId; + final String? rev; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final DateTime? lastSyncedAt; + final String key; + final String type; + final String value; + const ConfigsData( + {this.id, + this.userId, + required this.clientId, + this.rev, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + this.lastSyncedAt, + required this.key, + required this.type, + required this.value}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + map['client_id'] = Variable(clientId); + if (!nullToAbsent || rev != null) { + map['rev'] = Variable(rev); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || lastSyncedAt != null) { + map['last_synced_at'] = Variable(lastSyncedAt); + } + map['key'] = Variable(key); + map['type'] = Variable(type); + map['value'] = Variable(value); + return map; + } + + ConfigsCompanion toCompanion(bool nullToAbsent) { + return ConfigsCompanion( + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + userId: + userId == null && nullToAbsent ? const Value.absent() : Value(userId), + clientId: Value(clientId), + rev: rev == null && nullToAbsent ? const Value.absent() : Value(rev), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: deletedAt == null && nullToAbsent + ? const Value.absent() + : Value(deletedAt), + lastSyncedAt: lastSyncedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastSyncedAt), + key: Value(key), + type: Value(type), + value: Value(value), + ); + } + + factory ConfigsData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return ConfigsData( + id: serializer.fromJson(json['id']), + userId: serializer.fromJson(json['userId']), + clientId: serializer.fromJson(json['clientId']), + rev: serializer.fromJson(json['rev']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + lastSyncedAt: serializer.fromJson(json['lastSyncedAt']), + key: serializer.fromJson(json['key']), + type: serializer.fromJson(json['type']), + value: serializer.fromJson(json['value']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'userId': serializer.toJson(userId), + 'clientId': serializer.toJson(clientId), + 'rev': serializer.toJson(rev), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'lastSyncedAt': serializer.toJson(lastSyncedAt), + 'key': serializer.toJson(key), + 'type': serializer.toJson(type), + 'value': serializer.toJson(value), + }; + } + + ConfigsData copyWith( + {Value id = const Value.absent(), + Value userId = const Value.absent(), + String? clientId, + Value rev = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + Value lastSyncedAt = const Value.absent(), + String? key, + String? type, + String? value}) => + ConfigsData( + id: id.present ? id.value : this.id, + userId: userId.present ? userId.value : this.userId, + clientId: clientId ?? this.clientId, + rev: rev.present ? rev.value : this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + lastSyncedAt: + lastSyncedAt.present ? lastSyncedAt.value : this.lastSyncedAt, + key: key ?? this.key, + type: type ?? this.type, + value: value ?? this.value, + ); + ConfigsData copyWithCompanion(ConfigsCompanion data) { + return ConfigsData( + id: data.id.present ? data.id.value : this.id, + userId: data.userId.present ? data.userId.value : this.userId, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + rev: data.rev.present ? data.rev.value : this.rev, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + lastSyncedAt: data.lastSyncedAt.present + ? data.lastSyncedAt.value + : this.lastSyncedAt, + key: data.key.present ? data.key.value : this.key, + type: data.type.present ? data.type.value : this.type, + value: data.value.present ? data.value.value : this.value, + ); + } + + @override + String toString() { + return (StringBuffer('ConfigsData(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('key: $key, ') + ..write('type: $type, ') + ..write('value: $value') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, userId, clientId, rev, createdAt, + updatedAt, deletedAt, lastSyncedAt, key, type, value); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is ConfigsData && + other.id == this.id && + other.userId == this.userId && + other.clientId == this.clientId && + other.rev == this.rev && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.lastSyncedAt == this.lastSyncedAt && + other.key == this.key && + other.type == this.type && + other.value == this.value); +} + +class ConfigsCompanion extends UpdateCompanion { + final Value id; + final Value userId; + final Value clientId; + final Value rev; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value lastSyncedAt; + final Value key; + final Value type; + final Value value; + final Value rowid; + const ConfigsCompanion({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + this.key = const Value.absent(), + this.type = const Value.absent(), + this.value = const Value.absent(), + this.rowid = const Value.absent(), + }); + ConfigsCompanion.insert({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + required String key, + required String type, + required String value, + this.rowid = const Value.absent(), + }) : key = Value(key), + type = Value(type), + value = Value(value); + static Insertable custom({ + Expression? id, + Expression? userId, + Expression? clientId, + Expression? rev, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? lastSyncedAt, + Expression? key, + Expression? type, + Expression? value, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (userId != null) 'user_id': userId, + if (clientId != null) 'client_id': clientId, + if (rev != null) 'rev': rev, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (lastSyncedAt != null) 'last_synced_at': lastSyncedAt, + if (key != null) 'key': key, + if (type != null) 'type': type, + if (value != null) 'value': value, + if (rowid != null) 'rowid': rowid, + }); + } + + ConfigsCompanion copyWith( + {Value? id, + Value? userId, + Value? clientId, + Value? rev, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? lastSyncedAt, + Value? key, + Value? type, + Value? value, + Value? rowid}) { + return ConfigsCompanion( + id: id ?? this.id, + userId: userId ?? this.userId, + clientId: clientId ?? this.clientId, + rev: rev ?? this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt, + key: key ?? this.key, + type: type ?? this.type, + value: value ?? this.value, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (rev.present) { + map['rev'] = Variable(rev.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (lastSyncedAt.present) { + map['last_synced_at'] = Variable(lastSyncedAt.value); + } + if (key.present) { + map['key'] = Variable(key.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (value.present) { + map['value'] = Variable(value.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('ConfigsCompanion(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('key: $key, ') + ..write('type: $type, ') + ..write('value: $value, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Users extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Users(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn email = GeneratedColumn( + 'email', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn firstName = GeneratedColumn( + 'first_name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn lastName = GeneratedColumn( + 'last_name', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn username = GeneratedColumn( + 'username', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn phone = GeneratedColumn( + 'phone', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn avatar = GeneratedColumn( + 'avatar', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [ + id, + email, + firstName, + lastName, + username, + phone, + avatar, + createdAt, + updatedAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'users'; + @override + Set get $primaryKey => {id}; + @override + UsersData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return UsersData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + email: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}email'])!, + firstName: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}first_name'])!, + lastName: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}last_name']), + username: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}username']), + phone: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}phone']), + avatar: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}avatar']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at']), + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at']), + ); + } + + @override + Users createAlias(String alias) { + return Users(attachedDatabase, alias); + } +} + +class UsersData extends DataClass implements Insertable { + final int id; + final String email; + final String firstName; + final String? lastName; + final String? username; + final String? phone; + final String? avatar; + final DateTime? createdAt; + final DateTime? updatedAt; + const UsersData( + {required this.id, + required this.email, + required this.firstName, + this.lastName, + this.username, + this.phone, + this.avatar, + this.createdAt, + this.updatedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['email'] = Variable(email); + map['first_name'] = Variable(firstName); + if (!nullToAbsent || lastName != null) { + map['last_name'] = Variable(lastName); + } + if (!nullToAbsent || username != null) { + map['username'] = Variable(username); + } + if (!nullToAbsent || phone != null) { + map['phone'] = Variable(phone); + } + if (!nullToAbsent || avatar != null) { + map['avatar'] = Variable(avatar); + } + if (!nullToAbsent || createdAt != null) { + map['created_at'] = Variable(createdAt); + } + if (!nullToAbsent || updatedAt != null) { + map['updated_at'] = Variable(updatedAt); + } + return map; + } + + UsersCompanion toCompanion(bool nullToAbsent) { + return UsersCompanion( + id: Value(id), + email: Value(email), + firstName: Value(firstName), + lastName: lastName == null && nullToAbsent + ? const Value.absent() + : Value(lastName), + username: username == null && nullToAbsent + ? const Value.absent() + : Value(username), + phone: + phone == null && nullToAbsent ? const Value.absent() : Value(phone), + avatar: + avatar == null && nullToAbsent ? const Value.absent() : Value(avatar), + createdAt: createdAt == null && nullToAbsent + ? const Value.absent() + : Value(createdAt), + updatedAt: updatedAt == null && nullToAbsent + ? const Value.absent() + : Value(updatedAt), + ); + } + + factory UsersData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return UsersData( + id: serializer.fromJson(json['id']), + email: serializer.fromJson(json['email']), + firstName: serializer.fromJson(json['firstName']), + lastName: serializer.fromJson(json['lastName']), + username: serializer.fromJson(json['username']), + phone: serializer.fromJson(json['phone']), + avatar: serializer.fromJson(json['avatar']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'email': serializer.toJson(email), + 'firstName': serializer.toJson(firstName), + 'lastName': serializer.toJson(lastName), + 'username': serializer.toJson(username), + 'phone': serializer.toJson(phone), + 'avatar': serializer.toJson(avatar), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + }; + } + + UsersData copyWith( + {int? id, + String? email, + String? firstName, + Value lastName = const Value.absent(), + Value username = const Value.absent(), + Value phone = const Value.absent(), + Value avatar = const Value.absent(), + Value createdAt = const Value.absent(), + Value updatedAt = const Value.absent()}) => + UsersData( + id: id ?? this.id, + email: email ?? this.email, + firstName: firstName ?? this.firstName, + lastName: lastName.present ? lastName.value : this.lastName, + username: username.present ? username.value : this.username, + phone: phone.present ? phone.value : this.phone, + avatar: avatar.present ? avatar.value : this.avatar, + createdAt: createdAt.present ? createdAt.value : this.createdAt, + updatedAt: updatedAt.present ? updatedAt.value : this.updatedAt, + ); + UsersData copyWithCompanion(UsersCompanion data) { + return UsersData( + id: data.id.present ? data.id.value : this.id, + email: data.email.present ? data.email.value : this.email, + firstName: data.firstName.present ? data.firstName.value : this.firstName, + lastName: data.lastName.present ? data.lastName.value : this.lastName, + username: data.username.present ? data.username.value : this.username, + phone: data.phone.present ? data.phone.value : this.phone, + avatar: data.avatar.present ? data.avatar.value : this.avatar, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ); + } + + @override + String toString() { + return (StringBuffer('UsersData(') + ..write('id: $id, ') + ..write('email: $email, ') + ..write('firstName: $firstName, ') + ..write('lastName: $lastName, ') + ..write('username: $username, ') + ..write('phone: $phone, ') + ..write('avatar: $avatar, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, email, firstName, lastName, username, + phone, avatar, createdAt, updatedAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is UsersData && + other.id == this.id && + other.email == this.email && + other.firstName == this.firstName && + other.lastName == this.lastName && + other.username == this.username && + other.phone == this.phone && + other.avatar == this.avatar && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt); +} + +class UsersCompanion extends UpdateCompanion { + final Value id; + final Value email; + final Value firstName; + final Value lastName; + final Value username; + final Value phone; + final Value avatar; + final Value createdAt; + final Value updatedAt; + const UsersCompanion({ + this.id = const Value.absent(), + this.email = const Value.absent(), + this.firstName = const Value.absent(), + this.lastName = const Value.absent(), + this.username = const Value.absent(), + this.phone = const Value.absent(), + this.avatar = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + }); + UsersCompanion.insert({ + this.id = const Value.absent(), + required String email, + required String firstName, + this.lastName = const Value.absent(), + this.username = const Value.absent(), + this.phone = const Value.absent(), + this.avatar = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + }) : email = Value(email), + firstName = Value(firstName); + static Insertable custom({ + Expression? id, + Expression? email, + Expression? firstName, + Expression? lastName, + Expression? username, + Expression? phone, + Expression? avatar, + Expression? createdAt, + Expression? updatedAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (email != null) 'email': email, + if (firstName != null) 'first_name': firstName, + if (lastName != null) 'last_name': lastName, + if (username != null) 'username': username, + if (phone != null) 'phone': phone, + if (avatar != null) 'avatar': avatar, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + }); + } + + UsersCompanion copyWith( + {Value? id, + Value? email, + Value? firstName, + Value? lastName, + Value? username, + Value? phone, + Value? avatar, + Value? createdAt, + Value? updatedAt}) { + return UsersCompanion( + id: id ?? this.id, + email: email ?? this.email, + firstName: firstName ?? this.firstName, + lastName: lastName ?? this.lastName, + username: username ?? this.username, + phone: phone ?? this.phone, + avatar: avatar ?? this.avatar, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (email.present) { + map['email'] = Variable(email.value); + } + if (firstName.present) { + map['first_name'] = Variable(firstName.value); + } + if (lastName.present) { + map['last_name'] = Variable(lastName.value); + } + if (username.present) { + map['username'] = Variable(username.value); + } + if (phone.present) { + map['phone'] = Variable(phone.value); + } + if (avatar.present) { + map['avatar'] = Variable(avatar.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('UsersCompanion(') + ..write('id: $id, ') + ..write('email: $email, ') + ..write('firstName: $firstName, ') + ..write('lastName: $lastName, ') + ..write('username: $username, ') + ..write('phone: $phone, ') + ..write('avatar: $avatar, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt') + ..write(')')) + .toString(); + } +} + +class LocalChanges extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalChanges(this.attachedDatabase, [this._alias]); + late final GeneratedColumn entityType = GeneratedColumn( + 'entity_type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn entityId = GeneratedColumn( + 'entity_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn entityRev = GeneratedColumn( + 'entity_rev', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn deleted = GeneratedColumn( + 'deleted', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("deleted" IN (0, 1))')); + late final GeneratedColumn data = GeneratedColumn( + 'data', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn createAt = GeneratedColumn( + 'create_at', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + late final GeneratedColumn concluded = GeneratedColumn( + 'concluded', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("concluded" IN (0, 1))')); + late final GeneratedColumn concludedMoment = + GeneratedColumn('concluded_moment', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn error = GeneratedColumn( + 'error', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn dismissed = GeneratedColumn( + 'dismissed', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("dismissed" IN (0, 1))')); + late final GeneratedColumn attemptCount = GeneratedColumn( + 'attempt_count', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0')); + late final GeneratedColumn quarantinedAt = + GeneratedColumn('quarantined_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [ + entityType, + entityId, + entityRev, + deleted, + data, + createAt, + concluded, + concludedMoment, + error, + dismissed, + attemptCount, + quarantinedAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_changes'; + @override + Set get $primaryKey => {entityId, entityType}; + @override + LocalChangesData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalChangesData( + entityType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}entity_type'])!, + entityId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}entity_id'])!, + entityRev: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}entity_rev'])!, + deleted: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}deleted'])!, + data: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}data'])!, + createAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}create_at'])!, + concluded: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}concluded'])!, + concludedMoment: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}concluded_moment']), + error: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}error']), + dismissed: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}dismissed'])!, + attemptCount: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}attempt_count'])!, + quarantinedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}quarantined_at']), + ); + } + + @override + LocalChanges createAlias(String alias) { + return LocalChanges(attachedDatabase, alias); + } +} + +class LocalChangesData extends DataClass + implements Insertable { + final String entityType; + final String entityId; + final String entityRev; + final bool deleted; + final String data; + final DateTime createAt; + final bool concluded; + final DateTime? concludedMoment; + final String? error; + final bool dismissed; + final int attemptCount; + final DateTime? quarantinedAt; + const LocalChangesData( + {required this.entityType, + required this.entityId, + required this.entityRev, + required this.deleted, + required this.data, + required this.createAt, + required this.concluded, + this.concludedMoment, + this.error, + required this.dismissed, + required this.attemptCount, + this.quarantinedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['entity_type'] = Variable(entityType); + map['entity_id'] = Variable(entityId); + map['entity_rev'] = Variable(entityRev); + map['deleted'] = Variable(deleted); + map['data'] = Variable(data); + map['create_at'] = Variable(createAt); + map['concluded'] = Variable(concluded); + if (!nullToAbsent || concludedMoment != null) { + map['concluded_moment'] = Variable(concludedMoment); + } + if (!nullToAbsent || error != null) { + map['error'] = Variable(error); + } + map['dismissed'] = Variable(dismissed); + map['attempt_count'] = Variable(attemptCount); + if (!nullToAbsent || quarantinedAt != null) { + map['quarantined_at'] = Variable(quarantinedAt); + } + return map; + } + + LocalChangesCompanion toCompanion(bool nullToAbsent) { + return LocalChangesCompanion( + entityType: Value(entityType), + entityId: Value(entityId), + entityRev: Value(entityRev), + deleted: Value(deleted), + data: Value(data), + createAt: Value(createAt), + concluded: Value(concluded), + concludedMoment: concludedMoment == null && nullToAbsent + ? const Value.absent() + : Value(concludedMoment), + error: + error == null && nullToAbsent ? const Value.absent() : Value(error), + dismissed: Value(dismissed), + attemptCount: Value(attemptCount), + quarantinedAt: quarantinedAt == null && nullToAbsent + ? const Value.absent() + : Value(quarantinedAt), + ); + } + + factory LocalChangesData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalChangesData( + entityType: serializer.fromJson(json['entityType']), + entityId: serializer.fromJson(json['entityId']), + entityRev: serializer.fromJson(json['entityRev']), + deleted: serializer.fromJson(json['deleted']), + data: serializer.fromJson(json['data']), + createAt: serializer.fromJson(json['createAt']), + concluded: serializer.fromJson(json['concluded']), + concludedMoment: serializer.fromJson(json['concludedMoment']), + error: serializer.fromJson(json['error']), + dismissed: serializer.fromJson(json['dismissed']), + attemptCount: serializer.fromJson(json['attemptCount']), + quarantinedAt: serializer.fromJson(json['quarantinedAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'entityType': serializer.toJson(entityType), + 'entityId': serializer.toJson(entityId), + 'entityRev': serializer.toJson(entityRev), + 'deleted': serializer.toJson(deleted), + 'data': serializer.toJson(data), + 'createAt': serializer.toJson(createAt), + 'concluded': serializer.toJson(concluded), + 'concludedMoment': serializer.toJson(concludedMoment), + 'error': serializer.toJson(error), + 'dismissed': serializer.toJson(dismissed), + 'attemptCount': serializer.toJson(attemptCount), + 'quarantinedAt': serializer.toJson(quarantinedAt), + }; + } + + LocalChangesData copyWith( + {String? entityType, + String? entityId, + String? entityRev, + bool? deleted, + String? data, + DateTime? createAt, + bool? concluded, + Value concludedMoment = const Value.absent(), + Value error = const Value.absent(), + bool? dismissed, + int? attemptCount, + Value quarantinedAt = const Value.absent()}) => + LocalChangesData( + entityType: entityType ?? this.entityType, + entityId: entityId ?? this.entityId, + entityRev: entityRev ?? this.entityRev, + deleted: deleted ?? this.deleted, + data: data ?? this.data, + createAt: createAt ?? this.createAt, + concluded: concluded ?? this.concluded, + concludedMoment: concludedMoment.present + ? concludedMoment.value + : this.concludedMoment, + error: error.present ? error.value : this.error, + dismissed: dismissed ?? this.dismissed, + attemptCount: attemptCount ?? this.attemptCount, + quarantinedAt: + quarantinedAt.present ? quarantinedAt.value : this.quarantinedAt, + ); + LocalChangesData copyWithCompanion(LocalChangesCompanion data) { + return LocalChangesData( + entityType: + data.entityType.present ? data.entityType.value : this.entityType, + entityId: data.entityId.present ? data.entityId.value : this.entityId, + entityRev: data.entityRev.present ? data.entityRev.value : this.entityRev, + deleted: data.deleted.present ? data.deleted.value : this.deleted, + data: data.data.present ? data.data.value : this.data, + createAt: data.createAt.present ? data.createAt.value : this.createAt, + concluded: data.concluded.present ? data.concluded.value : this.concluded, + concludedMoment: data.concludedMoment.present + ? data.concludedMoment.value + : this.concludedMoment, + error: data.error.present ? data.error.value : this.error, + dismissed: data.dismissed.present ? data.dismissed.value : this.dismissed, + attemptCount: data.attemptCount.present + ? data.attemptCount.value + : this.attemptCount, + quarantinedAt: data.quarantinedAt.present + ? data.quarantinedAt.value + : this.quarantinedAt, + ); + } + + @override + String toString() { + return (StringBuffer('LocalChangesData(') + ..write('entityType: $entityType, ') + ..write('entityId: $entityId, ') + ..write('entityRev: $entityRev, ') + ..write('deleted: $deleted, ') + ..write('data: $data, ') + ..write('createAt: $createAt, ') + ..write('concluded: $concluded, ') + ..write('concludedMoment: $concludedMoment, ') + ..write('error: $error, ') + ..write('dismissed: $dismissed, ') + ..write('attemptCount: $attemptCount, ') + ..write('quarantinedAt: $quarantinedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + entityType, + entityId, + entityRev, + deleted, + data, + createAt, + concluded, + concludedMoment, + error, + dismissed, + attemptCount, + quarantinedAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalChangesData && + other.entityType == this.entityType && + other.entityId == this.entityId && + other.entityRev == this.entityRev && + other.deleted == this.deleted && + other.data == this.data && + other.createAt == this.createAt && + other.concluded == this.concluded && + other.concludedMoment == this.concludedMoment && + other.error == this.error && + other.dismissed == this.dismissed && + other.attemptCount == this.attemptCount && + other.quarantinedAt == this.quarantinedAt); +} + +class LocalChangesCompanion extends UpdateCompanion { + final Value entityType; + final Value entityId; + final Value entityRev; + final Value deleted; + final Value data; + final Value createAt; + final Value concluded; + final Value concludedMoment; + final Value error; + final Value dismissed; + final Value attemptCount; + final Value quarantinedAt; + final Value rowid; + const LocalChangesCompanion({ + this.entityType = const Value.absent(), + this.entityId = const Value.absent(), + this.entityRev = const Value.absent(), + this.deleted = const Value.absent(), + this.data = const Value.absent(), + this.createAt = const Value.absent(), + this.concluded = const Value.absent(), + this.concludedMoment = const Value.absent(), + this.error = const Value.absent(), + this.dismissed = const Value.absent(), + this.attemptCount = const Value.absent(), + this.quarantinedAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + LocalChangesCompanion.insert({ + required String entityType, + required String entityId, + required String entityRev, + required bool deleted, + required String data, + required DateTime createAt, + required bool concluded, + this.concludedMoment = const Value.absent(), + this.error = const Value.absent(), + required bool dismissed, + this.attemptCount = const Value.absent(), + this.quarantinedAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : entityType = Value(entityType), + entityId = Value(entityId), + entityRev = Value(entityRev), + deleted = Value(deleted), + data = Value(data), + createAt = Value(createAt), + concluded = Value(concluded), + dismissed = Value(dismissed); + static Insertable custom({ + Expression? entityType, + Expression? entityId, + Expression? entityRev, + Expression? deleted, + Expression? data, + Expression? createAt, + Expression? concluded, + Expression? concludedMoment, + Expression? error, + Expression? dismissed, + Expression? attemptCount, + Expression? quarantinedAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (entityType != null) 'entity_type': entityType, + if (entityId != null) 'entity_id': entityId, + if (entityRev != null) 'entity_rev': entityRev, + if (deleted != null) 'deleted': deleted, + if (data != null) 'data': data, + if (createAt != null) 'create_at': createAt, + if (concluded != null) 'concluded': concluded, + if (concludedMoment != null) 'concluded_moment': concludedMoment, + if (error != null) 'error': error, + if (dismissed != null) 'dismissed': dismissed, + if (attemptCount != null) 'attempt_count': attemptCount, + if (quarantinedAt != null) 'quarantined_at': quarantinedAt, + if (rowid != null) 'rowid': rowid, + }); + } + + LocalChangesCompanion copyWith( + {Value? entityType, + Value? entityId, + Value? entityRev, + Value? deleted, + Value? data, + Value? createAt, + Value? concluded, + Value? concludedMoment, + Value? error, + Value? dismissed, + Value? attemptCount, + Value? quarantinedAt, + Value? rowid}) { + return LocalChangesCompanion( + entityType: entityType ?? this.entityType, + entityId: entityId ?? this.entityId, + entityRev: entityRev ?? this.entityRev, + deleted: deleted ?? this.deleted, + data: data ?? this.data, + createAt: createAt ?? this.createAt, + concluded: concluded ?? this.concluded, + concludedMoment: concludedMoment ?? this.concludedMoment, + error: error ?? this.error, + dismissed: dismissed ?? this.dismissed, + attemptCount: attemptCount ?? this.attemptCount, + quarantinedAt: quarantinedAt ?? this.quarantinedAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (entityType.present) { + map['entity_type'] = Variable(entityType.value); + } + if (entityId.present) { + map['entity_id'] = Variable(entityId.value); + } + if (entityRev.present) { + map['entity_rev'] = Variable(entityRev.value); + } + if (deleted.present) { + map['deleted'] = Variable(deleted.value); + } + if (data.present) { + map['data'] = Variable(data.value); + } + if (createAt.present) { + map['create_at'] = Variable(createAt.value); + } + if (concluded.present) { + map['concluded'] = Variable(concluded.value); + } + if (concludedMoment.present) { + map['concluded_moment'] = Variable(concludedMoment.value); + } + if (error.present) { + map['error'] = Variable(error.value); + } + if (dismissed.present) { + map['dismissed'] = Variable(dismissed.value); + } + if (attemptCount.present) { + map['attempt_count'] = Variable(attemptCount.value); + } + if (quarantinedAt.present) { + map['quarantined_at'] = Variable(quarantinedAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalChangesCompanion(') + ..write('entityType: $entityType, ') + ..write('entityId: $entityId, ') + ..write('entityRev: $entityRev, ') + ..write('deleted: $deleted, ') + ..write('data: $data, ') + ..write('createAt: $createAt, ') + ..write('concluded: $concluded, ') + ..write('concludedMoment: $concludedMoment, ') + ..write('error: $error, ') + ..write('dismissed: $dismissed, ') + ..write('attemptCount: $attemptCount, ') + ..write('quarantinedAt: $quarantinedAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class SyncMetadata extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + SyncMetadata(this.attachedDatabase, [this._alias]); + late final GeneratedColumn entityType = GeneratedColumn( + 'entity_type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn lastSyncedAt = GeneratedColumn( + 'last_synced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [entityType, lastSyncedAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'sync_metadata'; + @override + Set get $primaryKey => {entityType}; + @override + SyncMetadataData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SyncMetadataData( + entityType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}entity_type'])!, + lastSyncedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_synced_at']), + ); + } + + @override + SyncMetadata createAlias(String alias) { + return SyncMetadata(attachedDatabase, alias); + } +} + +class SyncMetadataData extends DataClass + implements Insertable { + final String entityType; + final DateTime? lastSyncedAt; + const SyncMetadataData({required this.entityType, this.lastSyncedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['entity_type'] = Variable(entityType); + if (!nullToAbsent || lastSyncedAt != null) { + map['last_synced_at'] = Variable(lastSyncedAt); + } + return map; + } + + SyncMetadataCompanion toCompanion(bool nullToAbsent) { + return SyncMetadataCompanion( + entityType: Value(entityType), + lastSyncedAt: lastSyncedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastSyncedAt), + ); + } + + factory SyncMetadataData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SyncMetadataData( + entityType: serializer.fromJson(json['entityType']), + lastSyncedAt: serializer.fromJson(json['lastSyncedAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'entityType': serializer.toJson(entityType), + 'lastSyncedAt': serializer.toJson(lastSyncedAt), + }; + } + + SyncMetadataData copyWith( + {String? entityType, + Value lastSyncedAt = const Value.absent()}) => + SyncMetadataData( + entityType: entityType ?? this.entityType, + lastSyncedAt: + lastSyncedAt.present ? lastSyncedAt.value : this.lastSyncedAt, + ); + SyncMetadataData copyWithCompanion(SyncMetadataCompanion data) { + return SyncMetadataData( + entityType: + data.entityType.present ? data.entityType.value : this.entityType, + lastSyncedAt: data.lastSyncedAt.present + ? data.lastSyncedAt.value + : this.lastSyncedAt, + ); + } + + @override + String toString() { + return (StringBuffer('SyncMetadataData(') + ..write('entityType: $entityType, ') + ..write('lastSyncedAt: $lastSyncedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(entityType, lastSyncedAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SyncMetadataData && + other.entityType == this.entityType && + other.lastSyncedAt == this.lastSyncedAt); +} + +class SyncMetadataCompanion extends UpdateCompanion { + final Value entityType; + final Value lastSyncedAt; + final Value rowid; + const SyncMetadataCompanion({ + this.entityType = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + SyncMetadataCompanion.insert({ + required String entityType, + this.lastSyncedAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : entityType = Value(entityType); + static Insertable custom({ + Expression? entityType, + Expression? lastSyncedAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (entityType != null) 'entity_type': entityType, + if (lastSyncedAt != null) 'last_synced_at': lastSyncedAt, + if (rowid != null) 'rowid': rowid, + }); + } + + SyncMetadataCompanion copyWith( + {Value? entityType, + Value? lastSyncedAt, + Value? rowid}) { + return SyncMetadataCompanion( + entityType: entityType ?? this.entityType, + lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (entityType.present) { + map['entity_type'] = Variable(entityType.value); + } + if (lastSyncedAt.present) { + map['last_synced_at'] = Variable(lastSyncedAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SyncMetadataCompanion(') + ..write('entityType: $entityType, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Categorizables extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Categorizables(this.attachedDatabase, [this._alias]); + late final GeneratedColumn categorizableId = GeneratedColumn( + 'categorizable_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn categorizableType = + GeneratedColumn('categorizable_type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn categoryClientId = GeneratedColumn( + 'category_client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES categories (client_id)')); + @override + List get $columns => + [categorizableId, categorizableType, categoryClientId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'categorizables'; + @override + Set get $primaryKey => + {categorizableId, categorizableType, categoryClientId}; + @override + CategorizablesData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return CategorizablesData( + categorizableId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}categorizable_id'])!, + categorizableType: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}categorizable_type'])!, + categoryClientId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}category_client_id'])!, + ); + } + + @override + Categorizables createAlias(String alias) { + return Categorizables(attachedDatabase, alias); + } +} + +class CategorizablesData extends DataClass + implements Insertable { + final String categorizableId; + final String categorizableType; + final String categoryClientId; + const CategorizablesData( + {required this.categorizableId, + required this.categorizableType, + required this.categoryClientId}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['categorizable_id'] = Variable(categorizableId); + map['categorizable_type'] = Variable(categorizableType); + map['category_client_id'] = Variable(categoryClientId); + return map; + } + + CategorizablesCompanion toCompanion(bool nullToAbsent) { + return CategorizablesCompanion( + categorizableId: Value(categorizableId), + categorizableType: Value(categorizableType), + categoryClientId: Value(categoryClientId), + ); + } + + factory CategorizablesData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return CategorizablesData( + categorizableId: serializer.fromJson(json['categorizableId']), + categorizableType: serializer.fromJson(json['categorizableType']), + categoryClientId: serializer.fromJson(json['categoryClientId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'categorizableId': serializer.toJson(categorizableId), + 'categorizableType': serializer.toJson(categorizableType), + 'categoryClientId': serializer.toJson(categoryClientId), + }; + } + + CategorizablesData copyWith( + {String? categorizableId, + String? categorizableType, + String? categoryClientId}) => + CategorizablesData( + categorizableId: categorizableId ?? this.categorizableId, + categorizableType: categorizableType ?? this.categorizableType, + categoryClientId: categoryClientId ?? this.categoryClientId, + ); + CategorizablesData copyWithCompanion(CategorizablesCompanion data) { + return CategorizablesData( + categorizableId: data.categorizableId.present + ? data.categorizableId.value + : this.categorizableId, + categorizableType: data.categorizableType.present + ? data.categorizableType.value + : this.categorizableType, + categoryClientId: data.categoryClientId.present + ? data.categoryClientId.value + : this.categoryClientId, + ); + } + + @override + String toString() { + return (StringBuffer('CategorizablesData(') + ..write('categorizableId: $categorizableId, ') + ..write('categorizableType: $categorizableType, ') + ..write('categoryClientId: $categoryClientId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => + Object.hash(categorizableId, categorizableType, categoryClientId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is CategorizablesData && + other.categorizableId == this.categorizableId && + other.categorizableType == this.categorizableType && + other.categoryClientId == this.categoryClientId); +} + +class CategorizablesCompanion extends UpdateCompanion { + final Value categorizableId; + final Value categorizableType; + final Value categoryClientId; + final Value rowid; + const CategorizablesCompanion({ + this.categorizableId = const Value.absent(), + this.categorizableType = const Value.absent(), + this.categoryClientId = const Value.absent(), + this.rowid = const Value.absent(), + }); + CategorizablesCompanion.insert({ + required String categorizableId, + required String categorizableType, + required String categoryClientId, + this.rowid = const Value.absent(), + }) : categorizableId = Value(categorizableId), + categorizableType = Value(categorizableType), + categoryClientId = Value(categoryClientId); + static Insertable custom({ + Expression? categorizableId, + Expression? categorizableType, + Expression? categoryClientId, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (categorizableId != null) 'categorizable_id': categorizableId, + if (categorizableType != null) 'categorizable_type': categorizableType, + if (categoryClientId != null) 'category_client_id': categoryClientId, + if (rowid != null) 'rowid': rowid, + }); + } + + CategorizablesCompanion copyWith( + {Value? categorizableId, + Value? categorizableType, + Value? categoryClientId, + Value? rowid}) { + return CategorizablesCompanion( + categorizableId: categorizableId ?? this.categorizableId, + categorizableType: categorizableType ?? this.categorizableType, + categoryClientId: categoryClientId ?? this.categoryClientId, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (categorizableId.present) { + map['categorizable_id'] = Variable(categorizableId.value); + } + if (categorizableType.present) { + map['categorizable_type'] = Variable(categorizableType.value); + } + if (categoryClientId.present) { + map['category_client_id'] = Variable(categoryClientId.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('CategorizablesCompanion(') + ..write('categorizableId: $categorizableId, ') + ..write('categorizableType: $categorizableType, ') + ..write('categoryClientId: $categoryClientId, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Notifications extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Notifications(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\'')); + late final GeneratedColumn rev = GeneratedColumn( + 'rev', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'1\'')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn lastSyncedAt = GeneratedColumn( + 'last_synced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn title = GeneratedColumn( + 'title', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn body = GeneratedColumn( + 'body', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn data = GeneratedColumn( + 'data', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn readAt = GeneratedColumn( + 'read_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + type, + title, + body, + data, + readAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'notifications'; + @override + Set get $primaryKey => {clientId}; + @override + NotificationsData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return NotificationsData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id']), + userId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}user_id']), + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + rev: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}rev']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + deletedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}deleted_at']), + lastSyncedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_synced_at']), + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + title: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}title'])!, + body: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}body'])!, + data: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}data'])!, + readAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}read_at']), + ); + } + + @override + Notifications createAlias(String alias) { + return Notifications(attachedDatabase, alias); + } +} + +class NotificationsData extends DataClass + implements Insertable { + final int? id; + final int? userId; + final String clientId; + final String? rev; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final DateTime? lastSyncedAt; + final String type; + final String title; + final String body; + final String data; + final DateTime? readAt; + const NotificationsData( + {this.id, + this.userId, + required this.clientId, + this.rev, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + this.lastSyncedAt, + required this.type, + required this.title, + required this.body, + required this.data, + this.readAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + map['client_id'] = Variable(clientId); + if (!nullToAbsent || rev != null) { + map['rev'] = Variable(rev); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || lastSyncedAt != null) { + map['last_synced_at'] = Variable(lastSyncedAt); + } + map['type'] = Variable(type); + map['title'] = Variable(title); + map['body'] = Variable(body); + map['data'] = Variable(data); + if (!nullToAbsent || readAt != null) { + map['read_at'] = Variable(readAt); + } + return map; + } + + NotificationsCompanion toCompanion(bool nullToAbsent) { + return NotificationsCompanion( + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + userId: + userId == null && nullToAbsent ? const Value.absent() : Value(userId), + clientId: Value(clientId), + rev: rev == null && nullToAbsent ? const Value.absent() : Value(rev), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: deletedAt == null && nullToAbsent + ? const Value.absent() + : Value(deletedAt), + lastSyncedAt: lastSyncedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastSyncedAt), + type: Value(type), + title: Value(title), + body: Value(body), + data: Value(data), + readAt: + readAt == null && nullToAbsent ? const Value.absent() : Value(readAt), + ); + } + + factory NotificationsData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return NotificationsData( + id: serializer.fromJson(json['id']), + userId: serializer.fromJson(json['userId']), + clientId: serializer.fromJson(json['clientId']), + rev: serializer.fromJson(json['rev']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + lastSyncedAt: serializer.fromJson(json['lastSyncedAt']), + type: serializer.fromJson(json['type']), + title: serializer.fromJson(json['title']), + body: serializer.fromJson(json['body']), + data: serializer.fromJson(json['data']), + readAt: serializer.fromJson(json['readAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'userId': serializer.toJson(userId), + 'clientId': serializer.toJson(clientId), + 'rev': serializer.toJson(rev), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'lastSyncedAt': serializer.toJson(lastSyncedAt), + 'type': serializer.toJson(type), + 'title': serializer.toJson(title), + 'body': serializer.toJson(body), + 'data': serializer.toJson(data), + 'readAt': serializer.toJson(readAt), + }; + } + + NotificationsData copyWith( + {Value id = const Value.absent(), + Value userId = const Value.absent(), + String? clientId, + Value rev = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + Value lastSyncedAt = const Value.absent(), + String? type, + String? title, + String? body, + String? data, + Value readAt = const Value.absent()}) => + NotificationsData( + id: id.present ? id.value : this.id, + userId: userId.present ? userId.value : this.userId, + clientId: clientId ?? this.clientId, + rev: rev.present ? rev.value : this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + lastSyncedAt: + lastSyncedAt.present ? lastSyncedAt.value : this.lastSyncedAt, + type: type ?? this.type, + title: title ?? this.title, + body: body ?? this.body, + data: data ?? this.data, + readAt: readAt.present ? readAt.value : this.readAt, + ); + NotificationsData copyWithCompanion(NotificationsCompanion data) { + return NotificationsData( + id: data.id.present ? data.id.value : this.id, + userId: data.userId.present ? data.userId.value : this.userId, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + rev: data.rev.present ? data.rev.value : this.rev, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + lastSyncedAt: data.lastSyncedAt.present + ? data.lastSyncedAt.value + : this.lastSyncedAt, + type: data.type.present ? data.type.value : this.type, + title: data.title.present ? data.title.value : this.title, + body: data.body.present ? data.body.value : this.body, + data: data.data.present ? data.data.value : this.data, + readAt: data.readAt.present ? data.readAt.value : this.readAt, + ); + } + + @override + String toString() { + return (StringBuffer('NotificationsData(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('type: $type, ') + ..write('title: $title, ') + ..write('body: $body, ') + ..write('data: $data, ') + ..write('readAt: $readAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, userId, clientId, rev, createdAt, + updatedAt, deletedAt, lastSyncedAt, type, title, body, data, readAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is NotificationsData && + other.id == this.id && + other.userId == this.userId && + other.clientId == this.clientId && + other.rev == this.rev && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.lastSyncedAt == this.lastSyncedAt && + other.type == this.type && + other.title == this.title && + other.body == this.body && + other.data == this.data && + other.readAt == this.readAt); +} + +class NotificationsCompanion extends UpdateCompanion { + final Value id; + final Value userId; + final Value clientId; + final Value rev; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value lastSyncedAt; + final Value type; + final Value title; + final Value body; + final Value data; + final Value readAt; + final Value rowid; + const NotificationsCompanion({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + this.type = const Value.absent(), + this.title = const Value.absent(), + this.body = const Value.absent(), + this.data = const Value.absent(), + this.readAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + NotificationsCompanion.insert({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + required String type, + required String title, + required String body, + required String data, + this.readAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : type = Value(type), + title = Value(title), + body = Value(body), + data = Value(data); + static Insertable custom({ + Expression? id, + Expression? userId, + Expression? clientId, + Expression? rev, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? lastSyncedAt, + Expression? type, + Expression? title, + Expression? body, + Expression? data, + Expression? readAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (userId != null) 'user_id': userId, + if (clientId != null) 'client_id': clientId, + if (rev != null) 'rev': rev, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (lastSyncedAt != null) 'last_synced_at': lastSyncedAt, + if (type != null) 'type': type, + if (title != null) 'title': title, + if (body != null) 'body': body, + if (data != null) 'data': data, + if (readAt != null) 'read_at': readAt, + if (rowid != null) 'rowid': rowid, + }); + } + + NotificationsCompanion copyWith( + {Value? id, + Value? userId, + Value? clientId, + Value? rev, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? lastSyncedAt, + Value? type, + Value? title, + Value? body, + Value? data, + Value? readAt, + Value? rowid}) { + return NotificationsCompanion( + id: id ?? this.id, + userId: userId ?? this.userId, + clientId: clientId ?? this.clientId, + rev: rev ?? this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt, + type: type ?? this.type, + title: title ?? this.title, + body: body ?? this.body, + data: data ?? this.data, + readAt: readAt ?? this.readAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (rev.present) { + map['rev'] = Variable(rev.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (lastSyncedAt.present) { + map['last_synced_at'] = Variable(lastSyncedAt.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (title.present) { + map['title'] = Variable(title.value); + } + if (body.present) { + map['body'] = Variable(body.value); + } + if (data.present) { + map['data'] = Variable(data.value); + } + if (readAt.present) { + map['read_at'] = Variable(readAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('NotificationsCompanion(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('type: $type, ') + ..write('title: $title, ') + ..write('body: $body, ') + ..write('data: $data, ') + ..write('readAt: $readAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class MediaFiles extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + MediaFiles(this.attachedDatabase, [this._alias]); + late final GeneratedColumn path = GeneratedColumn( + 'path', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn fileableType = GeneratedColumn( + 'fileable_type', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn fileableId = GeneratedColumn( + 'fileable_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn localFileableType = + GeneratedColumn('local_fileable_type', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn localFileableId = GeneratedColumn( + 'local_fileable_id', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [ + path, + id, + type, + fileableType, + fileableId, + localFileableType, + localFileableId, + createdAt, + updatedAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'media_files'; + @override + Set get $primaryKey => {path}; + @override + MediaFilesData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return MediaFilesData( + path: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}path'])!, + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id']), + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type']), + fileableType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}fileable_type']), + fileableId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}fileable_id']), + localFileableType: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}local_fileable_type']), + localFileableId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}local_fileable_id']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at']), + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at']), + ); + } + + @override + MediaFiles createAlias(String alias) { + return MediaFiles(attachedDatabase, alias); + } +} + +class MediaFilesData extends DataClass implements Insertable { + final String path; + final int? id; + final String? type; + final String? fileableType; + final int? fileableId; + final String? localFileableType; + final String? localFileableId; + final DateTime? createdAt; + final DateTime? updatedAt; + const MediaFilesData( + {required this.path, + this.id, + this.type, + this.fileableType, + this.fileableId, + this.localFileableType, + this.localFileableId, + this.createdAt, + this.updatedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['path'] = Variable(path); + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || type != null) { + map['type'] = Variable(type); + } + if (!nullToAbsent || fileableType != null) { + map['fileable_type'] = Variable(fileableType); + } + if (!nullToAbsent || fileableId != null) { + map['fileable_id'] = Variable(fileableId); + } + if (!nullToAbsent || localFileableType != null) { + map['local_fileable_type'] = Variable(localFileableType); + } + if (!nullToAbsent || localFileableId != null) { + map['local_fileable_id'] = Variable(localFileableId); + } + if (!nullToAbsent || createdAt != null) { + map['created_at'] = Variable(createdAt); + } + if (!nullToAbsent || updatedAt != null) { + map['updated_at'] = Variable(updatedAt); + } + return map; + } + + MediaFilesCompanion toCompanion(bool nullToAbsent) { + return MediaFilesCompanion( + path: Value(path), + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + type: type == null && nullToAbsent ? const Value.absent() : Value(type), + fileableType: fileableType == null && nullToAbsent + ? const Value.absent() + : Value(fileableType), + fileableId: fileableId == null && nullToAbsent + ? const Value.absent() + : Value(fileableId), + localFileableType: localFileableType == null && nullToAbsent + ? const Value.absent() + : Value(localFileableType), + localFileableId: localFileableId == null && nullToAbsent + ? const Value.absent() + : Value(localFileableId), + createdAt: createdAt == null && nullToAbsent + ? const Value.absent() + : Value(createdAt), + updatedAt: updatedAt == null && nullToAbsent + ? const Value.absent() + : Value(updatedAt), + ); + } + + factory MediaFilesData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return MediaFilesData( + path: serializer.fromJson(json['path']), + id: serializer.fromJson(json['id']), + type: serializer.fromJson(json['type']), + fileableType: serializer.fromJson(json['fileableType']), + fileableId: serializer.fromJson(json['fileableId']), + localFileableType: + serializer.fromJson(json['localFileableType']), + localFileableId: serializer.fromJson(json['localFileableId']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'path': serializer.toJson(path), + 'id': serializer.toJson(id), + 'type': serializer.toJson(type), + 'fileableType': serializer.toJson(fileableType), + 'fileableId': serializer.toJson(fileableId), + 'localFileableType': serializer.toJson(localFileableType), + 'localFileableId': serializer.toJson(localFileableId), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + }; + } + + MediaFilesData copyWith( + {String? path, + Value id = const Value.absent(), + Value type = const Value.absent(), + Value fileableType = const Value.absent(), + Value fileableId = const Value.absent(), + Value localFileableType = const Value.absent(), + Value localFileableId = const Value.absent(), + Value createdAt = const Value.absent(), + Value updatedAt = const Value.absent()}) => + MediaFilesData( + path: path ?? this.path, + id: id.present ? id.value : this.id, + type: type.present ? type.value : this.type, + fileableType: + fileableType.present ? fileableType.value : this.fileableType, + fileableId: fileableId.present ? fileableId.value : this.fileableId, + localFileableType: localFileableType.present + ? localFileableType.value + : this.localFileableType, + localFileableId: localFileableId.present + ? localFileableId.value + : this.localFileableId, + createdAt: createdAt.present ? createdAt.value : this.createdAt, + updatedAt: updatedAt.present ? updatedAt.value : this.updatedAt, + ); + MediaFilesData copyWithCompanion(MediaFilesCompanion data) { + return MediaFilesData( + path: data.path.present ? data.path.value : this.path, + id: data.id.present ? data.id.value : this.id, + type: data.type.present ? data.type.value : this.type, + fileableType: data.fileableType.present + ? data.fileableType.value + : this.fileableType, + fileableId: + data.fileableId.present ? data.fileableId.value : this.fileableId, + localFileableType: data.localFileableType.present + ? data.localFileableType.value + : this.localFileableType, + localFileableId: data.localFileableId.present + ? data.localFileableId.value + : this.localFileableId, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ); + } + + @override + String toString() { + return (StringBuffer('MediaFilesData(') + ..write('path: $path, ') + ..write('id: $id, ') + ..write('type: $type, ') + ..write('fileableType: $fileableType, ') + ..write('fileableId: $fileableId, ') + ..write('localFileableType: $localFileableType, ') + ..write('localFileableId: $localFileableId, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(path, id, type, fileableType, fileableId, + localFileableType, localFileableId, createdAt, updatedAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is MediaFilesData && + other.path == this.path && + other.id == this.id && + other.type == this.type && + other.fileableType == this.fileableType && + other.fileableId == this.fileableId && + other.localFileableType == this.localFileableType && + other.localFileableId == this.localFileableId && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt); +} + +class MediaFilesCompanion extends UpdateCompanion { + final Value path; + final Value id; + final Value type; + final Value fileableType; + final Value fileableId; + final Value localFileableType; + final Value localFileableId; + final Value createdAt; + final Value updatedAt; + final Value rowid; + const MediaFilesCompanion({ + this.path = const Value.absent(), + this.id = const Value.absent(), + this.type = const Value.absent(), + this.fileableType = const Value.absent(), + this.fileableId = const Value.absent(), + this.localFileableType = const Value.absent(), + this.localFileableId = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + MediaFilesCompanion.insert({ + required String path, + this.id = const Value.absent(), + this.type = const Value.absent(), + this.fileableType = const Value.absent(), + this.fileableId = const Value.absent(), + this.localFileableType = const Value.absent(), + this.localFileableId = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : path = Value(path); + static Insertable custom({ + Expression? path, + Expression? id, + Expression? type, + Expression? fileableType, + Expression? fileableId, + Expression? localFileableType, + Expression? localFileableId, + Expression? createdAt, + Expression? updatedAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (path != null) 'path': path, + if (id != null) 'id': id, + if (type != null) 'type': type, + if (fileableType != null) 'fileable_type': fileableType, + if (fileableId != null) 'fileable_id': fileableId, + if (localFileableType != null) 'local_fileable_type': localFileableType, + if (localFileableId != null) 'local_fileable_id': localFileableId, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (rowid != null) 'rowid': rowid, + }); + } + + MediaFilesCompanion copyWith( + {Value? path, + Value? id, + Value? type, + Value? fileableType, + Value? fileableId, + Value? localFileableType, + Value? localFileableId, + Value? createdAt, + Value? updatedAt, + Value? rowid}) { + return MediaFilesCompanion( + path: path ?? this.path, + id: id ?? this.id, + type: type ?? this.type, + fileableType: fileableType ?? this.fileableType, + fileableId: fileableId ?? this.fileableId, + localFileableType: localFileableType ?? this.localFileableType, + localFileableId: localFileableId ?? this.localFileableId, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (path.present) { + map['path'] = Variable(path.value); + } + if (id.present) { + map['id'] = Variable(id.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (fileableType.present) { + map['fileable_type'] = Variable(fileableType.value); + } + if (fileableId.present) { + map['fileable_id'] = Variable(fileableId.value); + } + if (localFileableType.present) { + map['local_fileable_type'] = Variable(localFileableType.value); + } + if (localFileableId.present) { + map['local_fileable_id'] = Variable(localFileableId.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MediaFilesCompanion(') + ..write('path: $path, ') + ..write('id: $id, ') + ..write('type: $type, ') + ..write('fileableType: $fileableType, ') + ..write('fileableId: $fileableId, ') + ..write('localFileableType: $localFileableType, ') + ..write('localFileableId: $localFileableId, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Transfers extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Transfers(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\'')); + late final GeneratedColumn rev = GeneratedColumn( + 'rev', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'1\'')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn lastSyncedAt = GeneratedColumn( + 'last_synced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn amount = GeneratedColumn( + 'amount', aliasedName, false, + type: DriftSqlType.double, requiredDuringInsert: true); + late final GeneratedColumn fromWalletId = GeneratedColumn( + 'from_wallet_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn toWalletId = GeneratedColumn( + 'to_wallet_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn fromWalletClientId = + GeneratedColumn('from_wallet_client_id', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES wallets (client_id)')); + late final GeneratedColumn toWalletClientId = GeneratedColumn( + 'to_wallet_client_id', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES wallets (client_id)')); + late final GeneratedColumn exchangeRate = GeneratedColumn( + 'exchange_rate', aliasedName, true, + type: DriftSqlType.double, requiredDuringInsert: false); + late final GeneratedColumn datetime = GeneratedColumn( + 'datetime', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + late final GeneratedColumn expenseTransactionClientId = + GeneratedColumn( + 'expense_transaction_client_id', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES transactions (client_id)')); + late final GeneratedColumn incomeTransactionClientId = + GeneratedColumn('income_transaction_client_id', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES transactions (client_id)')); + @override + List get $columns => [ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + amount, + fromWalletId, + toWalletId, + fromWalletClientId, + toWalletClientId, + exchangeRate, + datetime, + expenseTransactionClientId, + incomeTransactionClientId + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'transfers'; + @override + Set get $primaryKey => {clientId}; + @override + TransfersData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return TransfersData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id']), + userId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}user_id']), + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + rev: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}rev']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + deletedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}deleted_at']), + lastSyncedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_synced_at']), + amount: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}amount'])!, + fromWalletId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}from_wallet_id']), + toWalletId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}to_wallet_id']), + fromWalletClientId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}from_wallet_client_id']), + toWalletClientId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}to_wallet_client_id']), + exchangeRate: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}exchange_rate']), + datetime: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}datetime'])!, + expenseTransactionClientId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}expense_transaction_client_id']), + incomeTransactionClientId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}income_transaction_client_id']), + ); + } + + @override + Transfers createAlias(String alias) { + return Transfers(attachedDatabase, alias); + } +} + +class TransfersData extends DataClass implements Insertable { + final int? id; + final int? userId; + final String clientId; + final String? rev; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final DateTime? lastSyncedAt; + final double amount; + final int? fromWalletId; + final int? toWalletId; + final String? fromWalletClientId; + final String? toWalletClientId; + final double? exchangeRate; + final DateTime datetime; + final String? expenseTransactionClientId; + final String? incomeTransactionClientId; + const TransfersData( + {this.id, + this.userId, + required this.clientId, + this.rev, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + this.lastSyncedAt, + required this.amount, + this.fromWalletId, + this.toWalletId, + this.fromWalletClientId, + this.toWalletClientId, + this.exchangeRate, + required this.datetime, + this.expenseTransactionClientId, + this.incomeTransactionClientId}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + map['client_id'] = Variable(clientId); + if (!nullToAbsent || rev != null) { + map['rev'] = Variable(rev); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || lastSyncedAt != null) { + map['last_synced_at'] = Variable(lastSyncedAt); + } + map['amount'] = Variable(amount); + if (!nullToAbsent || fromWalletId != null) { + map['from_wallet_id'] = Variable(fromWalletId); + } + if (!nullToAbsent || toWalletId != null) { + map['to_wallet_id'] = Variable(toWalletId); + } + if (!nullToAbsent || fromWalletClientId != null) { + map['from_wallet_client_id'] = Variable(fromWalletClientId); + } + if (!nullToAbsent || toWalletClientId != null) { + map['to_wallet_client_id'] = Variable(toWalletClientId); + } + if (!nullToAbsent || exchangeRate != null) { + map['exchange_rate'] = Variable(exchangeRate); + } + map['datetime'] = Variable(datetime); + if (!nullToAbsent || expenseTransactionClientId != null) { + map['expense_transaction_client_id'] = + Variable(expenseTransactionClientId); + } + if (!nullToAbsent || incomeTransactionClientId != null) { + map['income_transaction_client_id'] = + Variable(incomeTransactionClientId); + } + return map; + } + + TransfersCompanion toCompanion(bool nullToAbsent) { + return TransfersCompanion( + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + userId: + userId == null && nullToAbsent ? const Value.absent() : Value(userId), + clientId: Value(clientId), + rev: rev == null && nullToAbsent ? const Value.absent() : Value(rev), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: deletedAt == null && nullToAbsent + ? const Value.absent() + : Value(deletedAt), + lastSyncedAt: lastSyncedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastSyncedAt), + amount: Value(amount), + fromWalletId: fromWalletId == null && nullToAbsent + ? const Value.absent() + : Value(fromWalletId), + toWalletId: toWalletId == null && nullToAbsent + ? const Value.absent() + : Value(toWalletId), + fromWalletClientId: fromWalletClientId == null && nullToAbsent + ? const Value.absent() + : Value(fromWalletClientId), + toWalletClientId: toWalletClientId == null && nullToAbsent + ? const Value.absent() + : Value(toWalletClientId), + exchangeRate: exchangeRate == null && nullToAbsent + ? const Value.absent() + : Value(exchangeRate), + datetime: Value(datetime), + expenseTransactionClientId: + expenseTransactionClientId == null && nullToAbsent + ? const Value.absent() + : Value(expenseTransactionClientId), + incomeTransactionClientId: + incomeTransactionClientId == null && nullToAbsent + ? const Value.absent() + : Value(incomeTransactionClientId), + ); + } + + factory TransfersData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return TransfersData( + id: serializer.fromJson(json['id']), + userId: serializer.fromJson(json['userId']), + clientId: serializer.fromJson(json['clientId']), + rev: serializer.fromJson(json['rev']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + lastSyncedAt: serializer.fromJson(json['lastSyncedAt']), + amount: serializer.fromJson(json['amount']), + fromWalletId: serializer.fromJson(json['fromWalletId']), + toWalletId: serializer.fromJson(json['toWalletId']), + fromWalletClientId: + serializer.fromJson(json['fromWalletClientId']), + toWalletClientId: serializer.fromJson(json['toWalletClientId']), + exchangeRate: serializer.fromJson(json['exchangeRate']), + datetime: serializer.fromJson(json['datetime']), + expenseTransactionClientId: + serializer.fromJson(json['expenseTransactionClientId']), + incomeTransactionClientId: + serializer.fromJson(json['incomeTransactionClientId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'userId': serializer.toJson(userId), + 'clientId': serializer.toJson(clientId), + 'rev': serializer.toJson(rev), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'lastSyncedAt': serializer.toJson(lastSyncedAt), + 'amount': serializer.toJson(amount), + 'fromWalletId': serializer.toJson(fromWalletId), + 'toWalletId': serializer.toJson(toWalletId), + 'fromWalletClientId': serializer.toJson(fromWalletClientId), + 'toWalletClientId': serializer.toJson(toWalletClientId), + 'exchangeRate': serializer.toJson(exchangeRate), + 'datetime': serializer.toJson(datetime), + 'expenseTransactionClientId': + serializer.toJson(expenseTransactionClientId), + 'incomeTransactionClientId': + serializer.toJson(incomeTransactionClientId), + }; + } + + TransfersData copyWith( + {Value id = const Value.absent(), + Value userId = const Value.absent(), + String? clientId, + Value rev = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + Value lastSyncedAt = const Value.absent(), + double? amount, + Value fromWalletId = const Value.absent(), + Value toWalletId = const Value.absent(), + Value fromWalletClientId = const Value.absent(), + Value toWalletClientId = const Value.absent(), + Value exchangeRate = const Value.absent(), + DateTime? datetime, + Value expenseTransactionClientId = const Value.absent(), + Value incomeTransactionClientId = const Value.absent()}) => + TransfersData( + id: id.present ? id.value : this.id, + userId: userId.present ? userId.value : this.userId, + clientId: clientId ?? this.clientId, + rev: rev.present ? rev.value : this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + lastSyncedAt: + lastSyncedAt.present ? lastSyncedAt.value : this.lastSyncedAt, + amount: amount ?? this.amount, + fromWalletId: + fromWalletId.present ? fromWalletId.value : this.fromWalletId, + toWalletId: toWalletId.present ? toWalletId.value : this.toWalletId, + fromWalletClientId: fromWalletClientId.present + ? fromWalletClientId.value + : this.fromWalletClientId, + toWalletClientId: toWalletClientId.present + ? toWalletClientId.value + : this.toWalletClientId, + exchangeRate: + exchangeRate.present ? exchangeRate.value : this.exchangeRate, + datetime: datetime ?? this.datetime, + expenseTransactionClientId: expenseTransactionClientId.present + ? expenseTransactionClientId.value + : this.expenseTransactionClientId, + incomeTransactionClientId: incomeTransactionClientId.present + ? incomeTransactionClientId.value + : this.incomeTransactionClientId, + ); + TransfersData copyWithCompanion(TransfersCompanion data) { + return TransfersData( + id: data.id.present ? data.id.value : this.id, + userId: data.userId.present ? data.userId.value : this.userId, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + rev: data.rev.present ? data.rev.value : this.rev, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + lastSyncedAt: data.lastSyncedAt.present + ? data.lastSyncedAt.value + : this.lastSyncedAt, + amount: data.amount.present ? data.amount.value : this.amount, + fromWalletId: data.fromWalletId.present + ? data.fromWalletId.value + : this.fromWalletId, + toWalletId: + data.toWalletId.present ? data.toWalletId.value : this.toWalletId, + fromWalletClientId: data.fromWalletClientId.present + ? data.fromWalletClientId.value + : this.fromWalletClientId, + toWalletClientId: data.toWalletClientId.present + ? data.toWalletClientId.value + : this.toWalletClientId, + exchangeRate: data.exchangeRate.present + ? data.exchangeRate.value + : this.exchangeRate, + datetime: data.datetime.present ? data.datetime.value : this.datetime, + expenseTransactionClientId: data.expenseTransactionClientId.present + ? data.expenseTransactionClientId.value + : this.expenseTransactionClientId, + incomeTransactionClientId: data.incomeTransactionClientId.present + ? data.incomeTransactionClientId.value + : this.incomeTransactionClientId, + ); + } + + @override + String toString() { + return (StringBuffer('TransfersData(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('amount: $amount, ') + ..write('fromWalletId: $fromWalletId, ') + ..write('toWalletId: $toWalletId, ') + ..write('fromWalletClientId: $fromWalletClientId, ') + ..write('toWalletClientId: $toWalletClientId, ') + ..write('exchangeRate: $exchangeRate, ') + ..write('datetime: $datetime, ') + ..write('expenseTransactionClientId: $expenseTransactionClientId, ') + ..write('incomeTransactionClientId: $incomeTransactionClientId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + amount, + fromWalletId, + toWalletId, + fromWalletClientId, + toWalletClientId, + exchangeRate, + datetime, + expenseTransactionClientId, + incomeTransactionClientId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is TransfersData && + other.id == this.id && + other.userId == this.userId && + other.clientId == this.clientId && + other.rev == this.rev && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.lastSyncedAt == this.lastSyncedAt && + other.amount == this.amount && + other.fromWalletId == this.fromWalletId && + other.toWalletId == this.toWalletId && + other.fromWalletClientId == this.fromWalletClientId && + other.toWalletClientId == this.toWalletClientId && + other.exchangeRate == this.exchangeRate && + other.datetime == this.datetime && + other.expenseTransactionClientId == this.expenseTransactionClientId && + other.incomeTransactionClientId == this.incomeTransactionClientId); +} + +class TransfersCompanion extends UpdateCompanion { + final Value id; + final Value userId; + final Value clientId; + final Value rev; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value lastSyncedAt; + final Value amount; + final Value fromWalletId; + final Value toWalletId; + final Value fromWalletClientId; + final Value toWalletClientId; + final Value exchangeRate; + final Value datetime; + final Value expenseTransactionClientId; + final Value incomeTransactionClientId; + final Value rowid; + const TransfersCompanion({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + this.amount = const Value.absent(), + this.fromWalletId = const Value.absent(), + this.toWalletId = const Value.absent(), + this.fromWalletClientId = const Value.absent(), + this.toWalletClientId = const Value.absent(), + this.exchangeRate = const Value.absent(), + this.datetime = const Value.absent(), + this.expenseTransactionClientId = const Value.absent(), + this.incomeTransactionClientId = const Value.absent(), + this.rowid = const Value.absent(), + }); + TransfersCompanion.insert({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + required double amount, + this.fromWalletId = const Value.absent(), + this.toWalletId = const Value.absent(), + this.fromWalletClientId = const Value.absent(), + this.toWalletClientId = const Value.absent(), + this.exchangeRate = const Value.absent(), + required DateTime datetime, + this.expenseTransactionClientId = const Value.absent(), + this.incomeTransactionClientId = const Value.absent(), + this.rowid = const Value.absent(), + }) : amount = Value(amount), + datetime = Value(datetime); + static Insertable custom({ + Expression? id, + Expression? userId, + Expression? clientId, + Expression? rev, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? lastSyncedAt, + Expression? amount, + Expression? fromWalletId, + Expression? toWalletId, + Expression? fromWalletClientId, + Expression? toWalletClientId, + Expression? exchangeRate, + Expression? datetime, + Expression? expenseTransactionClientId, + Expression? incomeTransactionClientId, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (userId != null) 'user_id': userId, + if (clientId != null) 'client_id': clientId, + if (rev != null) 'rev': rev, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (lastSyncedAt != null) 'last_synced_at': lastSyncedAt, + if (amount != null) 'amount': amount, + if (fromWalletId != null) 'from_wallet_id': fromWalletId, + if (toWalletId != null) 'to_wallet_id': toWalletId, + if (fromWalletClientId != null) + 'from_wallet_client_id': fromWalletClientId, + if (toWalletClientId != null) 'to_wallet_client_id': toWalletClientId, + if (exchangeRate != null) 'exchange_rate': exchangeRate, + if (datetime != null) 'datetime': datetime, + if (expenseTransactionClientId != null) + 'expense_transaction_client_id': expenseTransactionClientId, + if (incomeTransactionClientId != null) + 'income_transaction_client_id': incomeTransactionClientId, + if (rowid != null) 'rowid': rowid, + }); + } + + TransfersCompanion copyWith( + {Value? id, + Value? userId, + Value? clientId, + Value? rev, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? lastSyncedAt, + Value? amount, + Value? fromWalletId, + Value? toWalletId, + Value? fromWalletClientId, + Value? toWalletClientId, + Value? exchangeRate, + Value? datetime, + Value? expenseTransactionClientId, + Value? incomeTransactionClientId, + Value? rowid}) { + return TransfersCompanion( + id: id ?? this.id, + userId: userId ?? this.userId, + clientId: clientId ?? this.clientId, + rev: rev ?? this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt, + amount: amount ?? this.amount, + fromWalletId: fromWalletId ?? this.fromWalletId, + toWalletId: toWalletId ?? this.toWalletId, + fromWalletClientId: fromWalletClientId ?? this.fromWalletClientId, + toWalletClientId: toWalletClientId ?? this.toWalletClientId, + exchangeRate: exchangeRate ?? this.exchangeRate, + datetime: datetime ?? this.datetime, + expenseTransactionClientId: + expenseTransactionClientId ?? this.expenseTransactionClientId, + incomeTransactionClientId: + incomeTransactionClientId ?? this.incomeTransactionClientId, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (rev.present) { + map['rev'] = Variable(rev.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (lastSyncedAt.present) { + map['last_synced_at'] = Variable(lastSyncedAt.value); + } + if (amount.present) { + map['amount'] = Variable(amount.value); + } + if (fromWalletId.present) { + map['from_wallet_id'] = Variable(fromWalletId.value); + } + if (toWalletId.present) { + map['to_wallet_id'] = Variable(toWalletId.value); + } + if (fromWalletClientId.present) { + map['from_wallet_client_id'] = Variable(fromWalletClientId.value); + } + if (toWalletClientId.present) { + map['to_wallet_client_id'] = Variable(toWalletClientId.value); + } + if (exchangeRate.present) { + map['exchange_rate'] = Variable(exchangeRate.value); + } + if (datetime.present) { + map['datetime'] = Variable(datetime.value); + } + if (expenseTransactionClientId.present) { + map['expense_transaction_client_id'] = + Variable(expenseTransactionClientId.value); + } + if (incomeTransactionClientId.present) { + map['income_transaction_client_id'] = + Variable(incomeTransactionClientId.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('TransfersCompanion(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('amount: $amount, ') + ..write('fromWalletId: $fromWalletId, ') + ..write('toWalletId: $toWalletId, ') + ..write('fromWalletClientId: $fromWalletClientId, ') + ..write('toWalletClientId: $toWalletClientId, ') + ..write('exchangeRate: $exchangeRate, ') + ..write('datetime: $datetime, ') + ..write('expenseTransactionClientId: $expenseTransactionClientId, ') + ..write('incomeTransactionClientId: $incomeTransactionClientId, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Budgets extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Budgets(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\'')); + late final GeneratedColumn rev = GeneratedColumn( + 'rev', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'1\'')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn lastSyncedAt = GeneratedColumn( + 'last_synced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn slug = GeneratedColumn( + 'slug', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn description = GeneratedColumn( + 'description', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn amount = GeneratedColumn( + 'amount', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn currency = GeneratedColumn( + 'currency', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn periodType = GeneratedColumn( + 'period_type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn startDate = GeneratedColumn( + 'start_date', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + late final GeneratedColumn endDate = GeneratedColumn( + 'end_date', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn rolloverEnabled = GeneratedColumn( + 'rollover_enabled', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("rollover_enabled" IN (0, 1))'), + defaultValue: const CustomExpression('0')); + late final GeneratedColumn thresholdPercent = GeneratedColumn( + 'threshold_percent', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('80')); + late final GeneratedColumn forecastAlertsEnabled = + GeneratedColumn('forecast_alerts_enabled', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("forecast_alerts_enabled" IN (0, 1))'), + defaultValue: const CustomExpression('0')); + late final GeneratedColumn isActive = GeneratedColumn( + 'is_active', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("is_active" IN (0, 1))'), + defaultValue: const CustomExpression('1')); + late final GeneratedColumn ownerType = GeneratedColumn( + 'owner_type', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'user\'')); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn progress = GeneratedColumn( + 'progress', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + @override + List get $columns => [ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + name, + slug, + description, + amount, + currency, + periodType, + startDate, + endDate, + rolloverEnabled, + thresholdPercent, + forecastAlertsEnabled, + isActive, + ownerType, + ownerId, + progress + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'budgets'; + @override + Set get $primaryKey => {clientId}; + @override + BudgetsData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return BudgetsData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id']), + userId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}user_id']), + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + rev: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}rev']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + deletedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}deleted_at']), + lastSyncedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_synced_at']), + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + slug: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}slug'])!, + description: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}description']), + amount: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}amount'])!, + currency: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}currency'])!, + periodType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}period_type'])!, + startDate: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}start_date'])!, + endDate: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}end_date']), + rolloverEnabled: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}rollover_enabled'])!, + thresholdPercent: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}threshold_percent'])!, + forecastAlertsEnabled: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}forecast_alerts_enabled'])!, + isActive: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}is_active'])!, + ownerType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}owner_type'])!, + ownerId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}owner_id']), + progress: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}progress']), + ); + } + + @override + Budgets createAlias(String alias) { + return Budgets(attachedDatabase, alias); + } +} + +class BudgetsData extends DataClass implements Insertable { + final int? id; + final int? userId; + final String clientId; + final String? rev; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final DateTime? lastSyncedAt; + final String name; + final String slug; + final String? description; + final String amount; + final String currency; + final String periodType; + final DateTime startDate; + final DateTime? endDate; + final bool rolloverEnabled; + final int thresholdPercent; + final bool forecastAlertsEnabled; + final bool isActive; + final String ownerType; + final int? ownerId; + final String? progress; + const BudgetsData( + {this.id, + this.userId, + required this.clientId, + this.rev, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + this.lastSyncedAt, + required this.name, + required this.slug, + this.description, + required this.amount, + required this.currency, + required this.periodType, + required this.startDate, + this.endDate, + required this.rolloverEnabled, + required this.thresholdPercent, + required this.forecastAlertsEnabled, + required this.isActive, + required this.ownerType, + this.ownerId, + this.progress}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + map['client_id'] = Variable(clientId); + if (!nullToAbsent || rev != null) { + map['rev'] = Variable(rev); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || lastSyncedAt != null) { + map['last_synced_at'] = Variable(lastSyncedAt); + } + map['name'] = Variable(name); + map['slug'] = Variable(slug); + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + map['amount'] = Variable(amount); + map['currency'] = Variable(currency); + map['period_type'] = Variable(periodType); + map['start_date'] = Variable(startDate); + if (!nullToAbsent || endDate != null) { + map['end_date'] = Variable(endDate); + } + map['rollover_enabled'] = Variable(rolloverEnabled); + map['threshold_percent'] = Variable(thresholdPercent); + map['forecast_alerts_enabled'] = Variable(forecastAlertsEnabled); + map['is_active'] = Variable(isActive); + map['owner_type'] = Variable(ownerType); + if (!nullToAbsent || ownerId != null) { + map['owner_id'] = Variable(ownerId); + } + if (!nullToAbsent || progress != null) { + map['progress'] = Variable(progress); + } + return map; + } + + BudgetsCompanion toCompanion(bool nullToAbsent) { + return BudgetsCompanion( + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + userId: + userId == null && nullToAbsent ? const Value.absent() : Value(userId), + clientId: Value(clientId), + rev: rev == null && nullToAbsent ? const Value.absent() : Value(rev), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: deletedAt == null && nullToAbsent + ? const Value.absent() + : Value(deletedAt), + lastSyncedAt: lastSyncedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastSyncedAt), + name: Value(name), + slug: Value(slug), + description: description == null && nullToAbsent + ? const Value.absent() + : Value(description), + amount: Value(amount), + currency: Value(currency), + periodType: Value(periodType), + startDate: Value(startDate), + endDate: endDate == null && nullToAbsent + ? const Value.absent() + : Value(endDate), + rolloverEnabled: Value(rolloverEnabled), + thresholdPercent: Value(thresholdPercent), + forecastAlertsEnabled: Value(forecastAlertsEnabled), + isActive: Value(isActive), + ownerType: Value(ownerType), + ownerId: ownerId == null && nullToAbsent + ? const Value.absent() + : Value(ownerId), + progress: progress == null && nullToAbsent + ? const Value.absent() + : Value(progress), + ); + } + + factory BudgetsData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return BudgetsData( + id: serializer.fromJson(json['id']), + userId: serializer.fromJson(json['userId']), + clientId: serializer.fromJson(json['clientId']), + rev: serializer.fromJson(json['rev']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + lastSyncedAt: serializer.fromJson(json['lastSyncedAt']), + name: serializer.fromJson(json['name']), + slug: serializer.fromJson(json['slug']), + description: serializer.fromJson(json['description']), + amount: serializer.fromJson(json['amount']), + currency: serializer.fromJson(json['currency']), + periodType: serializer.fromJson(json['periodType']), + startDate: serializer.fromJson(json['startDate']), + endDate: serializer.fromJson(json['endDate']), + rolloverEnabled: serializer.fromJson(json['rolloverEnabled']), + thresholdPercent: serializer.fromJson(json['thresholdPercent']), + forecastAlertsEnabled: + serializer.fromJson(json['forecastAlertsEnabled']), + isActive: serializer.fromJson(json['isActive']), + ownerType: serializer.fromJson(json['ownerType']), + ownerId: serializer.fromJson(json['ownerId']), + progress: serializer.fromJson(json['progress']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'userId': serializer.toJson(userId), + 'clientId': serializer.toJson(clientId), + 'rev': serializer.toJson(rev), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'lastSyncedAt': serializer.toJson(lastSyncedAt), + 'name': serializer.toJson(name), + 'slug': serializer.toJson(slug), + 'description': serializer.toJson(description), + 'amount': serializer.toJson(amount), + 'currency': serializer.toJson(currency), + 'periodType': serializer.toJson(periodType), + 'startDate': serializer.toJson(startDate), + 'endDate': serializer.toJson(endDate), + 'rolloverEnabled': serializer.toJson(rolloverEnabled), + 'thresholdPercent': serializer.toJson(thresholdPercent), + 'forecastAlertsEnabled': serializer.toJson(forecastAlertsEnabled), + 'isActive': serializer.toJson(isActive), + 'ownerType': serializer.toJson(ownerType), + 'ownerId': serializer.toJson(ownerId), + 'progress': serializer.toJson(progress), + }; + } + + BudgetsData copyWith( + {Value id = const Value.absent(), + Value userId = const Value.absent(), + String? clientId, + Value rev = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + Value lastSyncedAt = const Value.absent(), + String? name, + String? slug, + Value description = const Value.absent(), + String? amount, + String? currency, + String? periodType, + DateTime? startDate, + Value endDate = const Value.absent(), + bool? rolloverEnabled, + int? thresholdPercent, + bool? forecastAlertsEnabled, + bool? isActive, + String? ownerType, + Value ownerId = const Value.absent(), + Value progress = const Value.absent()}) => + BudgetsData( + id: id.present ? id.value : this.id, + userId: userId.present ? userId.value : this.userId, + clientId: clientId ?? this.clientId, + rev: rev.present ? rev.value : this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + lastSyncedAt: + lastSyncedAt.present ? lastSyncedAt.value : this.lastSyncedAt, + name: name ?? this.name, + slug: slug ?? this.slug, + description: description.present ? description.value : this.description, + amount: amount ?? this.amount, + currency: currency ?? this.currency, + periodType: periodType ?? this.periodType, + startDate: startDate ?? this.startDate, + endDate: endDate.present ? endDate.value : this.endDate, + rolloverEnabled: rolloverEnabled ?? this.rolloverEnabled, + thresholdPercent: thresholdPercent ?? this.thresholdPercent, + forecastAlertsEnabled: + forecastAlertsEnabled ?? this.forecastAlertsEnabled, + isActive: isActive ?? this.isActive, + ownerType: ownerType ?? this.ownerType, + ownerId: ownerId.present ? ownerId.value : this.ownerId, + progress: progress.present ? progress.value : this.progress, + ); + BudgetsData copyWithCompanion(BudgetsCompanion data) { + return BudgetsData( + id: data.id.present ? data.id.value : this.id, + userId: data.userId.present ? data.userId.value : this.userId, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + rev: data.rev.present ? data.rev.value : this.rev, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + lastSyncedAt: data.lastSyncedAt.present + ? data.lastSyncedAt.value + : this.lastSyncedAt, + name: data.name.present ? data.name.value : this.name, + slug: data.slug.present ? data.slug.value : this.slug, + description: + data.description.present ? data.description.value : this.description, + amount: data.amount.present ? data.amount.value : this.amount, + currency: data.currency.present ? data.currency.value : this.currency, + periodType: + data.periodType.present ? data.periodType.value : this.periodType, + startDate: data.startDate.present ? data.startDate.value : this.startDate, + endDate: data.endDate.present ? data.endDate.value : this.endDate, + rolloverEnabled: data.rolloverEnabled.present + ? data.rolloverEnabled.value + : this.rolloverEnabled, + thresholdPercent: data.thresholdPercent.present + ? data.thresholdPercent.value + : this.thresholdPercent, + forecastAlertsEnabled: data.forecastAlertsEnabled.present + ? data.forecastAlertsEnabled.value + : this.forecastAlertsEnabled, + isActive: data.isActive.present ? data.isActive.value : this.isActive, + ownerType: data.ownerType.present ? data.ownerType.value : this.ownerType, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + progress: data.progress.present ? data.progress.value : this.progress, + ); + } + + @override + String toString() { + return (StringBuffer('BudgetsData(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('name: $name, ') + ..write('slug: $slug, ') + ..write('description: $description, ') + ..write('amount: $amount, ') + ..write('currency: $currency, ') + ..write('periodType: $periodType, ') + ..write('startDate: $startDate, ') + ..write('endDate: $endDate, ') + ..write('rolloverEnabled: $rolloverEnabled, ') + ..write('thresholdPercent: $thresholdPercent, ') + ..write('forecastAlertsEnabled: $forecastAlertsEnabled, ') + ..write('isActive: $isActive, ') + ..write('ownerType: $ownerType, ') + ..write('ownerId: $ownerId, ') + ..write('progress: $progress') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hashAll([ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + name, + slug, + description, + amount, + currency, + periodType, + startDate, + endDate, + rolloverEnabled, + thresholdPercent, + forecastAlertsEnabled, + isActive, + ownerType, + ownerId, + progress + ]); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is BudgetsData && + other.id == this.id && + other.userId == this.userId && + other.clientId == this.clientId && + other.rev == this.rev && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.lastSyncedAt == this.lastSyncedAt && + other.name == this.name && + other.slug == this.slug && + other.description == this.description && + other.amount == this.amount && + other.currency == this.currency && + other.periodType == this.periodType && + other.startDate == this.startDate && + other.endDate == this.endDate && + other.rolloverEnabled == this.rolloverEnabled && + other.thresholdPercent == this.thresholdPercent && + other.forecastAlertsEnabled == this.forecastAlertsEnabled && + other.isActive == this.isActive && + other.ownerType == this.ownerType && + other.ownerId == this.ownerId && + other.progress == this.progress); +} + +class BudgetsCompanion extends UpdateCompanion { + final Value id; + final Value userId; + final Value clientId; + final Value rev; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value lastSyncedAt; + final Value name; + final Value slug; + final Value description; + final Value amount; + final Value currency; + final Value periodType; + final Value startDate; + final Value endDate; + final Value rolloverEnabled; + final Value thresholdPercent; + final Value forecastAlertsEnabled; + final Value isActive; + final Value ownerType; + final Value ownerId; + final Value progress; + final Value rowid; + const BudgetsCompanion({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + this.name = const Value.absent(), + this.slug = const Value.absent(), + this.description = const Value.absent(), + this.amount = const Value.absent(), + this.currency = const Value.absent(), + this.periodType = const Value.absent(), + this.startDate = const Value.absent(), + this.endDate = const Value.absent(), + this.rolloverEnabled = const Value.absent(), + this.thresholdPercent = const Value.absent(), + this.forecastAlertsEnabled = const Value.absent(), + this.isActive = const Value.absent(), + this.ownerType = const Value.absent(), + this.ownerId = const Value.absent(), + this.progress = const Value.absent(), + this.rowid = const Value.absent(), + }); + BudgetsCompanion.insert({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + required String name, + required String slug, + this.description = const Value.absent(), + required String amount, + required String currency, + required String periodType, + required DateTime startDate, + this.endDate = const Value.absent(), + this.rolloverEnabled = const Value.absent(), + this.thresholdPercent = const Value.absent(), + this.forecastAlertsEnabled = const Value.absent(), + this.isActive = const Value.absent(), + this.ownerType = const Value.absent(), + this.ownerId = const Value.absent(), + this.progress = const Value.absent(), + this.rowid = const Value.absent(), + }) : name = Value(name), + slug = Value(slug), + amount = Value(amount), + currency = Value(currency), + periodType = Value(periodType), + startDate = Value(startDate); + static Insertable custom({ + Expression? id, + Expression? userId, + Expression? clientId, + Expression? rev, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? lastSyncedAt, + Expression? name, + Expression? slug, + Expression? description, + Expression? amount, + Expression? currency, + Expression? periodType, + Expression? startDate, + Expression? endDate, + Expression? rolloverEnabled, + Expression? thresholdPercent, + Expression? forecastAlertsEnabled, + Expression? isActive, + Expression? ownerType, + Expression? ownerId, + Expression? progress, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (userId != null) 'user_id': userId, + if (clientId != null) 'client_id': clientId, + if (rev != null) 'rev': rev, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (lastSyncedAt != null) 'last_synced_at': lastSyncedAt, + if (name != null) 'name': name, + if (slug != null) 'slug': slug, + if (description != null) 'description': description, + if (amount != null) 'amount': amount, + if (currency != null) 'currency': currency, + if (periodType != null) 'period_type': periodType, + if (startDate != null) 'start_date': startDate, + if (endDate != null) 'end_date': endDate, + if (rolloverEnabled != null) 'rollover_enabled': rolloverEnabled, + if (thresholdPercent != null) 'threshold_percent': thresholdPercent, + if (forecastAlertsEnabled != null) + 'forecast_alerts_enabled': forecastAlertsEnabled, + if (isActive != null) 'is_active': isActive, + if (ownerType != null) 'owner_type': ownerType, + if (ownerId != null) 'owner_id': ownerId, + if (progress != null) 'progress': progress, + if (rowid != null) 'rowid': rowid, + }); + } + + BudgetsCompanion copyWith( + {Value? id, + Value? userId, + Value? clientId, + Value? rev, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? lastSyncedAt, + Value? name, + Value? slug, + Value? description, + Value? amount, + Value? currency, + Value? periodType, + Value? startDate, + Value? endDate, + Value? rolloverEnabled, + Value? thresholdPercent, + Value? forecastAlertsEnabled, + Value? isActive, + Value? ownerType, + Value? ownerId, + Value? progress, + Value? rowid}) { + return BudgetsCompanion( + id: id ?? this.id, + userId: userId ?? this.userId, + clientId: clientId ?? this.clientId, + rev: rev ?? this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt, + name: name ?? this.name, + slug: slug ?? this.slug, + description: description ?? this.description, + amount: amount ?? this.amount, + currency: currency ?? this.currency, + periodType: periodType ?? this.periodType, + startDate: startDate ?? this.startDate, + endDate: endDate ?? this.endDate, + rolloverEnabled: rolloverEnabled ?? this.rolloverEnabled, + thresholdPercent: thresholdPercent ?? this.thresholdPercent, + forecastAlertsEnabled: + forecastAlertsEnabled ?? this.forecastAlertsEnabled, + isActive: isActive ?? this.isActive, + ownerType: ownerType ?? this.ownerType, + ownerId: ownerId ?? this.ownerId, + progress: progress ?? this.progress, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (rev.present) { + map['rev'] = Variable(rev.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (lastSyncedAt.present) { + map['last_synced_at'] = Variable(lastSyncedAt.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (slug.present) { + map['slug'] = Variable(slug.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (amount.present) { + map['amount'] = Variable(amount.value); + } + if (currency.present) { + map['currency'] = Variable(currency.value); + } + if (periodType.present) { + map['period_type'] = Variable(periodType.value); + } + if (startDate.present) { + map['start_date'] = Variable(startDate.value); + } + if (endDate.present) { + map['end_date'] = Variable(endDate.value); + } + if (rolloverEnabled.present) { + map['rollover_enabled'] = Variable(rolloverEnabled.value); + } + if (thresholdPercent.present) { + map['threshold_percent'] = Variable(thresholdPercent.value); + } + if (forecastAlertsEnabled.present) { + map['forecast_alerts_enabled'] = + Variable(forecastAlertsEnabled.value); + } + if (isActive.present) { + map['is_active'] = Variable(isActive.value); + } + if (ownerType.present) { + map['owner_type'] = Variable(ownerType.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (progress.present) { + map['progress'] = Variable(progress.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('BudgetsCompanion(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('name: $name, ') + ..write('slug: $slug, ') + ..write('description: $description, ') + ..write('amount: $amount, ') + ..write('currency: $currency, ') + ..write('periodType: $periodType, ') + ..write('startDate: $startDate, ') + ..write('endDate: $endDate, ') + ..write('rolloverEnabled: $rolloverEnabled, ') + ..write('thresholdPercent: $thresholdPercent, ') + ..write('forecastAlertsEnabled: $forecastAlertsEnabled, ') + ..write('isActive: $isActive, ') + ..write('ownerType: $ownerType, ') + ..write('ownerId: $ownerId, ') + ..write('progress: $progress, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class BudgetTargets extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + BudgetTargets(this.attachedDatabase, [this._alias]); + late final GeneratedColumn budgetClientId = GeneratedColumn( + 'budget_client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES budgets (client_id)')); + late final GeneratedColumn targetType = GeneratedColumn( + 'target_type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn targetClientId = GeneratedColumn( + 'target_client_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => + [budgetClientId, targetType, targetClientId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'budget_targets'; + @override + Set get $primaryKey => + {budgetClientId, targetType, targetClientId}; + @override + BudgetTargetsData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return BudgetTargetsData( + budgetClientId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}budget_client_id'])!, + targetType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}target_type'])!, + targetClientId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}target_client_id'])!, + ); + } + + @override + BudgetTargets createAlias(String alias) { + return BudgetTargets(attachedDatabase, alias); + } +} + +class BudgetTargetsData extends DataClass + implements Insertable { + final String budgetClientId; + final String targetType; + final String targetClientId; + const BudgetTargetsData( + {required this.budgetClientId, + required this.targetType, + required this.targetClientId}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['budget_client_id'] = Variable(budgetClientId); + map['target_type'] = Variable(targetType); + map['target_client_id'] = Variable(targetClientId); + return map; + } + + BudgetTargetsCompanion toCompanion(bool nullToAbsent) { + return BudgetTargetsCompanion( + budgetClientId: Value(budgetClientId), + targetType: Value(targetType), + targetClientId: Value(targetClientId), + ); + } + + factory BudgetTargetsData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return BudgetTargetsData( + budgetClientId: serializer.fromJson(json['budgetClientId']), + targetType: serializer.fromJson(json['targetType']), + targetClientId: serializer.fromJson(json['targetClientId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'budgetClientId': serializer.toJson(budgetClientId), + 'targetType': serializer.toJson(targetType), + 'targetClientId': serializer.toJson(targetClientId), + }; + } + + BudgetTargetsData copyWith( + {String? budgetClientId, + String? targetType, + String? targetClientId}) => + BudgetTargetsData( + budgetClientId: budgetClientId ?? this.budgetClientId, + targetType: targetType ?? this.targetType, + targetClientId: targetClientId ?? this.targetClientId, + ); + BudgetTargetsData copyWithCompanion(BudgetTargetsCompanion data) { + return BudgetTargetsData( + budgetClientId: data.budgetClientId.present + ? data.budgetClientId.value + : this.budgetClientId, + targetType: + data.targetType.present ? data.targetType.value : this.targetType, + targetClientId: data.targetClientId.present + ? data.targetClientId.value + : this.targetClientId, + ); + } + + @override + String toString() { + return (StringBuffer('BudgetTargetsData(') + ..write('budgetClientId: $budgetClientId, ') + ..write('targetType: $targetType, ') + ..write('targetClientId: $targetClientId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(budgetClientId, targetType, targetClientId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is BudgetTargetsData && + other.budgetClientId == this.budgetClientId && + other.targetType == this.targetType && + other.targetClientId == this.targetClientId); +} + +class BudgetTargetsCompanion extends UpdateCompanion { + final Value budgetClientId; + final Value targetType; + final Value targetClientId; + final Value rowid; + const BudgetTargetsCompanion({ + this.budgetClientId = const Value.absent(), + this.targetType = const Value.absent(), + this.targetClientId = const Value.absent(), + this.rowid = const Value.absent(), + }); + BudgetTargetsCompanion.insert({ + required String budgetClientId, + required String targetType, + required String targetClientId, + this.rowid = const Value.absent(), + }) : budgetClientId = Value(budgetClientId), + targetType = Value(targetType), + targetClientId = Value(targetClientId); + static Insertable custom({ + Expression? budgetClientId, + Expression? targetType, + Expression? targetClientId, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (budgetClientId != null) 'budget_client_id': budgetClientId, + if (targetType != null) 'target_type': targetType, + if (targetClientId != null) 'target_client_id': targetClientId, + if (rowid != null) 'rowid': rowid, + }); + } + + BudgetTargetsCompanion copyWith( + {Value? budgetClientId, + Value? targetType, + Value? targetClientId, + Value? rowid}) { + return BudgetTargetsCompanion( + budgetClientId: budgetClientId ?? this.budgetClientId, + targetType: targetType ?? this.targetType, + targetClientId: targetClientId ?? this.targetClientId, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (budgetClientId.present) { + map['budget_client_id'] = Variable(budgetClientId.value); + } + if (targetType.present) { + map['target_type'] = Variable(targetType.value); + } + if (targetClientId.present) { + map['target_client_id'] = Variable(targetClientId.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('BudgetTargetsCompanion(') + ..write('budgetClientId: $budgetClientId, ') + ..write('targetType: $targetType, ') + ..write('targetClientId: $targetClientId, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class BudgetPeriodStates extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + BudgetPeriodStates(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\'')); + late final GeneratedColumn rev = GeneratedColumn( + 'rev', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'1\'')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn lastSyncedAt = GeneratedColumn( + 'last_synced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn budgetClientId = GeneratedColumn( + 'budget_client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES budgets (client_id)')); + late final GeneratedColumn periodStart = GeneratedColumn( + 'period_start', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + late final GeneratedColumn periodEnd = GeneratedColumn( + 'period_end', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + late final GeneratedColumn netSpent = GeneratedColumn( + 'net_spent', aliasedName, false, + type: DriftSqlType.double, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0.0')); + late final GeneratedColumn rolloverIn = GeneratedColumn( + 'rollover_in', aliasedName, false, + type: DriftSqlType.double, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0.0')); + late final GeneratedColumn rolloverOut = GeneratedColumn( + 'rollover_out', aliasedName, false, + type: DriftSqlType.double, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0.0')); + late final GeneratedColumn closedAt = GeneratedColumn( + 'closed_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + budgetClientId, + periodStart, + periodEnd, + netSpent, + rolloverIn, + rolloverOut, + closedAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'budget_period_states'; + @override + Set get $primaryKey => {clientId}; + @override + BudgetPeriodStatesData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return BudgetPeriodStatesData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id']), + userId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}user_id']), + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + rev: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}rev']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + deletedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}deleted_at']), + lastSyncedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_synced_at']), + budgetClientId: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}budget_client_id'])!, + periodStart: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}period_start'])!, + periodEnd: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}period_end'])!, + netSpent: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}net_spent'])!, + rolloverIn: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}rollover_in'])!, + rolloverOut: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}rollover_out'])!, + closedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}closed_at']), + ); + } + + @override + BudgetPeriodStates createAlias(String alias) { + return BudgetPeriodStates(attachedDatabase, alias); + } +} + +class BudgetPeriodStatesData extends DataClass + implements Insertable { + final int? id; + final int? userId; + final String clientId; + final String? rev; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final DateTime? lastSyncedAt; + final String budgetClientId; + final DateTime periodStart; + final DateTime periodEnd; + final double netSpent; + final double rolloverIn; + final double rolloverOut; + final DateTime? closedAt; + const BudgetPeriodStatesData( + {this.id, + this.userId, + required this.clientId, + this.rev, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + this.lastSyncedAt, + required this.budgetClientId, + required this.periodStart, + required this.periodEnd, + required this.netSpent, + required this.rolloverIn, + required this.rolloverOut, + this.closedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + map['client_id'] = Variable(clientId); + if (!nullToAbsent || rev != null) { + map['rev'] = Variable(rev); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || lastSyncedAt != null) { + map['last_synced_at'] = Variable(lastSyncedAt); + } + map['budget_client_id'] = Variable(budgetClientId); + map['period_start'] = Variable(periodStart); + map['period_end'] = Variable(periodEnd); + map['net_spent'] = Variable(netSpent); + map['rollover_in'] = Variable(rolloverIn); + map['rollover_out'] = Variable(rolloverOut); + if (!nullToAbsent || closedAt != null) { + map['closed_at'] = Variable(closedAt); + } + return map; + } + + BudgetPeriodStatesCompanion toCompanion(bool nullToAbsent) { + return BudgetPeriodStatesCompanion( + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + userId: + userId == null && nullToAbsent ? const Value.absent() : Value(userId), + clientId: Value(clientId), + rev: rev == null && nullToAbsent ? const Value.absent() : Value(rev), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: deletedAt == null && nullToAbsent + ? const Value.absent() + : Value(deletedAt), + lastSyncedAt: lastSyncedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastSyncedAt), + budgetClientId: Value(budgetClientId), + periodStart: Value(periodStart), + periodEnd: Value(periodEnd), + netSpent: Value(netSpent), + rolloverIn: Value(rolloverIn), + rolloverOut: Value(rolloverOut), + closedAt: closedAt == null && nullToAbsent + ? const Value.absent() + : Value(closedAt), + ); + } + + factory BudgetPeriodStatesData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return BudgetPeriodStatesData( + id: serializer.fromJson(json['id']), + userId: serializer.fromJson(json['userId']), + clientId: serializer.fromJson(json['clientId']), + rev: serializer.fromJson(json['rev']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + lastSyncedAt: serializer.fromJson(json['lastSyncedAt']), + budgetClientId: serializer.fromJson(json['budgetClientId']), + periodStart: serializer.fromJson(json['periodStart']), + periodEnd: serializer.fromJson(json['periodEnd']), + netSpent: serializer.fromJson(json['netSpent']), + rolloverIn: serializer.fromJson(json['rolloverIn']), + rolloverOut: serializer.fromJson(json['rolloverOut']), + closedAt: serializer.fromJson(json['closedAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'userId': serializer.toJson(userId), + 'clientId': serializer.toJson(clientId), + 'rev': serializer.toJson(rev), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'lastSyncedAt': serializer.toJson(lastSyncedAt), + 'budgetClientId': serializer.toJson(budgetClientId), + 'periodStart': serializer.toJson(periodStart), + 'periodEnd': serializer.toJson(periodEnd), + 'netSpent': serializer.toJson(netSpent), + 'rolloverIn': serializer.toJson(rolloverIn), + 'rolloverOut': serializer.toJson(rolloverOut), + 'closedAt': serializer.toJson(closedAt), + }; + } + + BudgetPeriodStatesData copyWith( + {Value id = const Value.absent(), + Value userId = const Value.absent(), + String? clientId, + Value rev = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + Value lastSyncedAt = const Value.absent(), + String? budgetClientId, + DateTime? periodStart, + DateTime? periodEnd, + double? netSpent, + double? rolloverIn, + double? rolloverOut, + Value closedAt = const Value.absent()}) => + BudgetPeriodStatesData( + id: id.present ? id.value : this.id, + userId: userId.present ? userId.value : this.userId, + clientId: clientId ?? this.clientId, + rev: rev.present ? rev.value : this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + lastSyncedAt: + lastSyncedAt.present ? lastSyncedAt.value : this.lastSyncedAt, + budgetClientId: budgetClientId ?? this.budgetClientId, + periodStart: periodStart ?? this.periodStart, + periodEnd: periodEnd ?? this.periodEnd, + netSpent: netSpent ?? this.netSpent, + rolloverIn: rolloverIn ?? this.rolloverIn, + rolloverOut: rolloverOut ?? this.rolloverOut, + closedAt: closedAt.present ? closedAt.value : this.closedAt, + ); + BudgetPeriodStatesData copyWithCompanion(BudgetPeriodStatesCompanion data) { + return BudgetPeriodStatesData( + id: data.id.present ? data.id.value : this.id, + userId: data.userId.present ? data.userId.value : this.userId, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + rev: data.rev.present ? data.rev.value : this.rev, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + lastSyncedAt: data.lastSyncedAt.present + ? data.lastSyncedAt.value + : this.lastSyncedAt, + budgetClientId: data.budgetClientId.present + ? data.budgetClientId.value + : this.budgetClientId, + periodStart: + data.periodStart.present ? data.periodStart.value : this.periodStart, + periodEnd: data.periodEnd.present ? data.periodEnd.value : this.periodEnd, + netSpent: data.netSpent.present ? data.netSpent.value : this.netSpent, + rolloverIn: + data.rolloverIn.present ? data.rolloverIn.value : this.rolloverIn, + rolloverOut: + data.rolloverOut.present ? data.rolloverOut.value : this.rolloverOut, + closedAt: data.closedAt.present ? data.closedAt.value : this.closedAt, + ); + } + + @override + String toString() { + return (StringBuffer('BudgetPeriodStatesData(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('budgetClientId: $budgetClientId, ') + ..write('periodStart: $periodStart, ') + ..write('periodEnd: $periodEnd, ') + ..write('netSpent: $netSpent, ') + ..write('rolloverIn: $rolloverIn, ') + ..write('rolloverOut: $rolloverOut, ') + ..write('closedAt: $closedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + budgetClientId, + periodStart, + periodEnd, + netSpent, + rolloverIn, + rolloverOut, + closedAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is BudgetPeriodStatesData && + other.id == this.id && + other.userId == this.userId && + other.clientId == this.clientId && + other.rev == this.rev && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.lastSyncedAt == this.lastSyncedAt && + other.budgetClientId == this.budgetClientId && + other.periodStart == this.periodStart && + other.periodEnd == this.periodEnd && + other.netSpent == this.netSpent && + other.rolloverIn == this.rolloverIn && + other.rolloverOut == this.rolloverOut && + other.closedAt == this.closedAt); +} + +class BudgetPeriodStatesCompanion + extends UpdateCompanion { + final Value id; + final Value userId; + final Value clientId; + final Value rev; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value lastSyncedAt; + final Value budgetClientId; + final Value periodStart; + final Value periodEnd; + final Value netSpent; + final Value rolloverIn; + final Value rolloverOut; + final Value closedAt; + final Value rowid; + const BudgetPeriodStatesCompanion({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + this.budgetClientId = const Value.absent(), + this.periodStart = const Value.absent(), + this.periodEnd = const Value.absent(), + this.netSpent = const Value.absent(), + this.rolloverIn = const Value.absent(), + this.rolloverOut = const Value.absent(), + this.closedAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + BudgetPeriodStatesCompanion.insert({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + required String budgetClientId, + required DateTime periodStart, + required DateTime periodEnd, + this.netSpent = const Value.absent(), + this.rolloverIn = const Value.absent(), + this.rolloverOut = const Value.absent(), + this.closedAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : budgetClientId = Value(budgetClientId), + periodStart = Value(periodStart), + periodEnd = Value(periodEnd); + static Insertable custom({ + Expression? id, + Expression? userId, + Expression? clientId, + Expression? rev, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? lastSyncedAt, + Expression? budgetClientId, + Expression? periodStart, + Expression? periodEnd, + Expression? netSpent, + Expression? rolloverIn, + Expression? rolloverOut, + Expression? closedAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (userId != null) 'user_id': userId, + if (clientId != null) 'client_id': clientId, + if (rev != null) 'rev': rev, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (lastSyncedAt != null) 'last_synced_at': lastSyncedAt, + if (budgetClientId != null) 'budget_client_id': budgetClientId, + if (periodStart != null) 'period_start': periodStart, + if (periodEnd != null) 'period_end': periodEnd, + if (netSpent != null) 'net_spent': netSpent, + if (rolloverIn != null) 'rollover_in': rolloverIn, + if (rolloverOut != null) 'rollover_out': rolloverOut, + if (closedAt != null) 'closed_at': closedAt, + if (rowid != null) 'rowid': rowid, + }); + } + + BudgetPeriodStatesCompanion copyWith( + {Value? id, + Value? userId, + Value? clientId, + Value? rev, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? lastSyncedAt, + Value? budgetClientId, + Value? periodStart, + Value? periodEnd, + Value? netSpent, + Value? rolloverIn, + Value? rolloverOut, + Value? closedAt, + Value? rowid}) { + return BudgetPeriodStatesCompanion( + id: id ?? this.id, + userId: userId ?? this.userId, + clientId: clientId ?? this.clientId, + rev: rev ?? this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt, + budgetClientId: budgetClientId ?? this.budgetClientId, + periodStart: periodStart ?? this.periodStart, + periodEnd: periodEnd ?? this.periodEnd, + netSpent: netSpent ?? this.netSpent, + rolloverIn: rolloverIn ?? this.rolloverIn, + rolloverOut: rolloverOut ?? this.rolloverOut, + closedAt: closedAt ?? this.closedAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (rev.present) { + map['rev'] = Variable(rev.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (lastSyncedAt.present) { + map['last_synced_at'] = Variable(lastSyncedAt.value); + } + if (budgetClientId.present) { + map['budget_client_id'] = Variable(budgetClientId.value); + } + if (periodStart.present) { + map['period_start'] = Variable(periodStart.value); + } + if (periodEnd.present) { + map['period_end'] = Variable(periodEnd.value); + } + if (netSpent.present) { + map['net_spent'] = Variable(netSpent.value); + } + if (rolloverIn.present) { + map['rollover_in'] = Variable(rolloverIn.value); + } + if (rolloverOut.present) { + map['rollover_out'] = Variable(rolloverOut.value); + } + if (closedAt.present) { + map['closed_at'] = Variable(closedAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('BudgetPeriodStatesCompanion(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('budgetClientId: $budgetClientId, ') + ..write('periodStart: $periodStart, ') + ..write('periodEnd: $periodEnd, ') + ..write('netSpent: $netSpent, ') + ..write('rolloverIn: $rolloverIn, ') + ..write('rolloverOut: $rolloverOut, ') + ..write('closedAt: $closedAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Holdings extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Holdings(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn symbol = GeneratedColumn( + 'symbol', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn quantity = GeneratedColumn( + 'quantity', aliasedName, false, + type: DriftSqlType.double, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0.0')); + late final GeneratedColumn currency = GeneratedColumn( + 'currency', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn unitPrice = GeneratedColumn( + 'unit_price', aliasedName, false, + type: DriftSqlType.double, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0.0')); + late final GeneratedColumn value = GeneratedColumn( + 'value', aliasedName, false, + type: DriftSqlType.double, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0.0')); + late final GeneratedColumn priceSource = GeneratedColumn( + 'price_source', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'manual\'')); + late final GeneratedColumn provider = GeneratedColumn( + 'provider', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn externalRef = GeneratedColumn( + 'external_ref', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn lastPricedAt = GeneratedColumn( + 'last_priced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [ + id, + name, + symbol, + quantity, + currency, + unitPrice, + value, + priceSource, + provider, + externalRef, + lastPricedAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'holdings'; + @override + Set get $primaryKey => {id}; + @override + HoldingsData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return HoldingsData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + symbol: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}symbol']), + quantity: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}quantity'])!, + currency: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}currency'])!, + unitPrice: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}unit_price'])!, + value: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}value'])!, + priceSource: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}price_source'])!, + provider: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}provider']), + externalRef: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}external_ref']), + lastPricedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_priced_at']), + ); + } + + @override + Holdings createAlias(String alias) { + return Holdings(attachedDatabase, alias); + } +} + +class HoldingsData extends DataClass implements Insertable { + final int id; + final String name; + final String? symbol; + final double quantity; + final String currency; + final double unitPrice; + final double value; + final String priceSource; + final String? provider; + final String? externalRef; + final DateTime? lastPricedAt; + const HoldingsData( + {required this.id, + required this.name, + this.symbol, + required this.quantity, + required this.currency, + required this.unitPrice, + required this.value, + required this.priceSource, + this.provider, + this.externalRef, + this.lastPricedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + if (!nullToAbsent || symbol != null) { + map['symbol'] = Variable(symbol); + } + map['quantity'] = Variable(quantity); + map['currency'] = Variable(currency); + map['unit_price'] = Variable(unitPrice); + map['value'] = Variable(value); + map['price_source'] = Variable(priceSource); + if (!nullToAbsent || provider != null) { + map['provider'] = Variable(provider); + } + if (!nullToAbsent || externalRef != null) { + map['external_ref'] = Variable(externalRef); + } + if (!nullToAbsent || lastPricedAt != null) { + map['last_priced_at'] = Variable(lastPricedAt); + } + return map; + } + + HoldingsCompanion toCompanion(bool nullToAbsent) { + return HoldingsCompanion( + id: Value(id), + name: Value(name), + symbol: + symbol == null && nullToAbsent ? const Value.absent() : Value(symbol), + quantity: Value(quantity), + currency: Value(currency), + unitPrice: Value(unitPrice), + value: Value(value), + priceSource: Value(priceSource), + provider: provider == null && nullToAbsent + ? const Value.absent() + : Value(provider), + externalRef: externalRef == null && nullToAbsent + ? const Value.absent() + : Value(externalRef), + lastPricedAt: lastPricedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastPricedAt), + ); + } + + factory HoldingsData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return HoldingsData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + symbol: serializer.fromJson(json['symbol']), + quantity: serializer.fromJson(json['quantity']), + currency: serializer.fromJson(json['currency']), + unitPrice: serializer.fromJson(json['unitPrice']), + value: serializer.fromJson(json['value']), + priceSource: serializer.fromJson(json['priceSource']), + provider: serializer.fromJson(json['provider']), + externalRef: serializer.fromJson(json['externalRef']), + lastPricedAt: serializer.fromJson(json['lastPricedAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'symbol': serializer.toJson(symbol), + 'quantity': serializer.toJson(quantity), + 'currency': serializer.toJson(currency), + 'unitPrice': serializer.toJson(unitPrice), + 'value': serializer.toJson(value), + 'priceSource': serializer.toJson(priceSource), + 'provider': serializer.toJson(provider), + 'externalRef': serializer.toJson(externalRef), + 'lastPricedAt': serializer.toJson(lastPricedAt), + }; + } + + HoldingsData copyWith( + {int? id, + String? name, + Value symbol = const Value.absent(), + double? quantity, + String? currency, + double? unitPrice, + double? value, + String? priceSource, + Value provider = const Value.absent(), + Value externalRef = const Value.absent(), + Value lastPricedAt = const Value.absent()}) => + HoldingsData( + id: id ?? this.id, + name: name ?? this.name, + symbol: symbol.present ? symbol.value : this.symbol, + quantity: quantity ?? this.quantity, + currency: currency ?? this.currency, + unitPrice: unitPrice ?? this.unitPrice, + value: value ?? this.value, + priceSource: priceSource ?? this.priceSource, + provider: provider.present ? provider.value : this.provider, + externalRef: externalRef.present ? externalRef.value : this.externalRef, + lastPricedAt: + lastPricedAt.present ? lastPricedAt.value : this.lastPricedAt, + ); + HoldingsData copyWithCompanion(HoldingsCompanion data) { + return HoldingsData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + symbol: data.symbol.present ? data.symbol.value : this.symbol, + quantity: data.quantity.present ? data.quantity.value : this.quantity, + currency: data.currency.present ? data.currency.value : this.currency, + unitPrice: data.unitPrice.present ? data.unitPrice.value : this.unitPrice, + value: data.value.present ? data.value.value : this.value, + priceSource: + data.priceSource.present ? data.priceSource.value : this.priceSource, + provider: data.provider.present ? data.provider.value : this.provider, + externalRef: + data.externalRef.present ? data.externalRef.value : this.externalRef, + lastPricedAt: data.lastPricedAt.present + ? data.lastPricedAt.value + : this.lastPricedAt, + ); + } + + @override + String toString() { + return (StringBuffer('HoldingsData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('symbol: $symbol, ') + ..write('quantity: $quantity, ') + ..write('currency: $currency, ') + ..write('unitPrice: $unitPrice, ') + ..write('value: $value, ') + ..write('priceSource: $priceSource, ') + ..write('provider: $provider, ') + ..write('externalRef: $externalRef, ') + ..write('lastPricedAt: $lastPricedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, name, symbol, quantity, currency, + unitPrice, value, priceSource, provider, externalRef, lastPricedAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is HoldingsData && + other.id == this.id && + other.name == this.name && + other.symbol == this.symbol && + other.quantity == this.quantity && + other.currency == this.currency && + other.unitPrice == this.unitPrice && + other.value == this.value && + other.priceSource == this.priceSource && + other.provider == this.provider && + other.externalRef == this.externalRef && + other.lastPricedAt == this.lastPricedAt); +} + +class HoldingsCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value symbol; + final Value quantity; + final Value currency; + final Value unitPrice; + final Value value; + final Value priceSource; + final Value provider; + final Value externalRef; + final Value lastPricedAt; + const HoldingsCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.symbol = const Value.absent(), + this.quantity = const Value.absent(), + this.currency = const Value.absent(), + this.unitPrice = const Value.absent(), + this.value = const Value.absent(), + this.priceSource = const Value.absent(), + this.provider = const Value.absent(), + this.externalRef = const Value.absent(), + this.lastPricedAt = const Value.absent(), + }); + HoldingsCompanion.insert({ + this.id = const Value.absent(), + required String name, + this.symbol = const Value.absent(), + this.quantity = const Value.absent(), + required String currency, + this.unitPrice = const Value.absent(), + this.value = const Value.absent(), + this.priceSource = const Value.absent(), + this.provider = const Value.absent(), + this.externalRef = const Value.absent(), + this.lastPricedAt = const Value.absent(), + }) : name = Value(name), + currency = Value(currency); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? symbol, + Expression? quantity, + Expression? currency, + Expression? unitPrice, + Expression? value, + Expression? priceSource, + Expression? provider, + Expression? externalRef, + Expression? lastPricedAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (symbol != null) 'symbol': symbol, + if (quantity != null) 'quantity': quantity, + if (currency != null) 'currency': currency, + if (unitPrice != null) 'unit_price': unitPrice, + if (value != null) 'value': value, + if (priceSource != null) 'price_source': priceSource, + if (provider != null) 'provider': provider, + if (externalRef != null) 'external_ref': externalRef, + if (lastPricedAt != null) 'last_priced_at': lastPricedAt, + }); + } + + HoldingsCompanion copyWith( + {Value? id, + Value? name, + Value? symbol, + Value? quantity, + Value? currency, + Value? unitPrice, + Value? value, + Value? priceSource, + Value? provider, + Value? externalRef, + Value? lastPricedAt}) { + return HoldingsCompanion( + id: id ?? this.id, + name: name ?? this.name, + symbol: symbol ?? this.symbol, + quantity: quantity ?? this.quantity, + currency: currency ?? this.currency, + unitPrice: unitPrice ?? this.unitPrice, + value: value ?? this.value, + priceSource: priceSource ?? this.priceSource, + provider: provider ?? this.provider, + externalRef: externalRef ?? this.externalRef, + lastPricedAt: lastPricedAt ?? this.lastPricedAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (symbol.present) { + map['symbol'] = Variable(symbol.value); + } + if (quantity.present) { + map['quantity'] = Variable(quantity.value); + } + if (currency.present) { + map['currency'] = Variable(currency.value); + } + if (unitPrice.present) { + map['unit_price'] = Variable(unitPrice.value); + } + if (value.present) { + map['value'] = Variable(value.value); + } + if (priceSource.present) { + map['price_source'] = Variable(priceSource.value); + } + if (provider.present) { + map['provider'] = Variable(provider.value); + } + if (externalRef.present) { + map['external_ref'] = Variable(externalRef.value); + } + if (lastPricedAt.present) { + map['last_priced_at'] = Variable(lastPricedAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('HoldingsCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('symbol: $symbol, ') + ..write('quantity: $quantity, ') + ..write('currency: $currency, ') + ..write('unitPrice: $unitPrice, ') + ..write('value: $value, ') + ..write('priceSource: $priceSource, ') + ..write('provider: $provider, ') + ..write('externalRef: $externalRef, ') + ..write('lastPricedAt: $lastPricedAt') + ..write(')')) + .toString(); + } +} + +class FinancialPositionCache extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + FinancialPositionCache(this.attachedDatabase, [this._alias]); + late final GeneratedColumn cacheKey = GeneratedColumn( + 'cache_key', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn payload = GeneratedColumn( + 'payload', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn currency = GeneratedColumn( + 'currency', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn fetchedAt = GeneratedColumn( + 'fetched_at', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + @override + List get $columns => + [cacheKey, payload, currency, fetchedAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'financial_position_cache'; + @override + Set get $primaryKey => {cacheKey}; + @override + FinancialPositionCacheData map(Map data, + {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return FinancialPositionCacheData( + cacheKey: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}cache_key'])!, + payload: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}payload'])!, + currency: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}currency']), + fetchedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}fetched_at'])!, + ); + } + + @override + FinancialPositionCache createAlias(String alias) { + return FinancialPositionCache(attachedDatabase, alias); + } +} + +class FinancialPositionCacheData extends DataClass + implements Insertable { + final String cacheKey; + final String payload; + final String? currency; + final DateTime fetchedAt; + const FinancialPositionCacheData( + {required this.cacheKey, + required this.payload, + this.currency, + required this.fetchedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['cache_key'] = Variable(cacheKey); + map['payload'] = Variable(payload); + if (!nullToAbsent || currency != null) { + map['currency'] = Variable(currency); + } + map['fetched_at'] = Variable(fetchedAt); + return map; + } + + FinancialPositionCacheCompanion toCompanion(bool nullToAbsent) { + return FinancialPositionCacheCompanion( + cacheKey: Value(cacheKey), + payload: Value(payload), + currency: currency == null && nullToAbsent + ? const Value.absent() + : Value(currency), + fetchedAt: Value(fetchedAt), + ); + } + + factory FinancialPositionCacheData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return FinancialPositionCacheData( + cacheKey: serializer.fromJson(json['cacheKey']), + payload: serializer.fromJson(json['payload']), + currency: serializer.fromJson(json['currency']), + fetchedAt: serializer.fromJson(json['fetchedAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'cacheKey': serializer.toJson(cacheKey), + 'payload': serializer.toJson(payload), + 'currency': serializer.toJson(currency), + 'fetchedAt': serializer.toJson(fetchedAt), + }; + } + + FinancialPositionCacheData copyWith( + {String? cacheKey, + String? payload, + Value currency = const Value.absent(), + DateTime? fetchedAt}) => + FinancialPositionCacheData( + cacheKey: cacheKey ?? this.cacheKey, + payload: payload ?? this.payload, + currency: currency.present ? currency.value : this.currency, + fetchedAt: fetchedAt ?? this.fetchedAt, + ); + FinancialPositionCacheData copyWithCompanion( + FinancialPositionCacheCompanion data) { + return FinancialPositionCacheData( + cacheKey: data.cacheKey.present ? data.cacheKey.value : this.cacheKey, + payload: data.payload.present ? data.payload.value : this.payload, + currency: data.currency.present ? data.currency.value : this.currency, + fetchedAt: data.fetchedAt.present ? data.fetchedAt.value : this.fetchedAt, + ); + } + + @override + String toString() { + return (StringBuffer('FinancialPositionCacheData(') + ..write('cacheKey: $cacheKey, ') + ..write('payload: $payload, ') + ..write('currency: $currency, ') + ..write('fetchedAt: $fetchedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(cacheKey, payload, currency, fetchedAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is FinancialPositionCacheData && + other.cacheKey == this.cacheKey && + other.payload == this.payload && + other.currency == this.currency && + other.fetchedAt == this.fetchedAt); +} + +class FinancialPositionCacheCompanion + extends UpdateCompanion { + final Value cacheKey; + final Value payload; + final Value currency; + final Value fetchedAt; + final Value rowid; + const FinancialPositionCacheCompanion({ + this.cacheKey = const Value.absent(), + this.payload = const Value.absent(), + this.currency = const Value.absent(), + this.fetchedAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + FinancialPositionCacheCompanion.insert({ + required String cacheKey, + required String payload, + this.currency = const Value.absent(), + required DateTime fetchedAt, + this.rowid = const Value.absent(), + }) : cacheKey = Value(cacheKey), + payload = Value(payload), + fetchedAt = Value(fetchedAt); + static Insertable custom({ + Expression? cacheKey, + Expression? payload, + Expression? currency, + Expression? fetchedAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (cacheKey != null) 'cache_key': cacheKey, + if (payload != null) 'payload': payload, + if (currency != null) 'currency': currency, + if (fetchedAt != null) 'fetched_at': fetchedAt, + if (rowid != null) 'rowid': rowid, + }); + } + + FinancialPositionCacheCompanion copyWith( + {Value? cacheKey, + Value? payload, + Value? currency, + Value? fetchedAt, + Value? rowid}) { + return FinancialPositionCacheCompanion( + cacheKey: cacheKey ?? this.cacheKey, + payload: payload ?? this.payload, + currency: currency ?? this.currency, + fetchedAt: fetchedAt ?? this.fetchedAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (cacheKey.present) { + map['cache_key'] = Variable(cacheKey.value); + } + if (payload.present) { + map['payload'] = Variable(payload.value); + } + if (currency.present) { + map['currency'] = Variable(currency.value); + } + if (fetchedAt.present) { + map['fetched_at'] = Variable(fetchedAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('FinancialPositionCacheCompanion(') + ..write('cacheKey: $cacheKey, ') + ..write('payload: $payload, ') + ..write('currency: $currency, ') + ..write('fetchedAt: $fetchedAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class Reminders extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + Reminders(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways('UNIQUE')); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', aliasedName, true, + type: DriftSqlType.int, requiredDuringInsert: false); + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\'')); + late final GeneratedColumn rev = GeneratedColumn( + 'rev', aliasedName, true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'1\'')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn lastSyncedAt = GeneratedColumn( + 'last_synced_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn title = GeneratedColumn( + 'title', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn description = GeneratedColumn( + 'description', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'custom\'')); + late final GeneratedColumn triggerAt = GeneratedColumn( + 'trigger_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn dueAt = GeneratedColumn( + 'due_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn repeatRule = GeneratedColumn( + 'repeat_rule', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn timezone = GeneratedColumn( + 'timezone', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn status = GeneratedColumn( + 'status', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'active\'')); + late final GeneratedColumn priority = GeneratedColumn( + 'priority', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0')); + late final GeneratedColumn snoozedUntil = GeneratedColumn( + 'snoozed_until', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn lastTriggeredAt = + GeneratedColumn('last_triggered_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + late final GeneratedColumn nextTriggerAt = + GeneratedColumn('next_trigger_at', aliasedName, true, + type: DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [ + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + title, + description, + type, + triggerAt, + dueAt, + repeatRule, + timezone, + status, + priority, + snoozedUntil, + lastTriggeredAt, + nextTriggerAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'reminders'; + @override + Set get $primaryKey => {clientId}; + @override + RemindersData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemindersData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id']), + userId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}user_id']), + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + rev: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}rev']), + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + deletedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}deleted_at']), + lastSyncedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_synced_at']), + title: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}title'])!, + description: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}description']), + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + triggerAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}trigger_at']), + dueAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}due_at']), + repeatRule: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}repeat_rule']), + timezone: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}timezone']), + status: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}status'])!, + priority: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}priority'])!, + snoozedUntil: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}snoozed_until']), + lastTriggeredAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}last_triggered_at']), + nextTriggerAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, data['${effectivePrefix}next_trigger_at']), + ); + } + + @override + Reminders createAlias(String alias) { + return Reminders(attachedDatabase, alias); + } +} + +class RemindersData extends DataClass implements Insertable { + final int? id; + final int? userId; + final String clientId; + final String? rev; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final DateTime? lastSyncedAt; + final String title; + final String? description; + final String type; + final DateTime? triggerAt; + final DateTime? dueAt; + final String? repeatRule; + final String? timezone; + final String status; + final int priority; + final DateTime? snoozedUntil; + final DateTime? lastTriggeredAt; + final DateTime? nextTriggerAt; + const RemindersData( + {this.id, + this.userId, + required this.clientId, + this.rev, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + this.lastSyncedAt, + required this.title, + this.description, + required this.type, + this.triggerAt, + this.dueAt, + this.repeatRule, + this.timezone, + required this.status, + required this.priority, + this.snoozedUntil, + this.lastTriggeredAt, + this.nextTriggerAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (!nullToAbsent || id != null) { + map['id'] = Variable(id); + } + if (!nullToAbsent || userId != null) { + map['user_id'] = Variable(userId); + } + map['client_id'] = Variable(clientId); + if (!nullToAbsent || rev != null) { + map['rev'] = Variable(rev); + } + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || lastSyncedAt != null) { + map['last_synced_at'] = Variable(lastSyncedAt); + } + map['title'] = Variable(title); + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + map['type'] = Variable(type); + if (!nullToAbsent || triggerAt != null) { + map['trigger_at'] = Variable(triggerAt); + } + if (!nullToAbsent || dueAt != null) { + map['due_at'] = Variable(dueAt); + } + if (!nullToAbsent || repeatRule != null) { + map['repeat_rule'] = Variable(repeatRule); + } + if (!nullToAbsent || timezone != null) { + map['timezone'] = Variable(timezone); + } + map['status'] = Variable(status); + map['priority'] = Variable(priority); + if (!nullToAbsent || snoozedUntil != null) { + map['snoozed_until'] = Variable(snoozedUntil); + } + if (!nullToAbsent || lastTriggeredAt != null) { + map['last_triggered_at'] = Variable(lastTriggeredAt); + } + if (!nullToAbsent || nextTriggerAt != null) { + map['next_trigger_at'] = Variable(nextTriggerAt); + } + return map; + } + + RemindersCompanion toCompanion(bool nullToAbsent) { + return RemindersCompanion( + id: id == null && nullToAbsent ? const Value.absent() : Value(id), + userId: + userId == null && nullToAbsent ? const Value.absent() : Value(userId), + clientId: Value(clientId), + rev: rev == null && nullToAbsent ? const Value.absent() : Value(rev), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: deletedAt == null && nullToAbsent + ? const Value.absent() + : Value(deletedAt), + lastSyncedAt: lastSyncedAt == null && nullToAbsent + ? const Value.absent() + : Value(lastSyncedAt), + title: Value(title), + description: description == null && nullToAbsent + ? const Value.absent() + : Value(description), + type: Value(type), + triggerAt: triggerAt == null && nullToAbsent + ? const Value.absent() + : Value(triggerAt), + dueAt: + dueAt == null && nullToAbsent ? const Value.absent() : Value(dueAt), + repeatRule: repeatRule == null && nullToAbsent + ? const Value.absent() + : Value(repeatRule), + timezone: timezone == null && nullToAbsent + ? const Value.absent() + : Value(timezone), + status: Value(status), + priority: Value(priority), + snoozedUntil: snoozedUntil == null && nullToAbsent + ? const Value.absent() + : Value(snoozedUntil), + lastTriggeredAt: lastTriggeredAt == null && nullToAbsent + ? const Value.absent() + : Value(lastTriggeredAt), + nextTriggerAt: nextTriggerAt == null && nullToAbsent + ? const Value.absent() + : Value(nextTriggerAt), + ); + } + + factory RemindersData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemindersData( + id: serializer.fromJson(json['id']), + userId: serializer.fromJson(json['userId']), + clientId: serializer.fromJson(json['clientId']), + rev: serializer.fromJson(json['rev']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + lastSyncedAt: serializer.fromJson(json['lastSyncedAt']), + title: serializer.fromJson(json['title']), + description: serializer.fromJson(json['description']), + type: serializer.fromJson(json['type']), + triggerAt: serializer.fromJson(json['triggerAt']), + dueAt: serializer.fromJson(json['dueAt']), + repeatRule: serializer.fromJson(json['repeatRule']), + timezone: serializer.fromJson(json['timezone']), + status: serializer.fromJson(json['status']), + priority: serializer.fromJson(json['priority']), + snoozedUntil: serializer.fromJson(json['snoozedUntil']), + lastTriggeredAt: serializer.fromJson(json['lastTriggeredAt']), + nextTriggerAt: serializer.fromJson(json['nextTriggerAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'userId': serializer.toJson(userId), + 'clientId': serializer.toJson(clientId), + 'rev': serializer.toJson(rev), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'lastSyncedAt': serializer.toJson(lastSyncedAt), + 'title': serializer.toJson(title), + 'description': serializer.toJson(description), + 'type': serializer.toJson(type), + 'triggerAt': serializer.toJson(triggerAt), + 'dueAt': serializer.toJson(dueAt), + 'repeatRule': serializer.toJson(repeatRule), + 'timezone': serializer.toJson(timezone), + 'status': serializer.toJson(status), + 'priority': serializer.toJson(priority), + 'snoozedUntil': serializer.toJson(snoozedUntil), + 'lastTriggeredAt': serializer.toJson(lastTriggeredAt), + 'nextTriggerAt': serializer.toJson(nextTriggerAt), + }; + } + + RemindersData copyWith( + {Value id = const Value.absent(), + Value userId = const Value.absent(), + String? clientId, + Value rev = const Value.absent(), + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + Value lastSyncedAt = const Value.absent(), + String? title, + Value description = const Value.absent(), + String? type, + Value triggerAt = const Value.absent(), + Value dueAt = const Value.absent(), + Value repeatRule = const Value.absent(), + Value timezone = const Value.absent(), + String? status, + int? priority, + Value snoozedUntil = const Value.absent(), + Value lastTriggeredAt = const Value.absent(), + Value nextTriggerAt = const Value.absent()}) => + RemindersData( + id: id.present ? id.value : this.id, + userId: userId.present ? userId.value : this.userId, + clientId: clientId ?? this.clientId, + rev: rev.present ? rev.value : this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + lastSyncedAt: + lastSyncedAt.present ? lastSyncedAt.value : this.lastSyncedAt, + title: title ?? this.title, + description: description.present ? description.value : this.description, + type: type ?? this.type, + triggerAt: triggerAt.present ? triggerAt.value : this.triggerAt, + dueAt: dueAt.present ? dueAt.value : this.dueAt, + repeatRule: repeatRule.present ? repeatRule.value : this.repeatRule, + timezone: timezone.present ? timezone.value : this.timezone, + status: status ?? this.status, + priority: priority ?? this.priority, + snoozedUntil: + snoozedUntil.present ? snoozedUntil.value : this.snoozedUntil, + lastTriggeredAt: lastTriggeredAt.present + ? lastTriggeredAt.value + : this.lastTriggeredAt, + nextTriggerAt: + nextTriggerAt.present ? nextTriggerAt.value : this.nextTriggerAt, + ); + RemindersData copyWithCompanion(RemindersCompanion data) { + return RemindersData( + id: data.id.present ? data.id.value : this.id, + userId: data.userId.present ? data.userId.value : this.userId, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + rev: data.rev.present ? data.rev.value : this.rev, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + lastSyncedAt: data.lastSyncedAt.present + ? data.lastSyncedAt.value + : this.lastSyncedAt, + title: data.title.present ? data.title.value : this.title, + description: + data.description.present ? data.description.value : this.description, + type: data.type.present ? data.type.value : this.type, + triggerAt: data.triggerAt.present ? data.triggerAt.value : this.triggerAt, + dueAt: data.dueAt.present ? data.dueAt.value : this.dueAt, + repeatRule: + data.repeatRule.present ? data.repeatRule.value : this.repeatRule, + timezone: data.timezone.present ? data.timezone.value : this.timezone, + status: data.status.present ? data.status.value : this.status, + priority: data.priority.present ? data.priority.value : this.priority, + snoozedUntil: data.snoozedUntil.present + ? data.snoozedUntil.value + : this.snoozedUntil, + lastTriggeredAt: data.lastTriggeredAt.present + ? data.lastTriggeredAt.value + : this.lastTriggeredAt, + nextTriggerAt: data.nextTriggerAt.present + ? data.nextTriggerAt.value + : this.nextTriggerAt, + ); + } + + @override + String toString() { + return (StringBuffer('RemindersData(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('title: $title, ') + ..write('description: $description, ') + ..write('type: $type, ') + ..write('triggerAt: $triggerAt, ') + ..write('dueAt: $dueAt, ') + ..write('repeatRule: $repeatRule, ') + ..write('timezone: $timezone, ') + ..write('status: $status, ') + ..write('priority: $priority, ') + ..write('snoozedUntil: $snoozedUntil, ') + ..write('lastTriggeredAt: $lastTriggeredAt, ') + ..write('nextTriggerAt: $nextTriggerAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + userId, + clientId, + rev, + createdAt, + updatedAt, + deletedAt, + lastSyncedAt, + title, + description, + type, + triggerAt, + dueAt, + repeatRule, + timezone, + status, + priority, + snoozedUntil, + lastTriggeredAt, + nextTriggerAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemindersData && + other.id == this.id && + other.userId == this.userId && + other.clientId == this.clientId && + other.rev == this.rev && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.lastSyncedAt == this.lastSyncedAt && + other.title == this.title && + other.description == this.description && + other.type == this.type && + other.triggerAt == this.triggerAt && + other.dueAt == this.dueAt && + other.repeatRule == this.repeatRule && + other.timezone == this.timezone && + other.status == this.status && + other.priority == this.priority && + other.snoozedUntil == this.snoozedUntil && + other.lastTriggeredAt == this.lastTriggeredAt && + other.nextTriggerAt == this.nextTriggerAt); +} + +class RemindersCompanion extends UpdateCompanion { + final Value id; + final Value userId; + final Value clientId; + final Value rev; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value lastSyncedAt; + final Value title; + final Value description; + final Value type; + final Value triggerAt; + final Value dueAt; + final Value repeatRule; + final Value timezone; + final Value status; + final Value priority; + final Value snoozedUntil; + final Value lastTriggeredAt; + final Value nextTriggerAt; + final Value rowid; + const RemindersCompanion({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + this.title = const Value.absent(), + this.description = const Value.absent(), + this.type = const Value.absent(), + this.triggerAt = const Value.absent(), + this.dueAt = const Value.absent(), + this.repeatRule = const Value.absent(), + this.timezone = const Value.absent(), + this.status = const Value.absent(), + this.priority = const Value.absent(), + this.snoozedUntil = const Value.absent(), + this.lastTriggeredAt = const Value.absent(), + this.nextTriggerAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + RemindersCompanion.insert({ + this.id = const Value.absent(), + this.userId = const Value.absent(), + this.clientId = const Value.absent(), + this.rev = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.lastSyncedAt = const Value.absent(), + required String title, + this.description = const Value.absent(), + this.type = const Value.absent(), + this.triggerAt = const Value.absent(), + this.dueAt = const Value.absent(), + this.repeatRule = const Value.absent(), + this.timezone = const Value.absent(), + this.status = const Value.absent(), + this.priority = const Value.absent(), + this.snoozedUntil = const Value.absent(), + this.lastTriggeredAt = const Value.absent(), + this.nextTriggerAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : title = Value(title); + static Insertable custom({ + Expression? id, + Expression? userId, + Expression? clientId, + Expression? rev, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? lastSyncedAt, + Expression? title, + Expression? description, + Expression? type, + Expression? triggerAt, + Expression? dueAt, + Expression? repeatRule, + Expression? timezone, + Expression? status, + Expression? priority, + Expression? snoozedUntil, + Expression? lastTriggeredAt, + Expression? nextTriggerAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (userId != null) 'user_id': userId, + if (clientId != null) 'client_id': clientId, + if (rev != null) 'rev': rev, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (lastSyncedAt != null) 'last_synced_at': lastSyncedAt, + if (title != null) 'title': title, + if (description != null) 'description': description, + if (type != null) 'type': type, + if (triggerAt != null) 'trigger_at': triggerAt, + if (dueAt != null) 'due_at': dueAt, + if (repeatRule != null) 'repeat_rule': repeatRule, + if (timezone != null) 'timezone': timezone, + if (status != null) 'status': status, + if (priority != null) 'priority': priority, + if (snoozedUntil != null) 'snoozed_until': snoozedUntil, + if (lastTriggeredAt != null) 'last_triggered_at': lastTriggeredAt, + if (nextTriggerAt != null) 'next_trigger_at': nextTriggerAt, + if (rowid != null) 'rowid': rowid, + }); + } + + RemindersCompanion copyWith( + {Value? id, + Value? userId, + Value? clientId, + Value? rev, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? lastSyncedAt, + Value? title, + Value? description, + Value? type, + Value? triggerAt, + Value? dueAt, + Value? repeatRule, + Value? timezone, + Value? status, + Value? priority, + Value? snoozedUntil, + Value? lastTriggeredAt, + Value? nextTriggerAt, + Value? rowid}) { + return RemindersCompanion( + id: id ?? this.id, + userId: userId ?? this.userId, + clientId: clientId ?? this.clientId, + rev: rev ?? this.rev, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt, + title: title ?? this.title, + description: description ?? this.description, + type: type ?? this.type, + triggerAt: triggerAt ?? this.triggerAt, + dueAt: dueAt ?? this.dueAt, + repeatRule: repeatRule ?? this.repeatRule, + timezone: timezone ?? this.timezone, + status: status ?? this.status, + priority: priority ?? this.priority, + snoozedUntil: snoozedUntil ?? this.snoozedUntil, + lastTriggeredAt: lastTriggeredAt ?? this.lastTriggeredAt, + nextTriggerAt: nextTriggerAt ?? this.nextTriggerAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (rev.present) { + map['rev'] = Variable(rev.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (lastSyncedAt.present) { + map['last_synced_at'] = Variable(lastSyncedAt.value); + } + if (title.present) { + map['title'] = Variable(title.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (triggerAt.present) { + map['trigger_at'] = Variable(triggerAt.value); + } + if (dueAt.present) { + map['due_at'] = Variable(dueAt.value); + } + if (repeatRule.present) { + map['repeat_rule'] = Variable(repeatRule.value); + } + if (timezone.present) { + map['timezone'] = Variable(timezone.value); + } + if (status.present) { + map['status'] = Variable(status.value); + } + if (priority.present) { + map['priority'] = Variable(priority.value); + } + if (snoozedUntil.present) { + map['snoozed_until'] = Variable(snoozedUntil.value); + } + if (lastTriggeredAt.present) { + map['last_triggered_at'] = Variable(lastTriggeredAt.value); + } + if (nextTriggerAt.present) { + map['next_trigger_at'] = Variable(nextTriggerAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemindersCompanion(') + ..write('id: $id, ') + ..write('userId: $userId, ') + ..write('clientId: $clientId, ') + ..write('rev: $rev, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('lastSyncedAt: $lastSyncedAt, ') + ..write('title: $title, ') + ..write('description: $description, ') + ..write('type: $type, ') + ..write('triggerAt: $triggerAt, ') + ..write('dueAt: $dueAt, ') + ..write('repeatRule: $repeatRule, ') + ..write('timezone: $timezone, ') + ..write('status: $status, ') + ..write('priority: $priority, ') + ..write('snoozedUntil: $snoozedUntil, ') + ..write('lastTriggeredAt: $lastTriggeredAt, ') + ..write('nextTriggerAt: $nextTriggerAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class DeferredRemoteItems extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + DeferredRemoteItems(this.attachedDatabase, [this._alias]); + late final GeneratedColumn entityType = GeneratedColumn( + 'entity_type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn clientId = GeneratedColumn( + 'client_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn data = GeneratedColumn( + 'data', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn parkedAt = GeneratedColumn( + 'parked_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP')); + @override + List get $columns => [entityType, clientId, data, parkedAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'deferred_remote_items'; + @override + Set get $primaryKey => {entityType, clientId}; + @override + DeferredRemoteItemsData map(Map data, + {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return DeferredRemoteItemsData( + entityType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}entity_type'])!, + clientId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}client_id'])!, + data: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}data'])!, + parkedAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}parked_at'])!, + ); + } + + @override + DeferredRemoteItems createAlias(String alias) { + return DeferredRemoteItems(attachedDatabase, alias); + } +} + +class DeferredRemoteItemsData extends DataClass + implements Insertable { + final String entityType; + final String clientId; + final String data; + final DateTime parkedAt; + const DeferredRemoteItemsData( + {required this.entityType, + required this.clientId, + required this.data, + required this.parkedAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['entity_type'] = Variable(entityType); + map['client_id'] = Variable(clientId); + map['data'] = Variable(data); + map['parked_at'] = Variable(parkedAt); + return map; + } + + DeferredRemoteItemsCompanion toCompanion(bool nullToAbsent) { + return DeferredRemoteItemsCompanion( + entityType: Value(entityType), + clientId: Value(clientId), + data: Value(data), + parkedAt: Value(parkedAt), + ); + } + + factory DeferredRemoteItemsData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return DeferredRemoteItemsData( + entityType: serializer.fromJson(json['entityType']), + clientId: serializer.fromJson(json['clientId']), + data: serializer.fromJson(json['data']), + parkedAt: serializer.fromJson(json['parkedAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'entityType': serializer.toJson(entityType), + 'clientId': serializer.toJson(clientId), + 'data': serializer.toJson(data), + 'parkedAt': serializer.toJson(parkedAt), + }; + } + + DeferredRemoteItemsData copyWith( + {String? entityType, + String? clientId, + String? data, + DateTime? parkedAt}) => + DeferredRemoteItemsData( + entityType: entityType ?? this.entityType, + clientId: clientId ?? this.clientId, + data: data ?? this.data, + parkedAt: parkedAt ?? this.parkedAt, + ); + DeferredRemoteItemsData copyWithCompanion(DeferredRemoteItemsCompanion data) { + return DeferredRemoteItemsData( + entityType: + data.entityType.present ? data.entityType.value : this.entityType, + clientId: data.clientId.present ? data.clientId.value : this.clientId, + data: data.data.present ? data.data.value : this.data, + parkedAt: data.parkedAt.present ? data.parkedAt.value : this.parkedAt, + ); + } + + @override + String toString() { + return (StringBuffer('DeferredRemoteItemsData(') + ..write('entityType: $entityType, ') + ..write('clientId: $clientId, ') + ..write('data: $data, ') + ..write('parkedAt: $parkedAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(entityType, clientId, data, parkedAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is DeferredRemoteItemsData && + other.entityType == this.entityType && + other.clientId == this.clientId && + other.data == this.data && + other.parkedAt == this.parkedAt); +} + +class DeferredRemoteItemsCompanion + extends UpdateCompanion { + final Value entityType; + final Value clientId; + final Value data; + final Value parkedAt; + final Value rowid; + const DeferredRemoteItemsCompanion({ + this.entityType = const Value.absent(), + this.clientId = const Value.absent(), + this.data = const Value.absent(), + this.parkedAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + DeferredRemoteItemsCompanion.insert({ + required String entityType, + required String clientId, + required String data, + this.parkedAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : entityType = Value(entityType), + clientId = Value(clientId), + data = Value(data); + static Insertable custom({ + Expression? entityType, + Expression? clientId, + Expression? data, + Expression? parkedAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (entityType != null) 'entity_type': entityType, + if (clientId != null) 'client_id': clientId, + if (data != null) 'data': data, + if (parkedAt != null) 'parked_at': parkedAt, + if (rowid != null) 'rowid': rowid, + }); + } + + DeferredRemoteItemsCompanion copyWith( + {Value? entityType, + Value? clientId, + Value? data, + Value? parkedAt, + Value? rowid}) { + return DeferredRemoteItemsCompanion( + entityType: entityType ?? this.entityType, + clientId: clientId ?? this.clientId, + data: data ?? this.data, + parkedAt: parkedAt ?? this.parkedAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (entityType.present) { + map['entity_type'] = Variable(entityType.value); + } + if (clientId.present) { + map['client_id'] = Variable(clientId.value); + } + if (data.present) { + map['data'] = Variable(data.value); + } + if (parkedAt.present) { + map['parked_at'] = Variable(parkedAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('DeferredRemoteItemsCompanion(') + ..write('entityType: $entityType, ') + ..write('clientId: $clientId, ') + ..write('data: $data, ') + ..write('parkedAt: $parkedAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class DatabaseAtV8 extends GeneratedDatabase { + DatabaseAtV8(QueryExecutor e) : super(e); + late final Wallets wallets = Wallets(this); + late final Parties parties = Parties(this); + late final Groups groups = Groups(this); + late final Transactions transactions = Transactions(this); + late final Categories categories = Categories(this); + late final Configs configs = Configs(this); + late final Users users = Users(this); + late final LocalChanges localChanges = LocalChanges(this); + late final SyncMetadata syncMetadata = SyncMetadata(this); + late final Categorizables categorizables = Categorizables(this); + late final Notifications notifications = Notifications(this); + late final MediaFiles mediaFiles = MediaFiles(this); + late final Transfers transfers = Transfers(this); + late final Budgets budgets = Budgets(this); + late final BudgetTargets budgetTargets = BudgetTargets(this); + late final BudgetPeriodStates budgetPeriodStates = BudgetPeriodStates(this); + late final Holdings holdings = Holdings(this); + late final FinancialPositionCache financialPositionCache = + FinancialPositionCache(this); + late final Reminders reminders = Reminders(this); + late final DeferredRemoteItems deferredRemoteItems = + DeferredRemoteItems(this); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [ + wallets, + parties, + groups, + transactions, + categories, + configs, + users, + localChanges, + syncMetadata, + categorizables, + notifications, + mediaFiles, + transfers, + budgets, + budgetTargets, + budgetPeriodStates, + holdings, + financialPositionCache, + reminders, + deferredRemoteItems + ]; + @override + int get schemaVersion => 8; + @override + DriftDatabaseOptions get options => + const DriftDatabaseOptions(storeDateTimeAsText: true); +} diff --git a/test/drift/default/migration_v8_test.dart b/test/drift/default/migration_v8_test.dart new file mode 100644 index 00000000..4ab3c889 --- /dev/null +++ b/test/drift/default/migration_v8_test.dart @@ -0,0 +1,26 @@ +// Verifies the v7 -> v8 migration (deferred_remote_items parking table for +// down-synced entities with unmet local dependencies). Runs the real +// `from7To8` step and validates the resulting schema against the generated +// v8 snapshot. +import 'package:drift/drift.dart'; +import 'package:drift_dev/api/migrations_native.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:trakli/data/database/app_database.dart'; + +import 'generated/schema.dart'; + +void main() { + driftRuntimeOptions.dontWarnAboutMultipleDatabases = true; + late SchemaVerifier verifier; + + setUpAll(() { + verifier = SchemaVerifier(GeneratedHelper()); + }); + + test('migrates v7 -> v8: adds deferred_remote_items', () async { + final schema = await verifier.schemaAt(7); + final db = AppDatabase(schema.newConnection()); + await verifier.migrateAndValidate(db, 8); + await db.close(); + }); +} diff --git a/test/unit/compute_local_progress_test.dart b/test/unit/compute_local_progress_test.dart index 8230ac78..44912523 100644 --- a/test/unit/compute_local_progress_test.dart +++ b/test/unit/compute_local_progress_test.dart @@ -52,12 +52,14 @@ void main() { String? groupClientId, Set categoryClientIds = const {}, int? transferId, + String? transferClientId, }) { return BudgetTxnInput( type: type, amount: amount, datetime: at ?? DateTime.utc(2026, 5, 10), transferId: transferId, + transferClientId: transferClientId, walletClientId: walletClientId, walletCurrency: walletCurrency, groupClientId: groupClientId, @@ -113,7 +115,8 @@ void main() { budget: makeBudget(), targets: const [], txns: [ - txn(amount: 100, transferId: 7), // transfer + txn(amount: 100, transferId: 7), // synced transfer + txn(amount: 100, transferClientId: 'tr-1'), // unsynced transfer txn(amount: 50, type: TransactionType.income), // income txn(amount: 10, at: DateTime.utc(2026, 4, 30)), // before window txn(amount: 10, at: DateTime.utc(2026, 6, 1)), // after window diff --git a/test/unit/deferred_remote_items_test.dart b/test/unit/deferred_remote_items_test.dart new file mode 100644 index 00000000..a57a0f20 --- /dev/null +++ b/test/unit/deferred_remote_items_test.dart @@ -0,0 +1,57 @@ +import 'package:drift/drift.dart' hide isNull, isNotNull; +import 'package:drift/native.dart'; +import 'package:drift_sync_core/drift_sync_core.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:trakli/data/database/app_database.dart'; + +void main() { + driftRuntimeOptions.dontWarnAboutMultipleDatabases = true; + late AppDatabase db; + + setUp(() { + db = AppDatabase(NativeDatabase.memory()); + }); + + tearDown(() async { + await db.close(); + }); + + group('parking store', () { + test('park / get / unpark round trip', () async { + await db.parkRemoteItem(const ParkedRemoteItem( + entityType: 'transfer', + clientId: 'device:t1', + data: {'amount': 50, 'client_generated_id': 'device:t1'}, + )); + + final parked = await db.getParkedRemoteItems('transfer'); + expect(parked, hasLength(1)); + expect(parked.single.clientId, 'device:t1'); + expect(parked.single.data['amount'], 50); + expect(parked.single.parkedAt, isNotNull); + + expect(await db.getParkedRemoteItems('transaction'), isEmpty, + reason: 'parking is scoped per entity type'); + + await db.unparkRemoteItem('transfer', 'device:t1'); + expect(await db.getParkedRemoteItems('transfer'), isEmpty); + }); + + test('re-parking the same key replaces the payload', () async { + await db.parkRemoteItem(const ParkedRemoteItem( + entityType: 'transfer', + clientId: 'device:t1', + data: {'amount': 50}, + )); + await db.parkRemoteItem(const ParkedRemoteItem( + entityType: 'transfer', + clientId: 'device:t1', + data: {'amount': 75}, + )); + + final parked = await db.getParkedRemoteItems('transfer'); + expect(parked, hasLength(1)); + expect(parked.single.data['amount'], 75); + }); + }); +} diff --git a/test/unit/local_changes_queue_test.dart b/test/unit/local_changes_queue_test.dart new file mode 100644 index 00000000..9a6a544a --- /dev/null +++ b/test/unit/local_changes_queue_test.dart @@ -0,0 +1,230 @@ +import 'package:drift/drift.dart' hide isNull; +import 'package:drift/native.dart'; +import 'package:drift_sync_core/drift_sync_core.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:trakli/data/database/app_database.dart'; + +PendingLocalChange _change( + String entityType, + String entityId, { + String? error, + DateTime? concludedMoment, + bool dismissed = false, + int attemptCount = 0, + DateTime? quarantinedAt, +}) { + return PendingLocalChange( + entityType: entityType, + entityId: entityId, + entityRev: '1', + deleted: false, + data: const {'k': 'v'}, + createMoment: DateTime(2026, 1, 1), + concluded: error != null, + concludedMoment: concludedMoment, + error: error, + dismissed: dismissed, + attemptCount: attemptCount, + quarantinedAt: quarantinedAt, + ); +} + +void main() { + driftRuntimeOptions.dontWarnAboutMultipleDatabases = true; + late AppDatabase db; + + setUp(() { + db = AppDatabase(NativeDatabase.memory()); + }); + + tearDown(() async { + await db.close(); + }); + + group('getPendingLocalChanges retry behavior', () { + test('returns changes that never errored', () async { + await db.insertLocalChange(_change('category', 'c1')); + + final pending = await db.getPendingLocalChanges(); + expect(pending.map((c) => c.entityId), ['c1']); + }); + + test('withholds an errored change while the retry delay has not passed', + () async { + await db.insertLocalChange(_change( + 'category', + 'c1', + error: 'HTTP 500', + concludedMoment: DateTime.now(), + )); + + expect(await db.getPendingLocalChanges(), isEmpty); + }); + + test('retries an errored change after the retry delay', () async { + await db.insertLocalChange(_change( + 'category', + 'c1', + error: 'HTTP 500', + concludedMoment: + DateTime.now().subtract(AppDatabase.failedChangeRetryDelay * 2), + )); + + final pending = await db.getPendingLocalChanges(); + expect(pending.map((c) => c.entityId), ['c1']); + }); + + test('never retries a dismissed change', () async { + await db.insertLocalChange(_change( + 'category', + 'c1', + error: 'HTTP 500', + concludedMoment: + DateTime.now().subtract(AppDatabase.failedChangeRetryDelay * 2), + dismissed: true, + )); + + expect(await db.getPendingLocalChanges(), isEmpty); + }); + + test('backoff grows with attemptCount', () async { + // 3 prior failures → backoff is base*4. Concluded base*3 ago: still + // withheld; base*5 ago: eligible. + const base = AppDatabase.failedChangeRetryDelay; + await db.insertLocalChange(_change( + 'category', + 'young', + error: 'HTTP 500', + attemptCount: 3, + concludedMoment: DateTime.now().subtract(base * 3), + )); + await db.insertLocalChange(_change( + 'category', + 'ready', + error: 'HTTP 500', + attemptCount: 3, + concludedMoment: DateTime.now().subtract(base * 5), + )); + + final pending = await db.getPendingLocalChanges(); + expect(pending.map((c) => c.entityId), ['ready']); + }); + + test('never retries a quarantined change', () async { + await db.insertLocalChange(_change( + 'category', + 'c1', + error: 'HTTP 422', + concludedMoment: + DateTime.now().subtract(AppDatabase.failedChangeRetryCap * 2), + quarantinedAt: DateTime.now(), + )); + + expect(await db.getPendingLocalChanges(), isEmpty); + }); + }); + + group('hasPendingTransactionChanges', () { + test('true for an ordinary pending transaction change', () async { + await db.insertLocalChange(_change('transaction', 't1')); + expect(await db.hasPendingTransactionChanges(), isTrue); + }); + + test('false once the only pending change is quarantined', () async { + // Regression: quarantine must count as "not blocking reports," or a + // permanently-failed change leaves the reports screen stuck on + // "local estimate" forever with no way to clear it. + await db.insertLocalChange(_change( + 'transaction', + 't1', + error: 'HTTP 422', + quarantinedAt: DateTime.now(), + )); + expect(await db.hasPendingTransactionChanges(), isFalse); + }); + + test('true again once a quarantined change is retried', () async { + await db.insertLocalChange(_change( + 'transfer', + 'tr1', + error: 'HTTP 422', + quarantinedAt: DateTime.now(), + )); + expect(await db.hasPendingTransactionChanges(), isFalse); + + // Editing the entity replaces the change with a fresh one — same + // effect as _retryQuarantinedChange clearing quarantinedAt. + await db.insertLocalChange(_change('transfer', 'tr1')); + expect(await db.hasPendingTransactionChanges(), isTrue); + }); + + test('false for a dismissed change', () async { + await db.insertLocalChange(_change( + 'transaction', + 't1', + error: 'HTTP 500', + dismissed: true, + )); + expect(await db.hasPendingTransactionChanges(), isFalse); + }); + + test('ignores entity types outside transaction/transfer', () async { + await db.insertLocalChange(_change('category', 'c1')); + expect(await db.hasPendingTransactionChanges(), isFalse); + }); + }); + + group('retryBackoff', () { + test('doubles per attempt and caps', () { + const base = AppDatabase.failedChangeRetryDelay; + expect(AppDatabase.retryBackoff(0), base); + expect(AppDatabase.retryBackoff(1), base); + expect(AppDatabase.retryBackoff(2), base * 2); + expect(AppDatabase.retryBackoff(3), base * 4); + expect(AppDatabase.retryBackoff(100), AppDatabase.failedChangeRetryCap); + }); + + test('caps correctly in the shift range below the old fast-path guard', + () { + // Regression: attemptCount 17-30 (shift 16-29) used to fall through + // to `base << shift` uncapped — safe on the VM's 64-bit int, but a + // magnitude that overflows 32-bit bitwise truncation on Dart web. + for (final attemptCount in [17, 20, 25, 29, 30]) { + expect(AppDatabase.retryBackoff(attemptCount), + AppDatabase.failedChangeRetryCap, + reason: 'attemptCount=$attemptCount'); + } + }); + }); + + group('concludeLocalChange', () { + test('marks only the change matching entityType and entityId as errored', + () async { + await db.insertLocalChange(_change('category', 'shared-id')); + await db.insertLocalChange(_change('transaction', 'shared-id')); + + await db.concludeLocalChange( + _change('category', 'shared-id'), + error: 'HTTP 422', + ); + + final rows = await db.select(db.localChanges).get(); + final category = rows.singleWhere((r) => r.entityType == 'category'); + final transaction = + rows.singleWhere((r) => r.entityType == 'transaction'); + expect(category.error, 'HTTP 422'); + expect(transaction.error, isNull); + }); + + test('removes the change after a successful sync', () async { + await db.insertLocalChange(_change('category', 'c1')); + + await db.concludeLocalChange( + _change('category', 'c1'), + persistedToRemote: true, + ); + + expect(await db.select(db.localChanges).get(), isEmpty); + }); + }); +} diff --git a/test/unit/month_in_review_test.dart b/test/unit/month_in_review_test.dart index 279c21f5..56b98139 100644 --- a/test/unit/month_in_review_test.dart +++ b/test/unit/month_in_review_test.dart @@ -38,6 +38,8 @@ TransactionCompleteEntity _txn({ required DateTime when, PartyEntity? party, List categories = const [], + int? transferId, + String? transferClientId, }) { return TransactionCompleteEntity( transaction: TransactionEntity( @@ -50,6 +52,8 @@ TransactionCompleteEntity _txn({ type: type, walletClientId: 'w1', partyClientId: party?.clientId, + transferId: transferId, + transferClientId: transferClientId, ), categories: categories, wallet: _wallet(), @@ -59,12 +63,13 @@ TransactionCompleteEntity _txn({ void main() { group('buildMonthInReview', () { - test('returns null only when there are no transactions at all', () { + test('returns null when there are no transactions', () { expect(buildMonthInReview(const []), isNull); }); test( - 'falls back to the most recent active month when the current month is empty', + 'anchors to the current month like web: no walk-back to an older ' + 'active month', () { final now = DateTime.now(); final twoMonthsAgo = DateTime(now.year, now.month - 2, 15); @@ -73,19 +78,39 @@ void main() { _txn(amount: 200, type: TransactionType.expense, when: twoMonthsAgo), ]; - final recap = buildMonthInReview(txns); - - expect(recap, isNotNull, - reason: - 'Recap must not be null when there is activity in an earlier month'); - expect(recap!.income, 500); - expect(recap.expense, 200); - expect(recap.net, 300); + expect(buildMonthInReview(txns), isNull, + reason: 'An empty current month must not surface older activity'); + expect(buildMonthInReview(txns, offsetMonths: 2)!.income, 500); }, ); - test('honours offsetMonths and ignores fallback when explicitly anchored', - () { + test('excludes transfer legs, synced or not', () { + final now = DateTime.now(); + final txns = [ + _txn(amount: 100, type: TransactionType.income, when: now), + _txn(amount: 40, type: TransactionType.expense, when: now), + _txn( + amount: 500, + type: TransactionType.expense, + when: now, + transferId: 7), + _txn( + amount: 500, + type: TransactionType.income, + when: now, + transferClientId: 'tr-1'), + ]; + + final recap = buildMonthInReview(txns); + expect(recap, isNotNull); + expect(recap!.income, 100); + expect(recap.expense, 40); + expect(recap.transactionCount, 2); + expect(recap.biggestExpense?.amount, 40, + reason: 'A transfer leg must never be the biggest expense'); + }); + + test('honours offsetMonths when explicitly anchored', () { final now = DateTime.now(); final thisMonth = DateTime(now.year, now.month, 5); final lastMonth = DateTime(now.year, now.month - 1, 5); diff --git a/test/unit/offline_dependency_sync_test.dart b/test/unit/offline_dependency_sync_test.dart new file mode 100644 index 00000000..3568b1ef --- /dev/null +++ b/test/unit/offline_dependency_sync_test.dart @@ -0,0 +1,168 @@ +import 'package:drift/drift.dart' hide isNull, isNotNull; +import 'package:drift/native.dart'; +import 'package:drift_sync_core/drift_sync_core.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:trakli/core/sync/sync_dependency_manager.dart'; +import 'package:trakli/data/database/app_database.dart'; +import 'package:trakli/data/datasources/category/category_remote_datasource.dart'; +import 'package:trakli/data/datasources/transaction/dto/transaction_complete_dto.dart'; +import 'package:trakli/data/datasources/transaction/transaction_remote_datasource.dart'; +import 'package:trakli/data/sync/category_sync_handler.dart'; +import 'package:trakli/data/sync/transaction_sync_handler.dart'; +import 'package:trakli/presentation/utils/enums.dart'; + +class _MockCategoryRemote extends Mock implements CategoryRemoteDataSource {} + +class _MockTransactionRemote extends Mock + implements TransactionRemoteDataSource {} + +class _AlwaysAuthorized implements RequestAuthorizationService { + @override + Future canSync() async => true; +} + +class _TestSynchronizer extends DriftSynchronizer { + _TestSynchronizer({ + required super.appDatabase, + required super.typeHandlers, + required super.dependencyManager, + required super.requestAuthorizationService, + }); +} + +void main() { + driftRuntimeOptions.dontWarnAboutMultipleDatabases = true; + + late AppDatabase db; + late _MockCategoryRemote categoryRemote; + late _MockTransactionRemote transactionRemote; + late CategorySyncHandler categoryHandler; + late TransactionSyncHandler transactionHandler; + late _TestSynchronizer synchronizer; + + setUp(() async { + db = AppDatabase(NativeDatabase.memory()); + categoryRemote = _MockCategoryRemote(); + transactionRemote = _MockTransactionRemote(); + categoryHandler = CategorySyncHandler(db, categoryRemote); + transactionHandler = TransactionSyncHandler(db, transactionRemote); + synchronizer = _TestSynchronizer( + appDatabase: db, + typeHandlers: {categoryHandler, transactionHandler}, + dependencyManager: SyncDependencyManager(), + requestAuthorizationService: _AlwaysAuthorized(), + ); + + // Wallet already synced (has a server id); the category is local-only. + await db.wallets.insertOne(WalletsCompanion.insert( + name: 'Cash', + type: WalletType.cash, + currency: 'XAF', + id: const Value(11), + clientId: const Value('w-1'), + )); + await db.categories.insertOne(CategoriesCompanion.insert( + name: 'Custom', + slug: 'custom', + type: TransactionType.expense, + clientId: const Value('c-1'), + )); + await db.transactions.insertOne(TransactionsCompanion.insert( + amount: 5000, + type: TransactionType.expense, + walletClientId: 'w-1', + clientId: const Value('t-1'), + datetime: Value(DateTime(2026, 7, 1)), + )); + await db.categorizables.insertOne(CategorizablesCompanion.insert( + categorizableId: 't-1', + categorizableType: CategorizableType.transaction, + categoryClientId: 'c-1', + )); + + final category = await categoryHandler.getLocalByClientId('c-1'); + final transaction = await transactionHandler.getLocalByClientId('t-1'); + registerFallbackValue(category); + registerFallbackValue(transaction); + + await db.insertLocalChange(PendingLocalChange( + entityType: CategorySyncHandler.entity, + entityId: 'c-1', + entityRev: '1', + deleted: false, + data: categoryHandler.marshal(category), + createMoment: DateTime(2026, 7, 1, 10), + )); + await db.insertLocalChange(PendingLocalChange( + entityType: TransactionSyncHandler.entity, + entityId: 't-1', + entityRev: '1', + deleted: false, + data: transactionHandler.marshal(transaction), + createMoment: DateTime(2026, 7, 1, 10, 1), + )); + }); + + tearDown(() async { + await db.close(); + }); + + Future changeOf(String type) async => + (await db.select(db.localChanges).get()) + .singleWhere((r) => r.entityType == type); + + test( + 'transaction deferred by the dependency gate is retried and synced ' + 'once its category syncs', () async { + // Pass 1: the category push fails server-side. The transaction must be + // deferred by the gate — still queued, not errored. + when(() => categoryRemote.insertCategory(any())) + .thenThrow(Exception('HTTP 500')); + + await synchronizer.uploadLocalChanges(); + + expect((await changeOf('category')).error, isNotNull); + expect((await changeOf('transaction')).error, isNull); + verifyNever(() => transactionRemote.insertTransaction(any())); + + // The retry delay elapses. + await (db.update(db.localChanges) + ..where((lc) => lc.entityType.equals('category'))) + .write(LocalChangesCompanion( + concludedMoment: Value( + DateTime.now().subtract(AppDatabase.failedChangeRetryDelay * 2)), + )); + + // Pass 2: the server recovers. The category gains its server id and the + // transaction follows in the same pass. + when(() => categoryRemote.insertCategory(any())).thenAnswer((inv) async { + final c = inv.positionalArguments.first as Category; + return Category.fromJson({...c.toJson(), 'id': 501}); + }); + when(() => transactionRemote.insertTransaction(any())) + .thenAnswer((inv) async { + final dto = inv.positionalArguments.first as TransactionCompleteDto; + final json = dto.toJson(); + json['transaction'] = { + ...(json['transaction'] as Map), + 'id': 900, + }; + return TransactionCompleteDto.fromJson(json); + }); + + await synchronizer.uploadLocalChanges(); + + verify(() => transactionRemote.insertTransaction(any())).called(1); + expect(await db.select(db.localChanges).get(), isEmpty); + + final syncedCategory = await (db.select(db.categories) + ..where((c) => c.clientId.equals('c-1'))) + .getSingle(); + final syncedTransaction = await (db.select(db.transactions) + ..where((t) => t.clientId.equals('t-1'))) + .getSingle(); + expect(syncedCategory.id, 501); + expect(syncedTransaction.id, 900); + }); +} diff --git a/test/unit/report_data_test.dart b/test/unit/report_data_test.dart index 52d518aa..966dd3b2 100644 --- a/test/unit/report_data_test.dart +++ b/test/unit/report_data_test.dart @@ -30,6 +30,8 @@ TransactionCompleteEntity _tx({ required TransactionType type, required DateTime when, List categories = const [], + int? transferId, + String? transferClientId, }) { return TransactionCompleteEntity( transaction: TransactionEntity( @@ -41,6 +43,8 @@ TransactionCompleteEntity _tx({ datetime: when, type: type, walletClientId: 'w1', + transferId: transferId, + transferClientId: transferClientId, ), categories: categories, wallet: _wallet(), @@ -49,6 +53,29 @@ TransactionCompleteEntity _tx({ void main() { group('buildReportData', () { + test('excludes transfer legs, synced or not, from totals and buckets', () { + final now = DateTime.now(); + final data = buildReportData([ + _tx(amount: 100, type: TransactionType.income, when: now), + _tx(amount: 40, type: TransactionType.expense, when: now), + _tx( + amount: 500, + type: TransactionType.expense, + when: now, + transferId: 7), + _tx( + amount: 500, + type: TransactionType.income, + when: now, + transferClientId: 'tr-1'), + ]); + + expect(data.totals.income, 100); + expect(data.totals.expense, 40); + expect(data.daily.last.txCount, 2, + reason: 'Transfer legs must not count as transactions'); + }); + test('daily buckets cover the requested period exactly', () { final data = buildReportData(const [], periodDays: 30); expect(data.daily.length, 30); diff --git a/test/unit/report_stats_cubit_test.dart b/test/unit/report_stats_cubit_test.dart new file mode 100644 index 00000000..f44ea6a9 --- /dev/null +++ b/test/unit/report_stats_cubit_test.dart @@ -0,0 +1,134 @@ +import 'dart:async'; + +import 'package:drift/native.dart'; +import 'package:drift_sync_core/drift_sync_core.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:trakli/core/services/auth_service.dart'; +import 'package:trakli/data/database/app_database.dart'; +import 'package:trakli/data/datasources/stats/dto/report_stats_dto.dart'; +import 'package:trakli/data/datasources/stats/stats_remote_datasource.dart'; +import 'package:trakli/presentation/statistics/cubit/report_stats_cubit.dart'; + +class _MockStatsRemote extends Mock implements StatsRemoteDataSource {} + +class _MockAuthService extends Mock implements AuthService {} + +const _serverStats = ReportStatsDto( + totalIncome: 1000, + totalExpenses: 400, + netCashFlow: 600, + savingsRate: 0.6, + expenseCategories: [], + incomeCategories: [], + partial: false, + unconvertedCurrencies: [], +); + +PendingLocalChange _transactionChange() => PendingLocalChange( + entityType: 'transaction', + entityId: 't-1', + entityRev: '1', + deleted: false, + data: const {'k': 'v'}, + createMoment: DateTime(2026, 7, 1), + ); + +void main() { + late AppDatabase db; + late _MockStatsRemote remote; + late _MockAuthService auth; + + setUp(() { + db = AppDatabase(NativeDatabase.memory()); + remote = _MockStatsRemote(); + auth = _MockAuthService(); + when(() => auth.isAuthenticated()).thenAnswer((_) async => true); + when(() => remote.getReportStats( + start: any(named: 'start'), + end: any(named: 'end'), + )).thenAnswer((_) async => _serverStats); + }); + + tearDown(() async { + await db.close(); + }); + + ReportStatsCubit cubit({Stream? syncStream}) => ReportStatsCubit( + remote: remote, + authService: auth, + db: db, + syncStream: syncStream, + ); + + test('applies server stats when signed in and nothing is pending', + () async { + final c = cubit(); + await c.load(90); + + expect(c.state.stats, _serverStats); + expect(c.state.isLocalOnly, isFalse); + expect(c.state.deferredForPendingSync, isFalse); + await c.close(); + }); + + test('signed-out users never fetch: local numbers are the only truth', + () async { + when(() => auth.isAuthenticated()).thenAnswer((_) async => false); + + final c = cubit(); + await c.load(90); + + expect(c.state.stats, isNull); + expect(c.state.isLocalOnly, isTrue); + verifyNever(() => remote.getReportStats( + start: any(named: 'start'), + end: any(named: 'end'), + )); + await c.close(); + }); + + test('withholds server stats while a transaction is waiting to sync', + () async { + await db.insertLocalChange(_transactionChange()); + + final c = cubit(); + await c.load(90); + + expect(c.state.stats, isNull, + reason: 'Server totals would be missing the unsynced transaction'); + expect(c.state.deferredForPendingSync, isTrue); + verifyNever(() => remote.getReportStats( + start: any(named: 'start'), + end: any(named: 'end'), + )); + await c.close(); + }); + + test('falls back to local numbers when the fetch fails', () async { + when(() => remote.getReportStats( + start: any(named: 'start'), + end: any(named: 'end'), + )).thenThrow(Exception('offline')); + + final c = cubit(); + await c.load(90); + + expect(c.state.stats, isNull); + expect(c.state.isLoading, isFalse); + await c.close(); + }); + + test('refetches when a sync run completes', () async { + final syncStates = StreamController(); + final c = cubit(syncStream: syncStates.stream); + + syncStates.add(const SyncState.initial()); + await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); + + expect(c.state.stats, _serverStats); + await c.close(); + await syncStates.close(); + }); +} diff --git a/test/unit/report_stats_dto_test.dart b/test/unit/report_stats_dto_test.dart new file mode 100644 index 00000000..0623f108 --- /dev/null +++ b/test/unit/report_stats_dto_test.dart @@ -0,0 +1,52 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:trakli/data/datasources/stats/dto/report_stats_dto.dart'; + +void main() { + group('ReportStatsDto.fromJson', () { + test('parses overview, charts and partial flags', () { + final dto = ReportStatsDto.fromJson({ + 'overview': { + 'total_income': 1000, + 'total_expenses': '250.50', + 'net_cash_flow': 749.5, + 'savings_rate': 74.95, + }, + 'charts': { + 'category_spending': [ + {'name': 'Groceries', 'amount': 200, 'percentage': 79.8}, + {'name': 'Coffee', 'amount': '50.50', 'percentage': 20.2}, + ], + 'income_sources': [ + {'name': 'Salary', 'amount': 1000, 'percentage': 100}, + ], + }, + 'partial': true, + 'unconverted_currencies': ['NGN'], + }); + + expect(dto.totalIncome, 1000); + expect(dto.totalExpenses, 250.50, + reason: 'String amounts from the API must parse'); + expect(dto.netCashFlow, 749.5); + expect(dto.savingsRate, closeTo(0.7495, 1e-9), + reason: 'Server percent must convert to a fraction'); + expect(dto.expenseCategories, hasLength(2)); + expect(dto.expenseCategories.first.name, 'Groceries'); + expect(dto.incomeCategories.single.amount, 1000); + expect(dto.partial, isTrue); + expect(dto.unconvertedCurrencies, ['NGN']); + }); + + test('tolerates missing sections', () { + final dto = ReportStatsDto.fromJson(const {}); + + expect(dto.totalIncome, 0); + expect(dto.totalExpenses, 0); + expect(dto.savingsRate, 0); + expect(dto.expenseCategories, isEmpty); + expect(dto.incomeCategories, isEmpty); + expect(dto.partial, isFalse); + expect(dto.unconvertedCurrencies, isEmpty); + }); + }); +} diff --git a/test/unit/sync_snapshot_unmarshal_test.dart b/test/unit/sync_snapshot_unmarshal_test.dart new file mode 100644 index 00000000..f65d7901 --- /dev/null +++ b/test/unit/sync_snapshot_unmarshal_test.dart @@ -0,0 +1,117 @@ +import 'package:drift/drift.dart' hide isNull, isNotNull; +import 'package:drift/native.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:trakli/data/database/app_database.dart'; +import 'package:trakli/data/datasources/transaction/transaction_local_datasource.dart'; +import 'package:trakli/data/datasources/transaction/transaction_remote_datasource.dart'; +import 'package:trakli/data/datasources/transfer/transfer_remote_datasource.dart'; +import 'package:trakli/data/sync/transaction_sync_handler.dart'; +import 'package:trakli/data/sync/transfer_sync_handler.dart'; +import 'package:trakli/presentation/utils/enums.dart'; + +class _MockTransferRemote extends Mock implements TransferRemoteDataSource {} + +class _MockTransactionRemote extends Mock + implements TransactionRemoteDataSource {} + +class _MockTransactionLocal extends Mock implements TransactionLocalDataSource { +} + +void main() { + driftRuntimeOptions.dontWarnAboutMultipleDatabases = true; + + late AppDatabase db; + late TransferSyncHandler transferHandler; + late TransactionSyncHandler transactionHandler; + + setUp(() async { + db = AppDatabase(NativeDatabase.memory()); + transferHandler = + TransferSyncHandler(db, _MockTransferRemote(), _MockTransactionLocal()); + transactionHandler = TransactionSyncHandler(db, _MockTransactionRemote()); + + await db.wallets.insertOne(WalletsCompanion.insert( + name: 'Cash', + type: WalletType.cash, + currency: 'XAF', + id: const Value(11), + clientId: const Value('w-1'), + )); + }); + + tearDown(() async { + await db.close(); + }); + + group('transfer snapshots', () { + Future insertTransfer() async { + await db.transfers.insertOne(TransfersCompanion.insert( + amount: 2500, + datetime: DateTime(2026, 7, 10), + clientId: const Value('tr-1'), + fromWalletClientId: const Value('w-1'), + )); + return transferHandler.getLocalByClientId('tr-1'); + } + + test('marshal/unmarshal round-trips the full row', () async { + final transfer = await insertTransfer(); + + final restored = + await transferHandler.unmarshal(transferHandler.marshal(transfer)); + + expect(restored.clientId, transfer.clientId); + expect(restored.updatedAt, transfer.updatedAt); + expect(restored.amount, transfer.amount); + expect(restored.datetime, transfer.datetime); + expect(restored.fromWalletClientId, transfer.fromWalletClientId); + }); + + test('legacy API-shaped snapshot still unmarshals', () async { + final transfer = await insertTransfer(); + + final restored = await transferHandler.unmarshal(toServerJson(transfer)); + + expect(restored.clientId, 'tr-1'); + expect(restored.updatedAt, isNotNull); + expect(restored.amount, transfer.amount); + }); + }); + + test('pre-v6 transaction snapshot without intent gets the column default', + () async { + await db.transactions.insertOne(TransactionsCompanion.insert( + amount: 5000, + type: TransactionType.expense, + walletClientId: 'w-1', + clientId: const Value('t-1'), + datetime: Value(DateTime(2026, 7, 1)), + )); + final dto = await transactionHandler.getLocalByClientId('t-1'); + + final snapshot = transactionHandler.marshal(dto); + (snapshot['transaction'] as Map).remove('intent'); + + final restored = await transactionHandler.unmarshal(snapshot); + expect(restored.transaction.intent, TransactionIntent.regular.serverKey); + }); + + test('pre-v7 transaction snapshot without is_refund defaults to false', + () async { + await db.transactions.insertOne(TransactionsCompanion.insert( + amount: 5000, + type: TransactionType.expense, + walletClientId: 'w-1', + clientId: const Value('t-2'), + datetime: Value(DateTime(2026, 7, 1)), + )); + final dto = await transactionHandler.getLocalByClientId('t-2'); + + final snapshot = transactionHandler.marshal(dto); + (snapshot['transaction'] as Map).remove('is_refund'); + + final restored = await transactionHandler.unmarshal(snapshot); + expect(restored.transaction.isRefund, false); + }); +}