Line data Source code
1 : // Copyright 2023 The terCAD team. All rights reserved.
2 : // Use of this source code is governed by a CC BY-NC-ND 4.0 license that can be found in the LICENSE file.
3 :
4 : import 'dart:async';
5 :
6 : import 'package:app_finance/_classes/herald/app_locale.dart';
7 : import 'package:app_finance/_classes/storage/app_data.dart';
8 : import 'package:app_finance/_classes/structure/account_app_data.dart';
9 : import 'package:app_finance/_classes/structure/bill_app_data.dart';
10 : import 'package:app_finance/_classes/structure/budget_app_data.dart';
11 : import 'package:app_finance/design/form/list_selector_item.dart';
12 : import 'package:app_finance/_classes/structure/interface_app_data.dart';
13 : import 'package:app_finance/_classes/structure/invoice_app_data.dart';
14 : import 'package:app_finance/_configs/account_type.dart';
15 : import 'package:flutter_currency_picker/flutter_currency_picker.dart';
16 : import 'package:intl/intl.dart';
17 :
18 : typedef SearchFunction = Function(AppDataType type, String value);
19 : typedef AddFunction = InterfaceAppData Function(InterfaceAppData item);
20 :
21 : class FileParser {
22 : static const attrBillUuid = 'billUuid';
23 : static const attrAccountName = 'accountName';
24 : static const attrCategoryName = 'categoryName';
25 : static const attrBillAmount = 'billAmount';
26 : static const attrBillType = 'billType';
27 : static const attrBillDate = 'billDate';
28 : static const attrBillCurrency = 'billCurrency';
29 : static const attrBillComment = 'billComment';
30 : static const defDateFormat = 'dateFormat';
31 :
32 : List<String> columnMap;
33 : SearchFunction search;
34 : AddFunction add;
35 :
36 : String? _defaultCurrency;
37 : final _cache = <AppDataType, Map<String, String?>>{};
38 :
39 0 : FileParser({
40 : required this.search,
41 : required this.add,
42 : this.columnMap = const [],
43 : });
44 :
45 0 : static List<ListSelectorItem> getMappingTypes() {
46 0 : final account = AppLocale.labels.account;
47 0 : final budget = AppLocale.labels.budget;
48 0 : final bill = AppLocale.labels.bill;
49 0 : final mapping = [
50 0 : ListSelectorItem(id: '', name: '-- ${AppLocale.labels.ignoreTooltip} --'),
51 0 : ListSelectorItem(id: attrAccountName, name: '$account: ${AppLocale.labels.title}'),
52 0 : ListSelectorItem(id: attrCategoryName, name: '$budget: ${AppLocale.labels.title}'),
53 0 : ListSelectorItem(id: attrBillAmount, name: '$bill: ${AppLocale.labels.expense}'),
54 0 : ListSelectorItem(id: attrBillType, name: '$bill: ${AppLocale.labels.flowTypeTooltip}'),
55 0 : ListSelectorItem(id: attrBillDate, name: '$bill: ${AppLocale.labels.expenseDateTime}'),
56 0 : ListSelectorItem(id: attrBillCurrency, name: '$bill: ${AppLocale.labels.currency}'),
57 0 : ListSelectorItem(id: attrBillComment, name: '$bill: ${AppLocale.labels.description}'),
58 0 : ListSelectorItem(id: attrBillUuid, name: '$bill: ${AppLocale.labels.uuid}'),
59 : ];
60 0 : mapping.sort((a, b) => a.name.compareTo(b.name));
61 : return mapping;
62 : }
63 :
64 0 : Future<InterfaceAppData> parseFileLine(List<dynamic> line, Map<String, dynamic> def) async {
65 0 : final defaultAccount = def[attrAccountName];
66 0 : final defaultBudget = def[attrCategoryName];
67 0 : final dateFormat = def[defDateFormat];
68 0 : _defaultCurrency = def[attrBillCurrency];
69 :
70 0 : dynamic amount = _get(line, attrBillAmount);
71 0 : if (amount is String) {
72 0 : amount = double.tryParse(amount);
73 : }
74 : dynamic newItem;
75 0 : dynamic account = await _find(AppDataType.accounts, line, _get(line, attrAccountName), defaultAccount);
76 0 : String? uuid = _get(line, attrBillUuid);
77 0 : String? dateValue = _get(line, attrBillDate);
78 : DateTime? date;
79 : if (dateValue != null) {
80 : try {
81 0 : date = DateFormat(dateFormat).parse(dateValue);
82 : } catch (e) {
83 0 : date = DateTime.parse(dateValue);
84 : }
85 : }
86 0 : if (_get(line, attrBillType) == AppLocale.labels.flowTypeInvoice) {
87 0 : newItem = InvoiceAppData(
88 : uuid: uuid,
89 : account: account,
90 0 : title: _get(line, attrBillComment).toString(),
91 0 : details: 0.0 + amount,
92 : createdAt: date,
93 : updatedAt: date,
94 0 : currency: _getCurrency(line, _defaultCurrency),
95 : hidden: false,
96 : );
97 : } else {
98 0 : newItem = BillAppData(
99 : uuid: uuid,
100 : account: account,
101 0 : category: await _find(AppDataType.budgets, line, _get(line, attrCategoryName), defaultBudget),
102 0 : title: _get(line, attrBillComment).toString(),
103 0 : details: 0.0 + amount,
104 : createdAt: date,
105 : updatedAt: date,
106 0 : currency: _getCurrency(line, _defaultCurrency),
107 : hidden: false,
108 : );
109 : }
110 : return newItem;
111 : }
112 :
113 0 : Future<String> _find(AppDataType type, List<dynamic> line, dynamic value, String? def) async {
114 : if (value == null) {
115 : return def ?? '';
116 : }
117 : String? uuid;
118 0 : if (_cache[type] == null) {
119 0 : _cache[type] = <String, String?>{};
120 : }
121 0 : if (_cache[type]?[value] != null) {
122 0 : uuid = _cache[type]?[value];
123 : } else {
124 0 : final item = search(type, value);
125 0 : uuid = item?.uuid;
126 0 : _cache[type]![value] = uuid ?? '';
127 : }
128 0 : return uuid ?? await _new(type, line, value);
129 : }
130 :
131 0 : Future<String> _new(AppDataType type, List<dynamic> line, dynamic value) async {
132 : InterfaceAppData newItem;
133 0 : if (type == AppDataType.accounts) {
134 0 : newItem = AccountAppData(
135 : title: value,
136 0 : type: AppAccountType.account.toString(),
137 : details: 0.0,
138 0 : currency: _getCurrency(line, _defaultCurrency),
139 : hidden: false,
140 : );
141 : } else {
142 0 : newItem = BudgetAppData(
143 : title: value,
144 0 : currency: _getCurrency(line, _defaultCurrency),
145 : hidden: false,
146 : );
147 : }
148 0 : newItem = add(newItem);
149 0 : _cache[type]![value] = newItem.uuid;
150 0 : return newItem.uuid!;
151 : }
152 :
153 0 : dynamic _get(List<dynamic> line, String type) {
154 0 : final index = columnMap.indexOf(type);
155 0 : return index >= 0 ? line[index] : null;
156 : }
157 :
158 0 : Currency? _getCurrency(List<dynamic> line, String? def) {
159 0 : return CurrencyProvider.find(_get(line, attrBillCurrency) ?? def);
160 : }
161 : }
|