LCOV - code coverage report
Current view: top level - lib/_classes/integration/fints - fints_settings.dart Coverage Total Hit
Test: lcov.info Lines: 0.0 % 49 0
Test Date: 2026-11-14 15:08:11 Functions: - 0 0

            Line data    Source code
       1              : // Copyright 2026 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:convert';
       5              : 
       6              : import 'package:app_finance/_classes/controller/encryption_handler.dart';
       7              : import 'package:app_finance/_classes/storage/app_preferences.dart';
       8              : import 'package:fints/fints.dart';
       9              : 
      10              : // Connection details of a FinTS 4.1 bank access, kept between sessions
      11              : // The PIN is never part of it - asked for on each connection
      12              : class FinTsSettings {
      13              :   // Product registration ID of the Deutsche Kreditwirtschaft
      14              :   // TBD: inject on build `--dart-define=FINTS_PRODUCT_ID=...`
      15              :   static const defaultProductId = String.fromEnvironment('FINTS_PRODUCT_ID');
      16              : 
      17              :   static const namespaces = {
      18              :     '4.1.1': FinTs4Namespaces.v411,
      19              :     '4.1': FinTs4Namespaces.v41,
      20              :   };
      21              : 
      22              :   String url;
      23              :   String bankCode;
      24              :   String userId;
      25              :   String customerId;
      26              :   String productId;
      27              :   String version;
      28              : 
      29              :   /// Bank account (accountKey) to the uuid of the application's account
      30              :   final Map<String, String> links;
      31              : 
      32              :   /// Bank account (accountKey) to the last day transactions were imported for
      33              :   final Map<String, DateTime> imported;
      34              : 
      35            0 :   FinTsSettings({
      36              :     this.url = '',
      37              :     this.bankCode = '',
      38              :     this.userId = '',
      39              :     this.customerId = '',
      40              :     this.productId = defaultProductId,
      41              :     this.version = '4.1.1',
      42              :     Map<String, String>? links,
      43              :     Map<String, DateTime>? imported,
      44            0 :   })  : links = links ?? {},
      45            0 :         imported = imported ?? {};
      46              : 
      47            0 :   bool get isComplete => url.isNotEmpty && bankCode.isNotEmpty && userId.isNotEmpty && productId.isNotEmpty;
      48              : 
      49            0 :   FinTs4Namespaces get namespace => namespaces[version] ?? FinTs4Namespaces.v411;
      50              : 
      51            0 :   FinTsConfig toConfig() => FinTsConfig(
      52            0 :         url: Uri.parse(url.trim()),
      53            0 :         bankCode: bankCode.trim(),
      54            0 :         userId: userId.trim(),
      55            0 :         customerId: customerId.trim().isEmpty ? null : customerId.trim(),
      56            0 :         productId: productId.trim(),
      57              :       );
      58              : 
      59            0 :   static String accountKey(Account account) {
      60            0 :     final iban = account.iban?.replaceAll(' ', '').toUpperCase();
      61            0 :     if (iban != null && iban.isNotEmpty) {
      62              :       return iban;
      63              :     }
      64            0 :     return [account.bankCode, account.accountNumber ?? '', account.subAccount ?? ''].join(':');
      65              :   }
      66              : 
      67            0 :   Map<String, dynamic> toJson() => {
      68            0 :         'url': url,
      69            0 :         'bankCode': bankCode,
      70            0 :         'userId': userId,
      71            0 :         'customerId': customerId,
      72            0 :         'productId': productId,
      73            0 :         'version': version,
      74            0 :         'links': links,
      75            0 :         'imported': imported.map((key, value) => MapEntry(key, value.toIso8601String())),
      76              :       };
      77              : 
      78            0 :   factory FinTsSettings.fromJson(Map<String, dynamic> json) => FinTsSettings(
      79            0 :         url: json['url'] ?? '',
      80            0 :         bankCode: json['bankCode'] ?? '',
      81            0 :         userId: json['userId'] ?? '',
      82            0 :         customerId: json['customerId'] ?? '',
      83            0 :         productId: (json['productId'] as String?)?.isNotEmpty == true ? json['productId'] : defaultProductId,
      84            0 :         version: namespaces.containsKey(json['version']) ? json['version'] : '4.1.1',
      85            0 :         links: (json['links'] as Map<String, dynamic>? ?? {}).map((key, value) => MapEntry(key, value.toString())),
      86            0 :         imported: (json['imported'] as Map<String, dynamic>? ?? {}).map(
      87            0 :           (key, value) => MapEntry(key, DateTime.parse(value.toString())),
      88              :         ),
      89              :       );
      90              : 
      91            0 :   static FinTsSettings load() {
      92            0 :     final value = AppPreferences.get(AppPreferences.prefFinTs);
      93            0 :     if (value == null || value.isEmpty) {
      94            0 :       return FinTsSettings();
      95              :     }
      96              :     try {
      97            0 :       return FinTsSettings.fromJson(jsonDecode(value));
      98            0 :     } on FormatException {
      99            0 :       return FinTsSettings();
     100              :     }
     101              :   }
     102              : 
     103            0 :   Future<void> save() => AppPreferences.set(AppPreferences.prefFinTs, jsonEncode(toJson()));
     104              : 
     105            0 :   static String? loadState() {
     106            0 :     final value = AppPreferences.get(AppPreferences.prefFinTsState);
     107            0 :     if (value == null || value.isEmpty) {
     108              :       return null;
     109              :     }
     110              :     try {
     111            0 :       return EncryptionHandler.decrypt(value);
     112              :     } catch (_) {
     113              :       return null;
     114              :     }
     115              :   }
     116              : 
     117            0 :   static Future<void> saveState(String state) =>
     118            0 :       AppPreferences.set(AppPreferences.prefFinTsState, EncryptionHandler.encrypt(state));
     119              : 
     120            0 :   static Future<void> clearState() => AppPreferences.clear(AppPreferences.prefFinTsState);
     121              : }
        

Generated by: LCOV version 2.0-1