307 lines
10 KiB
C++
307 lines
10 KiB
C++
#include "database.h"
|
|
#include <QSqlQuery>
|
|
#include <QSqlError>
|
|
#include <QSqlRecord>
|
|
#include <QFile>
|
|
#include <QTextStream>
|
|
#include <QDir>
|
|
|
|
Database& Database::instance() {
|
|
static Database instance;
|
|
return instance;
|
|
}
|
|
|
|
bool Database::initialize() {
|
|
m_db = QSqlDatabase::addDatabase("QSQLITE", "StationDB");
|
|
QString dbPath = QDir::currentPath() + "/station.db";
|
|
m_db.setDatabaseName(dbPath);
|
|
|
|
if (!m_db.open()) {
|
|
qDebug() << QDir::currentPath() + "/station.db";
|
|
qDebug() << "Database open error:" << m_db.lastError().text();
|
|
return false;
|
|
}
|
|
|
|
QSqlQuery query(m_db);
|
|
|
|
query.exec("CREATE TABLE IF NOT EXISTS users ("
|
|
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
"username TEXT UNIQUE NOT NULL, "
|
|
"password TEXT NOT NULL, "
|
|
"role TEXT NOT NULL)");
|
|
|
|
query.exec("CREATE TABLE IF NOT EXISTS routes ("
|
|
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
"route_name TEXT NOT NULL, "
|
|
"departure_time TEXT NOT NULL, "
|
|
"price REAL NOT NULL, "
|
|
"total_seats INTEGER NOT NULL, "
|
|
"available_seats INTEGER NOT NULL)");
|
|
|
|
query.exec("CREATE TABLE IF NOT EXISTS tickets ("
|
|
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
|
"route_id INTEGER NOT NULL, "
|
|
"passenger_name TEXT NOT NULL, "
|
|
"document_number TEXT NOT NULL, "
|
|
"seat_count INTEGER NOT NULL, "
|
|
"total_price REAL NOT NULL, "
|
|
"seller_id INTEGER NOT NULL, "
|
|
"sale_date TEXT NOT NULL, "
|
|
"FOREIGN KEY (route_id) REFERENCES routes(id), "
|
|
"FOREIGN KEY (seller_id) REFERENCES users(id))");
|
|
|
|
query.exec("SELECT COUNT(*) FROM users WHERE role = 'admin'");
|
|
if (query.next() && query.value(0).toInt() == 0) {
|
|
addUser("admin", "admin123", "admin");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
QString Database::hashPassword(const QString& password) {
|
|
QByteArray hash = QCryptographicHash::hash(
|
|
password.toUtf8(), QCryptographicHash::Sha256);
|
|
return hash.toHex();
|
|
}
|
|
|
|
bool Database::authenticate(const QString& username, const QString& password) {
|
|
QSqlQuery query(m_db);
|
|
query.prepare("SELECT password FROM users WHERE username = ?");
|
|
query.addBindValue(username);
|
|
|
|
if (query.exec() && query.next()) {
|
|
return query.value(0).toString() == hashPassword(password);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
User Database::getUser(const QString& username) {
|
|
User user;
|
|
QSqlQuery query(m_db);
|
|
query.prepare("SELECT id, username, password, role FROM users WHERE username = ?");
|
|
query.addBindValue(username);
|
|
|
|
if (query.exec() && query.next()) {
|
|
user.id = query.value(0).toInt();
|
|
user.username = query.value(1).toString();
|
|
user.password = query.value(2).toString();
|
|
user.role = query.value(3).toString();
|
|
}
|
|
return user;
|
|
}
|
|
|
|
QVector<User> Database::getAllUsers() {
|
|
QVector<User> users;
|
|
QSqlQuery query("SELECT id, username, password, role FROM users", m_db);
|
|
|
|
while (query.next()) {
|
|
User user;
|
|
user.id = query.value(0).toInt();
|
|
user.username = query.value(1).toString();
|
|
user.password = query.value(2).toString();
|
|
user.role = query.value(3).toString();
|
|
users.append(user);
|
|
}
|
|
return users;
|
|
}
|
|
|
|
bool Database::addUser(const QString& username, const QString& password, const QString& role) {
|
|
QSqlQuery query(m_db);
|
|
query.prepare("INSERT INTO users (username, password, role) VALUES (?, ?, ?)");
|
|
query.addBindValue(username);
|
|
query.addBindValue(hashPassword(password));
|
|
query.addBindValue(role);
|
|
return query.exec();
|
|
}
|
|
|
|
bool Database::deleteUser(int id) {
|
|
QSqlQuery query(m_db);
|
|
query.prepare("DELETE FROM users WHERE id = ? AND role != 'admin'");
|
|
query.addBindValue(id);
|
|
return query.exec();
|
|
}
|
|
|
|
QVector<Route> Database::getAllRoutes() {
|
|
QVector<Route> routes;
|
|
QSqlQuery query("SELECT id, route_name, departure_time, price, total_seats, available_seats FROM routes", m_db);
|
|
|
|
while (query.next()) {
|
|
Route route;
|
|
route.id = query.value(0).toInt();
|
|
route.routeName = query.value(1).toString();
|
|
route.departureTime = query.value(2).toString();
|
|
route.price = query.value(3).toDouble();
|
|
route.totalSeats = query.value(4).toInt();
|
|
route.availableSeats = query.value(5).toInt();
|
|
routes.append(route);
|
|
}
|
|
return routes;
|
|
}
|
|
|
|
Route Database::getRoute(int id) {
|
|
Route route;
|
|
QSqlQuery query(m_db);
|
|
query.prepare("SELECT id, route_name, departure_time, price, total_seats, available_seats FROM routes WHERE id = ?");
|
|
query.addBindValue(id);
|
|
|
|
if (query.exec() && query.next()) {
|
|
route.id = query.value(0).toInt();
|
|
route.routeName = query.value(1).toString();
|
|
route.departureTime = query.value(2).toString();
|
|
route.price = query.value(3).toDouble();
|
|
route.totalSeats = query.value(4).toInt();
|
|
route.availableSeats = query.value(5).toInt();
|
|
}
|
|
return route;
|
|
}
|
|
|
|
bool Database::addRoute(const QString& routeName, const QString& departureTime,
|
|
double price, int totalSeats) {
|
|
QSqlQuery query(m_db);
|
|
query.prepare("INSERT INTO routes (route_name, departure_time, price, total_seats, available_seats) "
|
|
"VALUES (?, ?, ?, ?, ?)");
|
|
query.addBindValue(routeName);
|
|
query.addBindValue(departureTime);
|
|
query.addBindValue(price);
|
|
query.addBindValue(totalSeats);
|
|
query.addBindValue(totalSeats);
|
|
return query.exec();
|
|
}
|
|
|
|
bool Database::updateRoute(const Route& route) {
|
|
QSqlQuery query(m_db);
|
|
query.prepare("UPDATE routes SET route_name = ?, departure_time = ?, price = ?, "
|
|
"total_seats = ?, available_seats = ? WHERE id = ?");
|
|
query.addBindValue(route.routeName);
|
|
query.addBindValue(route.departureTime);
|
|
query.addBindValue(route.price);
|
|
query.addBindValue(route.totalSeats);
|
|
query.addBindValue(route.availableSeats);
|
|
query.addBindValue(route.id);
|
|
return query.exec();
|
|
}
|
|
|
|
bool Database::deleteRoute(int id) {
|
|
QSqlQuery query(m_db);
|
|
query.prepare("DELETE FROM routes WHERE id = ?");
|
|
query.addBindValue(id);
|
|
return query.exec();
|
|
}
|
|
|
|
bool Database::updateAvailableSeats(int routeId, int change) {
|
|
QSqlQuery query(m_db);
|
|
query.prepare("UPDATE routes SET available_seats = available_seats + ? WHERE id = ?");
|
|
query.addBindValue(change);
|
|
query.addBindValue(routeId);
|
|
return query.exec();
|
|
}
|
|
|
|
QVector<Ticket> Database::getTicketsByRoute(int routeId) {
|
|
QVector<Ticket> tickets;
|
|
QSqlQuery query(m_db);
|
|
query.prepare("SELECT t.id, t.route_id, r.route_name, t.passenger_name, "
|
|
"t.document_number, t.seat_count, t.total_price, t.seller_id, "
|
|
"u.username, t.sale_date "
|
|
"FROM tickets t "
|
|
"JOIN routes r ON t.route_id = r.id "
|
|
"JOIN users u ON t.seller_id = u.id "
|
|
"WHERE t.route_id = :route_id");
|
|
query.bindValue(":route_id", routeId);
|
|
|
|
query.exec();
|
|
|
|
while (query.next()) {
|
|
Ticket ticket;
|
|
ticket.id = query.value(0).toInt();
|
|
ticket.routeId = query.value(1).toInt();
|
|
ticket.routeName = query.value(2).toString();
|
|
ticket.passengerName = query.value(3).toString();
|
|
ticket.documentNumber = query.value(4).toString();
|
|
ticket.seatCount = query.value(5).toInt();
|
|
ticket.totalPrice = query.value(6).toDouble();
|
|
ticket.sellerId = query.value(7).toInt();
|
|
ticket.sellerName = query.value(8).toString();
|
|
ticket.saleDate = query.value(9).toString();
|
|
tickets.append(ticket);
|
|
}
|
|
return tickets;
|
|
}
|
|
|
|
QVector<Ticket> Database::getAllTickets() {
|
|
QVector<Ticket> tickets;
|
|
QSqlQuery query("SELECT t.id, t.route_id, r.route_name, t.passenger_name, "
|
|
"t.document_number, t.seat_count, t.total_price, t.seller_id, "
|
|
"u.username, t.sale_date "
|
|
"FROM tickets t "
|
|
"JOIN routes r ON t.route_id = r.id "
|
|
"JOIN users u ON t.seller_id = u.id "
|
|
"ORDER BY t.sale_date DESC",m_db);
|
|
|
|
query.exec();
|
|
|
|
while (query.next()) {
|
|
Ticket ticket;
|
|
ticket.id = query.value(0).toInt();
|
|
ticket.routeId = query.value(1).toInt();
|
|
ticket.routeName = query.value(2).toString();
|
|
ticket.passengerName = query.value(3).toString();
|
|
ticket.documentNumber = query.value(4).toString();
|
|
ticket.seatCount = query.value(5).toInt();
|
|
ticket.totalPrice = query.value(6).toDouble();
|
|
ticket.sellerId = query.value(7).toInt();
|
|
ticket.sellerName = query.value(8).toString();
|
|
ticket.saleDate = query.value(9).toString();
|
|
tickets.append(ticket);
|
|
}
|
|
return tickets;
|
|
}
|
|
|
|
bool Database::addTicket(int routeId, const QString& passengerName,
|
|
const QString& documentNumber, int seatCount, int sellerId) {
|
|
Route route = getRoute(routeId);
|
|
double totalPrice = route.price * seatCount;
|
|
|
|
QSqlQuery query(m_db);
|
|
query.prepare("INSERT INTO tickets (route_id, passenger_name, document_number, "
|
|
"seat_count, total_price, seller_id, sale_date) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
|
query.addBindValue(routeId);
|
|
query.addBindValue(passengerName);
|
|
query.addBindValue(documentNumber);
|
|
query.addBindValue(seatCount);
|
|
query.addBindValue(totalPrice);
|
|
query.addBindValue(sellerId);
|
|
query.addBindValue(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
|
|
|
|
if (query.exec()) {
|
|
return updateAvailableSeats(routeId, -seatCount);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Database::deleteTicket(int id) {
|
|
QSqlQuery query(m_db);
|
|
query.prepare("SELECT route_id, seat_count FROM tickets WHERE id = ?");
|
|
query.addBindValue(id);
|
|
|
|
if (query.exec() && query.next()) {
|
|
int routeId = query.value(0).toInt();
|
|
int seatCount = query.value(1).toInt();
|
|
|
|
query.prepare("DELETE FROM tickets WHERE id = ?");
|
|
query.addBindValue(id);
|
|
|
|
if (query.exec()) {
|
|
return updateAvailableSeats(routeId, seatCount);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int Database::getLastTicketId() {
|
|
QSqlQuery query("SELECT last_insert_rowid()", m_db);
|
|
if (query.next()) {
|
|
return query.value(0).toInt();
|
|
}
|
|
return -1;
|
|
}
|