Files
sendico/frontend/pshared/lib/provider/recipient/pmethods.dart

105 lines
3.9 KiB
Dart

import 'package:collection/collection.dart';
import 'package:pshared/data/mapper/payment/method.dart';
import 'package:pshared/models/describable.dart';
import 'package:pshared/models/organization/bound.dart';
import 'package:pshared/models/payment/methods/data.dart';
import 'package:pshared/models/payment/methods/type.dart';
import 'package:pshared/models/payment/type.dart';
import 'package:pshared/models/recipient/recipient.dart';
import 'package:pshared/models/permissions/bound.dart';
import 'package:pshared/models/storable.dart';
import 'package:pshared/provider/organizations.dart';
import 'package:pshared/provider/recipient/provider.dart';
import 'package:pshared/provider/template.dart';
import 'package:pshared/service/recipient/pmethods.dart';
class PaymentMethodsProvider extends GenericProvider<PaymentMethod> {
late OrganizationsProvider _organizations;
PaymentMethodsProvider() : super(service: PaymentMethodService.basicService);
List<PaymentMethod> get methods => List<PaymentMethod>.unmodifiable(items.toList()..sort((a, b) => a.storable.createdAt.compareTo(b.storable.createdAt)));
List<PaymentMethod> methodsForRecipient(Recipient? recipient) {
if (recipient == null || !isReady) return [];
return methods
.where((method) => !method.isArchived && method.recipientRef == recipient.id)
.toList();
}
MethodMap availableTypesForRecipient(Recipient? recipient) => {
for (final method in methodsForRecipient(recipient)) method.type: method.data,
};
PaymentMethod? findMethodByType({
required PaymentType type,
required Recipient? recipient,
}) =>
methodsForRecipient(recipient).firstWhereOrNull((method) => method.type == type);
void updateProviders(OrganizationsProvider organizations, RecipientsProvider recipients) {
if (recipients.currentObject != null) loadMethods(organizations, recipients.currentObject?.id);
}
// TODO: current providers structure forces to use weird construction with in-place PaymentMethodsProviders
// it would be better to load reipients together with their payment methods in RecipientsProvider
Future<void> loadMethods(OrganizationsProvider organizations, String? recipientRef) async {
_organizations = organizations;
if (_organizations.isOrganizationSet && (recipientRef != null)) {
return load(_organizations.current.id, recipientRef);
}
}
// void reorderMethods(int oldIndex, int newIndex) {
// if (newIndex > oldIndex) newIndex--;
// final item = _methods.removeAt(oldIndex);
// _methods.insert(newIndex, item);
// notifyListeners();
// }
PaymentMethod? get main => methods.firstWhereOrNull((m) => m.isMain);
Future<void> updateMethod(PaymentMethod method) async => update(method.toDTO().toJson());
Future<void> setArchivedMethod({
required PaymentMethod method,
required bool newIsArchived,
}) async => setArchived(
organizationRef: _organizations.current.id,
objectRef: method.id,
newIsArchived: newIsArchived,
cascade: true,
);
Future<PaymentMethod> create({
required String reacipientRef,
required PaymentMethodData data,
required String name,
}) => createObject(
_organizations.current.id,
PaymentMethod(
storable: newStorable(),
permissionBound: newPermissionBound(
organizationBound: newOrganizationBound(organizationRef: _organizations.current.id),
),
recipientRef: reacipientRef,
data: data,
describable: newDescribable(name: name),
).toDTO().toJson(),
);
Future<void> makeMain(PaymentMethod method) {
// TODO: create separate backend method to manage main payment method
final updates = <Future<void>>[];
final currentMain = main;
if (currentMain != null) {
updates.add(updateMethod(currentMain.copyWith(isMain: false)));
}
updates.add(updateMethod(method.copyWith(isMain: true)));
return Future.wait(updates).then((_) => null);
}
}