diff --git a/consumePage.cpp b/consumePage.cpp index 61e0e00..9f8ad07 100644 --- a/consumePage.cpp +++ b/consumePage.cpp @@ -49,3 +49,224 @@ void MainWindow::on_consumeInventoryButton_clicked() ui->consumeCardIdBox->addItems(cardIdList); } } + + +/** + * @brief 消费 + * 该函数在用户点击“消费”按钮时触发,用于对指定卡片进行消费操作。 + * @param void + * @return void + * @details + * 函数首先检查软件是否已准备好并且数据库已连接。如果数据库未连接,函数将显示警告信息并返回。 + * 接着,函数检查是否选择了卡片。如果未选择卡片,函数将显示警告信息并返回。 + * 然后,函数检查并获取绑定的用户信息。如果卡片不存在或已挂失或未启用,函数将显示相应的警告信息并返回。 + * 如果消费金额大于50元,函数会要求进行密码验证。如果验证失败,函数将显示警告信息并返回。 + * 在所有检查通过后,函数调用 `deductCard` 函数进行消费操作,并在操作成功后显示消费结果。 + * @author 柯劲帆 + * @date 2024-07-30 + */ +void MainWindow::on_consumeButton_clicked() +{ + if (!softwareReady()) + { + QMessageBox::warning(this, QString("提示"), QString("数据库未连接,请设置。")); + if (ui->stackedWidget->currentWidget() != ui->settingPage) + { + ui->stackedWidget->setCurrentWidget(ui->settingPage); + } + return; + } + + if (ui->consumeCardIdBox->currentIndex() == -1) + { + QMessageBox::warning(this, "提示", "请放置卡片并点击查询按钮。"); + return; + } + QString cardId = ui->consumeCardIdBox->currentText(); + int userId; + int cardStatus; + double originalBalance; + + // 检查和获取绑定用户 + QSqlQuery query(db->getDatabase()); + query.prepare(QString("select userId, `status`, balance from card " + "where id = :cardId;")); + query.bindValue(":cardId", cardId); + bool success = false; + success = query.exec(); + if (!success) + { + QMessageBox::warning(this, QString("提示"), QString("数据库异常。消费失败。")); + return; + } + if (query.next()) // 卡已被注册,获取用户ID + { + cardStatus = query.value("status").toInt(); + if (cardStatus == -1) + { + QMessageBox::warning(this, QString("提示"), QString("此卡已被挂失。消费失败。")); + return; + } + if (cardStatus == 0) + { + QMessageBox::warning(this, QString("提示"), QString("此卡未被启用。消费失败。")); + return; + } + userId = query.value("userId").toInt(); + originalBalance = query.value("balance").toDouble(); + } + else // 卡没有注册 + { + query.finish(); + query.prepare(QString("insert into card " + "values (:cardId, 0, 0.0, null);")); + query.bindValue(":cardId", cardId); + success = query.exec(); + if (!success) + { + QMessageBox::warning(this, QString("提示"), QString("数据库异常。消费失败。")); + return; + } + + QMessageBox::warning(this, QString("提示"), QString("此卡未被启用。消费失败。")); + return; + } + + + double deductValue = ui->consumeValueBox->value(); + if (!(deductValue > 0.00)) + { + QMessageBox::warning(this, "提示", "请输入大于0.00的消费金额。"); + return; + } + if (originalBalance - deductValue < 0.00) + { + QMessageBox::warning(this, "提示", "余额不足。"); + return; + } + if (deductValue > 300.00) + { + QMessageBox::warning(this, "提示", "消费金额不得超过300.00元。"); + return; + } + + if (deductValue > 50.00) + { + QString prompt = "消费超过50.00元,需要密码验证。"; + QString info; + success = verifyUser(userId, prompt, info); + if (!success) + { + QMessageBox::warning(this, "提示", info + QString("\n用户验证不通过。消费失败。")); + return; + } + } + + QString info; + double finalBalance; + QString recordId; + success = deductCard(cardId, deductValue, originalBalance, finalBalance, recordId, info); + if (!success) + { + QMessageBox::warning(this, "提示", info + QString("\n消费失败。")); + return; + } + + QString consumeResultMessage = QString("消费成功:") + QString::number(deductValue) + QString("元\n"); + consumeResultMessage += QString("原余额:") + QString::number(originalBalance) + QString("元\n"); + consumeResultMessage += QString("消费后余额:") + QString::number(finalBalance) + QString("元\n"); + consumeResultMessage += QString("消费设备:") + device.getName() + QString("\n"); + consumeResultMessage += QString("交易记录号:") + recordId + QString("\n"); + QMessageBox::information(this, "消费成功", consumeResultMessage); + ui->consumeValueBox->setValue(0.00); + return; +} + + +/** + * @brief 卡消费 + * 该函数用于对指定卡片进行消费操作。消费前会进行一系列检查,包括卡片状态、余额是否足够以及单次消费额是否超过上限等。 + * 如果所有检查通过,将调用存储过程 `sp_consumeCard` 进行消费操作,并返回消费后的余额。 + * @param cardId 要消费的卡号 + * @param deductValue 消费金额 + * @param originalBalance 消费前的余额,通过引用返回 + * @param finalBalance 消费后的余额,通过引用返回 + * @param recordId 交易记录号,通过引用返回 + * @param info 如果出现异常,填入异常信息,通过引用返回 + * @return bool 是否消费成功 + * - true 成功 + * - false 失败 + * @author 柯劲帆 + * @date 2024-07-30 + */ +bool MainWindow::deductCard(QString cardId, double deductValue, double &originalBalance, double &finalBalance, QString &recordId, QString &info) +{ + QSqlQuery query(db->getDatabase()); + bool success; + query.prepare(QString("select userId, `status`, balance from card " + "where id = :cardId;")); + query.bindValue(":cardId", cardId); + success = query.exec(); + if (!success) + { + info = "数据库异常。"; + return false; + } + if (!query.next()) + { + info = "卡号不存在。"; + return false; + } + int cardStatus = query.value("status").toInt(); + if (cardStatus == -1) + { + info = "此卡已被挂失。"; + return false; + } + if (cardStatus == 0) + { + info = "此卡未被启用。"; + return false; + } + originalBalance = query.value("balance").toDouble(); + int userId = query.value("userId").toInt(); + + if (originalBalance - deductValue < 0.00) + { + info = "余额不足。"; + return false; + } + if (deductValue > 300.00) + { + info = "单次消费额上限为300.00元。"; + return false; + } + + QDateTime currentTime = QDateTime::currentDateTime(); + recordId = getRecordId(currentTime, userId, 1); + + query.finish(); + query.prepare(QString("call sp_consumeCard (:cardId, :value, :recordId, :device, :time, :type, @newBalance);")); + query.bindValue(":cardId", cardId); + query.bindValue(":value", deductValue); + query.bindValue(":recordId", recordId); + query.bindValue(":device", device.getId()); + query.bindValue(":time", currentTime.toString("yyyy-MM-dd hh:mm:ss")); + query.bindValue(":type", 1); + success = query.exec(); + if (!success) + { + info = "数据库异常。"; + return false; + } + query.exec("select @newBalance;"); + query.next(); + finalBalance = query.value("@newBalance").toDouble(); + + /// @todo 写卡 + + return true; +} + + + diff --git a/depositPage.cpp b/depositPage.cpp index 785a0f8..ad668bb 100644 --- a/depositPage.cpp +++ b/depositPage.cpp @@ -207,6 +207,7 @@ void MainWindow::on_depositByUserIdButton_clicked() depositResultMessage += QString("充值设备:") + device.getName() + QString("\n"); depositResultMessage += QString("交易记录号:") + recordId + QString("\n"); QMessageBox::information(this, "充值成功", depositResultMessage); + ui->depositValueBox->setValue(0.00); return; } diff --git a/mainwindow.cpp b/mainwindow.cpp index 31b7e02..22b9f93 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -63,3 +63,4 @@ MainWindow::~MainWindow() { delete ui; } + diff --git a/mainwindow.h b/mainwindow.h index 50a8408..96fc510 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -40,6 +40,7 @@ public: bool reopenCard(QString cardId, QString &info); bool topUpCard(QString cardId, double topUpValue, double &originalBalance, double &finalBalance, QString &recordId, QString &info); QString getRecordId(QDateTime currentTime, int userId, int recordType); + bool deductCard(QString cardId, double deductValue, double &originalBalance, double &finalBalance, QString &recordId, QString &info); private slots: void on_settingAction_triggered(); @@ -47,6 +48,7 @@ private slots: void on_NewCardAction_triggered(); void on_reportLossAction_triggered(); void on_depositAction_triggered(); + void on_ConsumptionAction_triggered(); void on_connectReaderButton_clicked(); void on_confirmQuitButton_clicked(); @@ -56,12 +58,9 @@ private slots: void on_reportLossButton_clicked(); void on_depositInventoryButton_clicked(); void on_depositByCardIdButton_clicked(); - void on_depositByUserIdButton_clicked(); - void on_consumeInventoryButton_clicked(); - - void on_ConsumptionAction_triggered(); + void on_consumeButton_clicked(); private: Ui::MainWindow *ui;