reports page

This commit is contained in:
Arseni
2026-02-16 21:05:38 +03:00
parent 11d4b9a608
commit 0eea39fb97
56 changed files with 2227 additions and 501 deletions

View File

@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
class PayoutVolumesController extends ChangeNotifier {
DateTimeRange _range;
PayoutVolumesController({DateTime? now})
: _range = _defaultRange(now ?? DateTime.now());
DateTimeRange get range => _range;
void setRange(DateTimeRange range) {
final normalized = _normalizeRange(range);
if (_isSameRange(_range, normalized)) return;
_range = normalized;
notifyListeners();
}
static DateTimeRange _defaultRange(DateTime now) {
final local = now.toLocal();
final start = DateTime(local.year, local.month, 1);
final end = DateTime(
local.year,
local.month,
local.day,
);
return DateTimeRange(start: start, end: end);
}
static DateTimeRange _normalizeRange(DateTimeRange range) {
final start = DateTime(range.start.year, range.start.month, range.start.day);
final end = DateTime(
range.end.year,
range.end.month,
range.end.day,
);
return DateTimeRange(start: start, end: end);
}
static bool _isSameRange(DateTimeRange a, DateTimeRange b) {
return a.start.isAtSameMomentAs(b.start) &&
a.end.isAtSameMomentAs(b.end);
}
}

View File

@@ -0,0 +1,44 @@
import 'package:flutter/foundation.dart';
import 'package:pshared/models/payment/operation.dart';
import 'package:pshared/provider/payment/payments.dart';
import 'package:pweb/utils/report/operations.dart';
import 'package:pweb/utils/report/payment_mapper.dart';
class RecentPaymentsController extends ChangeNotifier {
PaymentsProvider? _payments;
List<OperationItem> _recent = const [];
List<OperationItem> get recentOperations => _recent;
bool get isLoading => _payments?.isLoading ?? false;
Exception? get error => _payments?.error;
void update(PaymentsProvider provider) {
if (!identical(_payments, provider)) {
_payments?.removeListener(_onPaymentsChanged);
_payments = provider;
_payments?.addListener(_onPaymentsChanged);
}
_rebuild();
}
void _onPaymentsChanged() {
_rebuild();
}
void _rebuild() {
final operations = (_payments?.payments ?? const [])
.map(mapPaymentToOperation)
.toList();
_recent = sortOperations(operations).take(5).toList();
notifyListeners();
}
@override
void dispose() {
_payments?.removeListener(_onPaymentsChanged);
super.dispose();
}
}

View File

@@ -0,0 +1,115 @@
import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:pshared/models/payment/operation.dart';
import 'package:pshared/models/payment/status.dart';
import 'package:pshared/provider/payment/payments.dart';
import 'package:pweb/utils/report/operations.dart';
import 'package:pweb/utils/report/payment_mapper.dart';
class ReportOperationsController extends ChangeNotifier {
PaymentsProvider? _payments;
DateTimeRange? _selectedRange;
final Set<OperationStatus> _selectedStatuses = {};
List<OperationItem> _operations = const [];
List<OperationItem> _filtered = const [];
List<OperationItem> get operations => _operations;
List<OperationItem> get filteredOperations => _filtered;
DateTimeRange? get selectedRange => _selectedRange;
Set<OperationStatus> get selectedStatuses =>
UnmodifiableSetView(_selectedStatuses);
bool get isLoading => _payments?.isLoading ?? false;
Exception? get error => _payments?.error;
void update(PaymentsProvider provider) {
if (!identical(_payments, provider)) {
_payments?.removeListener(_onPaymentsChanged);
_payments = provider;
_payments?.addListener(_onPaymentsChanged);
}
_rebuildOperations();
}
void setRange(DateTimeRange? range) {
if (_isSameRange(_selectedRange, range)) return;
_selectedRange = range;
_rebuildFiltered();
}
void toggleStatus(OperationStatus status) {
if (_selectedStatuses.contains(status)) {
_selectedStatuses.remove(status);
} else {
_selectedStatuses.add(status);
}
_rebuildFiltered();
}
void clearFilters() {
if (_selectedRange == null && _selectedStatuses.isEmpty) return;
_selectedRange = null;
_selectedStatuses.clear();
_rebuildFiltered();
}
Future<void> refresh() async {
await _payments?.refresh();
}
void _onPaymentsChanged() {
_rebuildOperations();
}
void _rebuildOperations() {
final items = _payments?.payments ?? const [];
_operations = items.map(mapPaymentToOperation).toList();
_rebuildFiltered(notify: true);
}
void _rebuildFiltered({bool notify = true}) {
_filtered = _applyFilters(_operations);
if (notify) {
notifyListeners();
}
}
List<OperationItem> _applyFilters(List<OperationItem> operations) {
if (_selectedRange == null && _selectedStatuses.isEmpty) {
return sortOperations(operations);
}
final filtered = operations.where((op) {
final statusMatch =
_selectedStatuses.isEmpty || _selectedStatuses.contains(op.status);
final dateMatch = _selectedRange == null ||
isUnknownDate(op.date) ||
(op.date.isAfter(
_selectedRange!.start.subtract(const Duration(seconds: 1)),
) &&
op.date.isBefore(
_selectedRange!.end.add(const Duration(seconds: 1)),
));
return statusMatch && dateMatch;
}).toList();
return sortOperations(filtered);
}
bool _isSameRange(DateTimeRange? left, DateTimeRange? right) {
if (left == null && right == null) return true;
if (left == null || right == null) return false;
return left.start.isAtSameMomentAs(right.start) &&
left.end.isAtSameMomentAs(right.end);
}
@override
void dispose() {
_payments?.removeListener(_onPaymentsChanged);
super.dispose();
}
}

View File

@@ -1,20 +0,0 @@
import 'package:pshared/models/payment/payment.dart';
class UploadHistoryTableController {
const UploadHistoryTableController();
String amountText(Payment payment) {
final receivedAmount = payment.lastQuote?.expectedSettlementAmount;
if (receivedAmount != null) {
return '${receivedAmount.amount} ${receivedAmount.currency}';
}
final fallbackAmount = payment.lastQuote?.debitAmount;
if (fallbackAmount != null) {
return '${fallbackAmount.amount} ${fallbackAmount.currency}';
}
return '-';
}
}