#include "EventWindow.h" #include #include #include #include #include #include #include "dao/EventDAO.h" #include "net/NetworkService.h" static constexpr int COL_ID = 0; static constexpr int COL_TIME = 1; static constexpr int COL_TYPE = 2; static constexpr int COL_BANK = 3; static constexpr int COL_DEVICE = 4; static constexpr int COL_STATUS = 5; static constexpr int COL_AMOUNT = 6; static constexpr int COL_COMMENT = 7; static constexpr int COL_ACTION = 8; static void sendErrorToServer(const QString &type, const QString &materialId, const QString &bankName) { QJsonObject errData; errData["status"] = "error"; errData["description"] = "Closed manually"; QJsonObject obj; obj["type"] = type; obj["material_id"] = materialId; obj["bank_name"] = bankName; obj["data"] = errData; auto *thread = new QThread; auto *networkService = new NetworkService; networkService->moveToThread(thread); networkService->setPayload(QJsonDocument(obj).toJson()); QObject::connect(thread, &QThread::started, networkService, &NetworkService::postTaskResult); QObject::connect(networkService, &NetworkService::finished, thread, &QThread::quit); QObject::connect(networkService, &NetworkService::finished, networkService, &QObject::deleteLater); QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater); thread->start(); } static QString statusDisplayName(EventStatus s) { switch (s) { case EventStatus::Wait: return "Ожидание"; case EventStatus::InProgress: return "В работе"; case EventStatus::Complete: return "Завершено"; case EventStatus::Error: return "Ошибка"; default: return "—"; } } static QString typeDisplayName(EventType t) { switch (t) { case EventType::FetchProfile: return "Профиль"; case EventType::FetchTransactions: return "Транзакции"; case EventType::CreateTransaction: return "Платёж"; default: return "—"; } } EventWindow::EventWindow(QWidget *parent) : QDialog(parent) { setWindowTitle("События"); resize(1100, 600); // ── Таблица ─────────────────────────────────────────────────────────────── m_table = new QTableWidget(this); m_table->setColumnCount(9); m_table->setHorizontalHeaderLabels({ "#", "Время", "Тип", "Банк", "Устройство", "Статус", "Сумма", "Комментарий", "" }); m_table->setEditTriggers(QAbstractItemView::NoEditTriggers); m_table->setSelectionBehavior(QAbstractItemView::SelectRows); m_table->setSelectionMode(QAbstractItemView::SingleSelection); m_table->verticalHeader()->hide(); m_table->horizontalHeader()->setStretchLastSection(true); m_table->setColumnWidth(COL_ID, 45); m_table->setColumnWidth(COL_TIME, 145); m_table->setColumnWidth(COL_TYPE, 100); m_table->setColumnWidth(COL_BANK, 90); m_table->setColumnWidth(COL_DEVICE, 120); m_table->setColumnWidth(COL_STATUS, 100); m_table->setColumnWidth(COL_AMOUNT, 80); m_table->setColumnWidth(COL_ACTION, 80); // ── Пагинация ───────────────────────────────────────────────────────────── m_prevBtn = new QPushButton("←", this); m_nextBtn = new QPushButton("→", this); m_pageLabel = new QLabel(this); m_pageLabel->setAlignment(Qt::AlignCenter); m_pageLabel->setMinimumWidth(140); auto *refreshBtn = new QPushButton("Обновить", this); auto *paginationLayout = new QHBoxLayout; paginationLayout->addWidget(m_prevBtn); paginationLayout->addWidget(m_pageLabel); paginationLayout->addWidget(m_nextBtn); paginationLayout->addStretch(); paginationLayout->addWidget(refreshBtn); auto *mainLayout = new QVBoxLayout(this); mainLayout->addWidget(m_table, 1); mainLayout->addLayout(paginationLayout); // ── Сигналы ─────────────────────────────────────────────────────────────── connect(m_prevBtn, &QPushButton::clicked, this, [this]() { if (m_page > 0) { --m_page; loadPage(); } }); connect(m_nextBtn, &QPushButton::clicked, this, [this]() { if (m_page < m_totalPages - 1) { ++m_page; loadPage(); } }); connect(refreshBtn, &QPushButton::clicked, this, [this]() { m_page = 0; loadPage(); }); loadPage(); } void EventWindow::loadPage() { const int total = EventDAO::getTotalCount(); m_totalPages = qMax(1, (total + m_pageSize - 1) / m_pageSize); m_page = qBound(0, m_page, m_totalPages - 1); const QList events = EventDAO::getEvents(m_page, m_pageSize); m_table->setRowCount(static_cast(events.size())); for (int i = 0; i < events.size(); ++i) { const auto &e = events[i]; m_table->setItem(i, COL_ID, new QTableWidgetItem(QString::number(e.id))); m_table->setItem(i, COL_TIME, new QTableWidgetItem( e.timestamp.toLocalTime().toString("dd.MM.yy HH:mm:ss"))); m_table->setItem(i, COL_TYPE, new QTableWidgetItem(typeDisplayName(e.type))); m_table->setItem(i, COL_BANK, new QTableWidgetItem(e.bankName)); m_table->setItem(i, COL_DEVICE, new QTableWidgetItem(e.deviceId)); m_table->setItem(i, COL_STATUS, new QTableWidgetItem(statusDisplayName(e.status))); m_table->setItem(i, COL_AMOUNT, new QTableWidgetItem( e.amount > 0 ? QString::number(e.amount, 'f', 2) : "—")); m_table->setItem(i, COL_COMMENT, new QTableWidgetItem(e.comment)); // Подсветка строки по статусу QColor bg; switch (e.status) { case EventStatus::Error: bg = QColor(255, 230, 230); break; case EventStatus::Complete: bg = QColor(230, 255, 230); break; case EventStatus::InProgress: bg = QColor(230, 240, 255); break; default: bg = QColor(255, 255, 230); break; } for (int col = 0; col < m_table->columnCount(); ++col) { if (auto *item = m_table->item(i, col)) item->setBackground(bg); } // Кнопка "Закрыть" только для активных задач if (e.status == EventStatus::Wait || e.status == EventStatus::InProgress) { auto *closeBtn = new QPushButton("Закрыть"); closeBtn->setStyleSheet("background: #e74c3c; color: white; border: none; padding: 3px 8px; border-radius: 3px;"); const int eventId = e.id; const QString externalId = e.externalId; const QString bankName = e.bankName; const QString typeStr = eventTypeToString(e.type); connect(closeBtn, &QPushButton::clicked, this, [this, eventId, externalId, bankName, typeStr]() { EventDAO::updateEvent(eventId, EventStatus::Error, "Closed manually"); sendErrorToServer(typeStr, externalId, bankName); loadPage(); }); m_table->setCellWidget(i, COL_ACTION, closeBtn); } } updatePagination(); } void EventWindow::updatePagination() { m_pageLabel->setText(QString("Страница %1 из %2").arg(m_page + 1).arg(m_totalPages)); m_prevBtn->setEnabled(m_page > 0); m_nextBtn->setEnabled(m_page < m_totalPages - 1); }