diff --git a/lib/api/category.dart b/lib/api/category.dart index ee7f78d..4fe0f22 100644 --- a/lib/api/category.dart +++ b/lib/api/category.dart @@ -22,18 +22,36 @@ class WalletCategory { factory WalletCategory.fromJson(Map json) => _$WalletCategoryFromJson(json); + /// Default [WalletCategory] instance for json_serializable + factory WalletCategory.unknown() => WalletCategory( + name: "Unknown", + id: -1, + icon: Icons.question_mark, + color: Colors.green, + ); + /// User-defined name + @JsonKey(defaultValue: "Unknown") String name; /// Unique identificator of the category + @JsonKey(required: true, disallowNullValue: true) final int id; /// Selected Icon for the category - @JsonKey(fromJson: _iconDataFromJson, toJson: _iconDataToJson) + @JsonKey( + fromJson: _iconDataFromJson, + toJson: _iconDataToJson, + defaultValue: _defaultIcon, + ) IconData icon; /// The color that will be displayed with entry - @JsonKey(fromJson: _colorFromJson, toJson: _colorToJson) + @JsonKey( + fromJson: _colorFromJson, + toJson: _colorToJson, + defaultValue: _defaultColor, + ) Color color; /// Converts the data in this instance into a Map @@ -62,3 +80,6 @@ enum EntryType { /// Income income } + +IconData _defaultIcon() => Icons.question_mark; +Color _defaultColor() => Colors.green; diff --git a/lib/api/category.g.dart b/lib/api/category.g.dart index deaf100..e2140b3 100644 --- a/lib/api/category.g.dart +++ b/lib/api/category.g.dart @@ -6,13 +6,23 @@ part of 'category.dart'; // JsonSerializableGenerator // ************************************************************************** -WalletCategory _$WalletCategoryFromJson(Map json) => - WalletCategory( - name: json['name'] as String, - id: (json['id'] as num).toInt(), - icon: _iconDataFromJson(json['icon'] as Map), - color: _colorFromJson((json['color'] as num).toInt()), - ); +WalletCategory _$WalletCategoryFromJson(Map json) { + $checkKeys( + json, + requiredKeys: const ['id'], + disallowNullValues: const ['id'], + ); + return WalletCategory( + name: json['name'] as String? ?? 'Unknown', + id: (json['id'] as num).toInt(), + icon: json['icon'] == null + ? _defaultIcon() + : _iconDataFromJson(json['icon'] as Map), + color: json['color'] == null + ? _defaultColor() + : _colorFromJson((json['color'] as num).toInt()), + ); +} Map _$WalletCategoryToJson(WalletCategory instance) => { diff --git a/lib/api/debt_entry.dart b/lib/api/debt_entry.dart index 9f32489..b25f28b 100644 --- a/lib/api/debt_entry.dart +++ b/lib/api/debt_entry.dart @@ -25,14 +25,18 @@ class DebtEntry { Map toJson() => _$DebtEntryToJson(this); /// Unique identifier + @JsonKey(required: true, disallowNullValue: true) final int id; /// The payed amount + @JsonKey(defaultValue: 0) int amount; /// User-friendly identifier for the transaction + @JsonKey(defaultValue: "Unknown") String name; /// List of people who payed + @JsonKey(defaultValue: DebtPerson.unknownPerson) List whoPayed; } diff --git a/lib/api/debt_entry.g.dart b/lib/api/debt_entry.g.dart index 7ec825e..e939cf1 100644 --- a/lib/api/debt_entry.g.dart +++ b/lib/api/debt_entry.g.dart @@ -6,14 +6,22 @@ part of 'debt_entry.dart'; // JsonSerializableGenerator // ************************************************************************** -DebtEntry _$DebtEntryFromJson(Map json) => DebtEntry( - id: (json['id'] as num).toInt(), - amount: (json['amount'] as num).toInt(), - name: json['name'] as String, - whoPayed: (json['whoPayed'] as List) - .map((e) => DebtPerson.fromJson(e as Map)) - .toList(), - ); +DebtEntry _$DebtEntryFromJson(Map json) { + $checkKeys( + json, + requiredKeys: const ['id'], + disallowNullValues: const ['id'], + ); + return DebtEntry( + id: (json['id'] as num).toInt(), + amount: (json['amount'] as num?)?.toInt() ?? 0, + name: json['name'] as String? ?? 'Unknown', + whoPayed: (json['whoPayed'] as List?) + ?.map((e) => DebtPerson.fromJson(e as Map)) + .toList() ?? + DebtPerson.unknownPerson(), + ); +} Map _$DebtEntryToJson(DebtEntry instance) => { 'id': instance.id, diff --git a/lib/api/debt_person.dart b/lib/api/debt_person.dart index 47531fc..d17676f 100644 --- a/lib/api/debt_person.dart +++ b/lib/api/debt_person.dart @@ -8,6 +8,9 @@ class DebtPerson { /// Represents a single person in a debt scenario DebtPerson({required this.id, required this.name}); + /// Default [DebtPerson] instance for json_serializable + factory DebtPerson.unknownPerson() => DebtPerson(id: -1, name: "Unknown"); + /// Generates a class instance from a Map factory DebtPerson.fromJson(Map json) => _$DebtPersonFromJson(json); @@ -16,8 +19,10 @@ class DebtPerson { Map toJson() => _$DebtPersonToJson(this); /// Unique identifier + @JsonKey(required: true, disallowNullValue: true) final int id; /// Identifier that the user will see + @JsonKey(defaultValue: "Unknown") String name; } diff --git a/lib/api/debt_person.g.dart b/lib/api/debt_person.g.dart index d947448..e20c32b 100644 --- a/lib/api/debt_person.g.dart +++ b/lib/api/debt_person.g.dart @@ -6,10 +6,17 @@ part of 'debt_person.dart'; // JsonSerializableGenerator // ************************************************************************** -DebtPerson _$DebtPersonFromJson(Map json) => DebtPerson( - id: (json['id'] as num).toInt(), - name: json['name'] as String, - ); +DebtPerson _$DebtPersonFromJson(Map json) { + $checkKeys( + json, + requiredKeys: const ['id'], + disallowNullValues: const ['id'], + ); + return DebtPerson( + id: (json['id'] as num).toInt(), + name: json['name'] as String? ?? 'Unknown', + ); +} Map _$DebtPersonToJson(DebtPerson instance) => { diff --git a/lib/api/debt_scenario.dart b/lib/api/debt_scenario.dart index 0ede810..e3d7120 100644 --- a/lib/api/debt_scenario.dart +++ b/lib/api/debt_scenario.dart @@ -23,17 +23,24 @@ class DebtScenario { Map toJson() => _$DebtScenarioToJson(this); /// Unique identified + @JsonKey(disallowNullValue: true) final int id; /// User-friendly identifier + @JsonKey(defaultValue: "Unknown") String name; /// Whether this scenario should be shown under archived ones + @JsonKey(defaultValue: false) bool isArchived; /// All entries + @JsonKey(defaultValue: []) List entries; /// All people + @JsonKey(defaultValue: _defaultPeopleList) List people; } + +List _defaultPeopleList() => [DebtPerson.unknownPerson()]; diff --git a/lib/api/debt_scenario.g.dart b/lib/api/debt_scenario.g.dart index 38818cd..55b4980 100644 --- a/lib/api/debt_scenario.g.dart +++ b/lib/api/debt_scenario.g.dart @@ -6,19 +6,25 @@ part of 'debt_scenario.dart'; // JsonSerializableGenerator // ************************************************************************** -DebtScenario _$DebtScenarioFromJson(Map json) => DebtScenario( - id: (json['id'] as num).toInt(), - name: json['name'] as String, - isArchived: json['isArchived'] as bool, - entries: (json['entries'] as List?) - ?.map((e) => DebtEntry.fromJson(e as Map)) - .toList() ?? - const [], - people: (json['people'] as List?) - ?.map((e) => DebtPerson.fromJson(e as Map)) - .toList() ?? - const [], - ); +DebtScenario _$DebtScenarioFromJson(Map json) { + $checkKeys( + json, + disallowNullValues: const ['id'], + ); + return DebtScenario( + id: (json['id'] as num).toInt(), + name: json['name'] as String? ?? 'Unknown', + isArchived: json['isArchived'] as bool? ?? false, + entries: (json['entries'] as List?) + ?.map((e) => DebtEntry.fromJson(e as Map)) + .toList() ?? + [], + people: (json['people'] as List?) + ?.map((e) => DebtPerson.fromJson(e as Map)) + .toList() ?? + _defaultPeopleList(), + ); +} Map _$DebtScenarioToJson(DebtScenario instance) => { diff --git a/lib/api/entry_data.dart b/lib/api/entry_data.dart index 498e07e..d59f532 100644 --- a/lib/api/entry_data.dart +++ b/lib/api/entry_data.dart @@ -15,13 +15,19 @@ class EntryData { factory EntryData.fromJson(Map json) => _$EntryDataFromJson(json); + /// [EntryData] instance used as a default value for json_serializable + factory EntryData.unknown() => EntryData(name: "Unknown", amount: 0); + /// Name of entry + @JsonKey(defaultValue: "Unknown") String name; /// Optional description, default is empty + @JsonKey(defaultValue: "") String description; /// Amount for entry + @JsonKey(defaultValue: 0) double amount; /// Converts the data in this instance into a Map diff --git a/lib/api/entry_data.g.dart b/lib/api/entry_data.g.dart index 48a4faa..1ccbf8d 100644 --- a/lib/api/entry_data.g.dart +++ b/lib/api/entry_data.g.dart @@ -7,9 +7,9 @@ part of 'entry_data.dart'; // ************************************************************************** EntryData _$EntryDataFromJson(Map json) => EntryData( - name: json['name'] as String, - amount: (json['amount'] as num).toDouble(), - description: json['description'] as String? ?? "", + name: json['name'] as String? ?? 'Unknown', + amount: (json['amount'] as num?)?.toDouble() ?? 0, + description: json['description'] as String? ?? '', ); Map _$EntryDataToJson(EntryData instance) => { diff --git a/lib/api/recurring_entry.dart b/lib/api/recurring_entry.dart index fc57bc0..72b78f9 100644 --- a/lib/api/recurring_entry.dart +++ b/lib/api/recurring_entry.dart @@ -33,12 +33,15 @@ class RecurringWalletEntry extends WalletSingleEntry { Map toJson() => _$RecurringWalletEntryToJson(this); /// Last date the recurring entry was added into the single entry list + @JsonKey(defaultValue: DateTime.now) DateTime lastRunDate; /// After how many {recurType} should the entry recur + @JsonKey(defaultValue: 1) int repeatAfter; /// What type of recurrence should happen + @JsonKey(defaultValue: RecurType.month) RecurType recurType; } diff --git a/lib/api/recurring_entry.g.dart b/lib/api/recurring_entry.g.dart index a8abb86..4812c59 100644 --- a/lib/api/recurring_entry.g.dart +++ b/lib/api/recurring_entry.g.dart @@ -6,19 +6,33 @@ part of 'recurring_entry.dart'; // JsonSerializableGenerator // ************************************************************************** -RecurringWalletEntry _$RecurringWalletEntryFromJson( - Map json) => - RecurringWalletEntry( - data: EntryData.fromJson(json['data'] as Map), - type: $enumDecode(_$EntryTypeEnumMap, json['type']), - date: DateTime.parse(json['date'] as String), - category: - WalletCategory.fromJson(json['category'] as Map), - id: (json['id'] as num).toInt(), - lastRunDate: DateTime.parse(json['lastRunDate'] as String), - recurType: $enumDecode(_$RecurTypeEnumMap, json['recurType']), - repeatAfter: (json['repeatAfter'] as num?)?.toInt() ?? 1, - ); +RecurringWalletEntry _$RecurringWalletEntryFromJson(Map json) { + $checkKeys( + json, + requiredKeys: const ['id'], + disallowNullValues: const ['id'], + ); + return RecurringWalletEntry( + data: json['data'] == null + ? EntryData.unknown() + : EntryData.fromJson(json['data'] as Map), + type: $enumDecodeNullable(_$EntryTypeEnumMap, json['type']) ?? + EntryType.expense, + date: json['date'] == null + ? DateTime.now() + : DateTime.parse(json['date'] as String), + category: json['category'] == null + ? WalletCategory.unknown() + : WalletCategory.fromJson(json['category'] as Map), + id: (json['id'] as num).toInt(), + lastRunDate: json['lastRunDate'] == null + ? DateTime.now() + : DateTime.parse(json['lastRunDate'] as String), + recurType: $enumDecodeNullable(_$RecurTypeEnumMap, json['recurType']) ?? + RecurType.month, + repeatAfter: (json['repeatAfter'] as num?)?.toInt() ?? 1, + ); +} Map _$RecurringWalletEntryToJson( RecurringWalletEntry instance) => diff --git a/lib/api/wallet.dart b/lib/api/wallet.dart index df9f81e..b8cd91b 100644 --- a/lib/api/wallet.dart +++ b/lib/api/wallet.dart @@ -38,24 +38,32 @@ class Wallet { factory Wallet.fromJson(Map json) => _$WalletFromJson(json); /// A list of all [RecurringWalletEntry]s + @JsonKey(defaultValue: []) final List recurringEntries; /// Name of the wallet + @JsonKey(defaultValue: "Unknown") final String name; /// A list of available categories + @JsonKey(defaultValue: _defaultWalletCategory) final List categories; /// List of saved entries + @JsonKey(defaultValue: []) final List entries; /// The starting balance of the wallet /// /// Used to calculate current balance + @JsonKey(defaultValue: 0) double starterBalance; /// Selected currency - @JsonKey(fromJson: _currencyFromJson) + @JsonKey( + fromJson: _currencyFromJson, + defaultValue: _defaultCurrency, + ) final Currency currency; /// Converts the data in this instance into a Map @@ -281,3 +289,20 @@ class Wallet { WalletManager.saveWallet(this); } } + +List _defaultWalletCategory() => [WalletCategory.unknown()]; +Currency _defaultCurrency() => Currency.from( + json: { + "code": "USD", + "name": "United States Dollar", + "symbol": r"$", + "flag": "USD", + "decimal_digits": 2, + "number": 840, + "name_plural": "US dollars", + "thousands_separator": ",", + "decimal_separator": ".", + "space_between_amount_and_symbol": false, + "symbol_on_left": true, + }, + ); diff --git a/lib/api/wallet.g.dart b/lib/api/wallet.g.dart index 561b831..277d410 100644 --- a/lib/api/wallet.g.dart +++ b/lib/api/wallet.g.dart @@ -7,22 +7,24 @@ part of 'wallet.dart'; // ************************************************************************** Wallet _$WalletFromJson(Map json) => Wallet( - name: json['name'] as String, - currency: _currencyFromJson(json['currency'] as Map), + name: json['name'] as String? ?? 'Unknown', + currency: json['currency'] == null + ? _defaultCurrency() + : _currencyFromJson(json['currency'] as Map), categories: (json['categories'] as List?) ?.map((e) => WalletCategory.fromJson(e as Map)) .toList() ?? - const [], + _defaultWalletCategory(), entries: (json['entries'] as List?) ?.map( (e) => WalletSingleEntry.fromJson(e as Map)) .toList() ?? - const [], + [], recurringEntries: (json['recurringEntries'] as List?) ?.map((e) => RecurringWalletEntry.fromJson(e as Map)) .toList() ?? - const [], + [], starterBalance: (json['starterBalance'] as num?)?.toDouble() ?? 0, ); diff --git a/lib/api/wallet_entry.dart b/lib/api/wallet_entry.dart index 77aed05..10d586e 100644 --- a/lib/api/wallet_entry.dart +++ b/lib/api/wallet_entry.dart @@ -26,19 +26,24 @@ class WalletSingleEntry { _$WalletSingleEntryFromJson(json); /// Expense or income + @JsonKey(defaultValue: EntryType.expense) EntryType type; /// Actual entry data + @JsonKey(defaultValue: EntryData.unknown) EntryData data; /// Date of entry creation + @JsonKey(defaultValue: DateTime.now) DateTime date; /// Selected category + @JsonKey(defaultValue: WalletCategory.unknown) WalletCategory category; /// Unique entry ID - int id; + @JsonKey(required: true, disallowNullValue: true) + final int id; /// Converts the data in this instance into a Map Map toJson() => _$WalletSingleEntryToJson(this); diff --git a/lib/api/wallet_entry.g.dart b/lib/api/wallet_entry.g.dart index 4ce4cff..067bc4a 100644 --- a/lib/api/wallet_entry.g.dart +++ b/lib/api/wallet_entry.g.dart @@ -6,15 +6,27 @@ part of 'wallet_entry.dart'; // JsonSerializableGenerator // ************************************************************************** -WalletSingleEntry _$WalletSingleEntryFromJson(Map json) => - WalletSingleEntry( - data: EntryData.fromJson(json['data'] as Map), - type: $enumDecode(_$EntryTypeEnumMap, json['type']), - date: DateTime.parse(json['date'] as String), - category: - WalletCategory.fromJson(json['category'] as Map), - id: (json['id'] as num).toInt(), - ); +WalletSingleEntry _$WalletSingleEntryFromJson(Map json) { + $checkKeys( + json, + requiredKeys: const ['id'], + disallowNullValues: const ['id'], + ); + return WalletSingleEntry( + data: json['data'] == null + ? EntryData.unknown() + : EntryData.fromJson(json['data'] as Map), + type: $enumDecodeNullable(_$EntryTypeEnumMap, json['type']) ?? + EntryType.expense, + date: json['date'] == null + ? DateTime.now() + : DateTime.parse(json['date'] as String), + category: json['category'] == null + ? WalletCategory.unknown() + : WalletCategory.fromJson(json['category'] as Map), + id: (json['id'] as num).toInt(), + ); +} Map _$WalletSingleEntryToJson(WalletSingleEntry instance) => {