Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion assets/translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@
"export": "Exportieren",
"toPdf": "Als PDF",
"toExcel": "Als Excel",
"exportRequiresAccount": "Melden Sie sich an, um zu exportieren. Exporte werden auf dem Server erstellt.",
"exportAwaitingSync": "Synchronisieren Sie zuerst, damit der Export Ihre Anderungen enthalt.",
"exportPreparing": "Export wird vorbereitet...",
"family": "Familie",
"searchHint": "Suchen...",
"displaySettings": "Anzeigeeinstellungen",
Expand Down Expand Up @@ -924,4 +927,4 @@
"quarantinedHint": "Diese Änderungen sind dauerhaft fehlgeschlagen und werden nicht automatisch wiederholt. Nach Behebung der Ursache erneut versuchen oder verwerfen.",
"exchangeRateRequired": "Wechselkurs eingeben — kein aktueller Kurs verfügbar",
"currencySwitchRatesUnavailable": "Währungswechsel derzeit nicht möglich — Wechselkurse sind nicht verfügbar. Versuchen Sie es später erneut."
}
}
5 changes: 4 additions & 1 deletion assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@
"export": "Export",
"toPdf": "To PDF",
"toExcel": "To Excel",
"exportRequiresAccount": "Sign in to export. Exports are generated on the server.",
"exportAwaitingSync": "Sync your changes first so the export includes them.",
"exportPreparing": "Preparing your export...",
"family": "Family",
"searchHint": "Search...",
"displaySettings": "Display settings",
Expand Down Expand Up @@ -924,4 +927,4 @@
"budgetOf": "of",
"exchangeRateRequired": "Enter the exchange rate — no current rate is available",
"currencySwitchRatesUnavailable": "Can't switch currency right now — exchange rates are unavailable. Try again later."
}
}
5 changes: 4 additions & 1 deletion assets/translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@
"export": "Exportar",
"toPdf": "A PDF",
"toExcel": "A Excel",
"exportRequiresAccount": "Inicia sesion para exportar. Las exportaciones se generan en el servidor.",
"exportAwaitingSync": "Sincroniza tus cambios primero para que la exportacion los incluya.",
"exportPreparing": "Preparando la exportacion...",
"family": "Familia",
"searchHint": "Buscar...",
"totalIncome": "Ingresos totales",
Expand Down Expand Up @@ -924,4 +927,4 @@
"quarantinedHint": "Estos cambios fallaron permanentemente y no se reintentarán solos. Reinténtalos tras corregir la causa o descártalos.",
"exchangeRateRequired": "Introduce el tipo de cambio: no hay un tipo actual disponible",
"currencySwitchRatesUnavailable": "No se puede cambiar la moneda ahora: los tipos de cambio no están disponibles. Inténtalo de nuevo más tarde."
}
}
5 changes: 4 additions & 1 deletion assets/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@
"export": "Exporter",
"toPdf": "En PDF",
"toExcel": "En Excel",
"exportRequiresAccount": "Connectez-vous pour exporter. Les exports sont generes sur le serveur.",
"exportAwaitingSync": "Synchronisez vos modifications pour qu'elles figurent dans l'export.",
"exportPreparing": "Preparation de votre export...",
"family": "Famille",
"searchHint": "Rechercher...",
"totalIncome": "Revenu total",
Expand Down Expand Up @@ -924,4 +927,4 @@
"quarantinedHint": "Ces changements ont échoué définitivement et ne seront pas réessayés automatiquement. Réessayez-les après avoir corrigé la cause, ou ignorez-les.",
"exchangeRateRequired": "Saisissez le taux de change — aucun taux actuel disponible",
"currencySwitchRatesUnavailable": "Impossible de changer de devise pour le moment — les taux de change sont indisponibles. Réessayez plus tard."
}
}
5 changes: 4 additions & 1 deletion assets/translations/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@
"export": "Esporta",
"toPdf": "In PDF",
"toExcel": "In Excel",
"exportRequiresAccount": "Accedi per esportare. Le esportazioni vengono generate sul server.",
"exportAwaitingSync": "Sincronizza prima le modifiche cosi l'esportazione le includera.",
"exportPreparing": "Preparazione dell'esportazione...",
"family": "Famiglia",
"searchHint": "Cerca...",
"totalIncome": "Reddito totale",
Expand Down Expand Up @@ -924,4 +927,4 @@
"quarantinedHint": "Queste modifiche sono fallite definitivamente e non verranno ritentate automaticamente. Riprovale dopo aver corretto la causa oppure ignorale.",
"exchangeRateRequired": "Inserisci il tasso di cambio — nessun tasso attuale disponibile",
"currencySwitchRatesUnavailable": "Impossibile cambiare valuta al momento — i tassi di cambio non sono disponibili. Riprova più tardi."
}
}
5 changes: 4 additions & 1 deletion assets/translations/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@
"export": "Экспорт",
"toPdf": "В PDF",
"toExcel": "В Excel",
"exportRequiresAccount": "Войдите в аккаунт, чтобы экспортировать. Файлы создаются на сервере.",
"exportAwaitingSync": "Сначала синхронизируйте изменения, чтобы они попали в экспорт.",
"exportPreparing": "Подготовка экспорта...",
"family": "Семья",
"searchHint": "Поиск...",
"displaySettings": "Настройки отображения",
Expand Down Expand Up @@ -924,4 +927,4 @@
"quarantinedHint": "Эти изменения завершились с постоянной ошибкой и не будут повторяться автоматически. Повторите их после устранения причины или отклоните.",
"exchangeRateRequired": "Введите обменный курс — актуальный курс недоступен",
"currencySwitchRatesUnavailable": "Сейчас нельзя сменить валюту — обменные курсы недоступны. Повторите попытку позже."
}
}
62 changes: 62 additions & 0 deletions lib/data/datasources/export/export_remote_datasource.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import 'dart:typed_data';

