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
+61 -133
View File
@@ -148,98 +148,6 @@ const QString tElemento = "CREATE TABLE ELEMENT ("
"WIDTH FLOAT, " // 21. ID proveedor por defecto
"LENGHT FLOAT, " // 22. ID proveedor por defecto
/* Interesa??
// Proveedores:
"SUPPLIER_ID_0 VARCHAR(10), " // 23. ID del proveedor
"SUPPLIER_NAME_0 VARCHAR(60), " // 24. Nombre del proveedor
"SUPPLIER_REFERENCE_0 VARCHAR(20), " // 25. Ref. del elemento que tiene el proveedor
"SUPPLIER_REAL_PRICE_0 FLOAT, " // 26. PVP
"SUPPLIER_DISCOUNT_0 FLOAT, " // 27. Descuento
"SUPPLIER_PURCHASE_PRICE_0 FLOAT, " // 28. Precio compra
"SUPPLIER_MINIMUM_AMOUNT_0 FLOAT, " // 29. Cantidad mínima de pedido
"SUPPLIER_DATE_UPDATE_0 DATE, " // 30. Fecha de actualización del precio
"SUPPLIER_ID_1 VARCHAR(10), " // 18. ID del proveedor
"SUPPLIER_NAME_1 VARCHAR(60), " // 19. Nombre del proveedor
"SUPPLIER_REFERENCE_1 VARCHAR(20), " // 20. Ref. del elemento que tiene el proveedor
"SUPPLIER_REAL_PRICE_1 FLOAT, " // 21. PVP
"SUPPLIER_DISCOUNT_1 FLOAT, " // 22. Descuento
"SUPPLIER_PURCHASE_PRICE_1 FLOAT, " // 23. Precio compra
"SUPPLIER_MINIMUM_AMOUNT_1 FLOAT, " // 24. Cantidad mínima de pedido
"SUPPLIER_DATE_UPDATE_1 DATE, " // 25. Fecha de actualización del precio
"SUPPLIER_ID_2 VARCHAR(10), " // 18. ID del proveedor
"SUPPLIER_NAME_2 VARCHAR(60), " // 19. Nombre del proveedor
"SUPPLIER_REFERENCE_2 VARCHAR(20), " // 20. Ref. del elemento que tiene el proveedor
"SUPPLIER_REAL_PRICE_2 FLOAT, " // 21. PVP
"SUPPLIER_DISCOUNT_2 FLOAT, " // 22. Descuento
"SUPPLIER_PURCHASE_PRICE_2 FLOAT, " // 23. Precio compra
"SUPPLIER_MINIMUM_AMOUNT_2 FLOAT, " // 24. Cantidad mínima de pedido
"SUPPLIER_DATE_UPDATE_2 DATE, " // 25. Fecha de actualización del precio
"SUPPLIER_ID_3 VARCHAR(10), " // 18. ID del proveedor
"SUPPLIER_NAME_3 VARCHAR(60), " // 19. Nombre del proveedor
"SUPPLIER_REFERENCE_3 VARCHAR(20), " // 20. Ref. del elemento que tiene el proveedor
"SUPPLIER_REAL_PRICE_3 FLOAT, " // 21. PVP
"SUPPLIER_DISCOUNT_3 FLOAT, " // 22. Descuento
"SUPPLIER_PURCHASE_PRICE_3 FLOAT, " // 23. Precio compra
"SUPPLIER_MINIMUM_AMOUNT_3 FLOAT, " // 24. Cantidad mínima de pedido
"SUPPLIER_DATE_UPDATE_3 DATE, " // 25. Fecha de actualización del precio
"SUPPLIER_ID_4 VARCHAR(10), " // 18. ID del proveedor
"SUPPLIER_NAME_4 VARCHAR(60), " // 19. Nombre del proveedor
"SUPPLIER_REFERENCE_4 VARCHAR(20), " // 20. Ref. del elemento que tiene el proveedor
"SUPPLIER_REAL_PRICE_4 FLOAT, " // 21. PVP
"SUPPLIER_DISCOUNT_4 FLOAT, " // 22. Descuento
"SUPPLIER_PURCHASE_PRICE_4 FLOAT, " // 23. Precio compra
"SUPPLIER_MINIMUM_AMOUNT_4 FLOAT, " // 24. Cantidad mínima de pedido
"SUPPLIER_DATE_UPDATE_4 DATE, " // 25. Fecha de actualización del precio
"SUPPLIER_ID_5 VARCHAR(10), " // 18. ID del proveedor
"SUPPLIER_NAME_5 VARCHAR(60), " // 19. Nombre del proveedor
"SUPPLIER_REFERENCE_5 VARCHAR(20), " // 20. Ref. del elemento que tiene el proveedor
"SUPPLIER_REAL_PRICE_5 FLOAT, " // 21. PVP
"SUPPLIER_DISCOUNT_5 FLOAT, " // 22. Descuento
"SUPPLIER_PURCHASE_PRICE_5 FLOAT, " // 23. Precio compra
"SUPPLIER_MINIMUM_AMOUNT_5 FLOAT, " // 24. Cantidad mínima de pedido
"SUPPLIER_DATE_UPDATE_5 DATE, " // 25. Fecha de actualización del precio
"SUPPLIER_ID_6 VARCHAR(10), " // 18. ID del proveedor
"SUPPLIER_NAME_6 VARCHAR(60), " // 19. Nombre del proveedor
"SUPPLIER_REFERENCE_6 VARCHAR(20), " // 20. Ref. del elemento que tiene el proveedor
"SUPPLIER_REAL_PRICE_6 FLOAT, " // 21. PVP
"SUPPLIER_DISCOUNT_6 FLOAT, " // 22. Descuento
"SUPPLIER_PURCHASE_PRICE_6 FLOAT, " // 23. Precio compra
"SUPPLIER_MINIMUM_AMOUNT_6 FLOAT, " // 24. Cantidad mínima de pedido
"SUPPLIER_DATE_UPDATE_6 DATE, " // 25. Fecha de actualización del precio
"SUPPLIER_ID_7 VARCHAR(10), " // 18. ID del proveedor
"SUPPLIER_NAME_7 VARCHAR(60), " // 19. Nombre del proveedor
"SUPPLIER_REFERENCE_7 VARCHAR(20), " // 20. Ref. del elemento que tiene el proveedor
"SUPPLIER_REAL_PRICE_7 FLOAT, " // 21. PVP
"SUPPLIER_DISCOUNT_7 FLOAT, " // 22. Descuento
"SUPPLIER_PURCHASE_PRICE_7 FLOAT, " // 23. Precio compra
"SUPPLIER_MINIMUM_AMOUNT_7 FLOAT, " // 24. Cantidad mínima de pedido
"SUPPLIER_DATE_UPDATE_7 DATE, " // 25. Fecha de actualización del precio
"SUPPLIER_ID_8 VARCHAR(10), " // 18. ID del proveedor
"SUPPLIER_NAME_8 VARCHAR(60), " // 19. Nombre del proveedor
"SUPPLIER_REFERENCE_8 VARCHAR(20), " // 20. Ref. del elemento que tiene el proveedor
"SUPPLIER_REAL_PRICE_8 FLOAT, " // 21. PVP
"SUPPLIER_DISCOUNT_8 FLOAT, " // 22. Descuento
"SUPPLIER_PURCHASE_PRICE_8 FLOAT, " // 23. Precio compra
"SUPPLIER_MINIMUM_AMOUNT_8 FLOAT, " // 24. Cantidad mínima de pedido
"SUPPLIER_DATE_UPDATE_8 DATE, " // 25. Fecha de actualización del precio
"SUPPLIER_ID_9 VARCHAR(10), " // 18. ID del proveedor
"SUPPLIER_NAME_9 VARCHAR(60), " // 19. Nombre del proveedor
"SUPPLIER_REFERENCE_9 VARCHAR(20), " // 20. Ref. del elemento que tiene el proveedor
"SUPPLIER_REAL_PRICE_9 FLOAT, " // 21. PVP
"SUPPLIER_DISCOUNT_9 FLOAT, " // 22. Descuento
"SUPPLIER_PURCHASE_PRICE_9 FLOAT, " // 23. Precio compra
"SUPPLIER_MINIMUM_AMOUNT_9 FLOAT, " // 24. Cantidad mínima de pedido
"SUPPLIER_DATE_UPDATE_9 DATE, " // 97. Fecha de actualización del precio
*/
"SUPPLIER_DEFAULT VARCHAR(10), " // 98. CODE proveedor por defecto
"CREATEDAT DATE DEFAULT CURRENT_DATE, " // 25. Fecha de creación
@@ -417,7 +325,7 @@ const QString tDataDocVenta = "CREATE TABLE SALEDOCUMENTDATA ("
//---------------------- DOCUMENTOS DE COMPRA --------------------------------
const QString tDocCompra = "CREATE TABLE BUYDOCUMENT ("
"ID INTEGER PRIMARY KEY AUTOINCREMENT, " // 0. ID
"TYPE VARCHAR(2) NOT NULL, " // 1. Tipo de documento:
"TYPE VARCHAR(2)\tNOT NULL, " // 1. Tipo de documento:
"CODE VARCHAR(20) NOT NULL, " // 2. Código documento
"SUPPLIER_CODE VARCHAR(20) NOT NULL, " // 3. Código proveedor
"SUPPLIER_NAME VARCHAR(100) NOT NULL, " // 4. Nombre proveedor
@@ -439,7 +347,7 @@ const QString tDocCompra = "CREATE TABLE BUYDOCUMENT ("
const QString tDataDocCompra = "CREATE TABLE BUYDOCUMENTDATA ("
"ID INTEGER NOT NULL, " // 0. ID linea
"BUYDOCUMENT_CODE VARCHAR(10) NOT NULL, " // 1. ID Documento de compra
"BUYDOCUMENT_CODE\tVARCHAR(10)\tNOT NULL, " // 1. ID Documento de compra
"ELEMENT_CODE VARCHAR(20), " // 2. ID del elemento
"ELEMENT_SUPPLIER_CODE VARCHAR(20), " // 3. ID del elemento que tiene el proveedor
"ELEMENT_NAME VARCHAR(100), " // 4. Descripción del elemento
@@ -458,24 +366,24 @@ const QString tDataDocCompra = "CREATE TABLE BUYDOCUMENTDATA ("
//----------------------- PROYECTO -----------------------------------------
const QString tProyecto = "CREATE TABLE PROJECT ("
"ID INTEGER PRIMARY KEY AUTOINCREMENT, " // 0. ID
"CODE VARCHAR(20) NOT NULL, " // 1. ID
"TITLE VARCHAR(100) NOT NULL, " // 2. Título
"CUSTOMER_CODE VARCHAR(10) NOT NULL, " // 3. ID Cliente
"CUSTOMER_NAME VARCHAR(60) NOT NULL, " // 4. Nombre del cliente
"START_DATE DATE DEFAULT CURRENT_DATE, " // 5. Fecha de Inicio
"DURATION DATE, " // 6. Fecha de Inicio
"STATE VARCHAR(10), " // 7. Estado
"ID\tINTEGER PRIMARY KEY AUTOINCREMENT, " // 0. ID
"CODE\tVARCHAR(20) NOT NULL, " // 1. ID
"TITLE\tVARCHAR(100) NOT NULL, " // 2. Título
"CUSTOMER_CODE\tVARCHAR(10) NOT NULL, " // 3. ID Cliente
"CUSTOMER_NAME\tVARCHAR(60) NOT NULL, " // 4. Nombre del cliente
"START_DATE\tDATE DEFAULT CURRENT_DATE, " // 5. Fecha de Inicio
"DURATION\tDATE, " // 6. Fecha de Inicio
"STATE\tVARCHAR(10), " // 7. Estado
// Dirección de la obra
"CONTACT VARCHAR(60), " // 8. Contacto
"ADDRESS1 VARCHAR(40), " // 9. Dir L1
"ADDRESS2 VARCHAR(40), " // 10. Dir L2
"POSTCODE VARCHAR(9), " // 11. CP
"CITY VARCHAR(80), " // 12. Ciudad
"PHONE VARCHAR(20), " // 13. Telefono
"MOBILE VARCHAR(20), " // 14. Movil
"EMAIL VARCHAR(60), " // 15. e-mail
"CONTACT\tVARCHAR(60), " // 8. Contacto
"ADDRESS1\tVARCHAR(40), " // 9. Dir L1
"ADDRESS2\tVARCHAR(40), " // 10. Dir L2
"POSTCODE\tVARCHAR(9), " // 11. CP
"CITY\tVARCHAR(80), " // 12. Ciudad
"PHONE\tVARCHAR(20), " // 13. Telefono
"MOBILE\tVARCHAR(20), " // 14. Movil
"EMAIL\tVARCHAR(60), " // 15. e-mail
"pyGantt BLOB" // 16. Imagen
@@ -484,15 +392,15 @@ const QString tProyecto = "CREATE TABLE PROJECT ("
");";
const QString tProjectControl = "CREATE TABLE PROJECTCONTROL ("
"ID INTEGER PRIMARY KEY AUTOINCREMENT, " // 01. ID
"pcPYCODE VARCHAR(20) NOT NULL, " // 02. ID
"pcELID VARCHAR(20) NOT NULL, " // 03. ID
"ID\tINTEGER PRIMARY KEY AUTOINCREMENT, " // 01. ID
"pcPYCODE\tVARCHAR(20) NOT NULL, " // 02. ID
"pcELID\tVARCHAR(20) NOT NULL, " // 03. ID
"pcELTITLE VARCHAR(100) NOT NULL, " // 04. ID Cliente
"pcELTOTAL FLOAT, " // 05. Nombre del cliente
"pcELTOTAL\tFLOAT, " // 05. Nombre del cliente
"pcELINSTALLED FLOAT, " // 06. Fecha de Inicio
"pcELREST FLOAT, " // 07. Fecha de Inicio
"pcELUNIT VARCHAR(2), " // 08. Estado
"pcELDATE DATE DEFAULT CURRENT_DATE, " // 09. Estado
"pcELREST\tFLOAT, " // 07. Fecha de Inicio
"pcELUNIT\tVARCHAR(2), " // 08. Estado
"pcELDATE\tDATE DEFAULT CURRENT_DATE, " // 09. Estado
"pcELTYPE VARCHAR(3), "
"pcELNODEINDEX INTEGER, "
"pcTASK VARCHAR(50), "
@@ -501,14 +409,34 @@ const QString tProjectControl = "CREATE TABLE PROJECTCONTROL ("
"CREATEDAT DATETIME DEFAULT CURRENT_DATE"
");";
//----------------------- PROJECTDOCUMENT ------------------------------------
const QString tProjectDocument = "CREATE TABLE PROJECTDOCUMENT ("
"ID INTEGER PRIMARY KEY AUTOINCREMENT, "
"PROJECT_CODE VARCHAR(20) NOT NULL, "
"DOC_TYPE VARCHAR(2) NOT NULL, "
"DOC_CODE VARCHAR(20) NOT NULL, "
"CREATEDBY VARCHAR(100), "
"CREATEDAT DATETIME DEFAULT CURRENT_TIMESTAMP"
");";
//----------------------- PROJECTBUDGET --------------------------------------
const QString tProjectBudget = "CREATE TABLE PROJECTBUDGET ("
"ID INTEGER PRIMARY KEY AUTOINCREMENT, "
"PROJECT_CODE VARCHAR(20) NOT NULL, "
"CONCEPT VARCHAR(200), "
"AMOUNT FLOAT, "
"CREATEDBY VARCHAR(100), "
"CREATEDAT DATETIME DEFAULT CURRENT_TIMESTAMP"
");";
//----------------------- TRABAJADOR ---------------------------------------
const QString tTrabajador = "CREATE TABLE EMPLOYEE ("
"ID INTEGER PRIMARY KEY AUTOINCREMENT, " // 01. ID
"SURNAME VARCHAR(60) NOT NULL, " // 02. Apellidos
"NAME VARCHAR(60) NOT NULL, " // 03. Nombre
"STATE BOOLEAN DEFAULT FALSE, " // 04. Activo o inactivo
"STATE\tBOOLEAN\tDEFAULT FALSE, " // 04. Activo o inactivo
"CATEGORY VARCHAR(30), " // 05. Categoría
"PRICEPERHOUR FLOAT, " // 06. Precio Hora
"PRICEPERHOUR\tFLOAT, " // 06. Precio Hora
"NOTES BLOB," // 07. Notas
"PICTURE BLOB,"
@@ -518,19 +446,19 @@ const QString tTrabajador = "CREATE TABLE EMPLOYEE ("
//----------------------- CONTACTOS -----------------------------------------
const QString tContact = "CREATE TABLE CONTACT ("
"coID INTEGER PRIMARY KEY AUTOINCREMENT, " // 01. ID
"coCode VARCHAR(20) NOT NULL, " // 02. Code
"coNombre VARCHAR(60) NOT NULL, " // 03. Nombre
"coApellido VARCHAR(60) NOT NULL, " // 04. Apellidos
"coForma VARCHAR(10), " // 05. Forma
"coID\tINTEGER PRIMARY KEY AUTOINCREMENT, " // 01. ID
"coCode\tVARCHAR(20) NOT NULL, " // 02. Code
"coNombre\tVARCHAR(60) NOT NULL, " // 03. Nombre
"coApellido\tVARCHAR(60) NOT NULL, " // 04. Apellidos
"coForma\tVARCHAR(10), " // 05. Forma
"coPuesto VARCHAR(20), " // 06. Puesto
"coclCode VARCHAR(20), " // 07. Código Empresa
"coPuesto\tVARCHAR(20), " // 06. Puesto
"coclCode\tVARCHAR(20), " // 07. Código Empresa
"coclNom VARCHAR(100), " // 08. Nombre Empresa
"coTel VARCHAR(20), " // 09. Teléfono fijo
"coMovil VARCHAR(20), " // 10. Teléfono móvil
"coFax VARCHAR(20), " // 11. Fax
"coEMail VARCHAR(60)," // 12. e-mail
"coTel\tVARCHAR(20), " // 09. Teléfono fijo
"coMovil\tVARCHAR(20), " // 10. Teléfono móvil
"coFax\tVARCHAR(20), " // 11. Fax
"coEMail\tVARCHAR(60)," // 12. e-mail
"coImage BLOB," // 13. Imagen
"CREATEDAT DATE DEFAULT CURRENT_DATE, " // 25. Fecha de creación
@@ -559,9 +487,9 @@ const QString tTemplate = "CREATE TABLE TEMPLATE ("
");";
const QStringList dbTables = {tDBInfo, tEmpresaInfo, tThird, tElemento, tElemComp, tUnidad, tPropuestaVenta, tDataPropuestaVenta,
tDocVenta, tDataDocVenta, tDocCompra, tDataDocCompra, tContact, tTemplate};
tDocVenta, tDataDocVenta, tDocCompra, tDataDocCompra, tContact, tTemplate, tProjectDocument, tProjectBudget};
const QStringList dbTableNames = {"DBINFO", "ENTERPRISESINFO", "THIRD", "ELEMENT", "ELEMENTCOMPOSITION", "UNIT", "SALEPROPOSAL", "SALEPROPOSALDATA",
"SALEDOCUMENT", "SALEDOCUMENTDATA", "BUYDOCUMENT", "BUYDOCUMENTDATA", "CONTACT", "TEMPLATE"};
"SALEDOCUMENT", "SALEDOCUMENTDATA", "BUYDOCUMENT", "BUYDOCUMENTDATA", "CONTACT", "TEMPLATE", "PROJECTDOCUMENT", "PROJECTBUDGET"};
#endif // SQLTABLE_H
#endif // SQLTABLE_H
+328
View File
@@ -0,0 +1,328 @@
#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<Project> ProjectDAO::getAll()
{
QVector<Project> 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<ProjectDocument> ProjectDAO::getDocuments(const QString &projectCode)
{
QVector<ProjectDocument> 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<ProjectBudget> ProjectDAO::getBudget(const QString &projectCode)
{
QVector<ProjectBudget> 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<double, double> ProjectDAO::getFinancialSummary(const QString &projectCode)
{
double totalBudget = getTotalBudget(projectCode);
double totalCost = getTotalCost(projectCode);
return {totalBudget, totalCost};
}
+84
View File
@@ -0,0 +1,84 @@
#ifndef PROJECTDAO_H
#define PROJECTDAO_H
#include <QObject>
#include <QString>
#include <QSqlQuery>
#include <QSqlError>
#include <QDebug>
#include <QVector>
#include <QPair>
#include <QDate>
struct Project {
int id = 0;
QString code;
QString title;
QString customerCode;
QString customerName;
QDate startDate;
QDate duration;
QString state;
QString contact;
QString address1;
QString address2;
QString postcode;
QString city;
QString phone;
QString mobile;
QString email;
};
struct ProjectDocument {
int id = 0;
QString projectCode;
QString docType; // PR, FI, FC, OT
QString docCode;
};
struct ProjectBudget {
int id = 0;
QString projectCode;
QString concept;
double amount = 0.0;
};
class ProjectDAO : public QObject
{
Q_OBJECT
public:
explicit ProjectDAO(QObject *parent = nullptr) : QObject(parent) {}
// Project CRUD
static bool create(Project &proj);
static bool update(const Project &proj);
static bool remove(const QString &code);
static Project getByCode(const QString &code);
static Project getById(int id);
static QVector<Project> getAll();
static QStringList getAllCodes();
static bool exists(const QString &code);
// Project status management
static bool setState(const QString &code, const QString &state);
static QStringList getStates();
// Project documents
static bool attachDocument(const QString &projectCode, const QString &docType, const QString &docCode);
static bool removeDocument(int docId);
static QVector<ProjectDocument> getDocuments(const QString &projectCode);
// Project budget
static bool addBudgetLine(const QString &projectCode, const QString &concept, double amount);
static bool removeBudgetLine(int budgetId);
static QVector<ProjectBudget> getBudget(const QString &projectCode);
static double getTotalBudget(const QString &projectCode);
// Financial summary
static double getTotalCost(const QString &projectCode);
static double getTotalInvoiced(const QString &projectCode);
static QPair<double, double> getFinancialSummary(const QString &projectCode);
};
#endif // PROJECTDAO_H
+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) + "");
}
+48
View File
@@ -0,0 +1,48 @@
#ifndef FORMPROJECT_H
#define FORMPROJECT_H
#include <QMainWindow>
#include <QDate>
#include "projectdao.h"
namespace Ui {
class formProject;
}
class formProject : public QMainWindow
{
Q_OBJECT
public:
explicit formProject(QWidget *parent = nullptr);
~formProject();
void loadProject(const QString &code);
void setNewMode();
signals:
void projectSaved();
private slots:
void saveProject();
void onStateChanged(int index);
void addDocument();
void removeDocument();
void addBudgetLine();
void removeBudgetLine();
void refreshDocuments();
void refreshBudget();
void refreshFinancialSummary();
private:
Ui::formProject *ui;
Project m_project;
bool m_isNew;
void populateForm();
void readForm();
void clearForm();
void setupConnections();
};
#endif // FORMPROJECT_H
+92
View File
@@ -0,0 +1,92 @@
#include "formprojectlist.h"
#include "ui_formprojectlist.h"
#include "formproject.h"
#include "projectdao.h"
#include <QSqlQueryModel>
#include <QMessageBox>
formProjectList::formProjectList(QWidget *parent)
: QMainWindow(parent), ui(new Ui::formProjectList)
{
ui->setupUi(this);
setupModel();
connect(ui->refreshButton, &QPushButton::clicked, this, &formProjectList::refreshList);
connect(ui->newButton, &QPushButton::clicked, this, &formProjectList::createNewProject);
connect(ui->editButton, &QPushButton::clicked, this, &formProjectList::editProject);
connect(ui->deleteButton, &QPushButton::clicked, this, &formProjectList::deleteProject);
}
formProjectList::~formProjectList()
{
delete ui;
}
void formProjectList::setupModel()
{
QSqlQueryModel *model = new QSqlQueryModel(this);
model->setQuery("SELECT CODE, TITLE, CUSTOMER_NAME, STATE, START_DATE FROM PROJECT ORDER BY CODE");
model->setHeaderData(0, Qt::Horizontal, tr("Código"));
model->setHeaderData(1, Qt::Horizontal, tr("Título"));
model->setHeaderData(2, Qt::Horizontal, tr("Cliente"));
model->setHeaderData(3, Qt::Horizontal, tr("Estado"));
model->setHeaderData(4, Qt::Horizontal, tr("Fecha Inicio"));
ui->projectTable->setModel(model);
}
void formProjectList::refreshList()
{
QSqlQueryModel *model = qobject_cast<QSqlQueryModel*>(ui->projectTable->model());
if (model)
model->setQuery(model->query().lastQuery());
}
void formProjectList::createNewProject()
{
formProject *form = new formProject(this);
form->setNewMode();
connect(form, &formProject::projectSaved, this, [this]() {
refreshList();
});
form->show();
}
void formProjectList::editProject()
{
QModelIndex idx = ui->projectTable->currentIndex();
if (!idx.isValid()) {
QMessageBox::information(this, tr("Info"), tr("Selecciona un proyecto."));
return;
}
int row = idx.row();
QString code = ui->projectTable->model()->data(ui->projectTable->model()->index(row, 0)).toString();
formProject *form = new formProject(this);
form->loadProject(code);
connect(form, &formProject::projectSaved, this, [this]() {
refreshList();
});
form->show();
}
void formProjectList::deleteProject()
{
QModelIndex idx = ui->projectTable->currentIndex();
if (!idx.isValid()) {
QMessageBox::information(this, tr("Info"), tr("Selecciona un proyecto."));
return;
}
int row = idx.row();
QString code = ui->projectTable->model()->data(ui->projectTable->model()->index(row, 0)).toString();
int ret = QMessageBox::question(this, tr("Confirmar"), tr("¿Eliminar el proyecto %1?").arg(code),
QMessageBox::Yes | QMessageBox::No);
if (ret == QMessageBox::Yes) {
if (ProjectDAO::remove(code)) {
QMessageBox::information(this, tr("Éxito"), tr("Proyecto eliminado."));
refreshList();
} else {
QMessageBox::critical(this, tr("Error"), tr("No se pudo eliminar el proyecto."));
}
}
}
+30
View File
@@ -0,0 +1,30 @@
#ifndef FORMPROJECTLIST_H
#define FORMPROJECTLIST_H
#include <QMainWindow>
#include "projectdao.h"
namespace Ui {
class formProjectList;
}
class formProjectList : public QMainWindow
{
Q_OBJECT
public:
explicit formProjectList(QWidget *parent = nullptr);
~formProjectList();
public slots:
void refreshList();
void createNewProject();
void editProject();
void deleteProject();
private:
void setupModel();
Ui::formProjectList *ui;
};
#endif // FORMPROJECTLIST_H