payment quotation v2 + payment orchestration v2 draft
This commit is contained in:
@@ -8,7 +8,6 @@ import 'package:pshared/provider/resource.dart';
|
||||
import 'package:pshared/service/payment/service.dart';
|
||||
import 'package:pshared/utils/exception.dart';
|
||||
|
||||
|
||||
class PaymentsProvider with ChangeNotifier {
|
||||
static const Duration _pendingRefreshInterval = Duration(seconds: 10);
|
||||
|
||||
@@ -20,8 +19,9 @@ class PaymentsProvider with ChangeNotifier {
|
||||
bool _isLoadingMore = false;
|
||||
String? _nextCursor;
|
||||
int? _limit;
|
||||
String? _sourceRef;
|
||||
String? _destinationRef;
|
||||
String? _quotationRef;
|
||||
DateTime? _createdFrom;
|
||||
DateTime? _createdTo;
|
||||
List<String>? _states;
|
||||
|
||||
int _opSeq = 0;
|
||||
@@ -32,7 +32,8 @@ class PaymentsProvider with ChangeNotifier {
|
||||
List<Payment> get payments => _resource.data ?? [];
|
||||
bool get isLoading => _resource.isLoading;
|
||||
Exception? get error => _resource.error;
|
||||
bool get isReady => _isLoaded && !_resource.isLoading && _resource.error == null;
|
||||
bool get isReady =>
|
||||
_isLoaded && !_resource.isLoading && _resource.error == null;
|
||||
|
||||
bool get isLoadingMore => _isLoadingMore;
|
||||
String? get nextCursor => _nextCursor;
|
||||
@@ -54,14 +55,16 @@ class PaymentsProvider with ChangeNotifier {
|
||||
|
||||
Future<void> refresh({
|
||||
int? limit,
|
||||
String? sourceRef,
|
||||
String? destinationRef,
|
||||
String? quotationRef,
|
||||
DateTime? createdFrom,
|
||||
DateTime? createdTo,
|
||||
List<String>? states,
|
||||
}) async {
|
||||
await _refresh(
|
||||
limit: limit,
|
||||
sourceRef: sourceRef,
|
||||
destinationRef: destinationRef,
|
||||
quotationRef: quotationRef,
|
||||
createdFrom: createdFrom,
|
||||
createdTo: createdTo,
|
||||
states: states,
|
||||
showLoading: true,
|
||||
updateError: true,
|
||||
@@ -70,14 +73,16 @@ class PaymentsProvider with ChangeNotifier {
|
||||
|
||||
Future<void> refreshSilently({
|
||||
int? limit,
|
||||
String? sourceRef,
|
||||
String? destinationRef,
|
||||
String? quotationRef,
|
||||
DateTime? createdFrom,
|
||||
DateTime? createdTo,
|
||||
List<String>? states,
|
||||
}) async {
|
||||
await _refresh(
|
||||
limit: limit,
|
||||
sourceRef: sourceRef,
|
||||
destinationRef: destinationRef,
|
||||
quotationRef: quotationRef,
|
||||
createdFrom: createdFrom,
|
||||
createdTo: createdTo,
|
||||
states: states,
|
||||
showLoading: false,
|
||||
updateError: false,
|
||||
@@ -87,10 +92,7 @@ class PaymentsProvider with ChangeNotifier {
|
||||
void mergePayments(List<Payment> incoming) {
|
||||
if (incoming.isEmpty) return;
|
||||
final existing = List<Payment>.from(_resource.data ?? const []);
|
||||
final combined = <Payment>[
|
||||
...incoming,
|
||||
...existing,
|
||||
];
|
||||
final combined = <Payment>[...incoming, ...existing];
|
||||
final seen = <String>{};
|
||||
final merged = <Payment>[];
|
||||
|
||||
@@ -110,8 +112,9 @@ class PaymentsProvider with ChangeNotifier {
|
||||
|
||||
Future<void> _refresh({
|
||||
int? limit,
|
||||
String? sourceRef,
|
||||
String? destinationRef,
|
||||
String? quotationRef,
|
||||
DateTime? createdFrom,
|
||||
DateTime? createdTo,
|
||||
List<String>? states,
|
||||
required bool showLoading,
|
||||
required bool updateError,
|
||||
@@ -120,8 +123,9 @@ class PaymentsProvider with ChangeNotifier {
|
||||
if (org == null || !org.isOrganizationSet) return;
|
||||
|
||||
_limit = limit;
|
||||
_sourceRef = _normalize(sourceRef);
|
||||
_destinationRef = _normalize(destinationRef);
|
||||
_quotationRef = _normalize(quotationRef);
|
||||
_createdFrom = createdFrom?.toUtc();
|
||||
_createdTo = createdTo?.toUtc();
|
||||
_states = _normalizeStates(states);
|
||||
_nextCursor = null;
|
||||
_isLoadingMore = false;
|
||||
@@ -129,7 +133,10 @@ class PaymentsProvider with ChangeNotifier {
|
||||
final seq = ++_opSeq;
|
||||
|
||||
if (showLoading) {
|
||||
_applyResource(_resource.copyWith(isLoading: true, error: null), notify: true);
|
||||
_applyResource(
|
||||
_resource.copyWith(isLoading: true, error: null),
|
||||
notify: true,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -137,8 +144,9 @@ class PaymentsProvider with ChangeNotifier {
|
||||
org.current.id,
|
||||
limit: _limit,
|
||||
cursor: null,
|
||||
sourceRef: _sourceRef,
|
||||
destinationRef: _destinationRef,
|
||||
quotationRef: _quotationRef,
|
||||
createdFrom: _createdFrom,
|
||||
createdTo: _createdTo,
|
||||
states: _states,
|
||||
);
|
||||
|
||||
@@ -147,11 +155,7 @@ class PaymentsProvider with ChangeNotifier {
|
||||
_isLoaded = true;
|
||||
_nextCursor = _normalize(page.nextCursor);
|
||||
_applyResource(
|
||||
Resource(
|
||||
data: page.items,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
),
|
||||
Resource(data: page.items, isLoading: false, error: null),
|
||||
notify: true,
|
||||
);
|
||||
} catch (e) {
|
||||
@@ -162,10 +166,7 @@ class PaymentsProvider with ChangeNotifier {
|
||||
notify: true,
|
||||
);
|
||||
} else if (showLoading) {
|
||||
_applyResource(
|
||||
_resource.copyWith(isLoading: false),
|
||||
notify: true,
|
||||
);
|
||||
_applyResource(_resource.copyWith(isLoading: false), notify: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,8 +190,9 @@ class PaymentsProvider with ChangeNotifier {
|
||||
org.current.id,
|
||||
limit: _limit,
|
||||
cursor: cursor,
|
||||
sourceRef: _sourceRef,
|
||||
destinationRef: _destinationRef,
|
||||
quotationRef: _quotationRef,
|
||||
createdFrom: _createdFrom,
|
||||
createdTo: _createdTo,
|
||||
states: _states,
|
||||
);
|
||||
|
||||
@@ -206,10 +208,7 @@ class PaymentsProvider with ChangeNotifier {
|
||||
} catch (e) {
|
||||
if (seq != _opSeq) return;
|
||||
|
||||
_applyResource(
|
||||
_resource.copyWith(error: toException(e)),
|
||||
notify: false,
|
||||
);
|
||||
_applyResource(_resource.copyWith(error: toException(e)), notify: false);
|
||||
} finally {
|
||||
if (seq == _opSeq) {
|
||||
_isLoadingMore = false;
|
||||
@@ -224,15 +223,19 @@ class PaymentsProvider with ChangeNotifier {
|
||||
_isLoadingMore = false;
|
||||
_nextCursor = null;
|
||||
_limit = null;
|
||||
_sourceRef = null;
|
||||
_destinationRef = null;
|
||||
_quotationRef = null;
|
||||
_createdFrom = null;
|
||||
_createdTo = null;
|
||||
_states = null;
|
||||
_resource = Resource(data: []);
|
||||
_stopPendingRefreshTimer();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void _applyResource(Resource<List<Payment>> newResource, {required bool notify}) {
|
||||
void _applyResource(
|
||||
Resource<List<Payment>> newResource, {
|
||||
required bool notify,
|
||||
}) {
|
||||
_resource = newResource;
|
||||
_syncPendingRefresh();
|
||||
if (notify) notifyListeners();
|
||||
@@ -253,15 +256,15 @@ class PaymentsProvider with ChangeNotifier {
|
||||
List<String>? _normalizeStates(List<String>? states) {
|
||||
if (states == null || states.isEmpty) return null;
|
||||
final normalized = states
|
||||
.map((state) => state.trim())
|
||||
.where((state) => state.isNotEmpty)
|
||||
.toList();
|
||||
.map((state) => state.trim())
|
||||
.where((state) => state.isNotEmpty)
|
||||
.toList();
|
||||
if (normalized.isEmpty) return null;
|
||||
return normalized;
|
||||
}
|
||||
|
||||
void _syncPendingRefresh() {
|
||||
final hasPending = payments.any(_isPending);
|
||||
final hasPending = payments.any((payment) => payment.isPending);
|
||||
if (!hasPending) {
|
||||
_stopPendingRefreshTimer();
|
||||
return;
|
||||
@@ -286,8 +289,9 @@ class PaymentsProvider with ChangeNotifier {
|
||||
try {
|
||||
await refreshSilently(
|
||||
limit: _limit,
|
||||
sourceRef: _sourceRef,
|
||||
destinationRef: _destinationRef,
|
||||
quotationRef: _quotationRef,
|
||||
createdFrom: _createdFrom,
|
||||
createdTo: _createdTo,
|
||||
states: _states,
|
||||
);
|
||||
} finally {
|
||||
@@ -301,29 +305,9 @@ class PaymentsProvider with ChangeNotifier {
|
||||
_isPendingRefreshInFlight = false;
|
||||
}
|
||||
|
||||
bool _isPending(Payment payment) {
|
||||
final raw = payment.state;
|
||||
final trimmed = (raw ?? '').trim().toUpperCase();
|
||||
final normalized = trimmed.startsWith('PAYMENT_STATE_')
|
||||
? trimmed.substring('PAYMENT_STATE_'.length)
|
||||
: trimmed;
|
||||
|
||||
switch (normalized) {
|
||||
case 'SUCCESS':
|
||||
case 'FAILED':
|
||||
case 'CANCELLED':
|
||||
return false;
|
||||
case 'PROCESSING':
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_stopPendingRefreshTimer();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user