Fase 1: ProjectDAO, formProject, formProjectList, PROJECTDOCUMENT, PROJECTBUDGET en sqltable.h

This commit is contained in:
2026-06-10 00:22:41 +02:00
parent ed1ac4266c
commit d900ecb313
7 changed files with 904 additions and 133 deletions
+261
View File
@@ -0,0 +1,261 @@
#include "formproject.h"
#include "ui_formproject.h"
#include "projectdao.h"
#include <QMessageBox>
#include <QSqlQueryModel>
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<double, double> 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) + "");
}