#include "projectdao.h" // --------------- Project CRUD --------------- bool ProjectDAO::create(Project &proj) { QSqlQuery query; query.prepare("INSERT INTO PROJECT (CODE, TITLE, CUSTOMER_CODE, CUSTOMER_NAME, " "START_DATE, DURATION, STATE, CONTACT, ADDRESS1, ADDRESS2, " "POSTCODE, CITY, PHONE, MOBILE, EMAIL, CREATEDBY) " "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); query.addBindValue(proj.code); query.addBindValue(proj.title); query.addBindValue(proj.customerCode); query.addBindValue(proj.customerName); query.addBindValue(proj.startDate); query.addBindValue(proj.duration); query.addBindValue(proj.state); query.addBindValue(proj.contact); query.addBindValue(proj.address1); query.addBindValue(proj.address2); query.addBindValue(proj.postcode); query.addBindValue(proj.city); query.addBindValue(proj.phone); query.addBindValue(proj.mobile); query.addBindValue(proj.email); query.addBindValue("user"); if (!query.exec()) { qWarning() << "ProjectDAO::create - Error:" << query.lastError().text(); return false; } proj.id = query.lastInsertId().toInt(); return true; } bool ProjectDAO::update(const Project &proj) { QSqlQuery query; query.prepare("UPDATE PROJECT SET TITLE=?, CUSTOMER_CODE=?, CUSTOMER_NAME=?, " "START_DATE=?, DURATION=?, STATE=?, CONTACT=?, ADDRESS1=?, ADDRESS2=?, " "POSTCODE=?, CITY=?, PHONE=?, MOBILE=?, EMAIL=? WHERE CODE=?"); query.addBindValue(proj.title); query.addBindValue(proj.customerCode); query.addBindValue(proj.customerName); query.addBindValue(proj.startDate); query.addBindValue(proj.duration); query.addBindValue(proj.state); query.addBindValue(proj.contact); query.addBindValue(proj.address1); query.addBindValue(proj.address2); query.addBindValue(proj.postcode); query.addBindValue(proj.city); query.addBindValue(proj.phone); query.addBindValue(proj.mobile); query.addBindValue(proj.email); query.addBindValue(proj.code); if (!query.exec()) { qWarning() << "ProjectDAO::update - Error:" << query.lastError().text(); return false; } return query.numRowsAffected() > 0; } bool ProjectDAO::remove(const QString &code) { QSqlQuery query; query.prepare("DELETE FROM PROJECT WHERE CODE = ?"); query.addBindValue(code); if (!query.exec()) { qWarning() << "ProjectDAO::remove - Error:" << query.lastError().text(); return false; } return true; } Project ProjectDAO::getByCode(const QString &code) { Project proj; QSqlQuery query; query.prepare("SELECT ID, CODE, TITLE, CUSTOMER_CODE, CUSTOMER_NAME, " "START_DATE, DURATION, STATE, CONTACT, ADDRESS1, ADDRESS2, " "POSTCODE, CITY, PHONE, MOBILE, EMAIL FROM PROJECT WHERE CODE = ?"); query.addBindValue(code); if (query.exec() && query.next()) { proj.id = query.value(0).toInt(); proj.code = query.value(1).toString(); proj.title = query.value(2).toString(); proj.customerCode = query.value(3).toString(); proj.customerName = query.value(4).toString(); proj.startDate = query.value(5).toDate(); proj.duration = query.value(6).toDate(); proj.state = query.value(7).toString(); proj.contact = query.value(8).toString(); proj.address1 = query.value(9).toString(); proj.address2 = query.value(10).toString(); proj.postcode = query.value(11).toString(); proj.city = query.value(12).toString(); proj.phone = query.value(13).toString(); proj.mobile = query.value(14).toString(); proj.email = query.value(15).toString(); } return proj; } Project ProjectDAO::getById(int id) { Project proj; QSqlQuery query; query.prepare("SELECT ID, CODE, TITLE, CUSTOMER_CODE, CUSTOMER_NAME, " "START_DATE, DURATION, STATE, CONTACT, ADDRESS1, ADDRESS2, " "POSTCODE, CITY, PHONE, MOBILE, EMAIL FROM PROJECT WHERE ID = ?"); query.addBindValue(id); if (query.exec() && query.next()) { proj.id = query.value(0).toInt(); proj.code = query.value(1).toString(); proj.title = query.value(2).toString(); proj.customerCode = query.value(3).toString(); proj.customerName = query.value(4).toString(); proj.startDate = query.value(5).toDate(); proj.duration = query.value(6).toDate(); proj.state = query.value(7).toString(); proj.contact = query.value(8).toString(); proj.address1 = query.value(9).toString(); proj.address2 = query.value(10).toString(); proj.postcode = query.value(11).toString(); proj.city = query.value(12).toString(); proj.phone = query.value(13).toString(); proj.mobile = query.value(14).toString(); proj.email = query.value(15).toString(); } return proj; } QVector ProjectDAO::getAll() { QVector result; QSqlQuery query("SELECT ID, CODE, TITLE, CUSTOMER_CODE, CUSTOMER_NAME, " "START_DATE, DURATION, STATE, CONTACT, ADDRESS1, ADDRESS2, " "POSTCODE, CITY, PHONE, MOBILE, EMAIL FROM PROJECT ORDER BY CODE"); while (query.next()) { Project proj; proj.id = query.value(0).toInt(); proj.code = query.value(1).toString(); proj.title = query.value(2).toString(); proj.customerCode = query.value(3).toString(); proj.customerName = query.value(4).toString(); proj.startDate = query.value(5).toDate(); proj.duration = query.value(6).toDate(); proj.state = query.value(7).toString(); proj.contact = query.value(8).toString(); proj.address1 = query.value(9).toString(); proj.address2 = query.value(10).toString(); proj.postcode = query.value(11).toString(); proj.city = query.value(12).toString(); proj.phone = query.value(13).toString(); proj.mobile = query.value(14).toString(); proj.email = query.value(15).toString(); result.append(proj); } return result; } QStringList ProjectDAO::getAllCodes() { QStringList codes; QSqlQuery query("SELECT CODE FROM PROJECT ORDER BY CODE"); while (query.next()) codes.append(query.value(0).toString()); return codes; } bool ProjectDAO::exists(const QString &code) { QSqlQuery query; query.prepare("SELECT COUNT(*) FROM PROJECT WHERE CODE = ?"); query.addBindValue(code); if (query.exec() && query.next()) return query.value(0).toInt() > 0; return false; } // --------------- Project status --------------- bool ProjectDAO::setState(const QString &code, const QString &state) { QSqlQuery query; query.prepare("UPDATE PROJECT SET STATE = ? WHERE CODE = ?"); query.addBindValue(state); query.addBindValue(code); return query.exec(); } QStringList ProjectDAO::getStates() { return {"draft", "active", "paused", "completed", "cancelled"}; } // --------------- Project documents --------------- bool ProjectDAO::attachDocument(const QString &projectCode, const QString &docType, const QString &docCode) { QSqlQuery query; query.prepare("INSERT INTO PROJECTDOCUMENT (PROJECT_CODE, DOC_TYPE, DOC_CODE, CREATEDBY) " "VALUES (?, ?, ?, ?)"); query.addBindValue(projectCode); query.addBindValue(docType); query.addBindValue(docCode); query.addBindValue("user"); if (!query.exec()) { qWarning() << "ProjectDAO::attachDocument - Error:" << query.lastError().text(); return false; } return true; } bool ProjectDAO::removeDocument(int docId) { QSqlQuery query; query.prepare("DELETE FROM PROJECTDOCUMENT WHERE ID = ?"); query.addBindValue(docId); return query.exec(); } QVector ProjectDAO::getDocuments(const QString &projectCode) { QVector result; QSqlQuery query; query.prepare("SELECT ID, PROJECT_CODE, DOC_TYPE, DOC_CODE FROM PROJECTDOCUMENT WHERE PROJECT_CODE = ?"); query.addBindValue(projectCode); if (query.exec()) { while (query.next()) { ProjectDocument doc; doc.id = query.value(0).toInt(); doc.projectCode = query.value(1).toString(); doc.docType = query.value(2).toString(); doc.docCode = query.value(3).toString(); result.append(doc); } } return result; } // --------------- Project budget --------------- bool ProjectDAO::addBudgetLine(const QString &projectCode, const QString &concept, double amount) { QSqlQuery query; query.prepare("INSERT INTO PROJECTBUDGET (PROJECT_CODE, CONCEPT, AMOUNT, CREATEDBY) VALUES (?, ?, ?, ?)"); query.addBindValue(projectCode); query.addBindValue(concept); query.addBindValue(amount); query.addBindValue("user"); if (!query.exec()) { qWarning() << "ProjectDAO::addBudgetLine - Error:" << query.lastError().text(); return false; } return true; } bool ProjectDAO::removeBudgetLine(int budgetId) { QSqlQuery query; query.prepare("DELETE FROM PROJECTBUDGET WHERE ID = ?"); query.addBindValue(budgetId); return query.exec(); } QVector ProjectDAO::getBudget(const QString &projectCode) { QVector result; QSqlQuery query; query.prepare("SELECT ID, PROJECT_CODE, CONCEPT, AMOUNT FROM PROJECTBUDGET WHERE PROJECT_CODE = ?"); query.addBindValue(projectCode); if (query.exec()) { while (query.next()) { ProjectBudget b; b.id = query.value(0).toInt(); b.projectCode = query.value(1).toString(); b.concept = query.value(2).toString(); b.amount = query.value(3).toDouble(); result.append(b); } } return result; } double ProjectDAO::getTotalBudget(const QString &projectCode) { QSqlQuery query; query.prepare("SELECT COALESCE(SUM(AMOUNT), 0) FROM PROJECTBUDGET WHERE PROJECT_CODE = ?"); query.addBindValue(projectCode); if (query.exec() && query.next()) return query.value(0).toDouble(); return 0.0; } // --------------- Financial summary --------------- double ProjectDAO::getTotalCost(const QString &projectCode) { QSqlQuery query; query.prepare("SELECT COALESCE(SUM(PRICE), 0) FROM SALEDOCUMENT WHERE PROJECT_CODE = ?"); query.addBindValue(projectCode); if (query.exec() && query.next()) return query.value(0).toDouble(); return 0.0; } double ProjectDAO::getTotalInvoiced(const QString &projectCode) { QSqlQuery query; query.prepare("SELECT COALESCE(SUM(PRICE), 0) FROM SALEDOCUMENT WHERE PROJECT_CODE = ? AND TYPE = 'FA'"); query.addBindValue(projectCode); if (query.exec() && query.next()) return query.value(0).toDouble(); return 0.0; } QPair ProjectDAO::getFinancialSummary(const QString &projectCode) { double totalBudget = getTotalBudget(projectCode); double totalCost = getTotalCost(projectCode); return {totalBudget, totalCost}; }