import 'package:dio/dio.dart';
import 'package:injectable/injectable.dart';
import 'package:intl/intl.dart';

/// The file formats the export endpoints can produce.
enum ExportFormat {
pdf('pdf', 'application/pdf'),
xlsx('xlsx',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'),
csv('csv', 'text/csv');

const ExportFormat(this.key, this.mimeType);

final String key;
final String mimeType;
}

abstract class ExportRemoteDataSource {
/// Downloads the filtered transaction list. Filters mirror the list endpoint
/// so the file matches what the screen is showing.
Future<Uint8List> exportTransactions({
required ExportFormat format,
DateTime? from,
DateTime? to,
List<int> walletIds = const [],
List<int> categoryIds = const [],
});
}

@Injectable(as: ExportRemoteDataSource)
class ExportRemoteDataSourceImpl implements ExportRemoteDataSource {
final Dio dio;

ExportRemoteDataSourceImpl({required this.dio});

@override
Future<Uint8List> exportTransactions({
required ExportFormat format,
DateTime? from,
DateTime? to,
List<int> walletIds = const [],
List<int> categoryIds = const [],
}) async {
final response = await dio.get<List<int>>(
'transactions/export',
queryParameters: {
'format': format.key,
if (from != null) 'date_from': _ymd(from),
if (to != null) 'date_to': _ymd(to),
if (walletIds.isNotEmpty) 'wallet_ids': walletIds.join(','),
if (categoryIds.isNotEmpty) 'category_ids': categoryIds.join(','),
},
options: Options(responseType: ResponseType.bytes),
);

return Uint8List.fromList(response.data ?? []);
}

String _ymd(DateTime date) => DateFormat('yyyy-MM-dd').format(date);
}
34 changes: 34 additions & 0 deletions lib/data/repositories/export_repository_impl.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'dart:typed_data';

import 'package:fpdart/fpdart.dart';
import 'package:injectable/injectable.dart';
import 'package:trakli/core/error/failures/failures.dart';
import 'package:trakli/core/error/repository_error_handler.dart';
import 'package:trakli/data/datasources/export/export_remote_datasource.dart';
import 'package:trakli/domain/repositories/export_repository.dart';

@LazySingleton(as: ExportRepository)
class ExportRepositoryImpl implements ExportRepository {
final ExportRemoteDataSource _remote;

ExportRepositoryImpl(this._remote);

@override
Future<Either<Failure, Uint8List>> exportTransactions({
required ExportFormat format,
DateTime? from,
DateTime? to,
List<int> walletIds = const [],
List<int> categoryIds = const [],
}) {
return RepositoryErrorHandler.handleApiCall(
() => _remote.exportTransactions(
format: format,
from: from,
to: to,
walletIds: walletIds,
categoryIds: categoryIds,
),
);
}
}
Loading
Loading