From 7929f7c3513d3ab83ccbfbb4621cfaf7ed2be4a1 Mon Sep 17 00:00:00 2001 From: slava Date: Tue, 9 Jun 2026 00:18:57 +0500 Subject: [PATCH] Add delete profile functionality with UI integration, local cleanup, and server synchronization. --- database/dao/MaterialDAO.cpp | 12 ++++++ database/dao/MaterialDAO.h | 5 +++ services/net/NetworkService.cpp | 20 ++++++++++ services/net/NetworkService.h | 4 ++ views/bank/AccountSettingsWindow.cpp | 55 ++++++++++++++++++++++++++++ views/bank/AccountSettingsWindow.h | 1 + 6 files changed, 97 insertions(+) diff --git a/database/dao/MaterialDAO.cpp b/database/dao/MaterialDAO.cpp index e772136..685beff 100644 --- a/database/dao/MaterialDAO.cpp +++ b/database/dao/MaterialDAO.cpp @@ -426,3 +426,15 @@ bool MaterialDAO::deleteAccountsByApp(const QString &deviceId, const QString &ap } return true; } + +bool MaterialDAO::deleteAllAccountsByApp(const QString &deviceId, const QString &appCode) { + QSqlQuery query(DatabaseManager::instance().database()); + query.prepare("DELETE FROM materials WHERE device_id = :device_id AND app_code = :app_code"); + query.bindValue(":device_id", deviceId); + query.bindValue(":app_code", appCode); + if (!query.exec()) { + qWarning() << "[MaterialDAO] deleteAllAccountsByApp failed:" << query.lastError().text(); + return false; + } + return true; +} diff --git a/database/dao/MaterialDAO.h b/database/dao/MaterialDAO.h index e8b98f1..d9c47a3 100644 --- a/database/dao/MaterialDAO.h +++ b/database/dao/MaterialDAO.h @@ -59,4 +59,9 @@ public: [[nodiscard]] static bool migrateDeviceId(const QString &oldDeviceId, const QString &newDeviceId); [[nodiscard]] static bool deleteAccountsByApp(const QString &deviceId, const QString &appCode); + + // Удаляет ВСЕ счета (материалы) приложения, включая синхронизированные с + // сервером (material_id задан). Транзакции и события удаляются каскадом по + // materials.id. Используется при полном удалении банковского профиля. + [[nodiscard]] static bool deleteAllAccountsByApp(const QString &deviceId, const QString &appCode); }; diff --git a/services/net/NetworkService.cpp b/services/net/NetworkService.cpp index 940e5e2..ff38933 100644 --- a/services/net/NetworkService.cpp +++ b/services/net/NetworkService.cpp @@ -1219,6 +1219,26 @@ void NetworkService::patchBankProfile() { emit finished(); } +void NetworkService::deleteBankProfileFromServer() { + if (!ensureValidToken()) { emit finished(); return; } + + const QString bankProfileId = m_extraData.value("bank_profile_id").toString(); + if (bankProfileId.isEmpty()) { + qWarning() << "[NetworkService] deleteBankProfileFromServer: bank_profile_id is empty"; + emit finished(); + return; + } + + const QJsonValue result = deleteJson(m_apiBase + m_pathBankProfile + "/" + bankProfileId, true); + if (result.isUndefined()) { + qWarning() << "[NetworkService] deleteBankProfileFromServer failed for id:" << bankProfileId; + } else { + qDebug() << "[NetworkService] deleteBankProfileFromServer done for id:" << bankProfileId; + } + + emit finished(); +} + void NetworkService::patchMaterial() { if (!ensureValidToken()) { emit finishedWithResult(-1); emit finished(); return; } diff --git a/services/net/NetworkService.h b/services/net/NetworkService.h index 65594c8..4931962 100644 --- a/services/net/NetworkService.h +++ b/services/net/NetworkService.h @@ -49,6 +49,10 @@ public slots: void toggleBankProfile(); + // DELETE /api/v1/profile/bank_profile/{bank_profile_id}. Удаляет банковский + // профиль на сервере. bank_profile_id берётся из extra-данных. + void deleteBankProfileFromServer(); + void postMaterial(); void patchMaterial(); diff --git a/views/bank/AccountSettingsWindow.cpp b/views/bank/AccountSettingsWindow.cpp index ec8c221..c1c1201 100644 --- a/views/bank/AccountSettingsWindow.cpp +++ b/views/bank/AccountSettingsWindow.cpp @@ -83,6 +83,11 @@ AccountSettingsWindow::AccountSettingsWindow( checkPinBtn->setStyleSheet("background-color: orange; color: white; padding: 4px 12px;"); connect(checkPinBtn, &QPushButton::clicked, this, &AccountSettingsWindow::startCheckPinCode); pinRow->addWidget(checkPinBtn); + + auto *deleteProfileBtn = new QPushButton("Удалить профиль"); + deleteProfileBtn->setStyleSheet("background-color: #C62828; color: white; padding: 4px 12px;"); + connect(deleteProfileBtn, &QPushButton::clicked, this, &AccountSettingsWindow::deleteProfile); + pinRow->addWidget(deleteProfileBtn); layout->addLayout(pinRow); // ── Профиль ──────────────────────────────────────────────────────── @@ -308,6 +313,56 @@ void AccountSettingsWindow::toggleProfileStatus() { sendAppStatus(newStatus, std::move(onSuccess)); } +// ── Delete profile ─────────────────────────────────────────────────────────── + +void AccountSettingsWindow::deleteProfile() { + QMessageBox msgBox(this); + msgBox.setWindowTitle("Удалить профиль?"); + msgBox.setText("Точно удалить все данные банка: " + m_app.name + + "?\nБудут удалены профиль, счета, транзакции и события — на сервере и локально."); + QPushButton *confirmBtn = msgBox.addButton("Удалить", QMessageBox::AcceptRole); + QPushButton *cancelBtn = msgBox.addButton("Отмена", QMessageBox::RejectRole); + msgBox.setDefaultButton(cancelBtn); + msgBox.setModal(true); + msgBox.exec(); + if (msgBox.clickedButton() != confirmBtn) return; + + const QString deviceId = m_deviceId; + const QString appCode = m_app.code; + + // Локальное удаление: счета (каскадом транзакции и события) и сам профиль. + // Девайс не трогаем. + auto deleteLocal = [deviceId, appCode]() { + if (!MaterialDAO::deleteAllAccountsByApp(deviceId, appCode)) + qWarning() << "[AccountSettings] deleteProfile: не удалось удалить счета" << appCode; + if (!BankProfileDAO::deleteProfile(deviceId, appCode)) + qWarning() << "[AccountSettings] deleteProfile: не удалось удалить профиль" << appCode; + }; + + // Не синхронизирован с сервером — удаляем только локально и закрываем окно. + if (m_app.bankProfileId.isEmpty()) { + deleteLocal(); + close(); + return; + } + + showOverlay("Удаление профиля..."); + auto *thread = new QThread; + auto *net = new NetworkService; + net->moveToThread(thread); + net->addExtra("bank_profile_id", m_app.bankProfileId); + NetworkService::connectErrorDialog(this, net); + connect(thread, &QThread::started, net, &NetworkService::deleteBankProfileFromServer); + connect(net, &NetworkService::finished, this, [this, deleteLocal]() { + deleteLocal(); + hideOverlay(true, "Профиль удалён", [this]() { close(); }); + }, Qt::QueuedConnection); + connect(net, &NetworkService::finished, thread, &QThread::quit); + connect(net, &NetworkService::finished, net, &QObject::deleteLater); + connect(thread, &QThread::finished, thread, &QThread::deleteLater); + thread->start(); +} + // ── Edit PIN ─────────────────────────────────────────────────────────────── void AccountSettingsWindow::editPinCode() { diff --git a/views/bank/AccountSettingsWindow.h b/views/bank/AccountSettingsWindow.h index 7eccfa7..815c1a3 100644 --- a/views/bank/AccountSettingsWindow.h +++ b/views/bank/AccountSettingsWindow.h @@ -40,6 +40,7 @@ private: void updateStatusUI(); void toggleProfileStatus(); + void deleteProfile(); void editPinCode(); void startCheckPinCode(); void startGetProfileInfo();