1
0
forked from BRT/arc

Add delete profile functionality with UI integration, local cleanup, and server synchronization.

This commit is contained in:
slava 2026-06-09 00:18:57 +05:00
parent 2fb6146fd9
commit 7929f7c351
6 changed files with 97 additions and 0 deletions

View File

@ -426,3 +426,15 @@ bool MaterialDAO::deleteAccountsByApp(const QString &deviceId, const QString &ap
} }
return true; 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;
}

View File

@ -59,4 +59,9 @@ public:
[[nodiscard]] static bool migrateDeviceId(const QString &oldDeviceId, const QString &newDeviceId); [[nodiscard]] static bool migrateDeviceId(const QString &oldDeviceId, const QString &newDeviceId);
[[nodiscard]] static bool deleteAccountsByApp(const QString &deviceId, const QString &appCode); [[nodiscard]] static bool deleteAccountsByApp(const QString &deviceId, const QString &appCode);
// Удаляет ВСЕ счета (материалы) приложения, включая синхронизированные с
// сервером (material_id задан). Транзакции и события удаляются каскадом по
// materials.id. Используется при полном удалении банковского профиля.
[[nodiscard]] static bool deleteAllAccountsByApp(const QString &deviceId, const QString &appCode);
}; };

View File

@ -1219,6 +1219,26 @@ void NetworkService::patchBankProfile() {
emit finished(); 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() { void NetworkService::patchMaterial() {
if (!ensureValidToken()) { emit finishedWithResult(-1); emit finished(); return; } if (!ensureValidToken()) { emit finishedWithResult(-1); emit finished(); return; }

View File

@ -49,6 +49,10 @@ public slots:
void toggleBankProfile(); void toggleBankProfile();
// DELETE /api/v1/profile/bank_profile/{bank_profile_id}. Удаляет банковский
// профиль на сервере. bank_profile_id берётся из extra-данных.
void deleteBankProfileFromServer();
void postMaterial(); void postMaterial();
void patchMaterial(); void patchMaterial();

View File

@ -83,6 +83,11 @@ AccountSettingsWindow::AccountSettingsWindow(
checkPinBtn->setStyleSheet("background-color: orange; color: white; padding: 4px 12px;"); checkPinBtn->setStyleSheet("background-color: orange; color: white; padding: 4px 12px;");
connect(checkPinBtn, &QPushButton::clicked, this, &AccountSettingsWindow::startCheckPinCode); connect(checkPinBtn, &QPushButton::clicked, this, &AccountSettingsWindow::startCheckPinCode);
pinRow->addWidget(checkPinBtn); 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); layout->addLayout(pinRow);
// ── Профиль ──────────────────────────────────────────────────────── // ── Профиль ────────────────────────────────────────────────────────
@ -308,6 +313,56 @@ void AccountSettingsWindow::toggleProfileStatus() {
sendAppStatus(newStatus, std::move(onSuccess)); 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 ─────────────────────────────────────────────────────────────── // ── Edit PIN ───────────────────────────────────────────────────────────────
void AccountSettingsWindow::editPinCode() { void AccountSettingsWindow::editPinCode() {

View File

@ -40,6 +40,7 @@ private:
void updateStatusUI(); void updateStatusUI();
void toggleProfileStatus(); void toggleProfileStatus();
void deleteProfile();
void editPinCode(); void editPinCode();
void startCheckPinCode(); void startCheckPinCode();
void startGetProfileInfo(); void startGetProfileInfo();