mnemo_cards/mnemo_cards_backend/lib/database/daos/payment_dao.dart

154 lines
5.1 KiB
Dart
Raw Normal View History

2025-12-13 13:27:05 +00:00
import 'package:drift/drift.dart';
2025-12-13 23:35:14 +00:00
import 'package:drift_postgres/drift_postgres.dart';
2025-12-13 13:27:05 +00:00
import '../database.dart';
import '../tables/payments.dart';
part 'payment_dao.g.dart';
@DriftAccessor(tables: [Payments])
class PaymentDao extends DatabaseAccessor<AppDatabase> with _$PaymentDaoMixin {
PaymentDao(super.db);
/// Получить платеж по ID
2025-12-13 20:55:50 +00:00
Future<Payment?> getPaymentById(String id) {
2025-12-13 13:27:05 +00:00
return (select(payments)..where((p) => p.id.equals(id))).getSingleOrNull();
}
/// Получить платежи пользователя
2025-12-13 20:55:50 +00:00
Future<List<Payment>> getPaymentsByUserId(String userId, {
2025-12-13 13:27:05 +00:00
int? limit,
int? offset,
}) {
final query = select(payments)
..where((p) => p.userId.equals(userId))
..orderBy([(p) => OrderingTerm.desc(p.date)]);
if (limit != null) {
query.limit(limit, offset: offset);
}
return query.get();
}
/// Получить платежи по статусу
Future<List<Payment>> getPaymentsByStatus(String status) {
return (select(payments)
..where((p) => p.status.equals(status))
..orderBy([(p) => OrderingTerm.desc(p.date)])
).get();
}
/// Создать платеж
2025-12-13 20:55:50 +00:00
Future<String> createPayment(PaymentsCompanion payment) async {
final inserted = await into(payments).insertReturning(payment);
// Query back to get the id since Payment class doesn't have id field
// (database needs to be regenerated to include id in Payment class)
// Use externalToken if available, otherwise query by unique fields
if (inserted.externalToken != null && inserted.externalToken!.isNotEmpty) {
final result = await (customSelect(
'SELECT id FROM payments WHERE external_token = ? LIMIT 1',
variables: [Variable.withString(inserted.externalToken!)],
readsFrom: {payments},
).map((row) => row.read<String>('id')).getSingleOrNull());
if (result != null) return result;
}
// Fallback: query by userId, date, and amount
final result = await (customSelect(
'SELECT id FROM payments WHERE user_id = ? AND date = ? AND amount = ? ORDER BY created_at DESC LIMIT 1',
variables: [
Variable.withString(payment.userId.value),
2025-12-13 23:35:14 +00:00
Variable.withDateTime(inserted.date.dateTime),
2025-12-13 20:55:50 +00:00
Variable.withString(inserted.amount),
],
readsFrom: {payments},
).map((row) => row.read<String>('id')).getSingleOrNull());
if (result != null) return result;
throw Exception('Failed to retrieve payment ID after creation');
2025-12-13 13:27:05 +00:00
}
/// Обновить платеж
Future<bool> updatePayment(Payment payment) {
return update(payments).replace(payment);
}
/// Обновить платеж частично
2025-12-13 20:55:50 +00:00
Future<void> updatePaymentCompanion(String paymentId, PaymentsCompanion companion) {
2025-12-13 13:27:05 +00:00
return (update(payments)..where((p) => p.id.equals(paymentId)))
.write(companion);
}
/// Обновить статус платежа
2025-12-13 20:55:50 +00:00
Future<void> updatePaymentStatus(String paymentId, String status) {
2025-12-13 13:27:05 +00:00
return (update(payments)..where((p) => p.id.equals(paymentId)))
.write(PaymentsCompanion(
status: Value(status),
2025-12-13 23:35:14 +00:00
updatedAt: Value(PgDateTime(DateTime.now())),
2025-12-13 13:27:05 +00:00
));
}
/// Подсчитать платежи пользователя
2025-12-13 20:55:50 +00:00
Future<int> countPaymentsByUserId(String userId) async {
2025-12-13 13:27:05 +00:00
final countExpr = payments.id.count();
final query = selectOnly(payments)
..addColumns([countExpr])
..where(payments.userId.equals(userId));
return await query.map((row) => row.read(countExpr)!).getSingle();
}
/// Получить платеж по externalToken
Future<Payment?> getPaymentByExternalToken(String token) {
return (select(payments)..where((p) => p.externalToken.equals(token)))
.getSingleOrNull();
}
/// Получить платежи по продукту (store ID)
Future<List<Payment>> getPaymentsByProduct(String productId) async {
// Поиск по продуктам в JSON массиве
final query = select(payments)
..where((p) => p.products.like('%$productId%'));
return query.get();
}
/// Получить платежи по статусу с пагинацией
Future<List<Payment>> getPaymentsByStatusPaged(
String status, {
int? limit,
int? offset,
}) {
final query = select(payments)
..where((p) => p.status.equals(status))
..orderBy([(p) => OrderingTerm.desc(p.date)]);
if (limit != null) {
query.limit(limit, offset: offset);
}
return query.get();
}
/// Получить все платежи (для админки)
Future<List<Payment>> getAllPayments({
int? limit,
int? offset,
}) {
final query = select(payments)
..orderBy([(p) => OrderingTerm.desc(p.date)]);
if (limit != null) {
query.limit(limit, offset: offset);
}
return query.get();
}
/// Подсчитать все платежи
Future<int> countAllPayments() async {
final countExpr = payments.id.count();
final query = selectOnly(payments)..addColumns([countExpr]);
return await query.map((row) => row.read(countExpr)!).getSingle();
}
}