Compare commits
15 Commits
e0fba11f25
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| f8ff892104 | |||
| 121d0ec236 | |||
| 71993c2686 | |||
| cbe2d5a556 | |||
| c4f7d5745a | |||
| 567f5070e9 | |||
| baf0dfa99d | |||
| facbc16bb2 | |||
| 42b1bbd438 | |||
| 5dc474407c | |||
| 4d267eff88 | |||
| ba78685bfd | |||
| e0c16031ef | |||
| 88c9991e0d | |||
| c5aa165424 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -11,6 +11,7 @@
|
|||||||
.svn/
|
.svn/
|
||||||
.swiftpm/
|
.swiftpm/
|
||||||
migrate_working_dir/
|
migrate_working_dir/
|
||||||
|
.sentry-native/
|
||||||
|
|
||||||
# IntelliJ related
|
# IntelliJ related
|
||||||
*.iml
|
*.iml
|
||||||
@@ -45,4 +46,4 @@ app.*.map.json
|
|||||||
/android/app/release
|
/android/app/release
|
||||||
|
|
||||||
# Build artifacts
|
# Build artifacts
|
||||||
lib/i18n/*
|
lib/i18n/*
|
||||||
|
|||||||
@@ -26,3 +26,8 @@ linter:
|
|||||||
|
|
||||||
# Additional information about this file can be found at
|
# Additional information about this file can be found at
|
||||||
# https://dart.dev/guides/language/analysis-options
|
# https://dart.dev/guides/language/analysis-options
|
||||||
|
analyzer:
|
||||||
|
exclude:
|
||||||
|
- "**/*.g.dart"
|
||||||
|
- build/**
|
||||||
|
- .dart_tool/**
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import 'package:isar/isar.dart';
|
|
||||||
|
|
||||||
part 'account.g.dart';
|
|
||||||
|
|
||||||
@collection
|
|
||||||
class Account {
|
|
||||||
Id id = Isar.autoIncrement;
|
|
||||||
|
|
||||||
String? name;
|
|
||||||
}
|
|
||||||
@@ -1,469 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'account.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// IsarCollectionGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
// coverage:ignore-file
|
|
||||||
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
|
|
||||||
|
|
||||||
extension GetAccountCollection on Isar {
|
|
||||||
IsarCollection<Account> get accounts => this.collection();
|
|
||||||
}
|
|
||||||
|
|
||||||
const AccountSchema = CollectionSchema(
|
|
||||||
name: r'Account',
|
|
||||||
id: -6646797162501847804,
|
|
||||||
properties: {
|
|
||||||
r'name': PropertySchema(id: 0, name: r'name', type: IsarType.string),
|
|
||||||
},
|
|
||||||
estimateSize: _accountEstimateSize,
|
|
||||||
serialize: _accountSerialize,
|
|
||||||
deserialize: _accountDeserialize,
|
|
||||||
deserializeProp: _accountDeserializeProp,
|
|
||||||
idName: r'id',
|
|
||||||
indexes: {},
|
|
||||||
links: {},
|
|
||||||
embeddedSchemas: {},
|
|
||||||
getId: _accountGetId,
|
|
||||||
getLinks: _accountGetLinks,
|
|
||||||
attach: _accountAttach,
|
|
||||||
version: '3.1.0+1',
|
|
||||||
);
|
|
||||||
|
|
||||||
int _accountEstimateSize(
|
|
||||||
Account object,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
var bytesCount = offsets.last;
|
|
||||||
{
|
|
||||||
final value = object.name;
|
|
||||||
if (value != null) {
|
|
||||||
bytesCount += 3 + value.length * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _accountSerialize(
|
|
||||||
Account object,
|
|
||||||
IsarWriter writer,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
writer.writeString(offsets[0], object.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
Account _accountDeserialize(
|
|
||||||
Id id,
|
|
||||||
IsarReader reader,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
final object = Account();
|
|
||||||
object.id = id;
|
|
||||||
object.name = reader.readStringOrNull(offsets[0]);
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
P _accountDeserializeProp<P>(
|
|
||||||
IsarReader reader,
|
|
||||||
int propertyId,
|
|
||||||
int offset,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
switch (propertyId) {
|
|
||||||
case 0:
|
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
|
||||||
default:
|
|
||||||
throw IsarError('Unknown property with id $propertyId');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Id _accountGetId(Account object) {
|
|
||||||
return object.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<IsarLinkBase<dynamic>> _accountGetLinks(Account object) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
void _accountAttach(IsarCollection<dynamic> col, Id id, Account object) {
|
|
||||||
object.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AccountQueryWhereSort on QueryBuilder<Account, Account, QWhere> {
|
|
||||||
QueryBuilder<Account, Account, QAfterWhere> anyId() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(const IdWhereClause.any());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AccountQueryWhere on QueryBuilder<Account, Account, QWhereClause> {
|
|
||||||
QueryBuilder<Account, Account, QAfterWhereClause> idEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(IdWhereClause.between(lower: id, upper: id));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterWhereClause> idNotEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
if (query.whereSort == Sort.asc) {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterWhereClause> idGreaterThan(
|
|
||||||
Id id, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterWhereClause> idLessThan(
|
|
||||||
Id id, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterWhereClause> idBetween(
|
|
||||||
Id lowerId,
|
|
||||||
Id upperId, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.between(
|
|
||||||
lower: lowerId,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upperId,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AccountQueryFilter
|
|
||||||
on QueryBuilder<Account, Account, QFilterCondition> {
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> idEqualTo(Id value) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'id', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> idGreaterThan(
|
|
||||||
Id value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> idLessThan(
|
|
||||||
Id value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> idBetween(
|
|
||||||
Id lower,
|
|
||||||
Id upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'id',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> nameIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
const FilterCondition.isNull(property: r'name'),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> nameIsNotNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
const FilterCondition.isNotNull(property: r'name'),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> nameEqualTo(
|
|
||||||
String? value, {
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> nameGreaterThan(
|
|
||||||
String? value, {
|
|
||||||
bool include = false,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> nameLessThan(
|
|
||||||
String? value, {
|
|
||||||
bool include = false,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> nameBetween(
|
|
||||||
String? lower,
|
|
||||||
String? upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'name',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> nameStartsWith(
|
|
||||||
String value, {
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.startsWith(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> nameEndsWith(
|
|
||||||
String value, {
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.endsWith(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> nameContains(
|
|
||||||
String value, {
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.contains(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> nameMatches(
|
|
||||||
String pattern, {
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.matches(
|
|
||||||
property: r'name',
|
|
||||||
wildcard: pattern,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> nameIsEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'name', value: ''),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterFilterCondition> nameIsNotEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(property: r'name', value: ''),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AccountQueryObject
|
|
||||||
on QueryBuilder<Account, Account, QFilterCondition> {}
|
|
||||||
|
|
||||||
extension AccountQueryLinks
|
|
||||||
on QueryBuilder<Account, Account, QFilterCondition> {}
|
|
||||||
|
|
||||||
extension AccountQuerySortBy on QueryBuilder<Account, Account, QSortBy> {
|
|
||||||
QueryBuilder<Account, Account, QAfterSortBy> sortByName() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterSortBy> sortByNameDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AccountQuerySortThenBy
|
|
||||||
on QueryBuilder<Account, Account, QSortThenBy> {
|
|
||||||
QueryBuilder<Account, Account, QAfterSortBy> thenById() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterSortBy> thenByIdDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterSortBy> thenByName() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, Account, QAfterSortBy> thenByNameDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AccountQueryWhereDistinct
|
|
||||||
on QueryBuilder<Account, Account, QDistinct> {
|
|
||||||
QueryBuilder<Account, Account, QDistinct> distinctByName({
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'name', caseSensitive: caseSensitive);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension AccountQueryProperty
|
|
||||||
on QueryBuilder<Account, Account, QQueryProperty> {
|
|
||||||
QueryBuilder<Account, int, QQueryOperations> idProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Account, String?, QQueryOperations> nameProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'name');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import 'package:isar/isar.dart';
|
|
||||||
import 'package:okane/database/collections/account.dart';
|
|
||||||
|
|
||||||
part 'beneficiary.g.dart';
|
|
||||||
|
|
||||||
enum BeneficiaryType { account, other }
|
|
||||||
|
|
||||||
@collection
|
|
||||||
class Beneficiary {
|
|
||||||
Id id = Isar.autoIncrement;
|
|
||||||
|
|
||||||
late String name;
|
|
||||||
|
|
||||||
@Enumerated(EnumType.ordinal)
|
|
||||||
late BeneficiaryType type;
|
|
||||||
|
|
||||||
final account = IsarLink<Account>();
|
|
||||||
|
|
||||||
String? imagePath;
|
|
||||||
}
|
|
||||||
@@ -1,810 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'beneficiary.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// IsarCollectionGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
// coverage:ignore-file
|
|
||||||
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
|
|
||||||
|
|
||||||
extension GetBeneficiaryCollection on Isar {
|
|
||||||
IsarCollection<Beneficiary> get beneficiarys => this.collection();
|
|
||||||
}
|
|
||||||
|
|
||||||
const BeneficiarySchema = CollectionSchema(
|
|
||||||
name: r'Beneficiary',
|
|
||||||
id: -7106369371336791482,
|
|
||||||
properties: {
|
|
||||||
r'imagePath': PropertySchema(
|
|
||||||
id: 0,
|
|
||||||
name: r'imagePath',
|
|
||||||
type: IsarType.string,
|
|
||||||
),
|
|
||||||
r'name': PropertySchema(id: 1, name: r'name', type: IsarType.string),
|
|
||||||
r'type': PropertySchema(
|
|
||||||
id: 2,
|
|
||||||
name: r'type',
|
|
||||||
type: IsarType.byte,
|
|
||||||
enumMap: _BeneficiarytypeEnumValueMap,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
estimateSize: _beneficiaryEstimateSize,
|
|
||||||
serialize: _beneficiarySerialize,
|
|
||||||
deserialize: _beneficiaryDeserialize,
|
|
||||||
deserializeProp: _beneficiaryDeserializeProp,
|
|
||||||
idName: r'id',
|
|
||||||
indexes: {},
|
|
||||||
links: {
|
|
||||||
r'account': LinkSchema(
|
|
||||||
id: -725531860126526319,
|
|
||||||
name: r'account',
|
|
||||||
target: r'Account',
|
|
||||||
single: true,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
embeddedSchemas: {},
|
|
||||||
getId: _beneficiaryGetId,
|
|
||||||
getLinks: _beneficiaryGetLinks,
|
|
||||||
attach: _beneficiaryAttach,
|
|
||||||
version: '3.1.0+1',
|
|
||||||
);
|
|
||||||
|
|
||||||
int _beneficiaryEstimateSize(
|
|
||||||
Beneficiary object,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
var bytesCount = offsets.last;
|
|
||||||
{
|
|
||||||
final value = object.imagePath;
|
|
||||||
if (value != null) {
|
|
||||||
bytesCount += 3 + value.length * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bytesCount += 3 + object.name.length * 3;
|
|
||||||
return bytesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _beneficiarySerialize(
|
|
||||||
Beneficiary object,
|
|
||||||
IsarWriter writer,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
writer.writeString(offsets[0], object.imagePath);
|
|
||||||
writer.writeString(offsets[1], object.name);
|
|
||||||
writer.writeByte(offsets[2], object.type.index);
|
|
||||||
}
|
|
||||||
|
|
||||||
Beneficiary _beneficiaryDeserialize(
|
|
||||||
Id id,
|
|
||||||
IsarReader reader,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
final object = Beneficiary();
|
|
||||||
object.id = id;
|
|
||||||
object.imagePath = reader.readStringOrNull(offsets[0]);
|
|
||||||
object.name = reader.readString(offsets[1]);
|
|
||||||
object.type =
|
|
||||||
_BeneficiarytypeValueEnumMap[reader.readByteOrNull(offsets[2])] ??
|
|
||||||
BeneficiaryType.account;
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
P _beneficiaryDeserializeProp<P>(
|
|
||||||
IsarReader reader,
|
|
||||||
int propertyId,
|
|
||||||
int offset,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
switch (propertyId) {
|
|
||||||
case 0:
|
|
||||||
return (reader.readStringOrNull(offset)) as P;
|
|
||||||
case 1:
|
|
||||||
return (reader.readString(offset)) as P;
|
|
||||||
case 2:
|
|
||||||
return (_BeneficiarytypeValueEnumMap[reader.readByteOrNull(offset)] ??
|
|
||||||
BeneficiaryType.account)
|
|
||||||
as P;
|
|
||||||
default:
|
|
||||||
throw IsarError('Unknown property with id $propertyId');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const _BeneficiarytypeEnumValueMap = {'account': 0, 'other': 1};
|
|
||||||
const _BeneficiarytypeValueEnumMap = {
|
|
||||||
0: BeneficiaryType.account,
|
|
||||||
1: BeneficiaryType.other,
|
|
||||||
};
|
|
||||||
|
|
||||||
Id _beneficiaryGetId(Beneficiary object) {
|
|
||||||
return object.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<IsarLinkBase<dynamic>> _beneficiaryGetLinks(Beneficiary object) {
|
|
||||||
return [object.account];
|
|
||||||
}
|
|
||||||
|
|
||||||
void _beneficiaryAttach(
|
|
||||||
IsarCollection<dynamic> col,
|
|
||||||
Id id,
|
|
||||||
Beneficiary object,
|
|
||||||
) {
|
|
||||||
object.id = id;
|
|
||||||
object.account.attach(col, col.isar.collection<Account>(), r'account', id);
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BeneficiaryQueryWhereSort
|
|
||||||
on QueryBuilder<Beneficiary, Beneficiary, QWhere> {
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterWhere> anyId() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(const IdWhereClause.any());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BeneficiaryQueryWhere
|
|
||||||
on QueryBuilder<Beneficiary, Beneficiary, QWhereClause> {
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterWhereClause> idEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(IdWhereClause.between(lower: id, upper: id));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterWhereClause> idNotEqualTo(
|
|
||||||
Id id,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
if (query.whereSort == Sort.asc) {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterWhereClause> idGreaterThan(
|
|
||||||
Id id, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterWhereClause> idLessThan(
|
|
||||||
Id id, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterWhereClause> idBetween(
|
|
||||||
Id lowerId,
|
|
||||||
Id upperId, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.between(
|
|
||||||
lower: lowerId,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upperId,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BeneficiaryQueryFilter
|
|
||||||
on QueryBuilder<Beneficiary, Beneficiary, QFilterCondition> {
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> idEqualTo(
|
|
||||||
Id value,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'id', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> idGreaterThan(
|
|
||||||
Id value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> idLessThan(
|
|
||||||
Id value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> idBetween(
|
|
||||||
Id lower,
|
|
||||||
Id upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'id',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
imagePathIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
const FilterCondition.isNull(property: r'imagePath'),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
imagePathIsNotNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
const FilterCondition.isNotNull(property: r'imagePath'),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
imagePathEqualTo(String? value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(
|
|
||||||
property: r'imagePath',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
imagePathGreaterThan(
|
|
||||||
String? value, {
|
|
||||||
bool include = false,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'imagePath',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
imagePathLessThan(
|
|
||||||
String? value, {
|
|
||||||
bool include = false,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'imagePath',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
imagePathBetween(
|
|
||||||
String? lower,
|
|
||||||
String? upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'imagePath',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
imagePathStartsWith(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.startsWith(
|
|
||||||
property: r'imagePath',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
imagePathEndsWith(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.endsWith(
|
|
||||||
property: r'imagePath',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
imagePathContains(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.contains(
|
|
||||||
property: r'imagePath',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
imagePathMatches(String pattern, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.matches(
|
|
||||||
property: r'imagePath',
|
|
||||||
wildcard: pattern,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
imagePathIsEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'imagePath', value: ''),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
imagePathIsNotEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(property: r'imagePath', value: ''),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> nameEqualTo(
|
|
||||||
String value, {
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> nameGreaterThan(
|
|
||||||
String value, {
|
|
||||||
bool include = false,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> nameLessThan(
|
|
||||||
String value, {
|
|
||||||
bool include = false,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> nameBetween(
|
|
||||||
String lower,
|
|
||||||
String upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'name',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> nameStartsWith(
|
|
||||||
String value, {
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.startsWith(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> nameEndsWith(
|
|
||||||
String value, {
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.endsWith(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> nameContains(
|
|
||||||
String value, {
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.contains(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> nameMatches(
|
|
||||||
String pattern, {
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.matches(
|
|
||||||
property: r'name',
|
|
||||||
wildcard: pattern,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> nameIsEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'name', value: ''),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
nameIsNotEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(property: r'name', value: ''),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> typeEqualTo(
|
|
||||||
BeneficiaryType value,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'type', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> typeGreaterThan(
|
|
||||||
BeneficiaryType value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'type',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> typeLessThan(
|
|
||||||
BeneficiaryType value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'type',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> typeBetween(
|
|
||||||
BeneficiaryType lower,
|
|
||||||
BeneficiaryType upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'type',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BeneficiaryQueryObject
|
|
||||||
on QueryBuilder<Beneficiary, Beneficiary, QFilterCondition> {}
|
|
||||||
|
|
||||||
extension BeneficiaryQueryLinks
|
|
||||||
on QueryBuilder<Beneficiary, Beneficiary, QFilterCondition> {
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition> account(
|
|
||||||
FilterQuery<Account> q,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.link(q, r'account');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterFilterCondition>
|
|
||||||
accountIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'account', 0, true, 0, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BeneficiaryQuerySortBy
|
|
||||||
on QueryBuilder<Beneficiary, Beneficiary, QSortBy> {
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> sortByImagePath() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'imagePath', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> sortByImagePathDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'imagePath', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> sortByName() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> sortByNameDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> sortByType() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'type', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> sortByTypeDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'type', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BeneficiaryQuerySortThenBy
|
|
||||||
on QueryBuilder<Beneficiary, Beneficiary, QSortThenBy> {
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> thenById() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> thenByIdDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> thenByImagePath() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'imagePath', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> thenByImagePathDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'imagePath', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> thenByName() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> thenByNameDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> thenByType() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'type', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QAfterSortBy> thenByTypeDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'type', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BeneficiaryQueryWhereDistinct
|
|
||||||
on QueryBuilder<Beneficiary, Beneficiary, QDistinct> {
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QDistinct> distinctByImagePath({
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'imagePath', caseSensitive: caseSensitive);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QDistinct> distinctByName({
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'name', caseSensitive: caseSensitive);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, Beneficiary, QDistinct> distinctByType() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'type');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BeneficiaryQueryProperty
|
|
||||||
on QueryBuilder<Beneficiary, Beneficiary, QQueryProperty> {
|
|
||||||
QueryBuilder<Beneficiary, int, QQueryOperations> idProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, String?, QQueryOperations> imagePathProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'imagePath');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, String, QQueryOperations> nameProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'name');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Beneficiary, BeneficiaryType, QQueryOperations> typeProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'type');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import 'package:isar/isar.dart';
|
|
||||||
import 'package:okane/database/collections/expense_category.dart';
|
|
||||||
|
|
||||||
import 'account.dart';
|
|
||||||
|
|
||||||
part 'budget.g.dart';
|
|
||||||
|
|
||||||
enum BudgetPeriod { month }
|
|
||||||
|
|
||||||
@collection
|
|
||||||
class BudgetItem {
|
|
||||||
Id id = Isar.autoIncrement;
|
|
||||||
|
|
||||||
late double amount;
|
|
||||||
|
|
||||||
final expenseCategory = IsarLink<ExpenseCategory>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@collection
|
|
||||||
class Budget {
|
|
||||||
Id id = Isar.autoIncrement;
|
|
||||||
|
|
||||||
@Enumerated(EnumType.ordinal)
|
|
||||||
late BudgetPeriod period;
|
|
||||||
|
|
||||||
late String name;
|
|
||||||
|
|
||||||
late double income;
|
|
||||||
|
|
||||||
late bool includeOtherSpendings;
|
|
||||||
|
|
||||||
final account = IsarLink<Account>();
|
|
||||||
|
|
||||||
final items = IsarLinks<BudgetItem>();
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +0,0 @@
|
|||||||
import 'package:isar/isar.dart';
|
|
||||||
|
|
||||||
part 'expense_category.g.dart';
|
|
||||||
|
|
||||||
@collection
|
|
||||||
class ExpenseCategory {
|
|
||||||
Id id = Isar.autoIncrement;
|
|
||||||
|
|
||||||
late String name;
|
|
||||||
}
|
|
||||||
@@ -1,451 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'expense_category.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// IsarCollectionGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
// coverage:ignore-file
|
|
||||||
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
|
|
||||||
|
|
||||||
extension GetExpenseCategoryCollection on Isar {
|
|
||||||
IsarCollection<ExpenseCategory> get expenseCategorys => this.collection();
|
|
||||||
}
|
|
||||||
|
|
||||||
const ExpenseCategorySchema = CollectionSchema(
|
|
||||||
name: r'ExpenseCategory',
|
|
||||||
id: -6352499903118634,
|
|
||||||
properties: {
|
|
||||||
r'name': PropertySchema(id: 0, name: r'name', type: IsarType.string),
|
|
||||||
},
|
|
||||||
estimateSize: _expenseCategoryEstimateSize,
|
|
||||||
serialize: _expenseCategorySerialize,
|
|
||||||
deserialize: _expenseCategoryDeserialize,
|
|
||||||
deserializeProp: _expenseCategoryDeserializeProp,
|
|
||||||
idName: r'id',
|
|
||||||
indexes: {},
|
|
||||||
links: {},
|
|
||||||
embeddedSchemas: {},
|
|
||||||
getId: _expenseCategoryGetId,
|
|
||||||
getLinks: _expenseCategoryGetLinks,
|
|
||||||
attach: _expenseCategoryAttach,
|
|
||||||
version: '3.1.0+1',
|
|
||||||
);
|
|
||||||
|
|
||||||
int _expenseCategoryEstimateSize(
|
|
||||||
ExpenseCategory object,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
var bytesCount = offsets.last;
|
|
||||||
bytesCount += 3 + object.name.length * 3;
|
|
||||||
return bytesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _expenseCategorySerialize(
|
|
||||||
ExpenseCategory object,
|
|
||||||
IsarWriter writer,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
writer.writeString(offsets[0], object.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpenseCategory _expenseCategoryDeserialize(
|
|
||||||
Id id,
|
|
||||||
IsarReader reader,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
final object = ExpenseCategory();
|
|
||||||
object.id = id;
|
|
||||||
object.name = reader.readString(offsets[0]);
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
P _expenseCategoryDeserializeProp<P>(
|
|
||||||
IsarReader reader,
|
|
||||||
int propertyId,
|
|
||||||
int offset,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
switch (propertyId) {
|
|
||||||
case 0:
|
|
||||||
return (reader.readString(offset)) as P;
|
|
||||||
default:
|
|
||||||
throw IsarError('Unknown property with id $propertyId');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Id _expenseCategoryGetId(ExpenseCategory object) {
|
|
||||||
return object.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<IsarLinkBase<dynamic>> _expenseCategoryGetLinks(ExpenseCategory object) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
void _expenseCategoryAttach(
|
|
||||||
IsarCollection<dynamic> col,
|
|
||||||
Id id,
|
|
||||||
ExpenseCategory object,
|
|
||||||
) {
|
|
||||||
object.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ExpenseCategoryQueryWhereSort
|
|
||||||
on QueryBuilder<ExpenseCategory, ExpenseCategory, QWhere> {
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterWhere> anyId() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(const IdWhereClause.any());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ExpenseCategoryQueryWhere
|
|
||||||
on QueryBuilder<ExpenseCategory, ExpenseCategory, QWhereClause> {
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterWhereClause> idEqualTo(
|
|
||||||
Id id,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(IdWhereClause.between(lower: id, upper: id));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterWhereClause>
|
|
||||||
idNotEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
if (query.whereSort == Sort.asc) {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterWhereClause>
|
|
||||||
idGreaterThan(Id id, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterWhereClause> idLessThan(
|
|
||||||
Id id, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterWhereClause> idBetween(
|
|
||||||
Id lowerId,
|
|
||||||
Id upperId, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.between(
|
|
||||||
lower: lowerId,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upperId,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ExpenseCategoryQueryFilter
|
|
||||||
on QueryBuilder<ExpenseCategory, ExpenseCategory, QFilterCondition> {
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
idEqualTo(Id value) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'id', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
idGreaterThan(Id value, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
idLessThan(Id value, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
idBetween(
|
|
||||||
Id lower,
|
|
||||||
Id upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'id',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
nameEqualTo(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
nameGreaterThan(
|
|
||||||
String value, {
|
|
||||||
bool include = false,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
nameLessThan(
|
|
||||||
String value, {
|
|
||||||
bool include = false,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
nameBetween(
|
|
||||||
String lower,
|
|
||||||
String upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'name',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
nameStartsWith(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.startsWith(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
nameEndsWith(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.endsWith(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
nameContains(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.contains(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
nameMatches(String pattern, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.matches(
|
|
||||||
property: r'name',
|
|
||||||
wildcard: pattern,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
nameIsEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'name', value: ''),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterFilterCondition>
|
|
||||||
nameIsNotEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(property: r'name', value: ''),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ExpenseCategoryQueryObject
|
|
||||||
on QueryBuilder<ExpenseCategory, ExpenseCategory, QFilterCondition> {}
|
|
||||||
|
|
||||||
extension ExpenseCategoryQueryLinks
|
|
||||||
on QueryBuilder<ExpenseCategory, ExpenseCategory, QFilterCondition> {}
|
|
||||||
|
|
||||||
extension ExpenseCategoryQuerySortBy
|
|
||||||
on QueryBuilder<ExpenseCategory, ExpenseCategory, QSortBy> {
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterSortBy> sortByName() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterSortBy>
|
|
||||||
sortByNameDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ExpenseCategoryQuerySortThenBy
|
|
||||||
on QueryBuilder<ExpenseCategory, ExpenseCategory, QSortThenBy> {
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterSortBy> thenById() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterSortBy> thenByIdDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterSortBy> thenByName() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QAfterSortBy>
|
|
||||||
thenByNameDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ExpenseCategoryQueryWhereDistinct
|
|
||||||
on QueryBuilder<ExpenseCategory, ExpenseCategory, QDistinct> {
|
|
||||||
QueryBuilder<ExpenseCategory, ExpenseCategory, QDistinct> distinctByName({
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'name', caseSensitive: caseSensitive);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ExpenseCategoryQueryProperty
|
|
||||||
on QueryBuilder<ExpenseCategory, ExpenseCategory, QQueryProperty> {
|
|
||||||
QueryBuilder<ExpenseCategory, int, QQueryOperations> idProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<ExpenseCategory, String, QQueryOperations> nameProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'name');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import 'package:isar/isar.dart';
|
|
||||||
import 'package:okane/database/collections/account.dart';
|
|
||||||
import 'package:okane/database/collections/template.dart';
|
|
||||||
|
|
||||||
part 'recurrent.g.dart';
|
|
||||||
|
|
||||||
@collection
|
|
||||||
class RecurringTransaction {
|
|
||||||
Id id = Isar.autoIncrement;
|
|
||||||
|
|
||||||
late int days;
|
|
||||||
|
|
||||||
DateTime? lastExecution;
|
|
||||||
|
|
||||||
final template = IsarLink<TransactionTemplate>();
|
|
||||||
|
|
||||||
final account = IsarLink<Account>();
|
|
||||||
|
|
||||||
bool isDue(DateTime now) {
|
|
||||||
if (lastExecution == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
final expectedNextExecution = lastExecution!.add(Duration(days: days));
|
|
||||||
if (now.isAfter(expectedNextExecution)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return now.difference(expectedNextExecution).inDays.abs() <=
|
|
||||||
(days * 0.5).toInt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,633 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'recurrent.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// IsarCollectionGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
// coverage:ignore-file
|
|
||||||
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
|
|
||||||
|
|
||||||
extension GetRecurringTransactionCollection on Isar {
|
|
||||||
IsarCollection<RecurringTransaction> get recurringTransactions =>
|
|
||||||
this.collection();
|
|
||||||
}
|
|
||||||
|
|
||||||
const RecurringTransactionSchema = CollectionSchema(
|
|
||||||
name: r'RecurringTransaction',
|
|
||||||
id: 969840479390105118,
|
|
||||||
properties: {
|
|
||||||
r'days': PropertySchema(id: 0, name: r'days', type: IsarType.long),
|
|
||||||
r'lastExecution': PropertySchema(
|
|
||||||
id: 1,
|
|
||||||
name: r'lastExecution',
|
|
||||||
type: IsarType.dateTime,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
estimateSize: _recurringTransactionEstimateSize,
|
|
||||||
serialize: _recurringTransactionSerialize,
|
|
||||||
deserialize: _recurringTransactionDeserialize,
|
|
||||||
deserializeProp: _recurringTransactionDeserializeProp,
|
|
||||||
idName: r'id',
|
|
||||||
indexes: {},
|
|
||||||
links: {
|
|
||||||
r'template': LinkSchema(
|
|
||||||
id: -8891369755965227865,
|
|
||||||
name: r'template',
|
|
||||||
target: r'TransactionTemplate',
|
|
||||||
single: true,
|
|
||||||
),
|
|
||||||
r'account': LinkSchema(
|
|
||||||
id: -6028551496614242115,
|
|
||||||
name: r'account',
|
|
||||||
target: r'Account',
|
|
||||||
single: true,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
embeddedSchemas: {},
|
|
||||||
getId: _recurringTransactionGetId,
|
|
||||||
getLinks: _recurringTransactionGetLinks,
|
|
||||||
attach: _recurringTransactionAttach,
|
|
||||||
version: '3.1.0+1',
|
|
||||||
);
|
|
||||||
|
|
||||||
int _recurringTransactionEstimateSize(
|
|
||||||
RecurringTransaction object,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
var bytesCount = offsets.last;
|
|
||||||
return bytesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _recurringTransactionSerialize(
|
|
||||||
RecurringTransaction object,
|
|
||||||
IsarWriter writer,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
writer.writeLong(offsets[0], object.days);
|
|
||||||
writer.writeDateTime(offsets[1], object.lastExecution);
|
|
||||||
}
|
|
||||||
|
|
||||||
RecurringTransaction _recurringTransactionDeserialize(
|
|
||||||
Id id,
|
|
||||||
IsarReader reader,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
final object = RecurringTransaction();
|
|
||||||
object.days = reader.readLong(offsets[0]);
|
|
||||||
object.id = id;
|
|
||||||
object.lastExecution = reader.readDateTimeOrNull(offsets[1]);
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
P _recurringTransactionDeserializeProp<P>(
|
|
||||||
IsarReader reader,
|
|
||||||
int propertyId,
|
|
||||||
int offset,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
switch (propertyId) {
|
|
||||||
case 0:
|
|
||||||
return (reader.readLong(offset)) as P;
|
|
||||||
case 1:
|
|
||||||
return (reader.readDateTimeOrNull(offset)) as P;
|
|
||||||
default:
|
|
||||||
throw IsarError('Unknown property with id $propertyId');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Id _recurringTransactionGetId(RecurringTransaction object) {
|
|
||||||
return object.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<IsarLinkBase<dynamic>> _recurringTransactionGetLinks(
|
|
||||||
RecurringTransaction object,
|
|
||||||
) {
|
|
||||||
return [object.template, object.account];
|
|
||||||
}
|
|
||||||
|
|
||||||
void _recurringTransactionAttach(
|
|
||||||
IsarCollection<dynamic> col,
|
|
||||||
Id id,
|
|
||||||
RecurringTransaction object,
|
|
||||||
) {
|
|
||||||
object.id = id;
|
|
||||||
object.template.attach(
|
|
||||||
col,
|
|
||||||
col.isar.collection<TransactionTemplate>(),
|
|
||||||
r'template',
|
|
||||||
id,
|
|
||||||
);
|
|
||||||
object.account.attach(col, col.isar.collection<Account>(), r'account', id);
|
|
||||||
}
|
|
||||||
|
|
||||||
extension RecurringTransactionQueryWhereSort
|
|
||||||
on QueryBuilder<RecurringTransaction, RecurringTransaction, QWhere> {
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterWhere>
|
|
||||||
anyId() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(const IdWhereClause.any());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension RecurringTransactionQueryWhere
|
|
||||||
on QueryBuilder<RecurringTransaction, RecurringTransaction, QWhereClause> {
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterWhereClause>
|
|
||||||
idEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(IdWhereClause.between(lower: id, upper: id));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterWhereClause>
|
|
||||||
idNotEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
if (query.whereSort == Sort.asc) {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterWhereClause>
|
|
||||||
idGreaterThan(Id id, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterWhereClause>
|
|
||||||
idLessThan(Id id, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterWhereClause>
|
|
||||||
idBetween(
|
|
||||||
Id lowerId,
|
|
||||||
Id upperId, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.between(
|
|
||||||
lower: lowerId,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upperId,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension RecurringTransactionQueryFilter
|
|
||||||
on
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QFilterCondition
|
|
||||||
> {
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
daysEqualTo(int value) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'days', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
daysGreaterThan(int value, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'days',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
daysLessThan(int value, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'days',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
daysBetween(
|
|
||||||
int lower,
|
|
||||||
int upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'days',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
idEqualTo(Id value) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'id', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
idGreaterThan(Id value, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
idLessThan(Id value, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
idBetween(
|
|
||||||
Id lower,
|
|
||||||
Id upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'id',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
lastExecutionIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
const FilterCondition.isNull(property: r'lastExecution'),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
lastExecutionIsNotNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
const FilterCondition.isNotNull(property: r'lastExecution'),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
lastExecutionEqualTo(DateTime? value) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'lastExecution', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
lastExecutionGreaterThan(DateTime? value, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'lastExecution',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
lastExecutionLessThan(DateTime? value, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'lastExecution',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
lastExecutionBetween(
|
|
||||||
DateTime? lower,
|
|
||||||
DateTime? upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'lastExecution',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension RecurringTransactionQueryObject
|
|
||||||
on
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QFilterCondition
|
|
||||||
> {}
|
|
||||||
|
|
||||||
extension RecurringTransactionQueryLinks
|
|
||||||
on
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QFilterCondition
|
|
||||||
> {
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
template(FilterQuery<TransactionTemplate> q) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.link(q, r'template');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
templateIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'template', 0, true, 0, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
account(FilterQuery<Account> q) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.link(q, r'account');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QAfterFilterCondition
|
|
||||||
>
|
|
||||||
accountIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'account', 0, true, 0, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension RecurringTransactionQuerySortBy
|
|
||||||
on QueryBuilder<RecurringTransaction, RecurringTransaction, QSortBy> {
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterSortBy>
|
|
||||||
sortByDays() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'days', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterSortBy>
|
|
||||||
sortByDaysDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'days', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterSortBy>
|
|
||||||
sortByLastExecution() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'lastExecution', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterSortBy>
|
|
||||||
sortByLastExecutionDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'lastExecution', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension RecurringTransactionQuerySortThenBy
|
|
||||||
on QueryBuilder<RecurringTransaction, RecurringTransaction, QSortThenBy> {
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterSortBy>
|
|
||||||
thenByDays() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'days', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterSortBy>
|
|
||||||
thenByDaysDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'days', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterSortBy>
|
|
||||||
thenById() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterSortBy>
|
|
||||||
thenByIdDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterSortBy>
|
|
||||||
thenByLastExecution() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'lastExecution', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QAfterSortBy>
|
|
||||||
thenByLastExecutionDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'lastExecution', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension RecurringTransactionQueryWhereDistinct
|
|
||||||
on QueryBuilder<RecurringTransaction, RecurringTransaction, QDistinct> {
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QDistinct>
|
|
||||||
distinctByDays() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'days');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, RecurringTransaction, QDistinct>
|
|
||||||
distinctByLastExecution() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'lastExecution');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension RecurringTransactionQueryProperty
|
|
||||||
on
|
|
||||||
QueryBuilder<
|
|
||||||
RecurringTransaction,
|
|
||||||
RecurringTransaction,
|
|
||||||
QQueryProperty
|
|
||||||
> {
|
|
||||||
QueryBuilder<RecurringTransaction, int, QQueryOperations> idProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, int, QQueryOperations> daysProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'days');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<RecurringTransaction, DateTime?, QQueryOperations>
|
|
||||||
lastExecutionProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'lastExecution');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import 'package:isar/isar.dart';
|
|
||||||
import 'package:okane/database/collections/account.dart';
|
|
||||||
import 'package:okane/database/collections/beneficiary.dart';
|
|
||||||
import 'package:okane/database/collections/expense_category.dart';
|
|
||||||
|
|
||||||
part 'template.g.dart';
|
|
||||||
|
|
||||||
@collection
|
|
||||||
class TransactionTemplate {
|
|
||||||
Id id = Isar.autoIncrement;
|
|
||||||
|
|
||||||
late String name;
|
|
||||||
|
|
||||||
late double amount;
|
|
||||||
|
|
||||||
late bool recurring;
|
|
||||||
|
|
||||||
final expenseCategory = IsarLink<ExpenseCategory>();
|
|
||||||
|
|
||||||
final beneficiary = IsarLink<Beneficiary>();
|
|
||||||
|
|
||||||
final account = IsarLink<Account>();
|
|
||||||
}
|
|
||||||
@@ -1,721 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'template.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// IsarCollectionGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
// coverage:ignore-file
|
|
||||||
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
|
|
||||||
|
|
||||||
extension GetTransactionTemplateCollection on Isar {
|
|
||||||
IsarCollection<TransactionTemplate> get transactionTemplates =>
|
|
||||||
this.collection();
|
|
||||||
}
|
|
||||||
|
|
||||||
const TransactionTemplateSchema = CollectionSchema(
|
|
||||||
name: r'TransactionTemplate',
|
|
||||||
id: -2324989530163310644,
|
|
||||||
properties: {
|
|
||||||
r'amount': PropertySchema(id: 0, name: r'amount', type: IsarType.double),
|
|
||||||
r'name': PropertySchema(id: 1, name: r'name', type: IsarType.string),
|
|
||||||
r'recurring': PropertySchema(
|
|
||||||
id: 2,
|
|
||||||
name: r'recurring',
|
|
||||||
type: IsarType.bool,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
estimateSize: _transactionTemplateEstimateSize,
|
|
||||||
serialize: _transactionTemplateSerialize,
|
|
||||||
deserialize: _transactionTemplateDeserialize,
|
|
||||||
deserializeProp: _transactionTemplateDeserializeProp,
|
|
||||||
idName: r'id',
|
|
||||||
indexes: {},
|
|
||||||
links: {
|
|
||||||
r'expenseCategory': LinkSchema(
|
|
||||||
id: 3013186211408715712,
|
|
||||||
name: r'expenseCategory',
|
|
||||||
target: r'ExpenseCategory',
|
|
||||||
single: true,
|
|
||||||
),
|
|
||||||
r'beneficiary': LinkSchema(
|
|
||||||
id: -7565656011019083791,
|
|
||||||
name: r'beneficiary',
|
|
||||||
target: r'Beneficiary',
|
|
||||||
single: true,
|
|
||||||
),
|
|
||||||
r'account': LinkSchema(
|
|
||||||
id: 2465433941426054606,
|
|
||||||
name: r'account',
|
|
||||||
target: r'Account',
|
|
||||||
single: true,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
embeddedSchemas: {},
|
|
||||||
getId: _transactionTemplateGetId,
|
|
||||||
getLinks: _transactionTemplateGetLinks,
|
|
||||||
attach: _transactionTemplateAttach,
|
|
||||||
version: '3.1.0+1',
|
|
||||||
);
|
|
||||||
|
|
||||||
int _transactionTemplateEstimateSize(
|
|
||||||
TransactionTemplate object,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
var bytesCount = offsets.last;
|
|
||||||
bytesCount += 3 + object.name.length * 3;
|
|
||||||
return bytesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _transactionTemplateSerialize(
|
|
||||||
TransactionTemplate object,
|
|
||||||
IsarWriter writer,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
writer.writeDouble(offsets[0], object.amount);
|
|
||||||
writer.writeString(offsets[1], object.name);
|
|
||||||
writer.writeBool(offsets[2], object.recurring);
|
|
||||||
}
|
|
||||||
|
|
||||||
TransactionTemplate _transactionTemplateDeserialize(
|
|
||||||
Id id,
|
|
||||||
IsarReader reader,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
final object = TransactionTemplate();
|
|
||||||
object.amount = reader.readDouble(offsets[0]);
|
|
||||||
object.id = id;
|
|
||||||
object.name = reader.readString(offsets[1]);
|
|
||||||
object.recurring = reader.readBool(offsets[2]);
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
P _transactionTemplateDeserializeProp<P>(
|
|
||||||
IsarReader reader,
|
|
||||||
int propertyId,
|
|
||||||
int offset,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
switch (propertyId) {
|
|
||||||
case 0:
|
|
||||||
return (reader.readDouble(offset)) as P;
|
|
||||||
case 1:
|
|
||||||
return (reader.readString(offset)) as P;
|
|
||||||
case 2:
|
|
||||||
return (reader.readBool(offset)) as P;
|
|
||||||
default:
|
|
||||||
throw IsarError('Unknown property with id $propertyId');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Id _transactionTemplateGetId(TransactionTemplate object) {
|
|
||||||
return object.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<IsarLinkBase<dynamic>> _transactionTemplateGetLinks(
|
|
||||||
TransactionTemplate object,
|
|
||||||
) {
|
|
||||||
return [object.expenseCategory, object.beneficiary, object.account];
|
|
||||||
}
|
|
||||||
|
|
||||||
void _transactionTemplateAttach(
|
|
||||||
IsarCollection<dynamic> col,
|
|
||||||
Id id,
|
|
||||||
TransactionTemplate object,
|
|
||||||
) {
|
|
||||||
object.id = id;
|
|
||||||
object.expenseCategory.attach(
|
|
||||||
col,
|
|
||||||
col.isar.collection<ExpenseCategory>(),
|
|
||||||
r'expenseCategory',
|
|
||||||
id,
|
|
||||||
);
|
|
||||||
object.beneficiary.attach(
|
|
||||||
col,
|
|
||||||
col.isar.collection<Beneficiary>(),
|
|
||||||
r'beneficiary',
|
|
||||||
id,
|
|
||||||
);
|
|
||||||
object.account.attach(col, col.isar.collection<Account>(), r'account', id);
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionTemplateQueryWhereSort
|
|
||||||
on QueryBuilder<TransactionTemplate, TransactionTemplate, QWhere> {
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterWhere> anyId() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(const IdWhereClause.any());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionTemplateQueryWhere
|
|
||||||
on QueryBuilder<TransactionTemplate, TransactionTemplate, QWhereClause> {
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterWhereClause>
|
|
||||||
idEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(IdWhereClause.between(lower: id, upper: id));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterWhereClause>
|
|
||||||
idNotEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
if (query.whereSort == Sort.asc) {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterWhereClause>
|
|
||||||
idGreaterThan(Id id, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterWhereClause>
|
|
||||||
idLessThan(Id id, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterWhereClause>
|
|
||||||
idBetween(
|
|
||||||
Id lowerId,
|
|
||||||
Id upperId, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.between(
|
|
||||||
lower: lowerId,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upperId,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionTemplateQueryFilter
|
|
||||||
on
|
|
||||||
QueryBuilder<
|
|
||||||
TransactionTemplate,
|
|
||||||
TransactionTemplate,
|
|
||||||
QFilterCondition
|
|
||||||
> {
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
amountEqualTo(double value, {double epsilon = Query.epsilon}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(
|
|
||||||
property: r'amount',
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
amountGreaterThan(
|
|
||||||
double value, {
|
|
||||||
bool include = false,
|
|
||||||
double epsilon = Query.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'amount',
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
amountLessThan(
|
|
||||||
double value, {
|
|
||||||
bool include = false,
|
|
||||||
double epsilon = Query.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'amount',
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
amountBetween(
|
|
||||||
double lower,
|
|
||||||
double upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
double epsilon = Query.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'amount',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
idEqualTo(Id value) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'id', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
idGreaterThan(Id value, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
idLessThan(Id value, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
idBetween(
|
|
||||||
Id lower,
|
|
||||||
Id upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'id',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
nameEqualTo(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
nameGreaterThan(
|
|
||||||
String value, {
|
|
||||||
bool include = false,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
nameLessThan(
|
|
||||||
String value, {
|
|
||||||
bool include = false,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
nameBetween(
|
|
||||||
String lower,
|
|
||||||
String upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'name',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
nameStartsWith(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.startsWith(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
nameEndsWith(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.endsWith(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
nameContains(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.contains(
|
|
||||||
property: r'name',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
nameMatches(String pattern, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.matches(
|
|
||||||
property: r'name',
|
|
||||||
wildcard: pattern,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
nameIsEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'name', value: ''),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
nameIsNotEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(property: r'name', value: ''),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
recurringEqualTo(bool value) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'recurring', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionTemplateQueryObject
|
|
||||||
on
|
|
||||||
QueryBuilder<
|
|
||||||
TransactionTemplate,
|
|
||||||
TransactionTemplate,
|
|
||||||
QFilterCondition
|
|
||||||
> {}
|
|
||||||
|
|
||||||
extension TransactionTemplateQueryLinks
|
|
||||||
on
|
|
||||||
QueryBuilder<
|
|
||||||
TransactionTemplate,
|
|
||||||
TransactionTemplate,
|
|
||||||
QFilterCondition
|
|
||||||
> {
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
expenseCategory(FilterQuery<ExpenseCategory> q) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.link(q, r'expenseCategory');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
expenseCategoryIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'expenseCategory', 0, true, 0, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
beneficiary(FilterQuery<Beneficiary> q) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.link(q, r'beneficiary');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
beneficiaryIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'beneficiary', 0, true, 0, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
account(FilterQuery<Account> q) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.link(q, r'account');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterFilterCondition>
|
|
||||||
accountIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'account', 0, true, 0, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionTemplateQuerySortBy
|
|
||||||
on QueryBuilder<TransactionTemplate, TransactionTemplate, QSortBy> {
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
sortByAmount() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'amount', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
sortByAmountDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'amount', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
sortByName() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
sortByNameDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
sortByRecurring() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'recurring', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
sortByRecurringDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'recurring', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionTemplateQuerySortThenBy
|
|
||||||
on QueryBuilder<TransactionTemplate, TransactionTemplate, QSortThenBy> {
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
thenByAmount() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'amount', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
thenByAmountDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'amount', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
thenById() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
thenByIdDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
thenByName() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
thenByNameDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'name', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
thenByRecurring() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'recurring', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QAfterSortBy>
|
|
||||||
thenByRecurringDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'recurring', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionTemplateQueryWhereDistinct
|
|
||||||
on QueryBuilder<TransactionTemplate, TransactionTemplate, QDistinct> {
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QDistinct>
|
|
||||||
distinctByAmount() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'amount');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QDistinct>
|
|
||||||
distinctByName({bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'name', caseSensitive: caseSensitive);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, TransactionTemplate, QDistinct>
|
|
||||||
distinctByRecurring() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'recurring');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionTemplateQueryProperty
|
|
||||||
on QueryBuilder<TransactionTemplate, TransactionTemplate, QQueryProperty> {
|
|
||||||
QueryBuilder<TransactionTemplate, int, QQueryOperations> idProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, double, QQueryOperations> amountProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'amount');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, String, QQueryOperations> nameProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'name');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<TransactionTemplate, bool, QQueryOperations>
|
|
||||||
recurringProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'recurring');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import 'package:isar/isar.dart';
|
|
||||||
import 'package:okane/database/collections/account.dart';
|
|
||||||
import 'package:okane/database/collections/beneficiary.dart';
|
|
||||||
import 'package:okane/database/collections/expense_category.dart';
|
|
||||||
|
|
||||||
part 'transaction.g.dart';
|
|
||||||
|
|
||||||
@collection
|
|
||||||
class Transaction {
|
|
||||||
Id id = Isar.autoIncrement;
|
|
||||||
|
|
||||||
late double amount;
|
|
||||||
|
|
||||||
late List<String> tags;
|
|
||||||
|
|
||||||
late DateTime date;
|
|
||||||
|
|
||||||
final expenseCategory = IsarLink<ExpenseCategory>();
|
|
||||||
|
|
||||||
final account = IsarLink<Account>();
|
|
||||||
|
|
||||||
final beneficiary = IsarLink<Beneficiary>();
|
|
||||||
}
|
|
||||||
@@ -1,775 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'transaction.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// IsarCollectionGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
// coverage:ignore-file
|
|
||||||
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters, always_specify_types
|
|
||||||
|
|
||||||
extension GetTransactionCollection on Isar {
|
|
||||||
IsarCollection<Transaction> get transactions => this.collection();
|
|
||||||
}
|
|
||||||
|
|
||||||
const TransactionSchema = CollectionSchema(
|
|
||||||
name: r'Transaction',
|
|
||||||
id: 5320225499417954855,
|
|
||||||
properties: {
|
|
||||||
r'amount': PropertySchema(id: 0, name: r'amount', type: IsarType.double),
|
|
||||||
r'date': PropertySchema(id: 1, name: r'date', type: IsarType.dateTime),
|
|
||||||
r'tags': PropertySchema(id: 2, name: r'tags', type: IsarType.stringList),
|
|
||||||
},
|
|
||||||
estimateSize: _transactionEstimateSize,
|
|
||||||
serialize: _transactionSerialize,
|
|
||||||
deserialize: _transactionDeserialize,
|
|
||||||
deserializeProp: _transactionDeserializeProp,
|
|
||||||
idName: r'id',
|
|
||||||
indexes: {},
|
|
||||||
links: {
|
|
||||||
r'expenseCategory': LinkSchema(
|
|
||||||
id: 490804775908778298,
|
|
||||||
name: r'expenseCategory',
|
|
||||||
target: r'ExpenseCategory',
|
|
||||||
single: true,
|
|
||||||
),
|
|
||||||
r'account': LinkSchema(
|
|
||||||
id: -8467990729867616553,
|
|
||||||
name: r'account',
|
|
||||||
target: r'Account',
|
|
||||||
single: true,
|
|
||||||
),
|
|
||||||
r'beneficiary': LinkSchema(
|
|
||||||
id: -1184196133247909686,
|
|
||||||
name: r'beneficiary',
|
|
||||||
target: r'Beneficiary',
|
|
||||||
single: true,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
embeddedSchemas: {},
|
|
||||||
getId: _transactionGetId,
|
|
||||||
getLinks: _transactionGetLinks,
|
|
||||||
attach: _transactionAttach,
|
|
||||||
version: '3.1.0+1',
|
|
||||||
);
|
|
||||||
|
|
||||||
int _transactionEstimateSize(
|
|
||||||
Transaction object,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
var bytesCount = offsets.last;
|
|
||||||
bytesCount += 3 + object.tags.length * 3;
|
|
||||||
{
|
|
||||||
for (var i = 0; i < object.tags.length; i++) {
|
|
||||||
final value = object.tags[i];
|
|
||||||
bytesCount += value.length * 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _transactionSerialize(
|
|
||||||
Transaction object,
|
|
||||||
IsarWriter writer,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
writer.writeDouble(offsets[0], object.amount);
|
|
||||||
writer.writeDateTime(offsets[1], object.date);
|
|
||||||
writer.writeStringList(offsets[2], object.tags);
|
|
||||||
}
|
|
||||||
|
|
||||||
Transaction _transactionDeserialize(
|
|
||||||
Id id,
|
|
||||||
IsarReader reader,
|
|
||||||
List<int> offsets,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
final object = Transaction();
|
|
||||||
object.amount = reader.readDouble(offsets[0]);
|
|
||||||
object.date = reader.readDateTime(offsets[1]);
|
|
||||||
object.id = id;
|
|
||||||
object.tags = reader.readStringList(offsets[2]) ?? [];
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
P _transactionDeserializeProp<P>(
|
|
||||||
IsarReader reader,
|
|
||||||
int propertyId,
|
|
||||||
int offset,
|
|
||||||
Map<Type, List<int>> allOffsets,
|
|
||||||
) {
|
|
||||||
switch (propertyId) {
|
|
||||||
case 0:
|
|
||||||
return (reader.readDouble(offset)) as P;
|
|
||||||
case 1:
|
|
||||||
return (reader.readDateTime(offset)) as P;
|
|
||||||
case 2:
|
|
||||||
return (reader.readStringList(offset) ?? []) as P;
|
|
||||||
default:
|
|
||||||
throw IsarError('Unknown property with id $propertyId');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Id _transactionGetId(Transaction object) {
|
|
||||||
return object.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<IsarLinkBase<dynamic>> _transactionGetLinks(Transaction object) {
|
|
||||||
return [object.expenseCategory, object.account, object.beneficiary];
|
|
||||||
}
|
|
||||||
|
|
||||||
void _transactionAttach(
|
|
||||||
IsarCollection<dynamic> col,
|
|
||||||
Id id,
|
|
||||||
Transaction object,
|
|
||||||
) {
|
|
||||||
object.id = id;
|
|
||||||
object.expenseCategory.attach(
|
|
||||||
col,
|
|
||||||
col.isar.collection<ExpenseCategory>(),
|
|
||||||
r'expenseCategory',
|
|
||||||
id,
|
|
||||||
);
|
|
||||||
object.account.attach(col, col.isar.collection<Account>(), r'account', id);
|
|
||||||
object.beneficiary.attach(
|
|
||||||
col,
|
|
||||||
col.isar.collection<Beneficiary>(),
|
|
||||||
r'beneficiary',
|
|
||||||
id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionQueryWhereSort
|
|
||||||
on QueryBuilder<Transaction, Transaction, QWhere> {
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterWhere> anyId() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(const IdWhereClause.any());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionQueryWhere
|
|
||||||
on QueryBuilder<Transaction, Transaction, QWhereClause> {
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterWhereClause> idEqualTo(Id id) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(IdWhereClause.between(lower: id, upper: id));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterWhereClause> idNotEqualTo(
|
|
||||||
Id id,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
if (query.whereSort == Sort.asc) {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return query
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
|
||||||
)
|
|
||||||
.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterWhereClause> idGreaterThan(
|
|
||||||
Id id, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.greaterThan(lower: id, includeLower: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterWhereClause> idLessThan(
|
|
||||||
Id id, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.lessThan(upper: id, includeUpper: include),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterWhereClause> idBetween(
|
|
||||||
Id lowerId,
|
|
||||||
Id upperId, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addWhereClause(
|
|
||||||
IdWhereClause.between(
|
|
||||||
lower: lowerId,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upperId,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionQueryFilter
|
|
||||||
on QueryBuilder<Transaction, Transaction, QFilterCondition> {
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> amountEqualTo(
|
|
||||||
double value, {
|
|
||||||
double epsilon = Query.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(
|
|
||||||
property: r'amount',
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
amountGreaterThan(
|
|
||||||
double value, {
|
|
||||||
bool include = false,
|
|
||||||
double epsilon = Query.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'amount',
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> amountLessThan(
|
|
||||||
double value, {
|
|
||||||
bool include = false,
|
|
||||||
double epsilon = Query.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'amount',
|
|
||||||
value: value,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> amountBetween(
|
|
||||||
double lower,
|
|
||||||
double upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
double epsilon = Query.epsilon,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'amount',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
epsilon: epsilon,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> dateEqualTo(
|
|
||||||
DateTime value,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'date', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> dateGreaterThan(
|
|
||||||
DateTime value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'date',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> dateLessThan(
|
|
||||||
DateTime value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'date',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> dateBetween(
|
|
||||||
DateTime lower,
|
|
||||||
DateTime upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'date',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> idEqualTo(
|
|
||||||
Id value,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'id', value: value),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> idGreaterThan(
|
|
||||||
Id value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> idLessThan(
|
|
||||||
Id value, {
|
|
||||||
bool include = false,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'id',
|
|
||||||
value: value,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> idBetween(
|
|
||||||
Id lower,
|
|
||||||
Id upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'id',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsElementEqualTo(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(
|
|
||||||
property: r'tags',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsElementGreaterThan(
|
|
||||||
String value, {
|
|
||||||
bool include = false,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(
|
|
||||||
include: include,
|
|
||||||
property: r'tags',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsElementLessThan(
|
|
||||||
String value, {
|
|
||||||
bool include = false,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.lessThan(
|
|
||||||
include: include,
|
|
||||||
property: r'tags',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsElementBetween(
|
|
||||||
String lower,
|
|
||||||
String upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
bool caseSensitive = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.between(
|
|
||||||
property: r'tags',
|
|
||||||
lower: lower,
|
|
||||||
includeLower: includeLower,
|
|
||||||
upper: upper,
|
|
||||||
includeUpper: includeUpper,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsElementStartsWith(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.startsWith(
|
|
||||||
property: r'tags',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsElementEndsWith(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.endsWith(
|
|
||||||
property: r'tags',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsElementContains(String value, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.contains(
|
|
||||||
property: r'tags',
|
|
||||||
value: value,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsElementMatches(String pattern, {bool caseSensitive = true}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.matches(
|
|
||||||
property: r'tags',
|
|
||||||
wildcard: pattern,
|
|
||||||
caseSensitive: caseSensitive,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsElementIsEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.equalTo(property: r'tags', value: ''),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsElementIsNotEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addFilterCondition(
|
|
||||||
FilterCondition.greaterThan(property: r'tags', value: ''),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsLengthEqualTo(int length) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.listLength(r'tags', length, true, length, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> tagsIsEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.listLength(r'tags', 0, true, 0, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsIsNotEmpty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.listLength(r'tags', 0, false, 999999, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsLengthLessThan(int length, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.listLength(r'tags', 0, true, length, include);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsLengthGreaterThan(int length, {bool include = false}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.listLength(r'tags', length, include, 999999, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
tagsLengthBetween(
|
|
||||||
int lower,
|
|
||||||
int upper, {
|
|
||||||
bool includeLower = true,
|
|
||||||
bool includeUpper = true,
|
|
||||||
}) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.listLength(
|
|
||||||
r'tags',
|
|
||||||
lower,
|
|
||||||
includeLower,
|
|
||||||
upper,
|
|
||||||
includeUpper,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionQueryObject
|
|
||||||
on QueryBuilder<Transaction, Transaction, QFilterCondition> {}
|
|
||||||
|
|
||||||
extension TransactionQueryLinks
|
|
||||||
on QueryBuilder<Transaction, Transaction, QFilterCondition> {
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> expenseCategory(
|
|
||||||
FilterQuery<ExpenseCategory> q,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.link(q, r'expenseCategory');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
expenseCategoryIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'expenseCategory', 0, true, 0, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> account(
|
|
||||||
FilterQuery<Account> q,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.link(q, r'account');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
accountIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'account', 0, true, 0, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition> beneficiary(
|
|
||||||
FilterQuery<Beneficiary> q,
|
|
||||||
) {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.link(q, r'beneficiary');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterFilterCondition>
|
|
||||||
beneficiaryIsNull() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.linkLength(r'beneficiary', 0, true, 0, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionQuerySortBy
|
|
||||||
on QueryBuilder<Transaction, Transaction, QSortBy> {
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterSortBy> sortByAmount() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'amount', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterSortBy> sortByAmountDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'amount', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterSortBy> sortByDate() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'date', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterSortBy> sortByDateDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'date', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionQuerySortThenBy
|
|
||||||
on QueryBuilder<Transaction, Transaction, QSortThenBy> {
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterSortBy> thenByAmount() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'amount', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterSortBy> thenByAmountDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'amount', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterSortBy> thenByDate() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'date', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterSortBy> thenByDateDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'date', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterSortBy> thenById() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.asc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QAfterSortBy> thenByIdDesc() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addSortBy(r'id', Sort.desc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionQueryWhereDistinct
|
|
||||||
on QueryBuilder<Transaction, Transaction, QDistinct> {
|
|
||||||
QueryBuilder<Transaction, Transaction, QDistinct> distinctByAmount() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'amount');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QDistinct> distinctByDate() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'date');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, Transaction, QDistinct> distinctByTags() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addDistinctBy(r'tags');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionQueryProperty
|
|
||||||
on QueryBuilder<Transaction, Transaction, QQueryProperty> {
|
|
||||||
QueryBuilder<Transaction, int, QQueryOperations> idProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, double, QQueryOperations> amountProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'amount');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, DateTime, QQueryOperations> dateProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'date');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
QueryBuilder<Transaction, List<String>, QQueryOperations> tagsProperty() {
|
|
||||||
return QueryBuilder.apply(this, (query) {
|
|
||||||
return query.addPropertyName(r'tags');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,329 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:isar/isar.dart';
|
|
||||||
import 'package:get_it/get_it.dart';
|
|
||||||
import 'package:more/collection.dart';
|
|
||||||
import 'package:okane/database/collections/account.dart';
|
|
||||||
import 'package:okane/database/collections/beneficiary.dart';
|
|
||||||
import 'package:okane/database/collections/expense_category.dart';
|
|
||||||
import 'package:okane/database/collections/recurrent.dart';
|
|
||||||
import 'package:okane/database/collections/template.dart';
|
|
||||||
import 'package:okane/database/collections/transaction.dart';
|
|
||||||
import 'package:okane/ui/state/core.dart';
|
|
||||||
import 'package:okane/ui/utils.dart';
|
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
|
|
||||||
import 'collections/budget.dart';
|
|
||||||
|
|
||||||
Future<Isar> openDatabase() async {
|
|
||||||
final dir = await getApplicationDocumentsDirectory();
|
|
||||||
return Isar.open([
|
|
||||||
AccountSchema,
|
|
||||||
BeneficiarySchema,
|
|
||||||
TransactionSchema,
|
|
||||||
TransactionTemplateSchema,
|
|
||||||
RecurringTransactionSchema,
|
|
||||||
ExpenseCategorySchema,
|
|
||||||
BudgetSchema,
|
|
||||||
BudgetItemSchema,
|
|
||||||
], directory: dir.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<Account>> getAccounts() {
|
|
||||||
return GetIt.I.get<Isar>().accounts.where().findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<double> getTotalBalance(Account account) async {
|
|
||||||
return GetIt.I
|
|
||||||
.get<Isar>()
|
|
||||||
.transactions
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.amountProperty()
|
|
||||||
.sum();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<Transaction>> getLastTransactions(
|
|
||||||
Account account,
|
|
||||||
DateTime today,
|
|
||||||
int days,
|
|
||||||
) async {
|
|
||||||
return GetIt.I
|
|
||||||
.get<Isar>()
|
|
||||||
.transactions
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.dateGreaterThan(toMidnight(today.subtract(Duration(days: days))))
|
|
||||||
.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<RecurringTransaction>> getRecurringTransactions(Account? account) {
|
|
||||||
if (account == null) {
|
|
||||||
return Future.value([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetIt.I
|
|
||||||
.get<Isar>()
|
|
||||||
.recurringTransactions
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<void> watchRecurringTransactions(Account account) {
|
|
||||||
final account = GetIt.I.get<CoreCubit>().activeAccount!;
|
|
||||||
return GetIt.I
|
|
||||||
.get<Isar>()
|
|
||||||
.recurringTransactions
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.build()
|
|
||||||
.watchLazy(fireImmediately: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> upsertAccount(Account account) async {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.accounts.put(account);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> upsertBeneficiary(Beneficiary beneficiary) async {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.beneficiarys.put(beneficiary);
|
|
||||||
await beneficiary.account.save();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Beneficiary?> getAccountBeneficiary(Account account) {
|
|
||||||
return GetIt.I
|
|
||||||
.get<Isar>()
|
|
||||||
.beneficiarys
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.findFirst();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> upsertTransactionTemplate(TransactionTemplate template) async {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.transactionTemplates.put(template);
|
|
||||||
await template.beneficiary.save();
|
|
||||||
await template.account.save();
|
|
||||||
await template.expenseCategory.save();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteRecurringTransactionTemplate(RecurringTransaction template) {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.transactionTemplates.delete(template.template.value!.id);
|
|
||||||
await db.recurringTransactions.delete(template.id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> upsertRecurringTransaction(RecurringTransaction template) async {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.recurringTransactions.put(template);
|
|
||||||
await template.template.save();
|
|
||||||
await template.account.save();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> upsertTransaction(Transaction transaction) async {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.transactions.put(transaction);
|
|
||||||
await transaction.beneficiary.save();
|
|
||||||
await transaction.account.save();
|
|
||||||
await transaction.expenseCategory.save();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<void> watchAccounts() {
|
|
||||||
return GetIt.I.get<Isar>().accounts.watchLazy();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<void> watchTransactionTemplates(Account account) {
|
|
||||||
return GetIt.I
|
|
||||||
.get<Isar>()
|
|
||||||
.transactionTemplates
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.watchLazy(fireImmediately: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteTransactionTemplate(TransactionTemplate template) {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.transactionTemplates.delete(template.id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<TransactionTemplate>> getTransactionTemplates(Account? account) {
|
|
||||||
if (account == null) {
|
|
||||||
return Future.value([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetIt.I
|
|
||||||
.get<Isar>()
|
|
||||||
.transactionTemplates
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<void> watchTransactions(Account account) {
|
|
||||||
return GetIt.I
|
|
||||||
.get<Isar>()
|
|
||||||
.transactions
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.watchLazy(fireImmediately: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<Transaction>> getTransactions(Account? account) {
|
|
||||||
if (account == null) {
|
|
||||||
return Future.value([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetIt.I
|
|
||||||
.get<Isar>()
|
|
||||||
.transactions
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<void> watchBeneficiaries() {
|
|
||||||
return GetIt.I.get<Isar>().beneficiarys.watchLazy(fireImmediately: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<Beneficiary>> getBeneficiaries() {
|
|
||||||
return GetIt.I.get<Isar>().beneficiarys.where().findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<Beneficiary?> watchBeneficiaryObject(Id id) {
|
|
||||||
return GetIt.I.get<Isar>().beneficiarys.watchObject(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> upsertExpenseCategory(ExpenseCategory category) {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() => db.expenseCategorys.put(category));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<ExpenseCategory>> getExpenseCategories() {
|
|
||||||
return GetIt.I.get<Isar>().expenseCategorys.where().findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<void> watchExpenseCategory() {
|
|
||||||
return GetIt.I.get<Isar>().expenseCategorys.watchLazy(fireImmediately: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream<void> watchBudgets(Account account) {
|
|
||||||
return GetIt.I
|
|
||||||
.get<Isar>()
|
|
||||||
.budgets
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.watchLazy(fireImmediately: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<Budget>> getBudgets(Account? account) {
|
|
||||||
if (account == null) {
|
|
||||||
return Future.value([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetIt.I
|
|
||||||
.get<Isar>()
|
|
||||||
.budgets
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> upsertBudget(Budget budget) {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.budgets.put(budget);
|
|
||||||
await budget.items.save();
|
|
||||||
await budget.account.save();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> upsertBudgetItem(BudgetItem item) {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
await db.budgetItems.put(item);
|
|
||||||
await item.expenseCategory.save();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
enum TransactionQueryDateOption { thisMonth }
|
|
||||||
|
|
||||||
Future<List<Transaction>> getTransactionsInTimeframe(
|
|
||||||
Account account,
|
|
||||||
DateTime today,
|
|
||||||
TransactionQueryDateOption option,
|
|
||||||
) async {
|
|
||||||
final lower = switch (option) {
|
|
||||||
TransactionQueryDateOption.thisMonth => DateTime(
|
|
||||||
today.year,
|
|
||||||
today.month,
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
final upper = switch (option) {
|
|
||||||
TransactionQueryDateOption.thisMonth => monthEnding(today),
|
|
||||||
};
|
|
||||||
|
|
||||||
return GetIt.I
|
|
||||||
.get<Isar>()
|
|
||||||
.transactions
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.dateBetween(lower, upper)
|
|
||||||
.findAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteAccount(Account account) async {
|
|
||||||
final db = GetIt.I.get<Isar>();
|
|
||||||
final affectedBudgets =
|
|
||||||
await db.budgets
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.findAll();
|
|
||||||
final budgetIds = affectedBudgets.map((a) => a.id).toList();
|
|
||||||
final budgetItemIds =
|
|
||||||
affectedBudgets.map((a) => a.items.map((i) => i.id)).flatten().toList();
|
|
||||||
return db.writeTxn(() async {
|
|
||||||
// Remove transactions
|
|
||||||
await db.transactions
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.deleteAll();
|
|
||||||
await db.beneficiarys
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.deleteAll();
|
|
||||||
|
|
||||||
// Remove templates
|
|
||||||
await db.recurringTransactions
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.deleteAll();
|
|
||||||
await db.transactionTemplates
|
|
||||||
.filter()
|
|
||||||
.account((q) => q.idEqualTo(account.id))
|
|
||||||
.deleteAll();
|
|
||||||
|
|
||||||
// Remove all budgets
|
|
||||||
await db.budgetItems.deleteAll(budgetItemIds);
|
|
||||||
await db.budgets.deleteAll(budgetIds);
|
|
||||||
|
|
||||||
// Remove account
|
|
||||||
await db.accounts.delete(account.id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
690
lib/database/sqlite.dart
Normal file
690
lib/database/sqlite.dart
Normal file
@@ -0,0 +1,690 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:drift_flutter/drift_flutter.dart';
|
||||||
|
import 'package:okane/ui/utils.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
|
part 'sqlite.g.dart';
|
||||||
|
|
||||||
|
class Accounts extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
TextColumn get name => text()();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BeneficiaryType { account, other }
|
||||||
|
|
||||||
|
class Beneficiaries extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
TextColumn get name => text().unique()();
|
||||||
|
TextColumn get type => textEnum<BeneficiaryType>()();
|
||||||
|
IntColumn get accountId => integer().nullable().references(Accounts, #id)();
|
||||||
|
TextColumn get imagePath => text().nullable()();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExpenseCategories extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
TextColumn get name => text()();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BudgetPeriod { month }
|
||||||
|
|
||||||
|
class BudgetItems extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
RealColumn get amount => real()();
|
||||||
|
IntColumn get expenseCategoryId =>
|
||||||
|
integer().references(ExpenseCategories, #id)();
|
||||||
|
IntColumn get budgetId => integer().references(Budgets, #id)();
|
||||||
|
}
|
||||||
|
|
||||||
|
class BudgetItemDto {
|
||||||
|
final BudgetItem item;
|
||||||
|
final ExpenseCategory expenseCategory;
|
||||||
|
|
||||||
|
BudgetItemDto({required this.item, required this.expenseCategory});
|
||||||
|
}
|
||||||
|
|
||||||
|
class Budgets extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
TextColumn get period => textEnum<BudgetPeriod>()();
|
||||||
|
TextColumn get name => text()();
|
||||||
|
RealColumn get income => real()();
|
||||||
|
BoolColumn get includeOtherSpendings => boolean()();
|
||||||
|
|
||||||
|
IntColumn get accountId => integer().references(Accounts, #id)();
|
||||||
|
}
|
||||||
|
|
||||||
|
class BudgetsDto {
|
||||||
|
final Budget budget;
|
||||||
|
|
||||||
|
BudgetsDto({required this.budget});
|
||||||
|
}
|
||||||
|
|
||||||
|
class Loans extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
IntColumn get beneficiaryId => integer().references(Beneficiaries, #id)();
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoanChanges extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
IntColumn get loanId => integer().references(Loans, #id)();
|
||||||
|
RealColumn get amount => real()();
|
||||||
|
DateTimeColumn get date => dateTime()();
|
||||||
|
}
|
||||||
|
|
||||||
|
class LoanDto {
|
||||||
|
final Loan loan;
|
||||||
|
final Beneficiary beneficiary;
|
||||||
|
|
||||||
|
LoanDto({required this.loan, required this.beneficiary});
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecurringTransactions extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
IntColumn get days => integer()();
|
||||||
|
DateTimeColumn get lastExecution => dateTime().nullable()();
|
||||||
|
|
||||||
|
IntColumn get templateId => integer().references(TransactionTemplates, #id)();
|
||||||
|
|
||||||
|
IntColumn get accountId => integer().references(Accounts, #id)();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef RecurringTransactionDto =
|
||||||
|
({
|
||||||
|
RecurringTransaction recurring,
|
||||||
|
Beneficiary beneficiary,
|
||||||
|
TransactionTemplate template,
|
||||||
|
});
|
||||||
|
|
||||||
|
class TransactionTemplates extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
TextColumn get name => text()();
|
||||||
|
RealColumn get amount => real()();
|
||||||
|
BoolColumn get recurring => boolean()();
|
||||||
|
|
||||||
|
IntColumn get expenseCategoryId =>
|
||||||
|
integer().nullable().references(ExpenseCategories, #id)();
|
||||||
|
IntColumn get beneficiaryId => integer().references(Beneficiaries, #id)();
|
||||||
|
IntColumn get accountId => integer().references(Accounts, #id)();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef TransactionTemplateDto =
|
||||||
|
({
|
||||||
|
TransactionTemplate template,
|
||||||
|
Beneficiary beneficiary,
|
||||||
|
ExpenseCategory? expenseCategory,
|
||||||
|
});
|
||||||
|
|
||||||
|
class Transactions extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
|
||||||
|
RealColumn get amount => real()();
|
||||||
|
// TODO: tags
|
||||||
|
DateTimeColumn get date => dateTime()();
|
||||||
|
IntColumn get expenseCategoryId =>
|
||||||
|
integer().nullable().references(ExpenseCategories, #id)();
|
||||||
|
IntColumn get accountId => integer().references(Accounts, #id)();
|
||||||
|
IntColumn get beneficiaryId => integer().references(Beneficiaries, #id)();
|
||||||
|
}
|
||||||
|
|
||||||
|
class TransactionDto {
|
||||||
|
final Transaction transaction;
|
||||||
|
final Beneficiary beneficiary;
|
||||||
|
final ExpenseCategory? expenseCategory;
|
||||||
|
|
||||||
|
TransactionDto({
|
||||||
|
required this.transaction,
|
||||||
|
required this.beneficiary,
|
||||||
|
required this.expenseCategory,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@DriftDatabase(
|
||||||
|
tables: [
|
||||||
|
Accounts,
|
||||||
|
Beneficiaries,
|
||||||
|
Budgets,
|
||||||
|
BudgetItems,
|
||||||
|
ExpenseCategories,
|
||||||
|
Loans,
|
||||||
|
LoanChanges,
|
||||||
|
RecurringTransactions,
|
||||||
|
TransactionTemplates,
|
||||||
|
Transactions,
|
||||||
|
],
|
||||||
|
daos: [
|
||||||
|
AccountsDao,
|
||||||
|
BeneficiariesDao,
|
||||||
|
BudgetsDao,
|
||||||
|
ExpenseCategoriesDao,
|
||||||
|
LoansDao,
|
||||||
|
RecurringTransactionsDao,
|
||||||
|
TransactionTemplatesDao,
|
||||||
|
TransactionsDao,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
class OkaneDatabase extends _$OkaneDatabase {
|
||||||
|
OkaneDatabase() : super(_openConnection());
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get schemaVersion => 1;
|
||||||
|
|
||||||
|
static QueryExecutor _openConnection() {
|
||||||
|
return driftDatabase(
|
||||||
|
name: "okane",
|
||||||
|
native: const DriftNativeOptions(
|
||||||
|
databaseDirectory: getApplicationSupportDirectory,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DriftAccessor(
|
||||||
|
tables: [
|
||||||
|
Accounts,
|
||||||
|
Transactions,
|
||||||
|
TransactionTemplates,
|
||||||
|
RecurringTransactions,
|
||||||
|
Budgets,
|
||||||
|
Beneficiaries,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
class AccountsDao extends DatabaseAccessor<OkaneDatabase>
|
||||||
|
with _$AccountsDaoMixin {
|
||||||
|
AccountsDao(super.db);
|
||||||
|
|
||||||
|
Stream<List<Account>> accountsStream() {
|
||||||
|
return select(accounts).watch();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Account>> getAccounts() {
|
||||||
|
return select(accounts).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> upsertAccount(AccountsCompanion account) {
|
||||||
|
return into(accounts).insertOnConflictUpdate(account);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> removeAccount(Account account) async {
|
||||||
|
// Delete dependent data
|
||||||
|
await (delete(transactions)
|
||||||
|
..where((t) => t.accountId.equals(account.id))).go();
|
||||||
|
await (delete(recurringTransactions)
|
||||||
|
..where((r) => r.accountId.equals(account.id))).go();
|
||||||
|
await (delete(transactionTemplates)
|
||||||
|
..where((t) => t.accountId.equals(account.id))).go();
|
||||||
|
await (delete(budgets)..where((b) => b.accountId.equals(account.id))).go();
|
||||||
|
await (delete(beneficiaries)
|
||||||
|
..where((b) => b.accountId.equals(account.id))).go();
|
||||||
|
|
||||||
|
// Delete the account
|
||||||
|
await (delete(accounts)..where((a) => a.id.equals(account.id))).go();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TransactionQueryDateOption { thisMonth }
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [Transactions, Beneficiaries, ExpenseCategories])
|
||||||
|
class TransactionsDao extends DatabaseAccessor<OkaneDatabase>
|
||||||
|
with _$TransactionsDaoMixin {
|
||||||
|
TransactionsDao(super.db);
|
||||||
|
|
||||||
|
JoinedSelectStatement _transactionQuery(Account account) {
|
||||||
|
return (select(transactions)
|
||||||
|
..where((t) => t.accountId.equals(account.id))).join([
|
||||||
|
leftOuterJoin(
|
||||||
|
beneficiaries,
|
||||||
|
beneficiaries.id.equalsExp(transactions.beneficiaryId),
|
||||||
|
),
|
||||||
|
leftOuterJoin(
|
||||||
|
expenseCategories,
|
||||||
|
expenseCategories.id.equalsExp(transactions.expenseCategoryId),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionDto _mapToDto(TypedResult row) {
|
||||||
|
return TransactionDto(
|
||||||
|
transaction: row.readTable(transactions),
|
||||||
|
beneficiary: row.readTable(beneficiaries),
|
||||||
|
expenseCategory: row.readTableOrNull(expenseCategories),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<List<TransactionDto>> transactionsStream(Account account) {
|
||||||
|
return _transactionQuery(account).watch().map((rows) {
|
||||||
|
return rows.map(_mapToDto).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<TransactionDto>> getTransactions(Account? account) {
|
||||||
|
if (account == null) {
|
||||||
|
return Future.value(List.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
return _transactionQuery(
|
||||||
|
account,
|
||||||
|
).get().then((rows) => rows.map(_mapToDto).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<TransactionDto>> getLastTransactions(
|
||||||
|
Account account,
|
||||||
|
DateTime today,
|
||||||
|
int days,
|
||||||
|
) async {
|
||||||
|
return (select(transactions)..where(
|
||||||
|
(t) =>
|
||||||
|
t.accountId.equals(account.id) &
|
||||||
|
t.date.isBiggerThanValue(
|
||||||
|
toMidnight(today.subtract(Duration(days: days))),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.join([
|
||||||
|
leftOuterJoin(
|
||||||
|
beneficiaries,
|
||||||
|
beneficiaries.id.equalsExp(transactions.beneficiaryId),
|
||||||
|
),
|
||||||
|
leftOuterJoin(
|
||||||
|
expenseCategories,
|
||||||
|
expenseCategories.id.equalsExp(transactions.expenseCategoryId),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.get()
|
||||||
|
.then((rows) => rows.map(_mapToDto).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<double> getTotalBalance(Iterable<int> accountIds) async {
|
||||||
|
final sum = transactions.amount.sum();
|
||||||
|
final query =
|
||||||
|
selectOnly(transactions)
|
||||||
|
..where(transactions.accountId.isIn(accountIds))
|
||||||
|
..addColumns([sum]);
|
||||||
|
return query
|
||||||
|
.map((row) => row.read(sum))
|
||||||
|
.getSingleOrNull()
|
||||||
|
.then((v) => v ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<TransactionDto>> getTransactionsInTimeframe(
|
||||||
|
Account account,
|
||||||
|
DateTime today,
|
||||||
|
TransactionQueryDateOption option,
|
||||||
|
) {
|
||||||
|
final lower = switch (option) {
|
||||||
|
TransactionQueryDateOption.thisMonth => DateTime(
|
||||||
|
today.year,
|
||||||
|
today.month,
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
final upper = switch (option) {
|
||||||
|
TransactionQueryDateOption.thisMonth => monthEnding(today),
|
||||||
|
};
|
||||||
|
|
||||||
|
return (select(transactions)..where(
|
||||||
|
(t) =>
|
||||||
|
t.accountId.equals(account.id) &
|
||||||
|
t.date.isBetweenValues(lower, upper),
|
||||||
|
))
|
||||||
|
.join([
|
||||||
|
leftOuterJoin(
|
||||||
|
beneficiaries,
|
||||||
|
beneficiaries.id.equalsExp(transactions.beneficiaryId),
|
||||||
|
),
|
||||||
|
leftOuterJoin(
|
||||||
|
expenseCategories,
|
||||||
|
expenseCategories.id.equalsExp(transactions.expenseCategoryId),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.get()
|
||||||
|
.then((rows) => rows.map(_mapToDto).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Transaction> upsertTransaction(TransactionsCompanion t) {
|
||||||
|
return into(
|
||||||
|
transactions,
|
||||||
|
).insertReturning(t, mode: InsertMode.insertOrReplace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [Beneficiaries])
|
||||||
|
class BeneficiariesDao extends DatabaseAccessor<OkaneDatabase>
|
||||||
|
with _$BeneficiariesDaoMixin {
|
||||||
|
BeneficiariesDao(super.db);
|
||||||
|
|
||||||
|
Stream<List<Beneficiary>> beneficiariesStream() {
|
||||||
|
return select(beneficiaries).watch();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Beneficiary>> getBeneficiaries() {
|
||||||
|
return select(beneficiaries).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Beneficiary> upsertBeneficiary(BeneficiariesCompanion beneficiary) {
|
||||||
|
return into(
|
||||||
|
beneficiaries,
|
||||||
|
).insertReturning(beneficiary, mode: InsertMode.insertOrReplace);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Beneficiary> getAccountBeneficiary(Account account) {
|
||||||
|
return (select(beneficiaries)
|
||||||
|
..where((b) => b.accountId.equals(account.id))).getSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<Beneficiary> watchBeneficiary(int id) {
|
||||||
|
return (select(beneficiaries)..where((b) => b.id.equals(id))).watchSingle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [ExpenseCategories])
|
||||||
|
class ExpenseCategoriesDao extends DatabaseAccessor<OkaneDatabase>
|
||||||
|
with _$ExpenseCategoriesDaoMixin {
|
||||||
|
ExpenseCategoriesDao(super.db);
|
||||||
|
|
||||||
|
Stream<List<ExpenseCategory>> expenseCategoriesStream(Account account) {
|
||||||
|
return select(expenseCategories).watch();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<ExpenseCategory>> getExpenseCategories(Account? account) {
|
||||||
|
if (account == null) {
|
||||||
|
return Future.value(List.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
return select(expenseCategories).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ExpenseCategory> upsertCategory(ExpenseCategoriesCompanion category) {
|
||||||
|
return into(
|
||||||
|
expenseCategories,
|
||||||
|
).insertReturning(category, mode: InsertMode.insertOrReplace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [Budgets, BudgetItems])
|
||||||
|
class BudgetsDao extends DatabaseAccessor<OkaneDatabase>
|
||||||
|
with _$BudgetsDaoMixin {
|
||||||
|
BudgetsDao(super.db);
|
||||||
|
|
||||||
|
Stream<List<BudgetsDto>> budgetsStream(Account account) {
|
||||||
|
return (select(budgets)
|
||||||
|
..where((b) => b.accountId.equals(account.id))).watch().map((rows) {
|
||||||
|
return rows.map((row) {
|
||||||
|
return BudgetsDto(budget: row);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<BudgetsDto>> getBudgets(Account? account) {
|
||||||
|
if (account == null) {
|
||||||
|
return Future.value(List.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (select(budgets)
|
||||||
|
..where((b) => b.accountId.equals(account.id))).get().then((rows) {
|
||||||
|
return rows.map((row) {
|
||||||
|
return BudgetsDto(budget: row);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<List<BudgetItemDto>> watchBudgetItems(Budget budget) {
|
||||||
|
return (select(budgetItems)..where((b) => b.budgetId.equals(budget.id)))
|
||||||
|
.join([
|
||||||
|
leftOuterJoin(
|
||||||
|
expenseCategories,
|
||||||
|
expenseCategories.id.equalsExp(budgetItems.expenseCategoryId),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.watch()
|
||||||
|
.map((rows) {
|
||||||
|
return rows.map((row) {
|
||||||
|
return BudgetItemDto(
|
||||||
|
expenseCategory: row.readTable(expenseCategories),
|
||||||
|
item: row.readTable(budgetItems),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Budget> upsertBudget(BudgetsCompanion budget) {
|
||||||
|
return into(
|
||||||
|
budgets,
|
||||||
|
).insertReturning(budget, mode: InsertMode.insertOrReplace);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<BudgetItem> upsertBudgetItem(BudgetItemsCompanion item) {
|
||||||
|
return into(
|
||||||
|
budgetItems,
|
||||||
|
).insertReturning(item, mode: InsertMode.insertOrReplace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [Loans, LoanChanges, Beneficiaries])
|
||||||
|
class LoansDao extends DatabaseAccessor<OkaneDatabase> with _$LoansDaoMixin {
|
||||||
|
LoansDao(super.db);
|
||||||
|
|
||||||
|
Stream<List<LoanDto>> loansStream(Account account) {
|
||||||
|
return select(loans)
|
||||||
|
.join([
|
||||||
|
leftOuterJoin(
|
||||||
|
beneficiaries,
|
||||||
|
beneficiaries.id.equalsExp(loans.beneficiaryId),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.watch()
|
||||||
|
.map((rows) {
|
||||||
|
return rows.map((row) {
|
||||||
|
return LoanDto(
|
||||||
|
loan: row.readTable(loans),
|
||||||
|
beneficiary: row.readTable(beneficiaries),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<LoanDto>> getLoans(Account? account) {
|
||||||
|
if (account == null) {
|
||||||
|
return Future.value(List.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
return select(loans)
|
||||||
|
.join([
|
||||||
|
leftOuterJoin(
|
||||||
|
beneficiaries,
|
||||||
|
beneficiaries.id.equalsExp(loans.beneficiaryId),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.get()
|
||||||
|
.then((rows) {
|
||||||
|
return rows.map((row) {
|
||||||
|
return LoanDto(
|
||||||
|
loan: row.readTable(loans),
|
||||||
|
beneficiary: row.readTable(beneficiaries),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<double> getTotalLoanSum() async {
|
||||||
|
final count = loanChanges.amount.sum();
|
||||||
|
final query = selectOnly(loanChanges)..addColumns([count]);
|
||||||
|
return query
|
||||||
|
.map((row) => row.read(count))
|
||||||
|
.getSingleOrNull()
|
||||||
|
.then((v) => v ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Loan> upsertLoan(LoansCompanion loan) {
|
||||||
|
return into(loans).insertReturning(loan, mode: InsertMode.insertOrReplace);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<LoanChange> upsertLoanChange(LoanChangesCompanion loanChange) {
|
||||||
|
return into(
|
||||||
|
loanChanges,
|
||||||
|
).insertReturning(loanChange, mode: InsertMode.insertOrReplace);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<List<LoanChange>> watchLoanChanges(Loan loan) {
|
||||||
|
return (select(loanChanges)
|
||||||
|
..where((c) => c.loanId.equals(loan.id))).watch();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteLoanChange(int id) {
|
||||||
|
return (delete(loanChanges)..where((c) => c.id.equals(id))).go();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [TransactionTemplates, ExpenseCategories, Beneficiaries])
|
||||||
|
class TransactionTemplatesDao extends DatabaseAccessor<OkaneDatabase>
|
||||||
|
with _$TransactionTemplatesDaoMixin {
|
||||||
|
TransactionTemplatesDao(super.db);
|
||||||
|
|
||||||
|
Stream<List<TransactionTemplateDto>> transactionTemplatesStream(
|
||||||
|
Account account,
|
||||||
|
) {
|
||||||
|
return (select(transactionTemplates)
|
||||||
|
..where((b) => b.accountId.equals(account.id)))
|
||||||
|
.join([
|
||||||
|
leftOuterJoin(
|
||||||
|
beneficiaries,
|
||||||
|
beneficiaries.id.equalsExp(transactionTemplates.beneficiaryId),
|
||||||
|
),
|
||||||
|
leftOuterJoin(
|
||||||
|
expenseCategories,
|
||||||
|
expenseCategories.id.equalsExp(
|
||||||
|
transactionTemplates.expenseCategoryId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.watch()
|
||||||
|
.map((rows) {
|
||||||
|
return rows.map((row) {
|
||||||
|
return (
|
||||||
|
template: row.readTable(transactionTemplates),
|
||||||
|
beneficiary: row.readTable(beneficiaries),
|
||||||
|
expenseCategory: row.readTable(expenseCategories),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<TransactionTemplateDto>> getTransactionTemplates(
|
||||||
|
Account? account,
|
||||||
|
) {
|
||||||
|
if (account == null) {
|
||||||
|
return Future.value(List.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (select(transactionTemplates)
|
||||||
|
..where((b) => b.accountId.equals(account.id)))
|
||||||
|
.join([
|
||||||
|
leftOuterJoin(
|
||||||
|
beneficiaries,
|
||||||
|
beneficiaries.id.equalsExp(transactionTemplates.beneficiaryId),
|
||||||
|
),
|
||||||
|
leftOuterJoin(
|
||||||
|
expenseCategories,
|
||||||
|
expenseCategories.id.equalsExp(
|
||||||
|
transactionTemplates.expenseCategoryId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.get()
|
||||||
|
.then((rows) {
|
||||||
|
return rows.map((row) {
|
||||||
|
return (
|
||||||
|
template: row.readTable(transactionTemplates),
|
||||||
|
beneficiary: row.readTable(beneficiaries),
|
||||||
|
expenseCategory: row.readTable(expenseCategories),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<TransactionTemplate> upsertTemplate(
|
||||||
|
TransactionTemplatesCompanion template,
|
||||||
|
) {
|
||||||
|
return into(
|
||||||
|
transactionTemplates,
|
||||||
|
).insertReturning(template, mode: InsertMode.insertOrReplace);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteTemplate(TransactionTemplate template) {
|
||||||
|
return (delete(transactionTemplates)
|
||||||
|
..where((t) => t.id.equals(template.id))).go();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [TransactionTemplates, RecurringTransactions])
|
||||||
|
class RecurringTransactionsDao extends DatabaseAccessor<OkaneDatabase>
|
||||||
|
with _$RecurringTransactionsDaoMixin {
|
||||||
|
RecurringTransactionsDao(super.db);
|
||||||
|
|
||||||
|
Stream<List<RecurringTransactionDto>> recurringTransactionsStream(
|
||||||
|
Account account,
|
||||||
|
) {
|
||||||
|
return (select(recurringTransactions)
|
||||||
|
..where((b) => b.accountId.equals(account.id)))
|
||||||
|
.join([
|
||||||
|
leftOuterJoin(
|
||||||
|
transactionTemplates,
|
||||||
|
transactionTemplates.id.equalsExp(recurringTransactions.templateId),
|
||||||
|
),
|
||||||
|
leftOuterJoin(
|
||||||
|
beneficiaries,
|
||||||
|
beneficiaries.id.equalsExp(transactionTemplates.beneficiaryId),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.watch()
|
||||||
|
.map((rows) {
|
||||||
|
return rows.map((row) {
|
||||||
|
return (
|
||||||
|
recurring: row.readTable(recurringTransactions),
|
||||||
|
beneficiary: row.readTable(beneficiaries),
|
||||||
|
template: row.readTable(transactionTemplates),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<RecurringTransactionDto>> getRecurringTransactions(
|
||||||
|
Account? account,
|
||||||
|
) {
|
||||||
|
if (account == null) {
|
||||||
|
return Future.value(List.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (select(recurringTransactions)
|
||||||
|
..where((b) => b.accountId.equals(account.id)))
|
||||||
|
.join([
|
||||||
|
leftOuterJoin(
|
||||||
|
transactionTemplates,
|
||||||
|
transactionTemplates.id.equalsExp(recurringTransactions.templateId),
|
||||||
|
),
|
||||||
|
leftOuterJoin(
|
||||||
|
beneficiaries,
|
||||||
|
beneficiaries.id.equalsExp(transactionTemplates.beneficiaryId),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
.get()
|
||||||
|
.then((rows) {
|
||||||
|
return rows.map((row) {
|
||||||
|
return (
|
||||||
|
recurring: row.readTable(recurringTransactions),
|
||||||
|
beneficiary: row.readTable(beneficiaries),
|
||||||
|
template: row.readTable(transactionTemplates),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> upsertRecurringTransaction(RecurringTransactionsCompanion r) {
|
||||||
|
return into(recurringTransactions).insertOnConflictUpdate(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteTemplate(RecurringTransactionDto dto) async {
|
||||||
|
await db.transactionTemplatesDao.deleteTemplate(dto.template);
|
||||||
|
await (delete(recurringTransactions)
|
||||||
|
..where((t) => t.id.equals(dto.recurring.id))).go();
|
||||||
|
}
|
||||||
|
}
|
||||||
8248
lib/database/sqlite.g.dart
Normal file
8248
lib/database/sqlite.g.dart
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/screen.dart';
|
import 'package:okane/screen.dart';
|
||||||
import 'package:okane/ui/navigation.dart';
|
import 'package:okane/ui/navigation.dart';
|
||||||
@@ -13,6 +12,9 @@ import 'package:okane/ui/pages/budgets/budget_details.dart';
|
|||||||
import 'package:okane/ui/pages/transaction_details.dart';
|
import 'package:okane/ui/pages/transaction_details.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
import 'package:okane/ui/state/settings.dart';
|
import 'package:okane/ui/state/settings.dart';
|
||||||
|
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||||
|
|
||||||
|
import 'ui/pages/loans/loan_details.dart';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
@@ -20,11 +22,20 @@ Future<void> main() async {
|
|||||||
|
|
||||||
final settings = SettingsCubit();
|
final settings = SettingsCubit();
|
||||||
await settings.loadSettings();
|
await settings.loadSettings();
|
||||||
|
|
||||||
GetIt.I.registerSingleton<SettingsCubit>(settings);
|
GetIt.I.registerSingleton<SettingsCubit>(settings);
|
||||||
GetIt.I.registerSingleton<CoreCubit>(CoreCubit());
|
GetIt.I.registerSingleton<CoreCubit>(CoreCubit());
|
||||||
GetIt.I.registerSingleton<Isar>(await openDatabase());
|
GetIt.I.registerSingleton<OkaneDatabase>(OkaneDatabase());
|
||||||
|
|
||||||
runApp(const MyApp());
|
appRunner() => runApp(const MyApp());
|
||||||
|
if (settings.sentryDsn != null) {
|
||||||
|
print("Setting up Sentry!");
|
||||||
|
await SentryFlutter.init((options) {
|
||||||
|
options.dsn = settings.sentryDsn!;
|
||||||
|
}, appRunner: appRunner);
|
||||||
|
} else {
|
||||||
|
appRunner();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
@@ -66,6 +77,7 @@ class MyApp extends StatelessWidget {
|
|||||||
"/transactions/details" =>
|
"/transactions/details" =>
|
||||||
TransactionDetailsPage.mobileRoute,
|
TransactionDetailsPage.mobileRoute,
|
||||||
"/budgets/details" => BudgetDetailsPage.mobileRoute,
|
"/budgets/details" => BudgetDetailsPage.mobileRoute,
|
||||||
|
"/loans/details" => LoanDetailsPage.mobileRoute,
|
||||||
_ => MaterialPageRoute<void>(
|
_ => MaterialPageRoute<void>(
|
||||||
builder: (_) => Text("Unknown!!"),
|
builder: (_) => Text("Unknown!!"),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import 'package:okane/ui/pages/account/account.dart';
|
|||||||
import 'package:okane/ui/pages/beneficiary_list.dart';
|
import 'package:okane/ui/pages/beneficiary_list.dart';
|
||||||
import 'package:okane/ui/pages/budgets/budget_details.dart';
|
import 'package:okane/ui/pages/budgets/budget_details.dart';
|
||||||
import 'package:okane/ui/pages/budgets/budgets.dart';
|
import 'package:okane/ui/pages/budgets/budgets.dart';
|
||||||
|
import 'package:okane/ui/pages/loans/loan_details.dart';
|
||||||
|
import 'package:okane/ui/pages/loans/loan_list.dart';
|
||||||
import 'package:okane/ui/pages/settings.dart';
|
import 'package:okane/ui/pages/settings.dart';
|
||||||
import 'package:okane/ui/pages/template_list.dart';
|
import 'package:okane/ui/pages/template_list.dart';
|
||||||
import 'package:okane/ui/pages/transaction_details.dart';
|
import 'package:okane/ui/pages/transaction_details.dart';
|
||||||
@@ -18,6 +20,7 @@ enum OkanePage {
|
|||||||
beneficiaries,
|
beneficiaries,
|
||||||
templates,
|
templates,
|
||||||
budgets,
|
budgets,
|
||||||
|
loans,
|
||||||
settings,
|
settings,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +73,7 @@ final _pages = <OkanePageItem>[
|
|||||||
"Accounts",
|
"Accounts",
|
||||||
AccountListPage(isPage: false),
|
AccountListPage(isPage: false),
|
||||||
null,
|
null,
|
||||||
false,
|
true,
|
||||||
),
|
),
|
||||||
OkanePageItem(
|
OkanePageItem(
|
||||||
OkanePage.transactions,
|
OkanePage.transactions,
|
||||||
@@ -104,6 +107,14 @@ final _pages = <OkanePageItem>[
|
|||||||
(_) => BudgetDetailsPage(),
|
(_) => BudgetDetailsPage(),
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
|
OkanePageItem(
|
||||||
|
OkanePage.loans,
|
||||||
|
Icons.money_outlined,
|
||||||
|
"Loans",
|
||||||
|
LoanListPage(),
|
||||||
|
(_) => LoanDetailsPage(isPage: false),
|
||||||
|
false,
|
||||||
|
),
|
||||||
OkanePageItem(
|
OkanePageItem(
|
||||||
OkanePage.settings,
|
OkanePage.settings,
|
||||||
Icons.settings,
|
Icons.settings,
|
||||||
@@ -215,17 +226,10 @@ class OkaneNavigationLayout extends StatelessWidget {
|
|||||||
if (p.showAccountName &&
|
if (p.showAccountName &&
|
||||||
state.activeAccountIndex != null)
|
state.activeAccountIndex != null)
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(left: 8),
|
padding: EdgeInsets.symmetric(
|
||||||
child: Text(
|
horizontal: 8,
|
||||||
state
|
|
||||||
.accounts[state
|
|
||||||
.activeAccountIndex!]
|
|
||||||
.name!,
|
|
||||||
style:
|
|
||||||
Theme.of(
|
|
||||||
context,
|
|
||||||
).textTheme.titleLarge,
|
|
||||||
),
|
),
|
||||||
|
child: AccountSwitcher(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -238,12 +242,7 @@ class OkaneNavigationLayout extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
if (p.showAccountName &&
|
if (p.showAccountName &&
|
||||||
state.activeAccountIndex != null)
|
state.activeAccountIndex != null)
|
||||||
AccountIndicator(
|
AccountIndicator(),
|
||||||
accountName:
|
|
||||||
state
|
|
||||||
.accounts[state.activeAccountIndex!]
|
|
||||||
.name!,
|
|
||||||
),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child:
|
child:
|
||||||
p.details != null
|
p.details != null
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
|
import 'package:drift/drift.dart' show Value;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/collections/account.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/database/collections/beneficiary.dart';
|
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/ui/pages/account/breakdown_card.dart';
|
import 'package:okane/ui/pages/account/breakdown_card.dart';
|
||||||
import 'package:okane/ui/pages/account/delete_account.dart';
|
import 'package:okane/ui/pages/account/loan_card.dart';
|
||||||
import 'package:okane/ui/pages/account/total_balance_card.dart';
|
import 'package:okane/ui/pages/account/total_balance_card.dart';
|
||||||
import 'package:okane/ui/pages/account/upcoming_transactions_card.dart';
|
import 'package:okane/ui/pages/account/upcoming_transactions_card.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
@@ -26,95 +25,10 @@ class AccountListPageState extends State<AccountListPage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final bloc = GetIt.I.get<CoreCubit>();
|
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
ListView(
|
ListView(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
||||||
child: Text(
|
|
||||||
t.pages.accounts.title,
|
|
||||||
style: Theme.of(context).textTheme.titleLarge,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
||||||
child: BlocBuilder<CoreCubit, CoreState>(
|
|
||||||
builder:
|
|
||||||
(context, state) => Row(
|
|
||||||
children: [
|
|
||||||
OutlinedButton(
|
|
||||||
onPressed:
|
|
||||||
state.accounts.isEmpty
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
showDialogOrModal(
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(context) => ListView.builder(
|
|
||||||
shrinkWrap: true,
|
|
||||||
itemCount: state.accounts.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final item =
|
|
||||||
state.accounts[index];
|
|
||||||
return ListTile(
|
|
||||||
title: Text(item.name!),
|
|
||||||
trailing: IconButton(
|
|
||||||
icon: Icon(Icons.delete),
|
|
||||||
color: Colors.red,
|
|
||||||
onPressed: () async {
|
|
||||||
await showDialog(
|
|
||||||
context: context,
|
|
||||||
barrierDismissible: false,
|
|
||||||
builder:
|
|
||||||
(context) =>
|
|
||||||
DeleteAccountPopup(
|
|
||||||
account: item,
|
|
||||||
onCancel: () {
|
|
||||||
Navigator.of(
|
|
||||||
context,
|
|
||||||
).pop();
|
|
||||||
Navigator.of(
|
|
||||||
context,
|
|
||||||
).pop();
|
|
||||||
},
|
|
||||||
afterDelete: () {
|
|
||||||
Navigator.of(
|
|
||||||
context,
|
|
||||||
).pop();
|
|
||||||
Navigator.of(
|
|
||||||
context,
|
|
||||||
).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
GetIt.I
|
|
||||||
.get<CoreCubit>()
|
|
||||||
.setActiveAccountIndex(
|
|
||||||
index,
|
|
||||||
);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
bloc.activeAccount?.name ??
|
|
||||||
t.pages.accounts.accountSelector.none,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
child: BlocBuilder<CoreCubit, CoreState>(
|
child: BlocBuilder<CoreCubit, CoreState>(
|
||||||
@@ -130,7 +44,7 @@ class AccountListPageState extends State<AccountListPage> {
|
|||||||
width: 150,
|
width: 150,
|
||||||
height: 100,
|
height: 100,
|
||||||
child: Card(
|
child: Card(
|
||||||
color: colorHash(state.accounts[index].name!),
|
color: colorHash(state.accounts[index].name),
|
||||||
shape:
|
shape:
|
||||||
index == state.activeAccountIndex
|
index == state.activeAccountIndex
|
||||||
? RoundedRectangleBorder(
|
? RoundedRectangleBorder(
|
||||||
@@ -147,11 +61,14 @@ class AccountListPageState extends State<AccountListPage> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Text(state.accounts[index].name!),
|
Text(state.accounts[index].name),
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: getTotalBalance(
|
future: GetIt.I
|
||||||
state.accounts[index],
|
.get<OkaneDatabase>()
|
||||||
),
|
.transactionsDao
|
||||||
|
.getTotalBalance([
|
||||||
|
state.accounts[index].id,
|
||||||
|
]),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
return Container();
|
return Container();
|
||||||
@@ -184,7 +101,10 @@ class AccountListPageState extends State<AccountListPage> {
|
|||||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
|
||||||
child: UpcomingTransactionsCard(),
|
child: UpcomingTransactionsCard(),
|
||||||
),
|
),
|
||||||
|
|
||||||
Padding(padding: EdgeInsets.all(8), child: BreakdownCard()),
|
Padding(padding: EdgeInsets.all(8), child: BreakdownCard()),
|
||||||
|
|
||||||
|
Padding(padding: EdgeInsets.all(8), child: TotalLoanCard()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -221,16 +141,21 @@ class AccountListPageState extends State<AccountListPage> {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (_accountNameController.text.isEmpty) return;
|
if (_accountNameController.text.isEmpty) return;
|
||||||
|
|
||||||
final a =
|
final db = GetIt.I.get<OkaneDatabase>();
|
||||||
Account()..name = _accountNameController.text;
|
print("Adding account");
|
||||||
final b =
|
final accountId = await db.accountsDao
|
||||||
Beneficiary()
|
.upsertAccount(
|
||||||
..name = _accountNameController.text
|
AccountsCompanion(
|
||||||
..account.value =
|
name: Value(_accountNameController.text),
|
||||||
GetIt.I.get<CoreCubit>().activeAccount
|
),
|
||||||
..type = BeneficiaryType.account;
|
);
|
||||||
await upsertAccount(a);
|
print("Adding beneficiary");
|
||||||
await upsertBeneficiary(b);
|
final b = BeneficiariesCompanion(
|
||||||
|
name: Value(_accountNameController.text),
|
||||||
|
accountId: Value(accountId),
|
||||||
|
type: Value(BeneficiaryType.account),
|
||||||
|
);
|
||||||
|
await db.beneficiariesDao.upsertBeneficiary(b);
|
||||||
_accountNameController.text = "";
|
_accountNameController.text = "";
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import 'dart:collection';
|
|||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/database.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
import 'package:okane/ui/utils.dart';
|
import 'package:okane/ui/utils.dart';
|
||||||
@@ -26,21 +26,27 @@ class AccountBalanceGraphCard extends StatelessWidget {
|
|||||||
Future<List<FlSpot>> getAccountBalance() async {
|
Future<List<FlSpot>> getAccountBalance() async {
|
||||||
final coreCubit = GetIt.I.get<CoreCubit>();
|
final coreCubit = GetIt.I.get<CoreCubit>();
|
||||||
final today = toMidnight(DateTime.now());
|
final today = toMidnight(DateTime.now());
|
||||||
final transactions = await getLastTransactions(
|
final db = GetIt.I.get<OkaneDatabase>();
|
||||||
|
print("Getting transactions");
|
||||||
|
final transactions = await db.transactionsDao.getLastTransactions(
|
||||||
coreCubit.activeAccount!,
|
coreCubit.activeAccount!,
|
||||||
today,
|
today,
|
||||||
30,
|
30,
|
||||||
);
|
);
|
||||||
final totalBalance = await getTotalBalance(coreCubit.activeAccount!);
|
print("Got transactions. Getting balance");
|
||||||
|
final totalBalance = await db.transactionsDao.getTotalBalance([
|
||||||
|
coreCubit.activeAccount!.id,
|
||||||
|
]);
|
||||||
|
print("Got balance");
|
||||||
|
|
||||||
// Compute the differences per day
|
// Compute the differences per day
|
||||||
Map<int, double> differences = Map.fromEntries(
|
Map<int, double> differences = Map.fromEntries(
|
||||||
List.generate(30, (i) => i).map((i) => MapEntry(i, 0)),
|
List.generate(30, (i) => i).map((i) => MapEntry(i, 0)),
|
||||||
);
|
);
|
||||||
for (final item in transactions) {
|
for (final item in transactions) {
|
||||||
final diff = today.difference(toMidnight(item.date)).inDays;
|
final diff = today.difference(toMidnight(item.transaction.date)).inDays;
|
||||||
final balance = differences[diff]!;
|
final balance = differences[diff]!;
|
||||||
differences[diff] = balance + item.amount;
|
differences[diff] = balance + item.transaction.amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the balance
|
// Compute the balance
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/collections/transaction.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
import 'package:okane/ui/utils.dart';
|
import 'package:okane/ui/utils.dart';
|
||||||
@@ -45,32 +42,32 @@ class LegendItem extends StatelessWidget {
|
|||||||
class BreakdownCard extends StatelessWidget {
|
class BreakdownCard extends StatelessWidget {
|
||||||
const BreakdownCard({super.key});
|
const BreakdownCard({super.key});
|
||||||
|
|
||||||
LegendData _computeSections(List<Transaction> transactions) {
|
LegendData _computeSections(List<TransactionDto> transactions) {
|
||||||
Map<String, double> expenses = {};
|
Map<String, double> expenses = {};
|
||||||
Map<String, Color> colors = {};
|
Map<String, Color> colors = {};
|
||||||
double usableMoney = 0;
|
double usableMoney = 0;
|
||||||
transactions.forEach((t) {
|
for (var t in transactions) {
|
||||||
String category;
|
String category;
|
||||||
if (t.amount > 0) {
|
if (t.transaction.amount > 0) {
|
||||||
category = CATEGORY_INCOME;
|
category = CATEGORY_INCOME;
|
||||||
colors[CATEGORY_INCOME] = Colors.green;
|
colors[CATEGORY_INCOME] = Colors.green;
|
||||||
} else {
|
} else {
|
||||||
if (t.expenseCategory.value?.name == null) {
|
if (t.expenseCategory?.name == null) {
|
||||||
category = CATEGORY_OTHER;
|
category = CATEGORY_OTHER;
|
||||||
colors[category] = Colors.red;
|
colors[category] = Colors.red;
|
||||||
} else {
|
} else {
|
||||||
category = t.expenseCategory.value!.name;
|
category = t.expenseCategory!.name;
|
||||||
colors[category] = colorHash(t.expenseCategory.value!.name);
|
colors[category] = colorHash(t.expenseCategory!.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expenses.update(
|
expenses.update(
|
||||||
category,
|
category,
|
||||||
(value) => value + t.amount.abs(),
|
(value) => value + t.transaction.amount.abs(),
|
||||||
ifAbsent: () => t.amount.abs(),
|
ifAbsent: () => t.transaction.amount.abs().toDouble(),
|
||||||
);
|
);
|
||||||
usableMoney += t.amount;
|
usableMoney += t.transaction.amount;
|
||||||
});
|
}
|
||||||
return (expenses: expenses, colors: colors, usable: usableMoney);
|
return (expenses: expenses, colors: colors, usable: usableMoney);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,8 +94,13 @@ class BreakdownCard extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final db = GetIt.I.get<OkaneDatabase>();
|
||||||
return FutureBuilder(
|
return FutureBuilder(
|
||||||
future: getLastTransactions(bloc.activeAccount!, DateTime.now(), 30),
|
future: db.transactionsDao.getLastTransactions(
|
||||||
|
bloc.activeAccount!,
|
||||||
|
DateTime.now(),
|
||||||
|
30,
|
||||||
|
),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
return _buildCard(
|
return _buildCard(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/collections/account.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ class DeleteAccountPopup extends StatelessWidget {
|
|||||||
)
|
)
|
||||||
: Text(
|
: Text(
|
||||||
t.pages.accounts.deleteAccount.content(
|
t.pages.accounts.deleteAccount.content(
|
||||||
name: account.name!,
|
name: account.name,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
|
|||||||
37
lib/ui/pages/account/loan_card.dart
Normal file
37
lib/ui/pages/account/loan_card.dart
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:okane/database/sqlite.dart';
|
||||||
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
|
import 'package:okane/ui/state/core.dart';
|
||||||
|
import 'package:okane/ui/utils.dart';
|
||||||
|
import 'package:okane/ui/widgets/piechart_card.dart';
|
||||||
|
|
||||||
|
class TotalLoanCard extends StatelessWidget {
|
||||||
|
const TotalLoanCard({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<CoreCubit, CoreState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return ResponsiveCard(
|
||||||
|
titleText: "Loan Sum",
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(16),
|
||||||
|
child: FutureBuilder(
|
||||||
|
future: GetIt.I.get<OkaneDatabase>().loansDao.getTotalLoanSum(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return Text(
|
||||||
|
snapshot.hasData
|
||||||
|
? formatCurrency(snapshot.data!)
|
||||||
|
: t.pages.accounts.totalBalance.loading,
|
||||||
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:okane/database/collections/account.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/database.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
import 'package:okane/ui/utils.dart';
|
import 'package:okane/ui/utils.dart';
|
||||||
@@ -15,9 +15,13 @@ class TotalBalanceCard extends StatelessWidget {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
final results = await Future.wait(accounts.map(getTotalBalance).toList());
|
final db = GetIt.I.get<OkaneDatabase>();
|
||||||
|
final totalBalance = await db.transactionsDao.getTotalBalance(
|
||||||
|
accounts.map((a) => a.id),
|
||||||
|
);
|
||||||
|
|
||||||
return results.reduce((acc, val) => acc + val);
|
final loanSum = await db.loansDao.getTotalLoanSum();
|
||||||
|
return totalBalance + loanSum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -31,6 +35,7 @@ class TotalBalanceCard extends StatelessWidget {
|
|||||||
child: FutureBuilder(
|
child: FutureBuilder(
|
||||||
future: _getTotalBalance(state.accounts),
|
future: _getTotalBalance(state.accounts),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
print("SNAPSHOT: ${snapshot.data}");
|
||||||
return Text(
|
return Text(
|
||||||
snapshot.hasData
|
snapshot.hasData
|
||||||
? formatCurrency(snapshot.data!)
|
? formatCurrency(snapshot.data!)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
import 'package:drift/drift.dart' show Value;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/collections/recurrent.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
import 'package:okane/ui/utils.dart';
|
import 'package:okane/ui/utils.dart';
|
||||||
@@ -20,8 +20,10 @@ class UpcomingTransactionsCard extends StatelessWidget {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final today = DateTime.now();
|
final today = DateTime.now();
|
||||||
final upcomingRaw =
|
final upcomingRaw =
|
||||||
state.recurringTransactions.where((t) => t.isDue(today)).toList();
|
state.recurringTransactions
|
||||||
final List<RecurringTransaction> upcoming =
|
.where((t) => isTransactionDue(t.recurring, today))
|
||||||
|
.toList();
|
||||||
|
final List<RecurringTransactionDto> upcoming =
|
||||||
upcomingRaw.isEmpty
|
upcomingRaw.isEmpty
|
||||||
? List.empty()
|
? List.empty()
|
||||||
: upcomingRaw.sublist(0, min(upcomingRaw.length, 3));
|
: upcomingRaw.sublist(0, min(upcomingRaw.length, 3));
|
||||||
@@ -42,9 +44,9 @@ class UpcomingTransactionsCard extends StatelessWidget {
|
|||||||
(transaction) => ListTile(
|
(transaction) => ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
t.pages.accounts.upcomingTransactions.items.title(
|
t.pages.accounts.upcomingTransactions.items.title(
|
||||||
name: transaction.template.value!.name,
|
name: transaction.template.name,
|
||||||
amount:
|
amount:
|
||||||
"${formatCurrency(transaction.template.value!.amount)}€",
|
"${formatCurrency(transaction.template.amount)}€",
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
@@ -52,17 +54,18 @@ class UpcomingTransactionsCard extends StatelessWidget {
|
|||||||
number:
|
number:
|
||||||
today
|
today
|
||||||
.difference(
|
.difference(
|
||||||
transaction.lastExecution ?? today,
|
transaction.recurring.lastExecution ??
|
||||||
|
today,
|
||||||
)
|
)
|
||||||
.inDays,
|
.inDays,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
leading: Icon(
|
leading: Icon(
|
||||||
transaction.template.value!.amount < 0
|
transaction.template.amount < 0
|
||||||
? Icons.remove
|
? Icons.remove
|
||||||
: Icons.add,
|
: Icons.add,
|
||||||
color:
|
color:
|
||||||
transaction.template.value!.amount < 0
|
transaction.template.amount < 0
|
||||||
? Colors.red
|
? Colors.red
|
||||||
: Colors.green,
|
: Colors.green,
|
||||||
),
|
),
|
||||||
@@ -74,14 +77,27 @@ class UpcomingTransactionsCard extends StatelessWidget {
|
|||||||
builder:
|
builder:
|
||||||
(context) => AddTransactionWidget(
|
(context) => AddTransactionWidget(
|
||||||
activeAccountItem: bloc.activeAccount!,
|
activeAccountItem: bloc.activeAccount!,
|
||||||
template: transaction.template.value!,
|
template: (
|
||||||
|
template: transaction.template,
|
||||||
|
beneficiary: transaction.beneficiary,
|
||||||
|
expenseCategory: null,
|
||||||
|
),
|
||||||
onAdd: (newTransaction) async {
|
onAdd: (newTransaction) async {
|
||||||
// Update the recurring template
|
// Update the recurring template
|
||||||
transaction.lastExecution =
|
await GetIt.I
|
||||||
newTransaction.date;
|
.get<OkaneDatabase>()
|
||||||
await upsertRecurringTransaction(
|
.recurringTransactionsDao
|
||||||
transaction,
|
.upsertRecurringTransaction(
|
||||||
);
|
transaction.recurring
|
||||||
|
.copyWith(
|
||||||
|
lastExecution: Value(
|
||||||
|
newTransaction
|
||||||
|
.transaction
|
||||||
|
.date,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toCompanion(true),
|
||||||
|
);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
import 'package:drift/drift.dart' show Value;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/collections/budget.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
|
|
||||||
@@ -52,14 +52,17 @@ class AddBudgetState extends State<AddBudgetPopup> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final bloc = GetIt.I.get<CoreCubit>();
|
final bloc = GetIt.I.get<CoreCubit>();
|
||||||
final budget =
|
await GetIt.I.get<OkaneDatabase>().budgetsDao.upsertBudget(
|
||||||
Budget()
|
BudgetsCompanion(
|
||||||
..name = _budgetNameEditController.text
|
name: Value(_budgetNameEditController.text),
|
||||||
..period = BudgetPeriod.month
|
period: Value(BudgetPeriod.month),
|
||||||
..includeOtherSpendings = false
|
includeOtherSpendings: Value(false),
|
||||||
..income = double.parse(_budgetIncomeEditController.text)
|
income: Value(
|
||||||
..account.value = bloc.activeAccount!;
|
double.parse(_budgetIncomeEditController.text),
|
||||||
await upsertBudget(budget);
|
),
|
||||||
|
accountId: Value(bloc.activeAccount!.id),
|
||||||
|
),
|
||||||
|
);
|
||||||
widget.onDone();
|
widget.onDone();
|
||||||
},
|
},
|
||||||
child: Text(t.modals.add),
|
child: Text(t.modals.add),
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
|
import 'package:drift/drift.dart' show Value;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/collections/budget.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/database/collections/expense_category.dart';
|
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
|
||||||
import 'package:okane/ui/utils.dart';
|
import 'package:okane/ui/utils.dart';
|
||||||
import 'package:okane/ui/widgets/add_expense_category.dart';
|
import 'package:okane/ui/widgets/add_expense_category.dart';
|
||||||
|
|
||||||
class AddBudgetItemPopup extends StatefulWidget {
|
class AddBudgetItemPopup extends StatefulWidget {
|
||||||
final VoidCallback onDone;
|
final VoidCallback onDone;
|
||||||
final Budget budget;
|
final BudgetsDto budget;
|
||||||
|
final List<BudgetItemDto> items;
|
||||||
|
|
||||||
const AddBudgetItemPopup({
|
const AddBudgetItemPopup({
|
||||||
super.key,
|
super.key,
|
||||||
required this.onDone,
|
required this.onDone,
|
||||||
required this.budget,
|
required this.budget,
|
||||||
|
required this.items,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -74,26 +74,25 @@ class AddBudgetItemState extends State<AddBudgetItemPopup> {
|
|||||||
_expenseCategory == null) {
|
_expenseCategory == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (widget.budget.items
|
if (widget.items
|
||||||
.where(
|
.where(
|
||||||
(i) =>
|
(i) =>
|
||||||
i.expenseCategory.value!.name ==
|
i.expenseCategory.name == _expenseCategory!.name,
|
||||||
_expenseCategory!.name,
|
|
||||||
)
|
)
|
||||||
.firstOrNull !=
|
.firstOrNull !=
|
||||||
null) {
|
null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final item =
|
await GetIt.I.get<OkaneDatabase>().budgetsDao.upsertBudgetItem(
|
||||||
BudgetItem()
|
BudgetItemsCompanion(
|
||||||
..expenseCategory.value = _expenseCategory
|
amount: Value(
|
||||||
..amount = double.parse(
|
double.parse(_budgetItemAmountEditController.text),
|
||||||
_budgetItemAmountEditController.text,
|
),
|
||||||
);
|
expenseCategoryId: Value(_expenseCategory!.id),
|
||||||
await upsertBudgetItem(item);
|
budgetId: Value(widget.budget.budget.id),
|
||||||
widget.budget.items.add(item);
|
),
|
||||||
await upsertBudget(widget.budget);
|
);
|
||||||
widget.onDone();
|
widget.onDone();
|
||||||
},
|
},
|
||||||
child: Text(t.modals.add),
|
child: Text(t.modals.add),
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/collections/budget.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/pages/budgets/add_budget_item.dart';
|
import 'package:okane/ui/pages/budgets/add_budget_item.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
@@ -23,6 +22,7 @@ class BudgetDetailsPage extends StatelessWidget {
|
|||||||
builder:
|
builder:
|
||||||
(_) => AddBudgetItemPopup(
|
(_) => AddBudgetItemPopup(
|
||||||
budget: state.activeBudget!,
|
budget: state.activeBudget!,
|
||||||
|
items: state.budgetItems,
|
||||||
onDone: () {
|
onDone: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
@@ -56,7 +56,7 @@ class BudgetDetailsPage extends StatelessWidget {
|
|||||||
return Text(t.pages.budgets.details.noBudgetSelected);
|
return Text(t.pages.budgets.details.noBudgetSelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.activeBudget!.items.isEmpty) {
|
if (state.budgetItems.isEmpty) {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Text(t.pages.budgets.details.noBudgetItems),
|
Text(t.pages.budgets.details.noBudgetItems),
|
||||||
@@ -73,14 +73,15 @@ class BudgetDetailsPage extends StatelessWidget {
|
|||||||
|
|
||||||
final bloc = GetIt.I.get<CoreCubit>();
|
final bloc = GetIt.I.get<CoreCubit>();
|
||||||
final today = DateTime.now();
|
final today = DateTime.now();
|
||||||
|
final db = GetIt.I.get<OkaneDatabase>();
|
||||||
return FutureBuilder(
|
return FutureBuilder(
|
||||||
future: getTransactionsInTimeframe(
|
future: db.transactionsDao.getTransactionsInTimeframe(
|
||||||
bloc.activeAccount!,
|
bloc.activeAccount!,
|
||||||
today,
|
today,
|
||||||
TransactionQueryDateOption.thisMonth,
|
TransactionQueryDateOption.thisMonth,
|
||||||
),
|
),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final daysLeft = switch (state.activeBudget!.period) {
|
final daysLeft = switch (state.activeBudget!.budget.period) {
|
||||||
BudgetPeriod.month =>
|
BudgetPeriod.month =>
|
||||||
monthEnding(today).difference(today).inDays,
|
monthEnding(today).difference(today).inDays,
|
||||||
};
|
};
|
||||||
@@ -95,16 +96,16 @@ class BudgetDetailsPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
ListView.builder(
|
ListView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemCount: state.activeBudget!.items.length,
|
itemCount: state.budgetItems.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final item = state.activeBudget!.items.elementAt(
|
final item = state.budgetItems.elementAt(index);
|
||||||
index,
|
final amount = formatCurrency(item.item.amount);
|
||||||
);
|
|
||||||
final amount = formatCurrency(item.amount);
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
t.pages.budgets.details.items.title(
|
t.pages.budgets.details.items.title(
|
||||||
name: item.expenseCategory.value!.name,
|
// TODO
|
||||||
|
name: "lol",
|
||||||
|
//name: item.expenseCategory.value!.name,
|
||||||
amount: amount,
|
amount: amount,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -119,26 +120,28 @@ class BudgetDetailsPage extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final categories =
|
final categories =
|
||||||
state.activeBudget!.items
|
state.budgetItems
|
||||||
.map((i) => i.expenseCategory.value!.name)
|
// TODO
|
||||||
|
//.map((i) => i.expenseCategory.value!.name)
|
||||||
|
.map((i) => "lol")
|
||||||
.toList();
|
.toList();
|
||||||
final spending = <String, double>{};
|
final spending = <String, double>{};
|
||||||
for (final t in snapshot.data!) {
|
for (final t in snapshot.data!) {
|
||||||
String categoryName;
|
String categoryName;
|
||||||
if (!categories.contains(t.expenseCategory.value?.name)) {
|
if (!categories.contains(t.expenseCategory?.name)) {
|
||||||
if (!state.activeBudget!.includeOtherSpendings) {
|
if (!state.activeBudget!.budget.includeOtherSpendings) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
categoryName = "Other";
|
categoryName = "Other";
|
||||||
} else {
|
} else {
|
||||||
categoryName = t.expenseCategory.value!.name;
|
categoryName = t.expenseCategory!.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
spending.update(
|
spending.update(
|
||||||
categoryName,
|
categoryName,
|
||||||
(value) => value + t.amount,
|
(value) => value + t.transaction.amount,
|
||||||
ifAbsent: () => t.amount,
|
ifAbsent: () => t.transaction.amount,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,8 +149,8 @@ class BudgetDetailsPage extends StatelessWidget {
|
|||||||
spending.isEmpty
|
spending.isEmpty
|
||||||
? 0
|
? 0
|
||||||
: spending.values.reduce((acc, val) => acc + val);
|
: spending.values.reduce((acc, val) => acc + val);
|
||||||
final budgetTotal = state.activeBudget!.items
|
final budgetTotal = state.budgetItems
|
||||||
.map((i) => i.amount)
|
.map((i) => i.item.amount)
|
||||||
.reduce((acc, val) => acc + val);
|
.reduce((acc, val) => acc + val);
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -268,13 +271,13 @@ class BudgetDetailsPage extends StatelessWidget {
|
|||||||
fallbackText: "",
|
fallbackText: "",
|
||||||
valueConverter: formatCurrency,
|
valueConverter: formatCurrency,
|
||||||
items:
|
items:
|
||||||
state.activeBudget!.items
|
state.budgetItems
|
||||||
.map(
|
.map(
|
||||||
(i) => (
|
(i) => (
|
||||||
title: i.expenseCategory.value!.name,
|
title: i.expenseCategory.name,
|
||||||
value: i.amount,
|
value: i.item.amount,
|
||||||
color: colorHash(
|
color: colorHash(
|
||||||
i.expenseCategory.value!.name,
|
i.expenseCategory.name,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -339,18 +342,15 @@ class BudgetDetailsPage extends StatelessWidget {
|
|||||||
padding: EdgeInsets.all(8),
|
padding: EdgeInsets.all(8),
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemCount: state.activeBudget!.items.length,
|
itemCount: state.budgetItems.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final item = state.activeBudget!.items.elementAt(
|
final item = state.budgetItems.elementAt(index);
|
||||||
index,
|
final amount = formatCurrency(item.item.amount);
|
||||||
);
|
final spent = spending[item.expenseCategory.name];
|
||||||
final amount = formatCurrency(item.amount);
|
|
||||||
final spent =
|
|
||||||
spending[item.expenseCategory.value!.name];
|
|
||||||
final left =
|
final left =
|
||||||
spent == null
|
spent == null
|
||||||
? item.amount
|
? item.item.amount
|
||||||
: item.amount + spent;
|
: item.item.amount + spent;
|
||||||
final subtitleText =
|
final subtitleText =
|
||||||
left < 0
|
left < 0
|
||||||
? t.pages.budgets.details.items.over(
|
? t.pages.budgets.details.items.over(
|
||||||
@@ -361,7 +361,7 @@ class BudgetDetailsPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
"${item.expenseCategory.value!.name} ($amount)",
|
"${item.expenseCategory.name} ($amount)",
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
subtitleText,
|
subtitleText,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class BudgetListPage extends StatelessWidget {
|
|||||||
itemCount: state.budgets.length,
|
itemCount: state.budgets.length,
|
||||||
itemBuilder:
|
itemBuilder:
|
||||||
(context, index) => ListTile(
|
(context, index) => ListTile(
|
||||||
title: Text(state.budgets[index].name),
|
title: Text(state.budgets[index].budget.name),
|
||||||
selected: state.budgets[index] == state.activeBudget,
|
selected: state.budgets[index] == state.activeBudget,
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -68,7 +68,6 @@ class BudgetListPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
Positioned(
|
Positioned(
|
||||||
right: 16,
|
right: 16,
|
||||||
bottom: 16,
|
bottom: 16,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:okane/database/collections/budget.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/database.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
|
|
||||||
class EditBudgetPopup extends StatefulWidget {
|
class EditBudgetPopup extends StatefulWidget {
|
||||||
final Budget budget;
|
final BudgetsDto budget;
|
||||||
|
|
||||||
final VoidCallback onDone;
|
final VoidCallback onDone;
|
||||||
|
|
||||||
@@ -27,8 +27,8 @@ class EditBudgetState extends State<EditBudgetPopup> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
_budgetNameEditController.text = widget.budget.name;
|
_budgetNameEditController.text = widget.budget.budget.name;
|
||||||
_includeOtherSpendings = widget.budget.includeOtherSpendings;
|
_includeOtherSpendings = widget.budget.budget.includeOtherSpendings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -61,17 +61,22 @@ class EditBudgetState extends State<EditBudgetPopup> {
|
|||||||
if (_budgetNameEditController.text.isEmpty) {
|
if (_budgetNameEditController.text.isEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_budgetNameEditController.text == widget.budget.name &&
|
if (_budgetNameEditController.text ==
|
||||||
|
widget.budget.budget.name &&
|
||||||
_includeOtherSpendings ==
|
_includeOtherSpendings ==
|
||||||
widget.budget.includeOtherSpendings) {
|
widget.budget.budget.includeOtherSpendings) {
|
||||||
widget.onDone();
|
widget.onDone();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
widget.budget
|
await GetIt.I.get<OkaneDatabase>().budgetsDao.upsertBudget(
|
||||||
..name = _budgetNameEditController.text
|
widget.budget.budget
|
||||||
..includeOtherSpendings = _includeOtherSpendings;
|
.copyWith(
|
||||||
await upsertBudget(widget.budget);
|
name: _budgetNameEditController.text,
|
||||||
|
includeOtherSpendings: _includeOtherSpendings,
|
||||||
|
)
|
||||||
|
.toCompanion(false),
|
||||||
|
);
|
||||||
widget.onDone();
|
widget.onDone();
|
||||||
},
|
},
|
||||||
child: Text(t.modals.save),
|
child: Text(t.modals.save),
|
||||||
|
|||||||
141
lib/ui/pages/loans/add_loan.dart
Normal file
141
lib/ui/pages/loans/add_loan.dart
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
import 'package:drift/drift.dart' show Value;
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:okane/database/sqlite.dart';
|
||||||
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
|
import 'package:okane/ui/state/core.dart';
|
||||||
|
import 'package:searchfield/searchfield.dart';
|
||||||
|
|
||||||
|
class AddLoanPopup extends StatefulWidget {
|
||||||
|
final VoidCallback onDone;
|
||||||
|
|
||||||
|
const AddLoanPopup({super.key, required this.onDone});
|
||||||
|
|
||||||
|
@override
|
||||||
|
AddBudgetState createState() => AddBudgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddBudgetState extends State<AddLoanPopup> {
|
||||||
|
final TextEditingController _beneficiaryTextController =
|
||||||
|
TextEditingController();
|
||||||
|
SearchFieldListItem<Beneficiary>? _selectedBeneficiary;
|
||||||
|
|
||||||
|
String getBeneficiaryName(Beneficiary item) {
|
||||||
|
return switch (item.type) {
|
||||||
|
BeneficiaryType.account => t.common.beneficiary.nameWithAccount(
|
||||||
|
name: item.name,
|
||||||
|
),
|
||||||
|
BeneficiaryType.other => item.name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
|
child: BlocBuilder<CoreCubit, CoreState>(
|
||||||
|
builder:
|
||||||
|
(context, state) => SearchField<Beneficiary>(
|
||||||
|
suggestions:
|
||||||
|
state.beneficiaries
|
||||||
|
.where((el) {
|
||||||
|
final bloc = GetIt.I.get<CoreCubit>();
|
||||||
|
if (el.type == BeneficiaryType.account) {
|
||||||
|
return el.accountId ==
|
||||||
|
bloc.activeAccount?.id.toInt();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.map((el) {
|
||||||
|
return SearchFieldListItem(
|
||||||
|
getBeneficiaryName(el),
|
||||||
|
item: el,
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.toList(),
|
||||||
|
hint: "Beneficiary",
|
||||||
|
controller: _beneficiaryTextController,
|
||||||
|
selectedValue: _selectedBeneficiary,
|
||||||
|
onSuggestionTap: (beneficiary) {
|
||||||
|
setState(() => _selectedBeneficiary = beneficiary);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
OutlinedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final beneficiaryName = _beneficiaryTextController.text;
|
||||||
|
if (_selectedBeneficiary == null && beneficiaryName.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final db = GetIt.I.get<OkaneDatabase>();
|
||||||
|
Beneficiary? beneficiary = _selectedBeneficiary?.item;
|
||||||
|
if (beneficiary == null ||
|
||||||
|
getBeneficiaryName(beneficiary) != beneficiaryName) {
|
||||||
|
// Add a new beneficiary, if none was selected
|
||||||
|
final result = await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => AlertDialog(
|
||||||
|
title: Text(
|
||||||
|
t.common.beneficiary.addBeneficiary.title,
|
||||||
|
),
|
||||||
|
content: Text(
|
||||||
|
t.common.beneficiary.addBeneficiary.body(
|
||||||
|
name: beneficiaryName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
textStyle:
|
||||||
|
Theme.of(context).textTheme.labelLarge,
|
||||||
|
),
|
||||||
|
child: Text(t.modals.add),
|
||||||
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
textStyle:
|
||||||
|
Theme.of(context).textTheme.labelLarge,
|
||||||
|
),
|
||||||
|
child: Text(t.modals.cancel),
|
||||||
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (result == null || !result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
beneficiary = await db.beneficiariesDao.upsertBeneficiary(
|
||||||
|
BeneficiariesCompanion(
|
||||||
|
name: Value(beneficiaryName),
|
||||||
|
type: Value(BeneficiaryType.other),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.loansDao.upsertLoan(
|
||||||
|
LoansCompanion(beneficiaryId: Value(beneficiary.id)),
|
||||||
|
);
|
||||||
|
widget.onDone();
|
||||||
|
},
|
||||||
|
child: Text(t.modals.add),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
105
lib/ui/pages/loans/add_loan_change.dart
Normal file
105
lib/ui/pages/loans/add_loan_change.dart
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
import 'package:drift/drift.dart' show Value;
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:okane/database/sqlite.dart';
|
||||||
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
|
import 'package:okane/ui/utils.dart';
|
||||||
|
|
||||||
|
enum LoanChangeType { owe, loan }
|
||||||
|
|
||||||
|
class AddLoanChangePopup extends StatefulWidget {
|
||||||
|
final VoidCallback onDone;
|
||||||
|
|
||||||
|
final LoanDto loan;
|
||||||
|
|
||||||
|
const AddLoanChangePopup({
|
||||||
|
super.key,
|
||||||
|
required this.onDone,
|
||||||
|
required this.loan,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
AddLoanPopupState createState() => AddLoanPopupState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddLoanPopupState extends State<AddLoanChangePopup> {
|
||||||
|
LoanChangeType _loanChangeType = LoanChangeType.loan;
|
||||||
|
final TextEditingController _amountController = TextEditingController(
|
||||||
|
text: "0.00",
|
||||||
|
);
|
||||||
|
|
||||||
|
DateTime _selectedDate = DateTime.now();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
SegmentedButton(
|
||||||
|
segments: [
|
||||||
|
ButtonSegment(value: LoanChangeType.loan, label: Text("Loan")),
|
||||||
|
ButtonSegment(value: LoanChangeType.owe, label: Text("Owe")),
|
||||||
|
],
|
||||||
|
selected: {_loanChangeType},
|
||||||
|
onSelectionChanged: (values) {
|
||||||
|
setState(() {
|
||||||
|
_loanChangeType = values.first;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
icon: Icon(Icons.euro),
|
||||||
|
hintText: "Amount",
|
||||||
|
),
|
||||||
|
controller: _amountController,
|
||||||
|
keyboardType: TextInputType.numberWithOptions(
|
||||||
|
signed: false,
|
||||||
|
decimal: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text("Date"),
|
||||||
|
OutlinedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final dt = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: _selectedDate,
|
||||||
|
firstDate: DateTime(1),
|
||||||
|
lastDate: DateTime(9999),
|
||||||
|
);
|
||||||
|
if (dt == null) return;
|
||||||
|
|
||||||
|
setState(() => _selectedDate = dt);
|
||||||
|
},
|
||||||
|
child: Text(formatDateTime(_selectedDate)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final sign = switch (_loanChangeType) {
|
||||||
|
LoanChangeType.owe => -1,
|
||||||
|
LoanChangeType.loan => 1,
|
||||||
|
};
|
||||||
|
await GetIt.I.get<OkaneDatabase>().loansDao.upsertLoanChange(
|
||||||
|
LoanChangesCompanion(
|
||||||
|
amount: Value(
|
||||||
|
sign * double.parse(_amountController.text).abs(),
|
||||||
|
),
|
||||||
|
date: Value(DateTime.now()),
|
||||||
|
loanId: Value(widget.loan.loan.id),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
widget.onDone();
|
||||||
|
},
|
||||||
|
child: Text(t.modals.add),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
166
lib/ui/pages/loans/loan_details.dart
Normal file
166
lib/ui/pages/loans/loan_details.dart
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:grouped_list/grouped_list.dart';
|
||||||
|
import 'package:okane/database/sqlite.dart';
|
||||||
|
import 'package:okane/ui/pages/loans/add_loan_change.dart';
|
||||||
|
import 'package:okane/ui/state/core.dart';
|
||||||
|
import 'package:okane/ui/utils.dart';
|
||||||
|
import 'package:okane/ui/widgets/image_wrapper.dart';
|
||||||
|
|
||||||
|
class LoanDetailsPage extends StatelessWidget {
|
||||||
|
final bool isPage;
|
||||||
|
|
||||||
|
const LoanDetailsPage({super.key, required this.isPage});
|
||||||
|
|
||||||
|
static MaterialPageRoute<void> get mobileRoute =>
|
||||||
|
MaterialPageRoute(builder: (_) => LoanDetailsPage(isPage: true));
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
if (isPage)
|
||||||
|
SizedBox(
|
||||||
|
height: 50,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.arrow_back),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Expanded(
|
||||||
|
child: BlocBuilder<CoreCubit, CoreState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
if (state.activeLoan == null) {
|
||||||
|
return Text("No loan selected");
|
||||||
|
}
|
||||||
|
|
||||||
|
final loanSum =
|
||||||
|
state.loanChanges.isNotEmpty
|
||||||
|
? state.loanChanges
|
||||||
|
.map((c) => c.amount)
|
||||||
|
.reduce((acc, val) => acc + val)
|
||||||
|
: 0.0;
|
||||||
|
return CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
ImageWrapper(
|
||||||
|
title: state.activeLoan!.beneficiary.name,
|
||||||
|
path: state.activeLoan!.beneficiary.imagePath,
|
||||||
|
),
|
||||||
|
Text(state.activeLoan!.beneficiary.name),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Text("Total: ${formatCurrency(loanSum)}"),
|
||||||
|
),
|
||||||
|
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text("Loan Transactions"),
|
||||||
|
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
showDialogOrModal(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(_) => AddLoanChangePopup(
|
||||||
|
loan: state.activeLoan!,
|
||||||
|
onDone: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.add),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child:
|
||||||
|
state.loanChanges.isNotEmpty
|
||||||
|
? GroupedListView(
|
||||||
|
elements: state.loanChanges,
|
||||||
|
shrinkWrap: true,
|
||||||
|
reverse: true,
|
||||||
|
groupBy:
|
||||||
|
(LoanChange loanChange) =>
|
||||||
|
formatDateTime(loanChange.date),
|
||||||
|
groupHeaderBuilder:
|
||||||
|
(item) => Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
DecoratedBox(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.black.withAlpha(170),
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
8,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
child: Text(
|
||||||
|
formatDateTime(item.date),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
indexedItemBuilder:
|
||||||
|
(ctx, item, idx) => ListTile(
|
||||||
|
leading:
|
||||||
|
item.amount > 0
|
||||||
|
? Icon(
|
||||||
|
Icons.add,
|
||||||
|
color: Colors.green,
|
||||||
|
)
|
||||||
|
: Icon(
|
||||||
|
Icons.remove,
|
||||||
|
color: Colors.red,
|
||||||
|
),
|
||||||
|
title: Text(formatCurrency(item.amount)),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.delete,
|
||||||
|
color: Colors.red,
|
||||||
|
),
|
||||||
|
onPressed: () async {
|
||||||
|
await GetIt.I
|
||||||
|
.get<OkaneDatabase>()
|
||||||
|
.loansDao
|
||||||
|
.deleteLoanChange(item.id);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Text("No transactions available"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
79
lib/ui/pages/loans/loan_list.dart
Normal file
79
lib/ui/pages/loans/loan_list.dart
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:okane/screen.dart';
|
||||||
|
import 'package:okane/ui/pages/loans/add_loan.dart';
|
||||||
|
import 'package:okane/ui/state/core.dart';
|
||||||
|
import 'package:okane/ui/utils.dart';
|
||||||
|
import 'package:okane/ui/widgets/image_wrapper.dart';
|
||||||
|
|
||||||
|
class LoanListPage extends StatelessWidget {
|
||||||
|
const LoanListPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<CoreCubit, CoreState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
ListView.builder(
|
||||||
|
itemCount: state.loans.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final item = state.loans[index];
|
||||||
|
final beneficiary = item.beneficiary;
|
||||||
|
return ListTile(
|
||||||
|
leading: ImageWrapper(
|
||||||
|
title: beneficiary.name,
|
||||||
|
path: beneficiary.imagePath,
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
GetIt.I.get<CoreCubit>().setActiveLoan(item);
|
||||||
|
|
||||||
|
if (getScreenSize(context) == ScreenSize.small) {
|
||||||
|
Navigator.of(context).pushNamed("/loans/details");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trailing: IconButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final result = await confirm(
|
||||||
|
context,
|
||||||
|
"Delete Loan",
|
||||||
|
"Are you sure you want to delete the loan?",
|
||||||
|
);
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// await deleteLoan(item);
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.delete, color: Colors.red),
|
||||||
|
),
|
||||||
|
title: Text(beneficiary.name),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
right: 16,
|
||||||
|
bottom: 16,
|
||||||
|
child: FloatingActionButton(
|
||||||
|
child: Icon(Icons.add),
|
||||||
|
onPressed: () {
|
||||||
|
showDialogOrModal(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(_) => AddLoanPopup(
|
||||||
|
onDone: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,6 +67,74 @@ class SettingsPage extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
BlocBuilder<SettingsCubit, SettingsWrapper>(
|
||||||
|
builder:
|
||||||
|
(context, state) => ListTile(
|
||||||
|
title: Text("Sentry"),
|
||||||
|
subtitle: Text(
|
||||||
|
"When enabled sends errors to the configured Sentry DSN.",
|
||||||
|
),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: Icon(Icons.clear),
|
||||||
|
onPressed:
|
||||||
|
state.settings.sentryDsn == null
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
final result = await confirm(
|
||||||
|
context,
|
||||||
|
"Clear Sentry DSN",
|
||||||
|
"Are you sure you want to clear the Sentry DSN?",
|
||||||
|
);
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await GetIt.I.get<SettingsCubit>().setSettings(
|
||||||
|
state.settings.copyWith(sentryDsn: null),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
final controller = TextEditingController(
|
||||||
|
text: state.settings.sentryDsn ?? '',
|
||||||
|
);
|
||||||
|
final result = await showDialogOrModal<String>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
TextField(
|
||||||
|
controller: controller,
|
||||||
|
decoration: InputDecoration(hintText: "Sentry DSN"),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
OutlinedButton(
|
||||||
|
child: Text("Apply"),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(controller.text);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (result == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await GetIt.I.get<SettingsCubit>().setSettings(
|
||||||
|
state.settings.copyWith(sentryDsn: result),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/database.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
import 'package:okane/ui/utils.dart';
|
import 'package:okane/ui/utils.dart';
|
||||||
@@ -21,7 +21,9 @@ class TemplateListState extends State<TemplateListPage> {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final account = GetIt.I.get<CoreCubit>().activeAccount;
|
final account = GetIt.I.get<CoreCubit>().activeAccount;
|
||||||
final nonRecurringTemplates =
|
final nonRecurringTemplates =
|
||||||
state.transactionTemplates.where((t) => !t.recurring).toList();
|
state.transactionTemplates
|
||||||
|
.where((t) => !t.template.recurring)
|
||||||
|
.toList();
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
CustomScrollView(
|
CustomScrollView(
|
||||||
@@ -34,7 +36,7 @@ class TemplateListState extends State<TemplateListPage> {
|
|||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final template = nonRecurringTemplates[index];
|
final template = nonRecurringTemplates[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(template.name),
|
title: Text(template.template.name),
|
||||||
trailing: IconButton(
|
trailing: IconButton(
|
||||||
icon: Icon(Icons.delete),
|
icon: Icon(Icons.delete),
|
||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
@@ -43,14 +45,17 @@ class TemplateListState extends State<TemplateListPage> {
|
|||||||
context,
|
context,
|
||||||
t.pages.templates.removeTemplate.title,
|
t.pages.templates.removeTemplate.title,
|
||||||
t.pages.templates.removeTemplate.body(
|
t.pages.templates.removeTemplate.body(
|
||||||
name: template.name,
|
name: template.template.name,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await deleteTransactionTemplate(template);
|
await GetIt.I
|
||||||
|
.get<OkaneDatabase>()
|
||||||
|
.transactionTemplatesDao
|
||||||
|
.deleteTemplate(template.template);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -64,7 +69,7 @@ class TemplateListState extends State<TemplateListPage> {
|
|||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final template = state.recurringTransactions[index];
|
final template = state.recurringTransactions[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(template.template.value!.name),
|
title: Text(template.template.name),
|
||||||
trailing: IconButton(
|
trailing: IconButton(
|
||||||
icon: Icon(Icons.delete, color: Colors.red),
|
icon: Icon(Icons.delete, color: Colors.red),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
@@ -72,14 +77,17 @@ class TemplateListState extends State<TemplateListPage> {
|
|||||||
context,
|
context,
|
||||||
t.pages.templates.removeTemplate.title,
|
t.pages.templates.removeTemplate.title,
|
||||||
t.pages.templates.removeTemplate.body(
|
t.pages.templates.removeTemplate.body(
|
||||||
name: template.template.value!.name,
|
name: template.template.name,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await deleteRecurringTransactionTemplate(template);
|
await GetIt.I
|
||||||
|
.get<OkaneDatabase>()
|
||||||
|
.recurringTransactionsDao
|
||||||
|
.deleteTemplate(template);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:drift/drift.dart' show Value;
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/collections/beneficiary.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
import 'package:okane/ui/utils.dart';
|
import 'package:okane/ui/utils.dart';
|
||||||
@@ -43,8 +43,9 @@ class TransactionDetailsPage extends StatelessWidget {
|
|||||||
await File(file.path!).copy(imagePath);
|
await File(file.path!).copy(imagePath);
|
||||||
|
|
||||||
print("Updating DB");
|
print("Updating DB");
|
||||||
beneficiary.imagePath = imagePath;
|
await GetIt.I.get<OkaneDatabase>().beneficiariesDao.upsertBeneficiary(
|
||||||
await upsertBeneficiary(beneficiary);
|
beneficiary.copyWith(imagePath: Value(imagePath)).toCompanion(false),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -83,13 +84,16 @@ class TransactionDetailsPage extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
StreamBuilder(
|
StreamBuilder(
|
||||||
stream: watchBeneficiaryObject(
|
stream: GetIt.I
|
||||||
state.activeTransaction!.beneficiary.value!.id,
|
.get<OkaneDatabase>()
|
||||||
),
|
.beneficiariesDao
|
||||||
|
.watchBeneficiary(
|
||||||
|
state.activeTransaction!.beneficiary.id,
|
||||||
|
),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final obj =
|
final obj =
|
||||||
snapshot.data ??
|
snapshot.data ??
|
||||||
state.activeTransaction!.beneficiary.value!;
|
state.activeTransaction!.beneficiary;
|
||||||
return ImageWrapper(
|
return ImageWrapper(
|
||||||
title: obj.name,
|
title: obj.name,
|
||||||
path: obj.imagePath,
|
path: obj.imagePath,
|
||||||
@@ -116,7 +120,6 @@ class TransactionDetailsPage extends StatelessWidget {
|
|||||||
state
|
state
|
||||||
.activeTransaction!
|
.activeTransaction!
|
||||||
.beneficiary
|
.beneficiary
|
||||||
.value!
|
|
||||||
.name,
|
.name,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -132,7 +135,7 @@ class TransactionDetailsPage extends StatelessWidget {
|
|||||||
GetIt.I
|
GetIt.I
|
||||||
.get<CoreCubit>()
|
.get<CoreCubit>()
|
||||||
.activeAccount!
|
.activeAccount!
|
||||||
.name!,
|
.name,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -150,16 +153,16 @@ class TransactionDetailsPage extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
/*
|
||||||
Wrap(
|
Wrap(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children:
|
children:
|
||||||
state.activeTransaction!.tags
|
state.activeTransaction!.tags
|
||||||
.map((tag) => Chip(label: Text(tag)))
|
.map((tag) => Chip(label: Text(tag)))
|
||||||
.toList(),
|
.toList(),
|
||||||
),
|
),*/
|
||||||
|
if (state.activeTransaction!.expenseCategory != null)
|
||||||
if (state.activeTransaction!.expenseCategory.value !=
|
|
||||||
null)
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 8),
|
padding: EdgeInsets.symmetric(vertical: 8),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -172,8 +175,7 @@ class TransactionDetailsPage extends StatelessWidget {
|
|||||||
label: Text(
|
label: Text(
|
||||||
state
|
state
|
||||||
.activeTransaction!
|
.activeTransaction!
|
||||||
.expenseCategory
|
.expenseCategory!
|
||||||
.value!
|
|
||||||
.name,
|
.name,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -186,11 +188,13 @@ class TransactionDetailsPage extends StatelessWidget {
|
|||||||
padding: EdgeInsets.symmetric(vertical: 8),
|
padding: EdgeInsets.symmetric(vertical: 8),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
state.activeTransaction!.amount > 0
|
state.activeTransaction!.transaction.amount > 0
|
||||||
? Icon(Icons.add)
|
? Icon(Icons.add)
|
||||||
: Icon(Icons.remove),
|
: Icon(Icons.remove),
|
||||||
Text(
|
Text(
|
||||||
formatCurrency(state.activeTransaction!.amount),
|
formatCurrency(
|
||||||
|
state.activeTransaction!.transaction.amount,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:grouped_list/grouped_list.dart';
|
import 'package:grouped_list/grouped_list.dart';
|
||||||
import 'package:okane/database/collections/transaction.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/screen.dart';
|
import 'package:okane/screen.dart';
|
||||||
import 'package:okane/ui/pages/account/balance_graph_card.dart';
|
import 'package:okane/ui/pages/account/balance_graph_card.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
@@ -41,7 +41,9 @@ class TransactionListState extends State<TransactionListPage> {
|
|||||||
physics: NeverScrollableScrollPhysics(),
|
physics: NeverScrollableScrollPhysics(),
|
||||||
elements: state.transactions,
|
elements: state.transactions,
|
||||||
reverse: true,
|
reverse: true,
|
||||||
groupBy: (Transaction item) => formatDateTime(item.date),
|
groupBy:
|
||||||
|
(TransactionDto item) =>
|
||||||
|
formatDateTime(item.transaction.date),
|
||||||
groupHeaderBuilder:
|
groupHeaderBuilder:
|
||||||
(item) => Row(
|
(item) => Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
@@ -54,7 +56,7 @@ class TransactionListState extends State<TransactionListPage> {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.all(4),
|
padding: EdgeInsets.all(4),
|
||||||
child: Text(
|
child: Text(
|
||||||
formatDateTime(item.date),
|
formatDateTime(item.transaction.date),
|
||||||
style: TextStyle(color: Colors.white),
|
style: TextStyle(color: Colors.white),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,14 +1,8 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:okane/database/collections/account.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/collections/beneficiary.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/database/collections/budget.dart';
|
|
||||||
import 'package:okane/database/collections/expense_category.dart';
|
|
||||||
import 'package:okane/database/collections/recurrent.dart';
|
|
||||||
import 'package:okane/database/collections/template.dart';
|
|
||||||
import 'package:okane/database/collections/transaction.dart';
|
|
||||||
import 'package:okane/database/database.dart' as db;
|
|
||||||
import 'package:okane/ui/navigation.dart';
|
import 'package:okane/ui/navigation.dart';
|
||||||
|
|
||||||
part 'core.freezed.dart';
|
part 'core.freezed.dart';
|
||||||
@@ -18,15 +12,19 @@ abstract class CoreState with _$CoreState {
|
|||||||
const factory CoreState({
|
const factory CoreState({
|
||||||
@Default(OkanePage.accounts) OkanePage activePage,
|
@Default(OkanePage.accounts) OkanePage activePage,
|
||||||
int? activeAccountIndex,
|
int? activeAccountIndex,
|
||||||
@Default(null) Transaction? activeTransaction,
|
@Default(null) TransactionDto? activeTransaction,
|
||||||
@Default([]) List<Account> accounts,
|
@Default([]) List<Account> accounts,
|
||||||
@Default([]) List<RecurringTransaction> recurringTransactions,
|
@Default([]) List<RecurringTransactionDto> recurringTransactions,
|
||||||
@Default([]) List<Transaction> transactions,
|
@Default([]) List<TransactionDto> transactions,
|
||||||
@Default([]) List<TransactionTemplate> transactionTemplates,
|
@Default([]) List<TransactionTemplateDto> transactionTemplates,
|
||||||
@Default([]) List<Beneficiary> beneficiaries,
|
@Default([]) List<Beneficiary> beneficiaries,
|
||||||
@Default([]) List<ExpenseCategory> expenseCategories,
|
@Default([]) List<ExpenseCategory> expenseCategories,
|
||||||
@Default([]) List<Budget> budgets,
|
@Default([]) List<BudgetsDto> budgets,
|
||||||
@Default(null) Budget? activeBudget,
|
@Default([]) List<BudgetItemDto> budgetItems,
|
||||||
|
@Default(null) BudgetsDto? activeBudget,
|
||||||
|
@Default([]) List<LoanDto> loans,
|
||||||
|
@Default([]) List<LoanChange> loanChanges,
|
||||||
|
@Default(null) LoanDto? activeLoan,
|
||||||
@Default(false) bool isDeletingAccount,
|
@Default(false) bool isDeletingAccount,
|
||||||
}) = _CoreState;
|
}) = _CoreState;
|
||||||
}
|
}
|
||||||
@@ -41,79 +39,71 @@ class CoreCubit extends Cubit<CoreState> {
|
|||||||
StreamSubscription<void>? _beneficiariesStreamSubscription;
|
StreamSubscription<void>? _beneficiariesStreamSubscription;
|
||||||
StreamSubscription<void>? _expenseCategoryStreamSubscription;
|
StreamSubscription<void>? _expenseCategoryStreamSubscription;
|
||||||
StreamSubscription<void>? _budgetsStreamSubscription;
|
StreamSubscription<void>? _budgetsStreamSubscription;
|
||||||
|
StreamSubscription<void>? _budgetItemsStreamSubscription;
|
||||||
|
StreamSubscription<void>? _loanStreamSubscription;
|
||||||
|
StreamSubscription<void>? _loanChangesSubscription;
|
||||||
|
|
||||||
void setupAccountStream() {
|
void setupAccountStream() {
|
||||||
_accountsStreamSubscription?.cancel();
|
_accountsStreamSubscription?.cancel();
|
||||||
_accountsStreamSubscription = db.watchAccounts().listen((_) async {
|
_accountsStreamSubscription = GetIt.I
|
||||||
final resetStreams = state.activeAccountIndex == null;
|
.get<OkaneDatabase>()
|
||||||
final accounts = await db.getAccounts();
|
.accountsDao
|
||||||
emit(
|
.accountsStream()
|
||||||
state.copyWith(
|
.listen((accounts) {
|
||||||
accounts: accounts,
|
emit(
|
||||||
activeAccountIndex: state.activeAccountIndex ?? 0,
|
state.copyWith(
|
||||||
),
|
accounts: accounts,
|
||||||
);
|
activeAccountIndex:
|
||||||
|
accounts.isNotEmpty ? state.activeAccountIndex ?? 0 : null,
|
||||||
if (resetStreams) {
|
),
|
||||||
setupStreams(accounts[0]);
|
);
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupStreams(Account account) {
|
void setupStreams(Account account) {
|
||||||
|
final db = GetIt.I.get<OkaneDatabase>();
|
||||||
setupAccountStream();
|
setupAccountStream();
|
||||||
_recurringTransactionStreamSubscription?.cancel();
|
_recurringTransactionStreamSubscription?.cancel();
|
||||||
_recurringTransactionStreamSubscription = db
|
_recurringTransactionStreamSubscription = db.recurringTransactionsDao
|
||||||
.watchRecurringTransactions(activeAccount!)
|
.recurringTransactionsStream(account)
|
||||||
.listen((_) async {
|
.listen((recurring) async {
|
||||||
print("RECURRING UPDATE");
|
emit(state.copyWith(recurringTransactions: recurring));
|
||||||
emit(
|
|
||||||
state.copyWith(
|
|
||||||
recurringTransactions: await db.getRecurringTransactions(
|
|
||||||
activeAccount!,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
_transactionTemplatesStreamSubcription?.cancel();
|
_transactionTemplatesStreamSubcription?.cancel();
|
||||||
_transactionTemplatesStreamSubcription = db
|
_transactionTemplatesStreamSubcription = db.transactionTemplatesDao
|
||||||
.watchTransactionTemplates(activeAccount!)
|
.transactionTemplatesStream(account)
|
||||||
.listen((_) async {
|
.listen((templates) async {
|
||||||
emit(
|
emit(state.copyWith(transactionTemplates: templates));
|
||||||
state.copyWith(
|
|
||||||
transactionTemplates: await db.getTransactionTemplates(
|
|
||||||
activeAccount!,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
_transactionsStreamSubscription?.cancel();
|
_transactionsStreamSubscription?.cancel();
|
||||||
_transactionsStreamSubscription = db
|
_transactionsStreamSubscription = db.transactionsDao
|
||||||
.watchTransactions(activeAccount!)
|
.transactionsStream(activeAccount!)
|
||||||
.listen((_) async {
|
.listen((transactions) async {
|
||||||
emit(
|
emit(state.copyWith(transactions: transactions));
|
||||||
state.copyWith(
|
|
||||||
transactions: await db.getTransactions(activeAccount!),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
_beneficiariesStreamSubscription?.cancel();
|
_beneficiariesStreamSubscription?.cancel();
|
||||||
_beneficiariesStreamSubscription = db.watchBeneficiaries().listen((
|
_beneficiariesStreamSubscription = db.beneficiariesDao
|
||||||
_,
|
.beneficiariesStream()
|
||||||
) async {
|
.listen((beneficiaries) async {
|
||||||
emit(state.copyWith(beneficiaries: await db.getBeneficiaries()));
|
emit(state.copyWith(beneficiaries: beneficiaries));
|
||||||
});
|
});
|
||||||
_expenseCategoryStreamSubscription?.cancel();
|
_expenseCategoryStreamSubscription?.cancel();
|
||||||
_expenseCategoryStreamSubscription = db.watchExpenseCategory().listen((
|
_expenseCategoryStreamSubscription = db.expenseCategoriesDao
|
||||||
_,
|
.expenseCategoriesStream(account)
|
||||||
) async {
|
.listen((expenseCategories) async {
|
||||||
emit(state.copyWith(expenseCategories: await db.getExpenseCategories()));
|
emit(state.copyWith(expenseCategories: expenseCategories));
|
||||||
});
|
});
|
||||||
_budgetsStreamSubscription?.cancel();
|
_budgetsStreamSubscription?.cancel();
|
||||||
_budgetsStreamSubscription = db.watchBudgets(activeAccount!).listen((
|
_budgetsStreamSubscription = db.budgetsDao
|
||||||
_,
|
.budgetsStream(activeAccount!)
|
||||||
|
.listen((budgets) async {
|
||||||
|
emit(state.copyWith(budgets: budgets));
|
||||||
|
});
|
||||||
|
_loanStreamSubscription?.cancel();
|
||||||
|
_loanStreamSubscription = db.loansDao.loansStream(account).listen((
|
||||||
|
loans,
|
||||||
) async {
|
) async {
|
||||||
emit(state.copyWith(budgets: await db.getBudgets(activeAccount!)));
|
emit(state.copyWith(loans: loans));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,25 +115,22 @@ class CoreCubit extends Cubit<CoreState> {
|
|||||||
_expenseCategoryStreamSubscription?.cancel();
|
_expenseCategoryStreamSubscription?.cancel();
|
||||||
_transactionsStreamSubscription?.cancel();
|
_transactionsStreamSubscription?.cancel();
|
||||||
_transactionTemplatesStreamSubcription?.cancel();
|
_transactionTemplatesStreamSubcription?.cancel();
|
||||||
|
_loanStreamSubscription?.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
final accounts = await db.getAccounts();
|
final db = GetIt.I.get<OkaneDatabase>();
|
||||||
|
final accounts = await db.accountsDao.getAccounts();
|
||||||
final account = accounts.isEmpty ? null : accounts[0];
|
final account = accounts.isEmpty ? null : accounts[0];
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
accounts: accounts,
|
accounts: accounts,
|
||||||
activeAccountIndex: accounts.isEmpty ? null : 0,
|
activeAccountIndex: accounts.isEmpty ? null : 0,
|
||||||
transactions: await db.getTransactions(account),
|
|
||||||
beneficiaries: await db.getBeneficiaries(),
|
|
||||||
transactionTemplates: await db.getTransactionTemplates(account),
|
|
||||||
recurringTransactions: await db.getRecurringTransactions(account),
|
|
||||||
expenseCategories: await db.getExpenseCategories(),
|
|
||||||
budgets: await db.getBudgets(account),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (account != null) {
|
if (account != null) {
|
||||||
|
setupAccountStream();
|
||||||
setupStreams(account);
|
setupStreams(account);
|
||||||
} else {
|
} else {
|
||||||
setupAccountStream();
|
setupAccountStream();
|
||||||
@@ -156,23 +143,27 @@ class CoreCubit extends Cubit<CoreState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setActiveAccountIndex(int index) async {
|
Future<void> setActiveAccountIndex(int index) async {
|
||||||
|
final db = GetIt.I.get<OkaneDatabase>();
|
||||||
final account = state.accounts[index];
|
final account = state.accounts[index];
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
activeAccountIndex: index,
|
activeAccountIndex: index,
|
||||||
transactions: await db.getTransactions(account),
|
transactions: await db.transactionsDao.getTransactions(account),
|
||||||
beneficiaries: await db.getBeneficiaries(),
|
beneficiaries: await db.beneficiariesDao.getBeneficiaries(),
|
||||||
transactionTemplates: await db.getTransactionTemplates(account),
|
transactionTemplates: await db.transactionTemplatesDao
|
||||||
recurringTransactions: await db.getRecurringTransactions(account),
|
.getTransactionTemplates(account),
|
||||||
budgets: await db.getBudgets(account),
|
recurringTransactions: await db.recurringTransactionsDao
|
||||||
|
.getRecurringTransactions(account),
|
||||||
|
budgets: await db.budgetsDao.getBudgets(account),
|
||||||
activeBudget: null,
|
activeBudget: null,
|
||||||
activeTransaction: null,
|
activeTransaction: null,
|
||||||
|
activeLoan: null,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
setupStreams(account);
|
setupStreams(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setActiveTransaction(Transaction? item) {
|
void setActiveTransaction(TransactionDto? item) {
|
||||||
emit(state.copyWith(activeTransaction: item));
|
emit(state.copyWith(activeTransaction: item));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,8 +171,18 @@ class CoreCubit extends Cubit<CoreState> {
|
|||||||
emit(state.copyWith(accounts: accounts));
|
emit(state.copyWith(accounts: accounts));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setActiveBudget(Budget? budget) {
|
void setActiveBudget(BudgetsDto? budget) {
|
||||||
emit(state.copyWith(activeBudget: budget));
|
emit(state.copyWith(activeBudget: budget, budgetItems: []));
|
||||||
|
_budgetItemsStreamSubscription?.cancel();
|
||||||
|
if (budget != null) {
|
||||||
|
_budgetItemsStreamSubscription = GetIt.I
|
||||||
|
.get<OkaneDatabase>()
|
||||||
|
.budgetsDao
|
||||||
|
.watchBudgetItems(budget.budget)
|
||||||
|
.listen((items) {
|
||||||
|
emit(state.copyWith(budgetItems: items));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteAccount(Account account) async {
|
Future<void> deleteAccount(Account account) async {
|
||||||
@@ -192,13 +193,27 @@ class CoreCubit extends Cubit<CoreState> {
|
|||||||
|
|
||||||
cancelStreams();
|
cancelStreams();
|
||||||
try {
|
try {
|
||||||
await db.deleteAccount(account);
|
await GetIt.I.get<OkaneDatabase>().accountsDao.removeAccount(account);
|
||||||
} finally {
|
} finally {
|
||||||
emit(state.copyWith(isDeletingAccount: false));
|
emit(state.copyWith(isDeletingAccount: false));
|
||||||
}
|
}
|
||||||
await init();
|
await init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setActiveLoan(LoanDto? loan) {
|
||||||
|
emit(state.copyWith(activeLoan: loan, loanChanges: []));
|
||||||
|
_loanChangesSubscription?.cancel();
|
||||||
|
if (loan != null) {
|
||||||
|
_loanChangesSubscription = GetIt.I
|
||||||
|
.get<OkaneDatabase>()
|
||||||
|
.loansDao
|
||||||
|
.watchLoanChanges(loan.loan)
|
||||||
|
.listen((changes) {
|
||||||
|
emit(state.copyWith(loanChanges: changes));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Account? get activeAccount =>
|
Account? get activeAccount =>
|
||||||
state.activeAccountIndex == null
|
state.activeAccountIndex == null
|
||||||
? null
|
? null
|
||||||
|
|||||||
@@ -19,18 +19,22 @@ final _privateConstructorUsedError = UnsupportedError(
|
|||||||
mixin _$CoreState {
|
mixin _$CoreState {
|
||||||
OkanePage get activePage => throw _privateConstructorUsedError;
|
OkanePage get activePage => throw _privateConstructorUsedError;
|
||||||
int? get activeAccountIndex => throw _privateConstructorUsedError;
|
int? get activeAccountIndex => throw _privateConstructorUsedError;
|
||||||
Transaction? get activeTransaction => throw _privateConstructorUsedError;
|
TransactionDto? get activeTransaction => throw _privateConstructorUsedError;
|
||||||
List<Account> get accounts => throw _privateConstructorUsedError;
|
List<Account> get accounts => throw _privateConstructorUsedError;
|
||||||
List<RecurringTransaction> get recurringTransactions =>
|
List<RecurringTransactionDto> get recurringTransactions =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
List<Transaction> get transactions => throw _privateConstructorUsedError;
|
List<TransactionDto> get transactions => throw _privateConstructorUsedError;
|
||||||
List<TransactionTemplate> get transactionTemplates =>
|
List<TransactionTemplateDto> get transactionTemplates =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
List<Beneficiary> get beneficiaries => throw _privateConstructorUsedError;
|
List<Beneficiary> get beneficiaries => throw _privateConstructorUsedError;
|
||||||
List<ExpenseCategory> get expenseCategories =>
|
List<ExpenseCategory> get expenseCategories =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
List<Budget> get budgets => throw _privateConstructorUsedError;
|
List<BudgetsDto> get budgets => throw _privateConstructorUsedError;
|
||||||
Budget? get activeBudget => throw _privateConstructorUsedError;
|
List<BudgetItemDto> get budgetItems => throw _privateConstructorUsedError;
|
||||||
|
BudgetsDto? get activeBudget => throw _privateConstructorUsedError;
|
||||||
|
List<LoanDto> get loans => throw _privateConstructorUsedError;
|
||||||
|
List<LoanChange> get loanChanges => throw _privateConstructorUsedError;
|
||||||
|
LoanDto? get activeLoan => throw _privateConstructorUsedError;
|
||||||
bool get isDeletingAccount => throw _privateConstructorUsedError;
|
bool get isDeletingAccount => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@@ -46,15 +50,19 @@ abstract class $CoreStateCopyWith<$Res> {
|
|||||||
$Res call({
|
$Res call({
|
||||||
OkanePage activePage,
|
OkanePage activePage,
|
||||||
int? activeAccountIndex,
|
int? activeAccountIndex,
|
||||||
Transaction? activeTransaction,
|
TransactionDto? activeTransaction,
|
||||||
List<Account> accounts,
|
List<Account> accounts,
|
||||||
List<RecurringTransaction> recurringTransactions,
|
List<RecurringTransactionDto> recurringTransactions,
|
||||||
List<Transaction> transactions,
|
List<TransactionDto> transactions,
|
||||||
List<TransactionTemplate> transactionTemplates,
|
List<TransactionTemplateDto> transactionTemplates,
|
||||||
List<Beneficiary> beneficiaries,
|
List<Beneficiary> beneficiaries,
|
||||||
List<ExpenseCategory> expenseCategories,
|
List<ExpenseCategory> expenseCategories,
|
||||||
List<Budget> budgets,
|
List<BudgetsDto> budgets,
|
||||||
Budget? activeBudget,
|
List<BudgetItemDto> budgetItems,
|
||||||
|
BudgetsDto? activeBudget,
|
||||||
|
List<LoanDto> loans,
|
||||||
|
List<LoanChange> loanChanges,
|
||||||
|
LoanDto? activeLoan,
|
||||||
bool isDeletingAccount,
|
bool isDeletingAccount,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -82,7 +90,11 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
|
|||||||
Object? beneficiaries = null,
|
Object? beneficiaries = null,
|
||||||
Object? expenseCategories = null,
|
Object? expenseCategories = null,
|
||||||
Object? budgets = null,
|
Object? budgets = null,
|
||||||
|
Object? budgetItems = null,
|
||||||
Object? activeBudget = freezed,
|
Object? activeBudget = freezed,
|
||||||
|
Object? loans = null,
|
||||||
|
Object? loanChanges = null,
|
||||||
|
Object? activeLoan = freezed,
|
||||||
Object? isDeletingAccount = null,
|
Object? isDeletingAccount = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(
|
return _then(
|
||||||
@@ -101,7 +113,7 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
|
|||||||
freezed == activeTransaction
|
freezed == activeTransaction
|
||||||
? _value.activeTransaction
|
? _value.activeTransaction
|
||||||
: activeTransaction // ignore: cast_nullable_to_non_nullable
|
: activeTransaction // ignore: cast_nullable_to_non_nullable
|
||||||
as Transaction?,
|
as TransactionDto?,
|
||||||
accounts:
|
accounts:
|
||||||
null == accounts
|
null == accounts
|
||||||
? _value.accounts
|
? _value.accounts
|
||||||
@@ -111,17 +123,17 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
|
|||||||
null == recurringTransactions
|
null == recurringTransactions
|
||||||
? _value.recurringTransactions
|
? _value.recurringTransactions
|
||||||
: recurringTransactions // ignore: cast_nullable_to_non_nullable
|
: recurringTransactions // ignore: cast_nullable_to_non_nullable
|
||||||
as List<RecurringTransaction>,
|
as List<RecurringTransactionDto>,
|
||||||
transactions:
|
transactions:
|
||||||
null == transactions
|
null == transactions
|
||||||
? _value.transactions
|
? _value.transactions
|
||||||
: transactions // ignore: cast_nullable_to_non_nullable
|
: transactions // ignore: cast_nullable_to_non_nullable
|
||||||
as List<Transaction>,
|
as List<TransactionDto>,
|
||||||
transactionTemplates:
|
transactionTemplates:
|
||||||
null == transactionTemplates
|
null == transactionTemplates
|
||||||
? _value.transactionTemplates
|
? _value.transactionTemplates
|
||||||
: transactionTemplates // ignore: cast_nullable_to_non_nullable
|
: transactionTemplates // ignore: cast_nullable_to_non_nullable
|
||||||
as List<TransactionTemplate>,
|
as List<TransactionTemplateDto>,
|
||||||
beneficiaries:
|
beneficiaries:
|
||||||
null == beneficiaries
|
null == beneficiaries
|
||||||
? _value.beneficiaries
|
? _value.beneficiaries
|
||||||
@@ -136,12 +148,32 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
|
|||||||
null == budgets
|
null == budgets
|
||||||
? _value.budgets
|
? _value.budgets
|
||||||
: budgets // ignore: cast_nullable_to_non_nullable
|
: budgets // ignore: cast_nullable_to_non_nullable
|
||||||
as List<Budget>,
|
as List<BudgetsDto>,
|
||||||
|
budgetItems:
|
||||||
|
null == budgetItems
|
||||||
|
? _value.budgetItems
|
||||||
|
: budgetItems // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<BudgetItemDto>,
|
||||||
activeBudget:
|
activeBudget:
|
||||||
freezed == activeBudget
|
freezed == activeBudget
|
||||||
? _value.activeBudget
|
? _value.activeBudget
|
||||||
: activeBudget // ignore: cast_nullable_to_non_nullable
|
: activeBudget // ignore: cast_nullable_to_non_nullable
|
||||||
as Budget?,
|
as BudgetsDto?,
|
||||||
|
loans:
|
||||||
|
null == loans
|
||||||
|
? _value.loans
|
||||||
|
: loans // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<LoanDto>,
|
||||||
|
loanChanges:
|
||||||
|
null == loanChanges
|
||||||
|
? _value.loanChanges
|
||||||
|
: loanChanges // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<LoanChange>,
|
||||||
|
activeLoan:
|
||||||
|
freezed == activeLoan
|
||||||
|
? _value.activeLoan
|
||||||
|
: activeLoan // ignore: cast_nullable_to_non_nullable
|
||||||
|
as LoanDto?,
|
||||||
isDeletingAccount:
|
isDeletingAccount:
|
||||||
null == isDeletingAccount
|
null == isDeletingAccount
|
||||||
? _value.isDeletingAccount
|
? _value.isDeletingAccount
|
||||||
@@ -165,15 +197,19 @@ abstract class _$$CoreStateImplCopyWith<$Res>
|
|||||||
$Res call({
|
$Res call({
|
||||||
OkanePage activePage,
|
OkanePage activePage,
|
||||||
int? activeAccountIndex,
|
int? activeAccountIndex,
|
||||||
Transaction? activeTransaction,
|
TransactionDto? activeTransaction,
|
||||||
List<Account> accounts,
|
List<Account> accounts,
|
||||||
List<RecurringTransaction> recurringTransactions,
|
List<RecurringTransactionDto> recurringTransactions,
|
||||||
List<Transaction> transactions,
|
List<TransactionDto> transactions,
|
||||||
List<TransactionTemplate> transactionTemplates,
|
List<TransactionTemplateDto> transactionTemplates,
|
||||||
List<Beneficiary> beneficiaries,
|
List<Beneficiary> beneficiaries,
|
||||||
List<ExpenseCategory> expenseCategories,
|
List<ExpenseCategory> expenseCategories,
|
||||||
List<Budget> budgets,
|
List<BudgetsDto> budgets,
|
||||||
Budget? activeBudget,
|
List<BudgetItemDto> budgetItems,
|
||||||
|
BudgetsDto? activeBudget,
|
||||||
|
List<LoanDto> loans,
|
||||||
|
List<LoanChange> loanChanges,
|
||||||
|
LoanDto? activeLoan,
|
||||||
bool isDeletingAccount,
|
bool isDeletingAccount,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -200,7 +236,11 @@ class __$$CoreStateImplCopyWithImpl<$Res>
|
|||||||
Object? beneficiaries = null,
|
Object? beneficiaries = null,
|
||||||
Object? expenseCategories = null,
|
Object? expenseCategories = null,
|
||||||
Object? budgets = null,
|
Object? budgets = null,
|
||||||
|
Object? budgetItems = null,
|
||||||
Object? activeBudget = freezed,
|
Object? activeBudget = freezed,
|
||||||
|
Object? loans = null,
|
||||||
|
Object? loanChanges = null,
|
||||||
|
Object? activeLoan = freezed,
|
||||||
Object? isDeletingAccount = null,
|
Object? isDeletingAccount = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(
|
return _then(
|
||||||
@@ -219,7 +259,7 @@ class __$$CoreStateImplCopyWithImpl<$Res>
|
|||||||
freezed == activeTransaction
|
freezed == activeTransaction
|
||||||
? _value.activeTransaction
|
? _value.activeTransaction
|
||||||
: activeTransaction // ignore: cast_nullable_to_non_nullable
|
: activeTransaction // ignore: cast_nullable_to_non_nullable
|
||||||
as Transaction?,
|
as TransactionDto?,
|
||||||
accounts:
|
accounts:
|
||||||
null == accounts
|
null == accounts
|
||||||
? _value._accounts
|
? _value._accounts
|
||||||
@@ -229,17 +269,17 @@ class __$$CoreStateImplCopyWithImpl<$Res>
|
|||||||
null == recurringTransactions
|
null == recurringTransactions
|
||||||
? _value._recurringTransactions
|
? _value._recurringTransactions
|
||||||
: recurringTransactions // ignore: cast_nullable_to_non_nullable
|
: recurringTransactions // ignore: cast_nullable_to_non_nullable
|
||||||
as List<RecurringTransaction>,
|
as List<RecurringTransactionDto>,
|
||||||
transactions:
|
transactions:
|
||||||
null == transactions
|
null == transactions
|
||||||
? _value._transactions
|
? _value._transactions
|
||||||
: transactions // ignore: cast_nullable_to_non_nullable
|
: transactions // ignore: cast_nullable_to_non_nullable
|
||||||
as List<Transaction>,
|
as List<TransactionDto>,
|
||||||
transactionTemplates:
|
transactionTemplates:
|
||||||
null == transactionTemplates
|
null == transactionTemplates
|
||||||
? _value._transactionTemplates
|
? _value._transactionTemplates
|
||||||
: transactionTemplates // ignore: cast_nullable_to_non_nullable
|
: transactionTemplates // ignore: cast_nullable_to_non_nullable
|
||||||
as List<TransactionTemplate>,
|
as List<TransactionTemplateDto>,
|
||||||
beneficiaries:
|
beneficiaries:
|
||||||
null == beneficiaries
|
null == beneficiaries
|
||||||
? _value._beneficiaries
|
? _value._beneficiaries
|
||||||
@@ -254,12 +294,32 @@ class __$$CoreStateImplCopyWithImpl<$Res>
|
|||||||
null == budgets
|
null == budgets
|
||||||
? _value._budgets
|
? _value._budgets
|
||||||
: budgets // ignore: cast_nullable_to_non_nullable
|
: budgets // ignore: cast_nullable_to_non_nullable
|
||||||
as List<Budget>,
|
as List<BudgetsDto>,
|
||||||
|
budgetItems:
|
||||||
|
null == budgetItems
|
||||||
|
? _value._budgetItems
|
||||||
|
: budgetItems // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<BudgetItemDto>,
|
||||||
activeBudget:
|
activeBudget:
|
||||||
freezed == activeBudget
|
freezed == activeBudget
|
||||||
? _value.activeBudget
|
? _value.activeBudget
|
||||||
: activeBudget // ignore: cast_nullable_to_non_nullable
|
: activeBudget // ignore: cast_nullable_to_non_nullable
|
||||||
as Budget?,
|
as BudgetsDto?,
|
||||||
|
loans:
|
||||||
|
null == loans
|
||||||
|
? _value._loans
|
||||||
|
: loans // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<LoanDto>,
|
||||||
|
loanChanges:
|
||||||
|
null == loanChanges
|
||||||
|
? _value._loanChanges
|
||||||
|
: loanChanges // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<LoanChange>,
|
||||||
|
activeLoan:
|
||||||
|
freezed == activeLoan
|
||||||
|
? _value.activeLoan
|
||||||
|
: activeLoan // ignore: cast_nullable_to_non_nullable
|
||||||
|
as LoanDto?,
|
||||||
isDeletingAccount:
|
isDeletingAccount:
|
||||||
null == isDeletingAccount
|
null == isDeletingAccount
|
||||||
? _value.isDeletingAccount
|
? _value.isDeletingAccount
|
||||||
@@ -278,13 +338,17 @@ class _$CoreStateImpl implements _CoreState {
|
|||||||
this.activeAccountIndex,
|
this.activeAccountIndex,
|
||||||
this.activeTransaction = null,
|
this.activeTransaction = null,
|
||||||
final List<Account> accounts = const [],
|
final List<Account> accounts = const [],
|
||||||
final List<RecurringTransaction> recurringTransactions = const [],
|
final List<RecurringTransactionDto> recurringTransactions = const [],
|
||||||
final List<Transaction> transactions = const [],
|
final List<TransactionDto> transactions = const [],
|
||||||
final List<TransactionTemplate> transactionTemplates = const [],
|
final List<TransactionTemplateDto> transactionTemplates = const [],
|
||||||
final List<Beneficiary> beneficiaries = const [],
|
final List<Beneficiary> beneficiaries = const [],
|
||||||
final List<ExpenseCategory> expenseCategories = const [],
|
final List<ExpenseCategory> expenseCategories = const [],
|
||||||
final List<Budget> budgets = const [],
|
final List<BudgetsDto> budgets = const [],
|
||||||
|
final List<BudgetItemDto> budgetItems = const [],
|
||||||
this.activeBudget = null,
|
this.activeBudget = null,
|
||||||
|
final List<LoanDto> loans = const [],
|
||||||
|
final List<LoanChange> loanChanges = const [],
|
||||||
|
this.activeLoan = null,
|
||||||
this.isDeletingAccount = false,
|
this.isDeletingAccount = false,
|
||||||
}) : _accounts = accounts,
|
}) : _accounts = accounts,
|
||||||
_recurringTransactions = recurringTransactions,
|
_recurringTransactions = recurringTransactions,
|
||||||
@@ -292,7 +356,10 @@ class _$CoreStateImpl implements _CoreState {
|
|||||||
_transactionTemplates = transactionTemplates,
|
_transactionTemplates = transactionTemplates,
|
||||||
_beneficiaries = beneficiaries,
|
_beneficiaries = beneficiaries,
|
||||||
_expenseCategories = expenseCategories,
|
_expenseCategories = expenseCategories,
|
||||||
_budgets = budgets;
|
_budgets = budgets,
|
||||||
|
_budgetItems = budgetItems,
|
||||||
|
_loans = loans,
|
||||||
|
_loanChanges = loanChanges;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
@@ -301,7 +368,7 @@ class _$CoreStateImpl implements _CoreState {
|
|||||||
final int? activeAccountIndex;
|
final int? activeAccountIndex;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final Transaction? activeTransaction;
|
final TransactionDto? activeTransaction;
|
||||||
final List<Account> _accounts;
|
final List<Account> _accounts;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
@@ -311,29 +378,29 @@ class _$CoreStateImpl implements _CoreState {
|
|||||||
return EqualUnmodifiableListView(_accounts);
|
return EqualUnmodifiableListView(_accounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<RecurringTransaction> _recurringTransactions;
|
final List<RecurringTransactionDto> _recurringTransactions;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
List<RecurringTransaction> get recurringTransactions {
|
List<RecurringTransactionDto> get recurringTransactions {
|
||||||
if (_recurringTransactions is EqualUnmodifiableListView)
|
if (_recurringTransactions is EqualUnmodifiableListView)
|
||||||
return _recurringTransactions;
|
return _recurringTransactions;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_recurringTransactions);
|
return EqualUnmodifiableListView(_recurringTransactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<Transaction> _transactions;
|
final List<TransactionDto> _transactions;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
List<Transaction> get transactions {
|
List<TransactionDto> get transactions {
|
||||||
if (_transactions is EqualUnmodifiableListView) return _transactions;
|
if (_transactions is EqualUnmodifiableListView) return _transactions;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_transactions);
|
return EqualUnmodifiableListView(_transactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<TransactionTemplate> _transactionTemplates;
|
final List<TransactionTemplateDto> _transactionTemplates;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
List<TransactionTemplate> get transactionTemplates {
|
List<TransactionTemplateDto> get transactionTemplates {
|
||||||
if (_transactionTemplates is EqualUnmodifiableListView)
|
if (_transactionTemplates is EqualUnmodifiableListView)
|
||||||
return _transactionTemplates;
|
return _transactionTemplates;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
@@ -359,25 +426,55 @@ class _$CoreStateImpl implements _CoreState {
|
|||||||
return EqualUnmodifiableListView(_expenseCategories);
|
return EqualUnmodifiableListView(_expenseCategories);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<Budget> _budgets;
|
final List<BudgetsDto> _budgets;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
List<Budget> get budgets {
|
List<BudgetsDto> get budgets {
|
||||||
if (_budgets is EqualUnmodifiableListView) return _budgets;
|
if (_budgets is EqualUnmodifiableListView) return _budgets;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_budgets);
|
return EqualUnmodifiableListView(_budgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<BudgetItemDto> _budgetItems;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final Budget? activeBudget;
|
List<BudgetItemDto> get budgetItems {
|
||||||
|
if (_budgetItems is EqualUnmodifiableListView) return _budgetItems;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_budgetItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final BudgetsDto? activeBudget;
|
||||||
|
final List<LoanDto> _loans;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
List<LoanDto> get loans {
|
||||||
|
if (_loans is EqualUnmodifiableListView) return _loans;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_loans);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<LoanChange> _loanChanges;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
List<LoanChange> get loanChanges {
|
||||||
|
if (_loanChanges is EqualUnmodifiableListView) return _loanChanges;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_loanChanges);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final LoanDto? activeLoan;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final bool isDeletingAccount;
|
final bool isDeletingAccount;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'CoreState(activePage: $activePage, activeAccountIndex: $activeAccountIndex, activeTransaction: $activeTransaction, accounts: $accounts, recurringTransactions: $recurringTransactions, transactions: $transactions, transactionTemplates: $transactionTemplates, beneficiaries: $beneficiaries, expenseCategories: $expenseCategories, budgets: $budgets, activeBudget: $activeBudget, isDeletingAccount: $isDeletingAccount)';
|
return 'CoreState(activePage: $activePage, activeAccountIndex: $activeAccountIndex, activeTransaction: $activeTransaction, accounts: $accounts, recurringTransactions: $recurringTransactions, transactions: $transactions, transactionTemplates: $transactionTemplates, beneficiaries: $beneficiaries, expenseCategories: $expenseCategories, budgets: $budgets, budgetItems: $budgetItems, activeBudget: $activeBudget, loans: $loans, loanChanges: $loanChanges, activeLoan: $activeLoan, isDeletingAccount: $isDeletingAccount)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -413,8 +510,19 @@ class _$CoreStateImpl implements _CoreState {
|
|||||||
_expenseCategories,
|
_expenseCategories,
|
||||||
) &&
|
) &&
|
||||||
const DeepCollectionEquality().equals(other._budgets, _budgets) &&
|
const DeepCollectionEquality().equals(other._budgets, _budgets) &&
|
||||||
|
const DeepCollectionEquality().equals(
|
||||||
|
other._budgetItems,
|
||||||
|
_budgetItems,
|
||||||
|
) &&
|
||||||
(identical(other.activeBudget, activeBudget) ||
|
(identical(other.activeBudget, activeBudget) ||
|
||||||
other.activeBudget == activeBudget) &&
|
other.activeBudget == activeBudget) &&
|
||||||
|
const DeepCollectionEquality().equals(other._loans, _loans) &&
|
||||||
|
const DeepCollectionEquality().equals(
|
||||||
|
other._loanChanges,
|
||||||
|
_loanChanges,
|
||||||
|
) &&
|
||||||
|
(identical(other.activeLoan, activeLoan) ||
|
||||||
|
other.activeLoan == activeLoan) &&
|
||||||
(identical(other.isDeletingAccount, isDeletingAccount) ||
|
(identical(other.isDeletingAccount, isDeletingAccount) ||
|
||||||
other.isDeletingAccount == isDeletingAccount));
|
other.isDeletingAccount == isDeletingAccount));
|
||||||
}
|
}
|
||||||
@@ -432,7 +540,11 @@ class _$CoreStateImpl implements _CoreState {
|
|||||||
const DeepCollectionEquality().hash(_beneficiaries),
|
const DeepCollectionEquality().hash(_beneficiaries),
|
||||||
const DeepCollectionEquality().hash(_expenseCategories),
|
const DeepCollectionEquality().hash(_expenseCategories),
|
||||||
const DeepCollectionEquality().hash(_budgets),
|
const DeepCollectionEquality().hash(_budgets),
|
||||||
|
const DeepCollectionEquality().hash(_budgetItems),
|
||||||
activeBudget,
|
activeBudget,
|
||||||
|
const DeepCollectionEquality().hash(_loans),
|
||||||
|
const DeepCollectionEquality().hash(_loanChanges),
|
||||||
|
activeLoan,
|
||||||
isDeletingAccount,
|
isDeletingAccount,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -447,15 +559,19 @@ abstract class _CoreState implements CoreState {
|
|||||||
const factory _CoreState({
|
const factory _CoreState({
|
||||||
final OkanePage activePage,
|
final OkanePage activePage,
|
||||||
final int? activeAccountIndex,
|
final int? activeAccountIndex,
|
||||||
final Transaction? activeTransaction,
|
final TransactionDto? activeTransaction,
|
||||||
final List<Account> accounts,
|
final List<Account> accounts,
|
||||||
final List<RecurringTransaction> recurringTransactions,
|
final List<RecurringTransactionDto> recurringTransactions,
|
||||||
final List<Transaction> transactions,
|
final List<TransactionDto> transactions,
|
||||||
final List<TransactionTemplate> transactionTemplates,
|
final List<TransactionTemplateDto> transactionTemplates,
|
||||||
final List<Beneficiary> beneficiaries,
|
final List<Beneficiary> beneficiaries,
|
||||||
final List<ExpenseCategory> expenseCategories,
|
final List<ExpenseCategory> expenseCategories,
|
||||||
final List<Budget> budgets,
|
final List<BudgetsDto> budgets,
|
||||||
final Budget? activeBudget,
|
final List<BudgetItemDto> budgetItems,
|
||||||
|
final BudgetsDto? activeBudget,
|
||||||
|
final List<LoanDto> loans,
|
||||||
|
final List<LoanChange> loanChanges,
|
||||||
|
final LoanDto? activeLoan,
|
||||||
final bool isDeletingAccount,
|
final bool isDeletingAccount,
|
||||||
}) = _$CoreStateImpl;
|
}) = _$CoreStateImpl;
|
||||||
|
|
||||||
@@ -464,23 +580,31 @@ abstract class _CoreState implements CoreState {
|
|||||||
@override
|
@override
|
||||||
int? get activeAccountIndex;
|
int? get activeAccountIndex;
|
||||||
@override
|
@override
|
||||||
Transaction? get activeTransaction;
|
TransactionDto? get activeTransaction;
|
||||||
@override
|
@override
|
||||||
List<Account> get accounts;
|
List<Account> get accounts;
|
||||||
@override
|
@override
|
||||||
List<RecurringTransaction> get recurringTransactions;
|
List<RecurringTransactionDto> get recurringTransactions;
|
||||||
@override
|
@override
|
||||||
List<Transaction> get transactions;
|
List<TransactionDto> get transactions;
|
||||||
@override
|
@override
|
||||||
List<TransactionTemplate> get transactionTemplates;
|
List<TransactionTemplateDto> get transactionTemplates;
|
||||||
@override
|
@override
|
||||||
List<Beneficiary> get beneficiaries;
|
List<Beneficiary> get beneficiaries;
|
||||||
@override
|
@override
|
||||||
List<ExpenseCategory> get expenseCategories;
|
List<ExpenseCategory> get expenseCategories;
|
||||||
@override
|
@override
|
||||||
List<Budget> get budgets;
|
List<BudgetsDto> get budgets;
|
||||||
@override
|
@override
|
||||||
Budget? get activeBudget;
|
List<BudgetItemDto> get budgetItems;
|
||||||
|
@override
|
||||||
|
BudgetsDto? get activeBudget;
|
||||||
|
@override
|
||||||
|
List<LoanDto> get loans;
|
||||||
|
@override
|
||||||
|
List<LoanChange> get loanChanges;
|
||||||
|
@override
|
||||||
|
LoanDto? get activeLoan;
|
||||||
@override
|
@override
|
||||||
bool get isDeletingAccount;
|
bool get isDeletingAccount;
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ enum ColorSchemeSettings { light, dark, system }
|
|||||||
abstract class Settings with _$Settings {
|
abstract class Settings with _$Settings {
|
||||||
const factory Settings({
|
const factory Settings({
|
||||||
@Default(ColorSchemeSettings.system) ColorSchemeSettings colorScheme,
|
@Default(ColorSchemeSettings.system) ColorSchemeSettings colorScheme,
|
||||||
|
@Default(null) String? sentryDsn,
|
||||||
}) = _Settings;
|
}) = _Settings;
|
||||||
|
|
||||||
factory Settings.fromJson(Map<String, Object?> json) =>
|
factory Settings.fromJson(Map<String, Object?> json) =>
|
||||||
@@ -45,4 +46,6 @@ class SettingsCubit extends Cubit<SettingsWrapper> {
|
|||||||
|
|
||||||
await _prefs.setString("settings", jsonEncode(settings.toJson()));
|
await _prefs.setString("settings", jsonEncode(settings.toJson()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String? get sentryDsn => state.settings.sentryDsn;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ Settings _$SettingsFromJson(Map<String, dynamic> json) {
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$Settings {
|
mixin _$Settings {
|
||||||
ColorSchemeSettings get colorScheme => throw _privateConstructorUsedError;
|
ColorSchemeSettings get colorScheme => throw _privateConstructorUsedError;
|
||||||
|
String? get sentryDsn => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@@ -34,7 +35,7 @@ abstract class $SettingsCopyWith<$Res> {
|
|||||||
factory $SettingsCopyWith(Settings value, $Res Function(Settings) then) =
|
factory $SettingsCopyWith(Settings value, $Res Function(Settings) then) =
|
||||||
_$SettingsCopyWithImpl<$Res, Settings>;
|
_$SettingsCopyWithImpl<$Res, Settings>;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({ColorSchemeSettings colorScheme});
|
$Res call({ColorSchemeSettings colorScheme, String? sentryDsn});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -49,7 +50,7 @@ class _$SettingsCopyWithImpl<$Res, $Val extends Settings>
|
|||||||
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({Object? colorScheme = null}) {
|
$Res call({Object? colorScheme = null, Object? sentryDsn = freezed}) {
|
||||||
return _then(
|
return _then(
|
||||||
_value.copyWith(
|
_value.copyWith(
|
||||||
colorScheme:
|
colorScheme:
|
||||||
@@ -57,6 +58,11 @@ class _$SettingsCopyWithImpl<$Res, $Val extends Settings>
|
|||||||
? _value.colorScheme
|
? _value.colorScheme
|
||||||
: colorScheme // ignore: cast_nullable_to_non_nullable
|
: colorScheme // ignore: cast_nullable_to_non_nullable
|
||||||
as ColorSchemeSettings,
|
as ColorSchemeSettings,
|
||||||
|
sentryDsn:
|
||||||
|
freezed == sentryDsn
|
||||||
|
? _value.sentryDsn
|
||||||
|
: sentryDsn // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
)
|
)
|
||||||
as $Val,
|
as $Val,
|
||||||
);
|
);
|
||||||
@@ -72,7 +78,7 @@ abstract class _$$SettingsImplCopyWith<$Res>
|
|||||||
) = __$$SettingsImplCopyWithImpl<$Res>;
|
) = __$$SettingsImplCopyWithImpl<$Res>;
|
||||||
@override
|
@override
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({ColorSchemeSettings colorScheme});
|
$Res call({ColorSchemeSettings colorScheme, String? sentryDsn});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -86,7 +92,7 @@ class __$$SettingsImplCopyWithImpl<$Res>
|
|||||||
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({Object? colorScheme = null}) {
|
$Res call({Object? colorScheme = null, Object? sentryDsn = freezed}) {
|
||||||
return _then(
|
return _then(
|
||||||
_$SettingsImpl(
|
_$SettingsImpl(
|
||||||
colorScheme:
|
colorScheme:
|
||||||
@@ -94,6 +100,11 @@ class __$$SettingsImplCopyWithImpl<$Res>
|
|||||||
? _value.colorScheme
|
? _value.colorScheme
|
||||||
: colorScheme // ignore: cast_nullable_to_non_nullable
|
: colorScheme // ignore: cast_nullable_to_non_nullable
|
||||||
as ColorSchemeSettings,
|
as ColorSchemeSettings,
|
||||||
|
sentryDsn:
|
||||||
|
freezed == sentryDsn
|
||||||
|
? _value.sentryDsn
|
||||||
|
: sentryDsn // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -102,7 +113,10 @@ class __$$SettingsImplCopyWithImpl<$Res>
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class _$SettingsImpl implements _Settings {
|
class _$SettingsImpl implements _Settings {
|
||||||
const _$SettingsImpl({this.colorScheme = ColorSchemeSettings.system});
|
const _$SettingsImpl({
|
||||||
|
this.colorScheme = ColorSchemeSettings.system,
|
||||||
|
this.sentryDsn = null,
|
||||||
|
});
|
||||||
|
|
||||||
factory _$SettingsImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$SettingsImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
_$$SettingsImplFromJson(json);
|
_$$SettingsImplFromJson(json);
|
||||||
@@ -110,10 +124,13 @@ class _$SettingsImpl implements _Settings {
|
|||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final ColorSchemeSettings colorScheme;
|
final ColorSchemeSettings colorScheme;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final String? sentryDsn;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'Settings(colorScheme: $colorScheme)';
|
return 'Settings(colorScheme: $colorScheme, sentryDsn: $sentryDsn)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -122,12 +139,14 @@ class _$SettingsImpl implements _Settings {
|
|||||||
(other.runtimeType == runtimeType &&
|
(other.runtimeType == runtimeType &&
|
||||||
other is _$SettingsImpl &&
|
other is _$SettingsImpl &&
|
||||||
(identical(other.colorScheme, colorScheme) ||
|
(identical(other.colorScheme, colorScheme) ||
|
||||||
other.colorScheme == colorScheme));
|
other.colorScheme == colorScheme) &&
|
||||||
|
(identical(other.sentryDsn, sentryDsn) ||
|
||||||
|
other.sentryDsn == sentryDsn));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType, colorScheme);
|
int get hashCode => Object.hash(runtimeType, colorScheme, sentryDsn);
|
||||||
|
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
@@ -142,8 +161,10 @@ class _$SettingsImpl implements _Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class _Settings implements Settings {
|
abstract class _Settings implements Settings {
|
||||||
const factory _Settings({final ColorSchemeSettings colorScheme}) =
|
const factory _Settings({
|
||||||
_$SettingsImpl;
|
final ColorSchemeSettings colorScheme,
|
||||||
|
final String? sentryDsn,
|
||||||
|
}) = _$SettingsImpl;
|
||||||
|
|
||||||
factory _Settings.fromJson(Map<String, dynamic> json) =
|
factory _Settings.fromJson(Map<String, dynamic> json) =
|
||||||
_$SettingsImpl.fromJson;
|
_$SettingsImpl.fromJson;
|
||||||
@@ -151,6 +172,8 @@ abstract class _Settings implements Settings {
|
|||||||
@override
|
@override
|
||||||
ColorSchemeSettings get colorScheme;
|
ColorSchemeSettings get colorScheme;
|
||||||
@override
|
@override
|
||||||
|
String? get sentryDsn;
|
||||||
|
@override
|
||||||
@JsonKey(ignore: true)
|
@JsonKey(ignore: true)
|
||||||
_$$SettingsImplCopyWith<_$SettingsImpl> get copyWith =>
|
_$$SettingsImplCopyWith<_$SettingsImpl> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
|
|||||||
@@ -14,11 +14,13 @@ _$SettingsImpl _$$SettingsImplFromJson(Map<String, dynamic> json) =>
|
|||||||
json['colorScheme'],
|
json['colorScheme'],
|
||||||
) ??
|
) ??
|
||||||
ColorSchemeSettings.system,
|
ColorSchemeSettings.system,
|
||||||
|
sentryDsn: json['sentryDsn'] as String? ?? null,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$$SettingsImplToJson(_$SettingsImpl instance) =>
|
Map<String, dynamic> _$$SettingsImplToJson(_$SettingsImpl instance) =>
|
||||||
<String, dynamic>{
|
<String, dynamic>{
|
||||||
'colorScheme': _$ColorSchemeSettingsEnumMap[instance.colorScheme]!,
|
'colorScheme': _$ColorSchemeSettingsEnumMap[instance.colorScheme]!,
|
||||||
|
'sentryDsn': instance.sentryDsn,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$ColorSchemeSettingsEnumMap = {
|
const _$ColorSchemeSettingsEnumMap = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:okane/database/collections/template.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/screen.dart';
|
import 'package:okane/screen.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
|
|
||||||
@@ -47,8 +47,10 @@ Future<T?> showDialogOrModal<T>({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<TransactionTemplate?> selectTransactionTemplate(BuildContext context) {
|
Future<TransactionTemplateDto?> selectTransactionTemplate(
|
||||||
return showDialogOrModal<TransactionTemplate>(
|
BuildContext context,
|
||||||
|
) {
|
||||||
|
return showDialogOrModal<TransactionTemplateDto>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return BlocBuilder<CoreCubit, CoreState>(
|
return BlocBuilder<CoreCubit, CoreState>(
|
||||||
@@ -64,7 +66,7 @@ Future<TransactionTemplate?> selectTransactionTemplate(BuildContext context) {
|
|||||||
itemCount: state.transactionTemplates.length,
|
itemCount: state.transactionTemplates.length,
|
||||||
itemBuilder:
|
itemBuilder:
|
||||||
(context, index) => ListTile(
|
(context, index) => ListTile(
|
||||||
title: Text(state.transactionTemplates[index].name),
|
title: Text(state.transactionTemplates[index].template.name),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(
|
Navigator.of(
|
||||||
context,
|
context,
|
||||||
@@ -142,3 +144,17 @@ Future<bool> confirm(BuildContext context, String title, String body) async {
|
|||||||
);
|
);
|
||||||
return result ?? false;
|
return result ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isTransactionDue(RecurringTransaction r, DateTime now) {
|
||||||
|
if (r.lastExecution == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final expectedNextExecution = r.lastExecution!.add(Duration(days: r.days));
|
||||||
|
if (now.isAfter(expectedNextExecution)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return now.difference(expectedNextExecution).inDays.abs() <=
|
||||||
|
(r.days * 0.5).toInt();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,11 +1,86 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:get_it/get_it.dart';
|
||||||
|
import 'package:okane/ui/pages/account/delete_account.dart';
|
||||||
|
import 'package:okane/ui/state/core.dart';
|
||||||
|
import 'package:okane/ui/utils.dart';
|
||||||
|
|
||||||
|
class AccountSwitcher extends StatelessWidget {
|
||||||
|
const AccountSwitcher({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final bloc = GetIt.I.get<CoreCubit>();
|
||||||
|
return BlocBuilder<CoreCubit, CoreState>(
|
||||||
|
builder:
|
||||||
|
(context, state) => InkWell(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
onTap: () {
|
||||||
|
showDialogOrModal(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount: state.accounts.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final item = state.accounts[index];
|
||||||
|
return ListTile(
|
||||||
|
title: Text(item.name),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: Icon(Icons.delete),
|
||||||
|
color: Colors.red,
|
||||||
|
onPressed: () async {
|
||||||
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: false,
|
||||||
|
builder:
|
||||||
|
(context) => DeleteAccountPopup(
|
||||||
|
account: item,
|
||||||
|
onCancel: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
afterDelete: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
GetIt.I.get<CoreCubit>().setActiveAccountIndex(
|
||||||
|
index,
|
||||||
|
);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
bloc.activeAccount!.name,
|
||||||
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
|
),
|
||||||
|
Icon(Icons.arrow_drop_down),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class AccountIndicator extends StatelessWidget {
|
class AccountIndicator extends StatelessWidget {
|
||||||
final String accountName;
|
|
||||||
|
|
||||||
final Widget? trailing;
|
final Widget? trailing;
|
||||||
|
|
||||||
const AccountIndicator({super.key, this.trailing, required this.accountName});
|
const AccountIndicator({super.key, this.trailing});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -15,11 +90,8 @@ class AccountIndicator extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.all(8),
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
child: Text(
|
child: AccountSwitcher(),
|
||||||
accountName,
|
|
||||||
style: Theme.of(context).textTheme.titleLarge,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
if (trailing != null) trailing!,
|
if (trailing != null) trailing!,
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
|
import 'package:drift/drift.dart' show Value;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:okane/database/collections/expense_category.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/database.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
|
|
||||||
@@ -50,10 +51,14 @@ class AddExpenseCategoryState extends State<AddExpenseCategory> {
|
|||||||
Spacer(),
|
Spacer(),
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final category =
|
final category = await GetIt.I
|
||||||
ExpenseCategory()
|
.get<OkaneDatabase>()
|
||||||
..name = _categoryNameController.text;
|
.expenseCategoriesDao
|
||||||
await upsertExpenseCategory(category);
|
.upsertCategory(
|
||||||
|
ExpenseCategoriesCompanion(
|
||||||
|
name: Value(_categoryNameController.text),
|
||||||
|
),
|
||||||
|
);
|
||||||
_categoryNameController.text = "";
|
_categoryNameController.text = "";
|
||||||
Navigator.of(context).pop(category);
|
Navigator.of(context).pop(category);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
|
import 'package:drift/drift.dart' show Value;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/collections/account.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/database/collections/beneficiary.dart';
|
|
||||||
import 'package:okane/database/collections/expense_category.dart';
|
|
||||||
import 'package:okane/database/collections/recurrent.dart';
|
|
||||||
import 'package:okane/database/collections/template.dart';
|
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
import 'package:okane/ui/transaction.dart';
|
import 'package:okane/ui/transaction.dart';
|
||||||
@@ -68,6 +64,7 @@ class _AddTransactionTemplateWidgetState
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final db = GetIt.I.get<OkaneDatabase>();
|
||||||
Beneficiary? beneficiary = _selectedBeneficiary?.item;
|
Beneficiary? beneficiary = _selectedBeneficiary?.item;
|
||||||
if (beneficiary == null ||
|
if (beneficiary == null ||
|
||||||
getBeneficiaryName(beneficiary) != beneficiaryName) {
|
getBeneficiaryName(beneficiary) != beneficiaryName) {
|
||||||
@@ -101,12 +98,12 @@ class _AddTransactionTemplateWidgetState
|
|||||||
if (result == null || !result) {
|
if (result == null || !result) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
beneficiary = await db.beneficiariesDao.upsertBeneficiary(
|
||||||
beneficiary =
|
BeneficiariesCompanion(
|
||||||
Beneficiary()
|
name: Value(beneficiaryName),
|
||||||
..name = beneficiaryName
|
type: Value(BeneficiaryType.other),
|
||||||
..type = BeneficiaryType.other;
|
),
|
||||||
await upsertBeneficiary(beneficiary);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final factor = switch (_selectedDirection) {
|
final factor = switch (_selectedDirection) {
|
||||||
@@ -114,15 +111,16 @@ class _AddTransactionTemplateWidgetState
|
|||||||
TransactionDirection.receive => 1,
|
TransactionDirection.receive => 1,
|
||||||
};
|
};
|
||||||
final amount = factor * double.parse(_amountTextController.text).abs();
|
final amount = factor * double.parse(_amountTextController.text).abs();
|
||||||
final template =
|
final template = await db.transactionTemplatesDao.upsertTemplate(
|
||||||
TransactionTemplate()
|
TransactionTemplatesCompanion(
|
||||||
..name = _templateNameController.text
|
name: Value(_templateNameController.text),
|
||||||
..account.value = widget.activeAccountItem
|
accountId: Value(widget.activeAccountItem.id),
|
||||||
..beneficiary.value = beneficiary
|
beneficiaryId: Value(beneficiary.id),
|
||||||
..expenseCategory.value = _expenseCategory
|
expenseCategoryId: Value(_expenseCategory?.id),
|
||||||
..recurring = _isRecurring
|
recurring: Value(_isRecurring),
|
||||||
..amount = amount;
|
amount: Value(amount),
|
||||||
await upsertTransactionTemplate(template);
|
),
|
||||||
|
);
|
||||||
|
|
||||||
if (_isRecurring) {
|
if (_isRecurring) {
|
||||||
final days = switch (_selectedPeriod) {
|
final days = switch (_selectedPeriod) {
|
||||||
@@ -131,13 +129,14 @@ class _AddTransactionTemplateWidgetState
|
|||||||
Period.months => _periodSize * 31,
|
Period.months => _periodSize * 31,
|
||||||
Period.years => _periodSize * 365,
|
Period.years => _periodSize * 365,
|
||||||
};
|
};
|
||||||
final recurringTransaction =
|
await db.recurringTransactionsDao.upsertRecurringTransaction(
|
||||||
RecurringTransaction()
|
RecurringTransactionsCompanion(
|
||||||
..account.value = widget.activeAccountItem
|
accountId: Value(widget.activeAccountItem.id),
|
||||||
..template.value = template
|
templateId: Value(template.id),
|
||||||
..lastExecution = null
|
lastExecution: Value(null),
|
||||||
..days = days;
|
days: Value(days),
|
||||||
await upsertRecurringTransaction(recurringTransaction);
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
widget.onAdd();
|
widget.onAdd();
|
||||||
}
|
}
|
||||||
@@ -190,8 +189,7 @@ class _AddTransactionTemplateWidgetState
|
|||||||
.where((el) {
|
.where((el) {
|
||||||
final bloc = GetIt.I.get<CoreCubit>();
|
final bloc = GetIt.I.get<CoreCubit>();
|
||||||
if (el.type == BeneficiaryType.account) {
|
if (el.type == BeneficiaryType.account) {
|
||||||
return el.account.value?.id !=
|
return el.accountId != bloc.activeAccount?.id;
|
||||||
bloc.activeAccount?.id;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:get_it/get_it.dart';
|
import 'package:get_it/get_it.dart';
|
||||||
import 'package:okane/database/collections/account.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/database/collections/beneficiary.dart';
|
|
||||||
import 'package:okane/database/collections/expense_category.dart';
|
|
||||||
import 'package:okane/database/collections/template.dart';
|
|
||||||
import 'package:okane/database/collections/transaction.dart';
|
|
||||||
import 'package:okane/database/database.dart';
|
|
||||||
import 'package:okane/i18n/strings.g.dart';
|
import 'package:okane/i18n/strings.g.dart';
|
||||||
import 'package:okane/ui/state/core.dart';
|
import 'package:okane/ui/state/core.dart';
|
||||||
import 'package:okane/ui/transaction.dart';
|
import 'package:okane/ui/transaction.dart';
|
||||||
@@ -14,14 +10,14 @@ import 'package:okane/ui/utils.dart';
|
|||||||
import 'package:okane/ui/widgets/add_expense_category.dart';
|
import 'package:okane/ui/widgets/add_expense_category.dart';
|
||||||
import 'package:searchfield/searchfield.dart';
|
import 'package:searchfield/searchfield.dart';
|
||||||
|
|
||||||
typedef AddTransactionCallback = void Function(Transaction);
|
typedef AddTransactionCallback = void Function(TransactionDto);
|
||||||
|
|
||||||
class AddTransactionWidget extends StatefulWidget {
|
class AddTransactionWidget extends StatefulWidget {
|
||||||
final AddTransactionCallback onAdd;
|
final AddTransactionCallback onAdd;
|
||||||
|
|
||||||
final Account activeAccountItem;
|
final Account activeAccountItem;
|
||||||
|
|
||||||
final TransactionTemplate? template;
|
final TransactionTemplateDto? template;
|
||||||
|
|
||||||
const AddTransactionWidget({
|
const AddTransactionWidget({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -51,6 +47,8 @@ class _AddTransactionWidgetState extends State<AddTransactionWidget> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
/*
|
||||||
if (widget.template != null) {
|
if (widget.template != null) {
|
||||||
_selectedDirection =
|
_selectedDirection =
|
||||||
widget.template!.amount > 0
|
widget.template!.amount > 0
|
||||||
@@ -58,12 +56,12 @@ class _AddTransactionWidgetState extends State<AddTransactionWidget> {
|
|||||||
: TransactionDirection.send;
|
: TransactionDirection.send;
|
||||||
_amountTextController.text = widget.template!.amount.toString();
|
_amountTextController.text = widget.template!.amount.toString();
|
||||||
_beneficiaryTextController.text =
|
_beneficiaryTextController.text =
|
||||||
widget.template!.beneficiary.value!.name;
|
widget.template!;
|
||||||
_selectedBeneficiary = SearchFieldListItem(
|
_selectedBeneficiary = SearchFieldListItem(
|
||||||
getBeneficiaryName(widget.template!.beneficiary.value!),
|
getBeneficiaryName(widget.template!.beneficiary.value!),
|
||||||
item: widget.template!.beneficiary.value!,
|
item: widget.template!.beneficiary.value!,
|
||||||
);
|
);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
String getBeneficiaryName(Beneficiary item) {
|
String getBeneficiaryName(Beneficiary item) {
|
||||||
@@ -81,6 +79,7 @@ class _AddTransactionWidgetState extends State<AddTransactionWidget> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final db = GetIt.I.get<OkaneDatabase>();
|
||||||
Beneficiary? beneficiary = _selectedBeneficiary?.item;
|
Beneficiary? beneficiary = _selectedBeneficiary?.item;
|
||||||
if (beneficiary == null ||
|
if (beneficiary == null ||
|
||||||
getBeneficiaryName(beneficiary) != beneficiaryName) {
|
getBeneficiaryName(beneficiary) != beneficiaryName) {
|
||||||
@@ -115,11 +114,12 @@ class _AddTransactionWidgetState extends State<AddTransactionWidget> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
beneficiary =
|
beneficiary = await db.beneficiariesDao.upsertBeneficiary(
|
||||||
Beneficiary()
|
BeneficiariesCompanion(
|
||||||
..name = beneficiaryName
|
name: Value(beneficiaryName),
|
||||||
..type = BeneficiaryType.other;
|
type: Value(BeneficiaryType.other),
|
||||||
await upsertBeneficiary(beneficiary);
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final factor = switch (_selectedDirection) {
|
final factor = switch (_selectedDirection) {
|
||||||
@@ -127,30 +127,38 @@ class _AddTransactionWidgetState extends State<AddTransactionWidget> {
|
|||||||
TransactionDirection.receive => 1,
|
TransactionDirection.receive => 1,
|
||||||
};
|
};
|
||||||
final amount = factor * double.parse(_amountTextController.text).abs();
|
final amount = factor * double.parse(_amountTextController.text).abs();
|
||||||
final transaction =
|
final rawTransaction = TransactionsCompanion(
|
||||||
Transaction()
|
accountId: Value(widget.activeAccountItem.id),
|
||||||
..account.value = widget.activeAccountItem
|
beneficiaryId: Value(beneficiary.id),
|
||||||
..beneficiary.value = beneficiary
|
amount: Value(amount),
|
||||||
..amount = amount
|
// tags: [],
|
||||||
..tags = []
|
expenseCategoryId: Value(_expenseCategory?.id),
|
||||||
..expenseCategory.value = _expenseCategory
|
date: Value(_selectedDate),
|
||||||
..date = _selectedDate;
|
);
|
||||||
await upsertTransaction(transaction);
|
final transaction = await db.transactionsDao.upsertTransaction(
|
||||||
|
rawTransaction,
|
||||||
|
);
|
||||||
|
|
||||||
if (beneficiary.type == BeneficiaryType.account) {
|
if (beneficiary.type == BeneficiaryType.account) {
|
||||||
final otherTransaction =
|
final otherTransaction = rawTransaction.copyWith(
|
||||||
Transaction()
|
accountId: Value(beneficiary.accountId!),
|
||||||
..account.value = beneficiary.account.value!
|
beneficiaryId: Value(
|
||||||
..beneficiary.value = await getAccountBeneficiary(
|
(await db.beneficiariesDao.getAccountBeneficiary(
|
||||||
widget.activeAccountItem,
|
widget.activeAccountItem,
|
||||||
)
|
)).id,
|
||||||
..date = _selectedDate
|
),
|
||||||
..expenseCategory.value = _expenseCategory
|
amount: Value(-1 * rawTransaction.amount.value),
|
||||||
..amount = -1 * amount;
|
);
|
||||||
await upsertTransaction(otherTransaction);
|
await db.transactionsDao.upsertTransaction(otherTransaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
widget.onAdd(transaction);
|
widget.onAdd(
|
||||||
|
TransactionDto(
|
||||||
|
transaction: transaction,
|
||||||
|
beneficiary: beneficiary,
|
||||||
|
expenseCategory: _expenseCategory,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -167,17 +175,17 @@ class _AddTransactionWidgetState extends State<AddTransactionWidget> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_amountTextController.text = template.amount.toString();
|
_amountTextController.text = template.template.amount.toString();
|
||||||
_selectedDirection =
|
_selectedDirection =
|
||||||
template.amount > 0
|
template.template.amount > 0
|
||||||
? TransactionDirection.receive
|
? TransactionDirection.receive
|
||||||
: TransactionDirection.send;
|
: TransactionDirection.send;
|
||||||
_selectedBeneficiary = SearchFieldListItem(
|
_selectedBeneficiary = SearchFieldListItem(
|
||||||
getBeneficiaryName(template.beneficiary.value!),
|
getBeneficiaryName(template.beneficiary),
|
||||||
item: template.beneficiary.value!,
|
item: template.beneficiary,
|
||||||
);
|
);
|
||||||
_beneficiaryTextController.text = getBeneficiaryName(
|
_beneficiaryTextController.text = getBeneficiaryName(
|
||||||
template.beneficiary.value!,
|
template.beneficiary,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text(t.pages.transactions.addTransaction.useTemplate),
|
child: Text(t.pages.transactions.addTransaction.useTemplate),
|
||||||
@@ -216,7 +224,7 @@ class _AddTransactionWidgetState extends State<AddTransactionWidget> {
|
|||||||
.where((el) {
|
.where((el) {
|
||||||
final bloc = GetIt.I.get<CoreCubit>();
|
final bloc = GetIt.I.get<CoreCubit>();
|
||||||
if (el.type == BeneficiaryType.account) {
|
if (el.type == BeneficiaryType.account) {
|
||||||
return el.account.value?.id.toInt() ==
|
return el.accountId ==
|
||||||
bloc.activeAccount?.id.toInt();
|
bloc.activeAccount?.id.toInt();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:okane/database/collections/transaction.dart';
|
import 'package:okane/database/sqlite.dart';
|
||||||
import 'package:okane/ui/utils.dart';
|
import 'package:okane/ui/utils.dart';
|
||||||
import 'package:okane/ui/widgets/image_wrapper.dart';
|
import 'package:okane/ui/widgets/image_wrapper.dart';
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ class TransactionCard extends StatelessWidget {
|
|||||||
this.subtitle,
|
this.subtitle,
|
||||||
});
|
});
|
||||||
|
|
||||||
final Transaction transaction;
|
final TransactionDto transaction;
|
||||||
|
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
|
|
||||||
@@ -24,19 +24,22 @@ class TransactionCard extends StatelessWidget {
|
|||||||
child: ListTile(
|
child: ListTile(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
leading: ImageWrapper(
|
leading: ImageWrapper(
|
||||||
title: transaction.beneficiary.value!.name,
|
title: transaction.beneficiary.name,
|
||||||
path: transaction.beneficiary.value!.imagePath,
|
path: transaction.beneficiary.imagePath,
|
||||||
),
|
),
|
||||||
trailing: Text(formatDateTime(transaction.date)),
|
trailing: Text(formatDateTime(transaction.transaction.date)),
|
||||||
title: Text(transaction.beneficiary.value!.name),
|
title: Text(transaction.beneficiary.name),
|
||||||
subtitle: Column(
|
subtitle: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
formatCurrency(transaction.amount),
|
formatCurrency(transaction.transaction.amount),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: transaction.amount < 0 ? Colors.red : Colors.green,
|
color:
|
||||||
|
transaction.transaction.amount < 0
|
||||||
|
? Colors.red
|
||||||
|
: Colors.green,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (subtitle != null) subtitle!,
|
if (subtitle != null) subtitle!,
|
||||||
|
|||||||
@@ -6,10 +6,14 @@
|
|||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
|
#include <sentry_flutter/sentry_flutter_plugin.h>
|
||||||
|
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
g_autoptr(FlPluginRegistrar) isar_flutter_libs_registrar =
|
g_autoptr(FlPluginRegistrar) sentry_flutter_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "IsarFlutterLibsPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin");
|
||||||
isar_flutter_libs_plugin_register_with_registrar(isar_flutter_libs_registrar);
|
sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar);
|
||||||
|
g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin");
|
||||||
|
sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
isar_flutter_libs
|
sentry_flutter
|
||||||
|
sqlite3_flutter_libs
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|||||||
195
pubspec.lock
195
pubspec.lock
@@ -5,18 +5,23 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: _fe_analyzer_shared
|
name: _fe_analyzer_shared
|
||||||
sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
|
sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "61.0.0"
|
version: "76.0.0"
|
||||||
|
_macros:
|
||||||
|
dependency: transitive
|
||||||
|
description: dart
|
||||||
|
source: sdk
|
||||||
|
version: "0.3.3"
|
||||||
analyzer:
|
analyzer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: analyzer
|
name: analyzer
|
||||||
sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
|
sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.13.0"
|
version: "6.11.0"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -121,6 +126,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.0"
|
||||||
|
charcode:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: charcode
|
||||||
|
sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.0"
|
||||||
checked_yaml:
|
checked_yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -129,6 +142,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.3"
|
version: "2.0.3"
|
||||||
|
cli_util:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: cli_util
|
||||||
|
sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.2"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -197,18 +218,34 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: dart_style
|
name: dart_style
|
||||||
sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55"
|
sha256: "7306ab8a2359a48d22310ad823521d723acfed60ee1f7e37388e8986853b6820"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.2"
|
version: "2.3.8"
|
||||||
dartx:
|
drift:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: dartx
|
name: drift
|
||||||
sha256: "8b25435617027257d43e6508b5fe061012880ddfdaa75a71d607c3de2a13d244"
|
sha256: b584ddeb2b74436735dd2cf746d2d021e19a9a6770f409212fd5cbc2814ada85
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "2.26.1"
|
||||||
|
drift_dev:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: drift_dev
|
||||||
|
sha256: "0d3f8b33b76cf1c6a82ee34d9511c40957549c4674b8f1688609e6d6c7306588"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.26.0"
|
||||||
|
drift_flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: drift_flutter
|
||||||
|
sha256: "0cadbf3b8733409a6cf61d18ba2e94e149df81df7de26f48ae0695b48fd71922"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.4"
|
||||||
equatable:
|
equatable:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -368,6 +405,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.0"
|
version: "6.0.0"
|
||||||
|
http:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http
|
||||||
|
sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.0"
|
||||||
http_multi_server:
|
http_multi_server:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -392,30 +437,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.5"
|
version: "1.0.5"
|
||||||
isar:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: isar
|
|
||||||
sha256: "99165dadb2cf2329d3140198363a7e7bff9bbd441871898a87e26914d25cf1ea"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.0+1"
|
|
||||||
isar_flutter_libs:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: isar_flutter_libs
|
|
||||||
sha256: bc6768cc4b9c61aabff77152e7f33b4b17d2fc93134f7af1c3dd51500fe8d5e8
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.0+1"
|
|
||||||
isar_generator:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: isar_generator
|
|
||||||
sha256: "76c121e1295a30423604f2f819bc255bc79f852f3bc8743a24017df6068ad133"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.0+1"
|
|
||||||
js:
|
js:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -488,6 +509,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.3.0"
|
||||||
|
macros:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: macros
|
||||||
|
sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.3-main.0"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -544,6 +573,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.0"
|
version: "2.2.0"
|
||||||
|
package_info_plus:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: package_info_plus
|
||||||
|
sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.3.0"
|
||||||
|
package_info_plus_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: package_info_plus_platform_interface
|
||||||
|
sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.0"
|
||||||
path:
|
path:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -648,6 +693,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.0"
|
version: "1.5.0"
|
||||||
|
recase:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: recase
|
||||||
|
sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.0"
|
||||||
searchfield:
|
searchfield:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -656,6 +709,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.9"
|
version: "1.2.9"
|
||||||
|
sentry:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sentry
|
||||||
|
sha256: "599701ca0693a74da361bc780b0752e1abc98226cf5095f6b069648116c896bb"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.14.2"
|
||||||
|
sentry_flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: sentry_flutter
|
||||||
|
sha256: "5ba2cf40646a77d113b37a07bd69f61bb3ec8a73cbabe5537b05a7c89d2656f8"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "8.14.2"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -781,6 +850,38 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.1"
|
version: "1.10.1"
|
||||||
|
sprintf:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sprintf
|
||||||
|
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.0"
|
||||||
|
sqlite3:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqlite3
|
||||||
|
sha256: "310af39c40dd0bb2058538333c9d9840a2725ae0b9f77e4fd09ad6696aa8f66e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.7.5"
|
||||||
|
sqlite3_flutter_libs:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqlite3_flutter_libs
|
||||||
|
sha256: "1a96b59227828d9eb1463191d684b37a27d66ee5ed7597fcf42eee6452c88a14"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.32"
|
||||||
|
sqlparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: sqlparser
|
||||||
|
sha256: "27dd0a9f0c02e22ac0eb42a23df9ea079ce69b52bb4a3b478d64e0ef34a263ee"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.41.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -829,14 +930,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.4"
|
version: "0.7.4"
|
||||||
time:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: time
|
|
||||||
sha256: "370572cf5d1e58adcb3e354c47515da3f7469dac3a95b447117e728e7be6f461"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.5"
|
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -853,6 +946,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.4.0"
|
||||||
|
uuid:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: uuid
|
||||||
|
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.5.1"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -917,14 +1018,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
xxh3:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: xxh3
|
|
||||||
sha256: "399a0438f5d426785723c99da6b16e136f4953fb1e9db0bf270bd41dd4619916"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.0"
|
|
||||||
yaml:
|
yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
13
pubspec.yaml
13
pubspec.yaml
@@ -1,8 +1,8 @@
|
|||||||
name: okane
|
name: okane
|
||||||
description: "A cross-platform finance tracker."
|
description: "A cross-platform finance tracker."
|
||||||
publish_to: 'none'
|
publish_to: "none"
|
||||||
|
|
||||||
version: 1.0.0+1
|
version: 1.0.0+6
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.7.0
|
sdk: ^3.7.0
|
||||||
|
|
||||||
@@ -21,13 +21,16 @@ dependencies:
|
|||||||
path: ^1.9.1
|
path: ^1.9.1
|
||||||
fl_chart: ^0.71.0
|
fl_chart: ^0.71.0
|
||||||
flutter_picker_plus: ^1.5.1
|
flutter_picker_plus: ^1.5.1
|
||||||
isar: ^3.1.0+1
|
|
||||||
isar_flutter_libs: ^3.1.0+1
|
|
||||||
shared_preferences: ^2.5.3
|
shared_preferences: ^2.5.3
|
||||||
json_annotation: ^4.9.0
|
json_annotation: ^4.9.0
|
||||||
more: 4.5.0
|
more: 4.5.0
|
||||||
slang: ^3.0.0
|
slang: ^3.0.0
|
||||||
slang_flutter: ^3.0.0
|
slang_flutter: ^3.0.0
|
||||||
|
drift: ^2.26.1
|
||||||
|
drift_flutter: ^0.2.4
|
||||||
|
|
||||||
|
# For optional error tracking
|
||||||
|
sentry_flutter: ^8.14.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -35,9 +38,9 @@ dev_dependencies:
|
|||||||
flutter_lints: ^5.0.0
|
flutter_lints: ^5.0.0
|
||||||
build_runner: ^2.4.13
|
build_runner: ^2.4.13
|
||||||
freezed: 2.5.0
|
freezed: 2.5.0
|
||||||
isar_generator: ^3.1.0+1
|
|
||||||
json_serializable: ^6.4.0
|
json_serializable: ^6.4.0
|
||||||
slang_build_runner: ^3.0.0
|
slang_build_runner: ^3.0.0
|
||||||
|
drift_dev: ^2.20.1
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
import 'package:okane/database/collections/recurrent.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
group("isDue", () {
|
|
||||||
test("null value", () {
|
|
||||||
final t = RecurringTransaction()..lastExecution = null;
|
|
||||||
expect(t.isDue(DateTime.now()), true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Date before", () {
|
|
||||||
final now = DateTime.now();
|
|
||||||
final t =
|
|
||||||
RecurringTransaction()
|
|
||||||
..lastExecution = now
|
|
||||||
..days = 30;
|
|
||||||
expect(t.isDue(now.add(Duration(days: 10))), false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Date before warning", () {
|
|
||||||
final now = DateTime.now();
|
|
||||||
final t =
|
|
||||||
RecurringTransaction()
|
|
||||||
..lastExecution = now
|
|
||||||
..days = 30;
|
|
||||||
expect(t.isDue(now.add(Duration(days: 20))), true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Expired", () {
|
|
||||||
final now = DateTime.now();
|
|
||||||
final t =
|
|
||||||
RecurringTransaction()
|
|
||||||
..lastExecution = now
|
|
||||||
..days = 30;
|
|
||||||
expect(t.isDue(now.add(Duration(days: 31))), true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user