mnemo_cards/mnemo_cards_backend/lib/database/daos/payment_dao.dart
Dmitry 39eeda7fa7
Some checks failed
Backend CI / test (push) Has been cancelled
Deploy Mnemo Cards / Deploy Backend (push) Has been cancelled
Backend CI / build (push) Has been cancelled
Deploy Mnemo Cards / Deploy Web App (push) Has been cancelled
Deploy Mnemo Cards / Final Verification (push) Has been cancelled
back fix
2026-01-03 17:48:57 +03:00

168 lines
5.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:drift/drift.dart';
import 'package:drift_postgres/drift_postgres.dart';
import '../database.dart';
import '../tables/payments.dart';
import 'mixins/soft_delete_mixin.dart';
part 'payment_dao.g.dart';
@DriftAccessor(tables: [Payments])
class PaymentDao extends DatabaseAccessor<AppDatabase>
with _$PaymentDaoMixin, SoftDeleteMixin<Payments, Payment> {
PaymentDao(super.db);
@override
TableInfo<Payments, Payment> get table => payments;
/// Получить платеж по ID (только активные)
Future<Payment?> getPaymentById(String id) {
return getActiveById(id);
}
/// Получить платежи пользователя (только активные)
Future<List<Payment>> getPaymentsByUserId(
String userId, {
int? limit,
int? offset,
}) {
final query = selectActive()
..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 (selectActive()
..where((p) => p.status.equals(status))
..orderBy([(p) => OrderingTerm.desc(p.date)]))
.get();
}
/// Создать платеж
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),
Variable.withDateTime(inserted.date.dateTime),
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');
}
/// Обновить платеж
Future<bool> updatePayment(Payment payment) {
return update(payments).replace(payment);
}
/// Обновить платеж частично
Future<void> updatePaymentCompanion(
String paymentId,
PaymentsCompanion companion,
) {
return (update(
payments,
)..where((p) => p.id.equals(paymentId))).write(companion);
}
/// Обновить статус платежа
Future<void> updatePaymentStatus(String paymentId, String status) {
return (update(payments)..where((p) => p.id.equals(paymentId))).write(
PaymentsCompanion(
status: Value(status),
updatedAt: Value(PgDateTime(DateTime.now())),
),
);
}
/// Получить платеж по externalToken (только активные)
Future<Payment?> getPaymentByExternalToken(String token) async {
final query = selectActive()
..where((p) => p.externalToken.equals(token))
..limit(1);
final results = await query.get();
return results.isNotEmpty ? results.first : null;
}
/// Получить платежи по продукту (store ID) (только активные)
Future<List<Payment>> getPaymentsByProduct(String productId) async {
// Поиск по продуктам в JSON массиве
final query = selectActive()..where((p) => p.products.like('%$productId%'));
return query.get();
}
/// Получить платежи по статусу с пагинацией (только активные)
Future<List<Payment>> getPaymentsByStatusPaged(
String status, {
int? limit,
int? offset,
}) {
final query = selectActive()
..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 = selectActive()..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])
..where(payments.isDeleted.equals(false));
return await query.map((row) => row.read(countExpr)!).getSingle();
}
/// Подсчитать платежи пользователя (только активные)
@override
Future<int> countPaymentsByUserId(String userId) async {
final countExpr = payments.id.count();
final query = selectOnly(payments)
..addColumns([countExpr])
..where(
payments.userId.equals(userId) & payments.isDeleted.equals(false),
);
return await query.map((row) => row.read(countExpr)!).getSingle();
}
}