#include "formproject.h" #include "ui_formproject.h" #include "projectdao.h" #include #include formProject::formProject(QWidget *parent) : QMainWindow(parent), ui(new Ui::formProject), m_isNew(true) { ui->setupUi(this); setupConnections(); clearForm(); // Populate state combo ui->stateCombo->addItems(ProjectDAO::getStates()); ui->docTypeCombo->addItems({"PR", "FI", "FC", "OT"}); } formProject::~formProject() { delete ui; } void formProject::setupConnections() { connect(ui->saveButton, &QPushButton::clicked, this, &formProject::saveProject); connect(ui->addDocButton, &QPushButton::clicked, this, &formProject::addDocument); connect(ui->removeDocButton, &QPushButton::clicked, this, &formProject::removeDocument); connect(ui->addBudgetButton, &QPushButton::clicked, this, &formProject::addBudgetLine); connect(ui->removeBudgetButton, &QPushButton::clicked, this, &formProject::removeBudgetLine); } void formProject::setNewMode() { m_isNew = true; m_project = Project(); clearForm(); ui->codeEdit->setEnabled(true); ui->codeEdit->setFocus(); } void formProject::clearForm() { ui->codeEdit->clear(); ui->titleEdit->clear(); ui->customerCodeEdit->clear(); ui->customerNameEdit->clear(); ui->startDateEdit->setDate(QDate::currentDate()); ui->durationDateEdit->setDate(QDate::currentDate().addYears(1)); ui->stateCombo->setCurrentIndex(0); ui->contactEdit->clear(); ui->address1Edit->clear(); ui->address2Edit->clear(); ui->postcodeEdit->clear(); ui->cityEdit->clear(); ui->phoneEdit->clear(); ui->mobileEdit->clear(); ui->emailEdit->clear(); } void formProject::loadProject(const QString &code) { m_isNew = false; m_project = ProjectDAO::getByCode(code); ui->codeEdit->setEnabled(false); populateForm(); refreshDocuments(); refreshBudget(); refreshFinancialSummary(); } void formProject::populateForm() { ui->codeEdit->setText(m_project.code); ui->titleEdit->setText(m_project.title); ui->customerCodeEdit->setText(m_project.customerCode); ui->customerNameEdit->setText(m_project.customerName); ui->startDateEdit->setDate(m_project.startDate); ui->durationDateEdit->setDate(m_project.duration); int stateIdx = ui->stateCombo->findText(m_project.state); if (stateIdx >= 0) ui->stateCombo->setCurrentIndex(stateIdx); ui->contactEdit->setText(m_project.contact); ui->address1Edit->setText(m_project.address1); ui->address2Edit->setText(m_project.address2); ui->postcodeEdit->setText(m_project.postcode); ui->cityEdit->setText(m_project.city); ui->phoneEdit->setText(m_project.phone); ui->mobileEdit->setText(m_project.mobile); ui->emailEdit->setText(m_project.email); } void formProject::readForm() { m_project.code = ui->codeEdit->text(); m_project.title = ui->titleEdit->text(); m_project.customerCode = ui->customerCodeEdit->text(); m_project.customerName = ui->customerNameEdit->text(); m_project.startDate = ui->startDateEdit->date(); m_project.duration = ui->durationDateEdit->date(); m_project.state = ui->stateCombo->currentText(); m_project.contact = ui->contactEdit->text(); m_project.address1 = ui->address1Edit->text(); m_project.address2 = ui->address2Edit->text(); m_project.postcode = ui->postcodeEdit->text(); m_project.city = ui->cityEdit->text(); m_project.phone = ui->phoneEdit->text(); m_project.mobile = ui->mobileEdit->text(); m_project.email = ui->emailEdit->text(); } void formProject::saveProject() { readForm(); if (m_project.code.isEmpty() || m_project.title.isEmpty()) { QMessageBox::warning(this, tr("Aviso"), tr("Código y Título son obligatorios.")); return; } bool ok; if (m_isNew) { if (ProjectDAO::exists(m_project.code)) { QMessageBox::warning(this, tr("Error"), tr("Ya existe un proyecto con ese código.")); return; } ok = ProjectDAO::create(m_project); } else { ok = ProjectDAO::update(m_project); } if (ok) { QMessageBox::information(this, tr("Éxito"), tr("Proyecto guardado correctamente.")); m_isNew = false; ui->codeEdit->setEnabled(false); emit projectSaved(); } else { QMessageBox::critical(this, tr("Error"), tr("No se pudo guardar el proyecto.")); } } void formProject::onStateChanged(int index) { Q_UNUSED(index); } // --------------- Documents tab --------------- void formProject::addDocument() { if (m_project.code.isEmpty()) { QMessageBox::warning(this, tr("Aviso"), tr("Guarda el proyecto primero.")); return; } QString docType = ui->docTypeCombo->currentText(); QString docCode = ui->docCodeEdit->text(); if (docCode.isEmpty()) { QMessageBox::warning(this, tr("Aviso"), tr("Introduce el código del documento.")); return; } if (ProjectDAO::attachDocument(m_project.code, docType, docCode)) { ui->docCodeEdit->clear(); refreshDocuments(); } else { QMessageBox::critical(this, tr("Error"), tr("No se pudo adjuntar el documento.")); } } void formProject::removeDocument() { QModelIndex idx = ui->documentsTable->currentIndex(); if (!idx.isValid()) { QMessageBox::information(this, tr("Info"), tr("Selecciona un documento.")); return; } int row = idx.row(); int docId = ui->documentsTable->model()->data(ui->documentsTable->model()->index(row, 0)).toInt(); if (ProjectDAO::removeDocument(docId)) { refreshDocuments(); } else { QMessageBox::critical(this, tr("Error"), tr("No se pudo eliminar el documento.")); } } void formProject::refreshDocuments() { QSqlQueryModel *model = new QSqlQueryModel(this); QSqlQuery query; query.prepare("SELECT ID, DOC_TYPE, DOC_CODE FROM PROJECTDOCUMENT WHERE PROJECT_CODE = ?"); query.addBindValue(m_project.code); query.exec(); model->setQuery(query); model->setHeaderData(0, Qt::Horizontal, tr("ID")); model->setHeaderData(1, Qt::Horizontal, tr("Tipo")); model->setHeaderData(2, Qt::Horizontal, tr("Código")); ui->documentsTable->setModel(model); ui->documentsTable->setColumnHidden(0, true); } // --------------- Budget tab --------------- void formProject::addBudgetLine() { if (m_project.code.isEmpty()) { QMessageBox::warning(this, tr("Aviso"), tr("Guarda el proyecto primero.")); return; } QString concept = ui->budgetConceptEdit->text(); double amount = ui->budgetAmountSpin->value(); if (concept.isEmpty() || amount <= 0) { QMessageBox::warning(this, tr("Aviso"), tr("Introduce concepto y cantidad.")); return; } if (ProjectDAO::addBudgetLine(m_project.code, concept, amount)) { ui->budgetConceptEdit->clear(); ui->budgetAmountSpin->setValue(0); refreshBudget(); refreshFinancialSummary(); } else { QMessageBox::critical(this, tr("Error"), tr("No se pudo añadir la línea de presupuesto.")); } } void formProject::removeBudgetLine() { QModelIndex idx = ui->budgetTable->currentIndex(); if (!idx.isValid()) { QMessageBox::information(this, tr("Info"), tr("Selecciona una línea de presupuesto.")); return; } int row = idx.row(); int budgetId = ui->budgetTable->model()->data(ui->budgetTable->model()->index(row, 0)).toInt(); if (ProjectDAO::removeBudgetLine(budgetId)) { refreshBudget(); refreshFinancialSummary(); } else { QMessageBox::critical(this, tr("Error"), tr("No se pudo eliminar la línea.")); } } void formProject::refreshBudget() { QSqlQueryModel *model = new QSqlQueryModel(this); QSqlQuery query; query.prepare("SELECT ID, CONCEPT, AMOUNT FROM PROJECTBUDGET WHERE PROJECT_CODE = ?"); query.addBindValue(m_project.code); query.exec(); model->setQuery(query); model->setHeaderData(0, Qt::Horizontal, tr("ID")); model->setHeaderData(1, Qt::Horizontal, tr("Concepto")); model->setHeaderData(2, Qt::Horizontal, tr("Cantidad")); ui->budgetTable->setModel(model); ui->budgetTable->setColumnHidden(0, true); } void formProject::refreshFinancialSummary() { QPair summary = ProjectDAO::getFinancialSummary(m_project.code); ui->totalBudgetLabel->setText(QString::number(summary.first, 'f', 2) + " €"); ui->totalCostLabel->setText(QString::number(summary.second, 'f', 2) + " €"); ui->balanceLabel->setText(QString::number(summary.first - summary.second, 'f', 2) + " €"); }