Compare commits
7 Commits
bf57c455cd
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a2d3eda4e9 | |||
| 5475fc301d | |||
| d900ecb313 | |||
| ed1ac4266c | |||
| 7d607f5139 | |||
| d3ae41e94d | |||
| f94f34f397 |
@@ -0,0 +1 @@
|
||||
*.o
|
||||
@@ -0,0 +1,82 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(BudgetPro VERSION 1.0 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Qt 6 Configuration
|
||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Sql)
|
||||
|
||||
# Define directories for easier management
|
||||
set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(SRC_DIR ${SOURCE_DIR}/src)
|
||||
set(GUI_DIR ${SOURCE_DIR}/src/gui)
|
||||
set(WIDGET_DIR ${SOURCE_DIR}/src/gui/widgets)
|
||||
set(FORMS_DIR ${SOURCE_DIR}/src/gui/forms)
|
||||
set(MODELS_DIR ${SOURCE_DIR}/src/models)
|
||||
set(DAO_DIR ${SOURCE_DIR}/src/dao)
|
||||
set(UTILS_DIR ${SOURCE_DIR}/src/utils)
|
||||
set(APP_DIR ${SOURCE_DIR}/src/app)
|
||||
set(ROOT_WIDGET_DIR ${SOURCE_DIR}/widget)
|
||||
|
||||
# Include Paths
|
||||
include_directories(
|
||||
${GUI_DIR}
|
||||
${WIDGET_DIR}
|
||||
${FORMS_DIR}
|
||||
${MODELS_DIR}
|
||||
${DAO_DIR}
|
||||
${UTILS_DIR}
|
||||
${APP_DIR}
|
||||
${ROOT_WIDGET_DIR}
|
||||
${SOURCE_DIR}/data
|
||||
${SOURCE_DIR}/gui/SARibbon
|
||||
${SOURCE_DIR}/gui/qtRibbonGUI
|
||||
)
|
||||
|
||||
# SARibbon Library Integration
|
||||
# Assuming SARibbon is integrated as a sub-project or pre-compiled
|
||||
add_subdirectory(gui/SARibbon)
|
||||
|
||||
# Collect Sources
|
||||
file(GLOB_RECURSIVE SOURCES
|
||||
"src/*.cpp"
|
||||
"src/*.h"
|
||||
"widget/*.cpp"
|
||||
"widget/*.h"
|
||||
"utils/*.cpp"
|
||||
"utils/*.h"
|
||||
)
|
||||
|
||||
# Collect Forms
|
||||
file(GLOB_RECURSIVE FORMS
|
||||
"src/gui/*.ui"
|
||||
"src/gui/forms/*.ui"
|
||||
"widget/*.ui"
|
||||
)
|
||||
|
||||
# Collect Resources
|
||||
file(GLOB_RECURSIVE RESOURCES
|
||||
"resources/*.qss"
|
||||
"resources/*.svg"
|
||||
"resources/*.png"
|
||||
"*.qrc"
|
||||
)
|
||||
|
||||
# Create Executable
|
||||
add_executable(BudgetPro
|
||||
${SOURCES}
|
||||
${FORMS}
|
||||
${RESOURCES}
|
||||
)
|
||||
|
||||
# Link Libraries
|
||||
target_link_libraries(BudgetPro PRIVATE Qt6::Widgets Qt6::Sql SARibbonBar)
|
||||
|
||||
# OS Specific configurations
|
||||
if(WIN32)
|
||||
set_target_properties(BudgetPro PROPERTIES WIN32_EXECUTABLE TRUE)
|
||||
target_compile_definitions(BudgetPro PRIVATE NOMINMAX)
|
||||
elseif(APPLE)
|
||||
set_target_properties(BudgetPro PROPERTIES MACOSX_BUNDLE TRUE)
|
||||
endif()
|
||||
@@ -87,7 +87,12 @@ SOURCES = src/gui/mainwindow.cpp \
|
||||
widget/msqlquerymodel.cpp \
|
||||
src/gui/forms/forminvoiceinlist.cpp \
|
||||
src/gui/forms/formbase.cpp \
|
||||
treeitem.cpp qrc_editabletreemodel.cpp \
|
||||
treeitem.cpp \
|
||||
src/dao/productdao.cpp \
|
||||
src/dao/enterprisedao.cpp \
|
||||
src/dao/thirddao.cpp \
|
||||
src/dao/budgetdao.cpp \
|
||||
src/dao/elementdao.cpp qrc_editabletreemodel.cpp \
|
||||
moc_mainwindow.cpp \
|
||||
moc_formbaselist.cpp \
|
||||
moc_formbudgetlist.cpp \
|
||||
@@ -153,6 +158,11 @@ OBJECTS = mainwindow.o \
|
||||
forminvoiceinlist.o \
|
||||
formbase.o \
|
||||
treeitem.o \
|
||||
productdao.o \
|
||||
enterprisedao.o \
|
||||
thirddao.o \
|
||||
budgetdao.o \
|
||||
elementdao.o \
|
||||
qrc_editabletreemodel.o \
|
||||
moc_mainwindow.o \
|
||||
moc_formbaselist.o \
|
||||
@@ -305,7 +315,12 @@ DIST = /usr/lib/x86_64-linux-gnu/qt5/mkspecs/features/spec_pre.prf \
|
||||
src/gui/forms/forminvoiceinlist.h \
|
||||
src/gui/forms/formbase.h \
|
||||
treeitem.h \
|
||||
utils/dbutils.h src/gui/mainwindow.cpp \
|
||||
utils/dbutils.h \
|
||||
src/dao/productdao.h \
|
||||
src/dao/enterprisedao.h \
|
||||
src/dao/thirddao.h \
|
||||
src/dao/budgetdao.h \
|
||||
src/dao/elementdao.h src/gui/mainwindow.cpp \
|
||||
utils/dbutils.cpp \
|
||||
src/gui/forms/formbaselist.cpp \
|
||||
src/gui/forms/formbudgetlist.cpp \
|
||||
@@ -340,7 +355,12 @@ DIST = /usr/lib/x86_64-linux-gnu/qt5/mkspecs/features/spec_pre.prf \
|
||||
widget/msqlquerymodel.cpp \
|
||||
src/gui/forms/forminvoiceinlist.cpp \
|
||||
src/gui/forms/formbase.cpp \
|
||||
treeitem.cpp
|
||||
treeitem.cpp \
|
||||
src/dao/productdao.cpp \
|
||||
src/dao/enterprisedao.cpp \
|
||||
src/dao/thirddao.cpp \
|
||||
src/dao/budgetdao.cpp \
|
||||
src/dao/elementdao.cpp
|
||||
QMAKE_TARGET = budgetPro
|
||||
DESTDIR =
|
||||
TARGET = budgetPro
|
||||
@@ -547,8 +567,8 @@ distdir: FORCE
|
||||
$(COPY_FILE) --parents $(DIST) $(DISTDIR)/
|
||||
$(COPY_FILE) --parents editabletreemodel.qrc $(DISTDIR)/
|
||||
$(COPY_FILE) --parents /usr/lib/x86_64-linux-gnu/qt5/mkspecs/features/data/dummy.cpp $(DISTDIR)/
|
||||
$(COPY_FILE) --parents src/gui/mainwindow.h src/gui/forms/formbaselist.h src/gui/forms/formbudgetlist.h src/models/treemodel.h itemnumberdelegate.h qmtreeview.h itemtextdelegate.h header.h mapplication.h src/gui/forms/formbudget.h utils/fiebdc.h utils/filterlineedit.h utils/filtertableheader.h widget/widgetcomboboxpopuptable.h src/gui/forms/formthird.h widget/avatarwidget.h src/gui/forms/formproduct.h data/sqltable.h itemrichtextdelegate.h src/gui/forms/dialogcreateenterprise.h utils/frameless.h src/gui/forms/dialogopencompany.h widget/companylistitemdelegate.h src/gui/forms/formelementlist.h src/gui/forms/formthirdlist.h widget/mlineeditbutton.h itemtextpopupdelegate.h widget/lineedittag.h widget/treemodelcomposeelement.h itemcomboboxdelegate.h src/gui/widgets/qlistmodel.h widget/msqlquerymodel.h src/gui/forms/forminvoiceinlist.h src/gui/forms/formbase.h treeitem.h utils/dbutils.h $(DISTDIR)/
|
||||
$(COPY_FILE) --parents src/gui/mainwindow.cpp utils/dbutils.cpp src/gui/forms/formbaselist.cpp src/gui/forms/formbudgetlist.cpp src/models/treemodel.cpp main.cpp itemnumberdelegate.cpp qmtreeview.cpp itemtextdelegate.cpp header.cpp mapplication.cpp src/gui/forms/formbudget.cpp utils/fiebdc.cpp utils/filterlineedit.cpp utils/filtertableheader.cpp widget/widgetcomboboxpopuptable.cpp src/gui/forms/formthird.cpp widget/avatarwidget.cpp src/gui/forms/formproduct.cpp itemrichtextdelegate.cpp src/gui/forms/dialogcreateenterprise.cpp utils/frameless.cpp src/gui/forms/dialogopencompany.cpp widget/companylistitemdelegate.cpp src/gui/forms/formelementlist.cpp src/gui/forms/formthirdlist.cpp widget/mlineeditbutton.cpp itemtextpopupdelegate.cpp widget/lineedittag.cpp widget/treemodelcomposeelement.cpp itemcomboboxdelegate.cpp src/gui/widgets/qlistmodel.cpp widget/msqlquerymodel.cpp src/gui/forms/forminvoiceinlist.cpp src/gui/forms/formbase.cpp treeitem.cpp $(DISTDIR)/
|
||||
$(COPY_FILE) --parents src/gui/mainwindow.h src/gui/forms/formbaselist.h src/gui/forms/formbudgetlist.h src/models/treemodel.h itemnumberdelegate.h qmtreeview.h itemtextdelegate.h header.h mapplication.h src/gui/forms/formbudget.h utils/fiebdc.h utils/filterlineedit.h utils/filtertableheader.h widget/widgetcomboboxpopuptable.h src/gui/forms/formthird.h widget/avatarwidget.h src/gui/forms/formproduct.h data/sqltable.h itemrichtextdelegate.h src/gui/forms/dialogcreateenterprise.h utils/frameless.h src/gui/forms/dialogopencompany.h widget/companylistitemdelegate.h src/gui/forms/formelementlist.h src/gui/forms/formthirdlist.h widget/mlineeditbutton.h itemtextpopupdelegate.h widget/lineedittag.h widget/treemodelcomposeelement.h itemcomboboxdelegate.h src/gui/widgets/qlistmodel.h widget/msqlquerymodel.h src/gui/forms/forminvoiceinlist.h src/gui/forms/formbase.h treeitem.h utils/dbutils.h src/dao/productdao.h src/dao/enterprisedao.h src/dao/thirddao.h src/dao/budgetdao.h src/dao/elementdao.h $(DISTDIR)/
|
||||
$(COPY_FILE) --parents src/gui/mainwindow.cpp utils/dbutils.cpp src/gui/forms/formbaselist.cpp src/gui/forms/formbudgetlist.cpp src/models/treemodel.cpp main.cpp itemnumberdelegate.cpp qmtreeview.cpp itemtextdelegate.cpp header.cpp mapplication.cpp src/gui/forms/formbudget.cpp utils/fiebdc.cpp utils/filterlineedit.cpp utils/filtertableheader.cpp widget/widgetcomboboxpopuptable.cpp src/gui/forms/formthird.cpp widget/avatarwidget.cpp src/gui/forms/formproduct.cpp itemrichtextdelegate.cpp src/gui/forms/dialogcreateenterprise.cpp utils/frameless.cpp src/gui/forms/dialogopencompany.cpp widget/companylistitemdelegate.cpp src/gui/forms/formelementlist.cpp src/gui/forms/formthirdlist.cpp widget/mlineeditbutton.cpp itemtextpopupdelegate.cpp widget/lineedittag.cpp widget/treemodelcomposeelement.cpp itemcomboboxdelegate.cpp src/gui/widgets/qlistmodel.cpp widget/msqlquerymodel.cpp src/gui/forms/forminvoiceinlist.cpp src/gui/forms/formbase.cpp treeitem.cpp src/dao/productdao.cpp src/dao/enterprisedao.cpp src/dao/thirddao.cpp src/dao/budgetdao.cpp src/dao/elementdao.cpp $(DISTDIR)/
|
||||
$(COPY_FILE) --parents src/gui/mainwindow.ui src/gui/forms/formbaselist.ui src/gui/forms/formbudget.ui src/gui/forms/formbudgetlist.ui widget/widgetcomboboxpopuptable.ui src/gui/forms/formthird.ui src/gui/forms/formproduct.ui src/gui/forms/dialogcreateenterprise.ui src/gui/forms/dialogopencompany.ui src/gui/forms/formelementlist.ui src/gui/forms/formthirdlist.ui src/gui/forms/forminvoiceinlist.ui src/gui/forms/formbase.ui $(DISTDIR)/
|
||||
|
||||
|
||||
@@ -958,12 +978,14 @@ formbudget.o: src/gui/forms/formbudget.cpp src/gui/forms/formbudget.h \
|
||||
treeitem.h \
|
||||
mapplication.h \
|
||||
src/elementtype.h \
|
||||
src/dao/elementdao.h \
|
||||
widget/widgetcomboboxpopuptable.h \
|
||||
ui_widgetcomboboxpopuptable.h \
|
||||
itemnumberdelegate.h \
|
||||
itemtextdelegate.h \
|
||||
itemtextpopupdelegate.h \
|
||||
itemcomboboxdelegate.h
|
||||
itemcomboboxdelegate.h \
|
||||
src/dao/budgetdao.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o formbudget.o src/gui/forms/formbudget.cpp
|
||||
|
||||
fiebdc.o: utils/fiebdc.cpp utils/fiebdc.h
|
||||
@@ -986,7 +1008,8 @@ formthird.o: src/gui/forms/formthird.cpp src/gui/forms/formthird.h \
|
||||
src/gui/forms/formbase.h \
|
||||
ui_formthird.h \
|
||||
widget/avatarwidget.h \
|
||||
mapplication.h
|
||||
mapplication.h \
|
||||
src/dao/thirddao.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o formthird.o src/gui/forms/formthird.cpp
|
||||
|
||||
avatarwidget.o: widget/avatarwidget.cpp widget/avatarwidget.h
|
||||
@@ -1003,7 +1026,9 @@ formproduct.o: src/gui/forms/formproduct.cpp src/gui/forms/formproduct.h \
|
||||
itemnumberdelegate.h \
|
||||
itemtextdelegate.h \
|
||||
itemtextpopupdelegate.h \
|
||||
itemcomboboxdelegate.h
|
||||
itemcomboboxdelegate.h \
|
||||
src/dao/productdao.h \
|
||||
data/sqltable.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o formproduct.o src/gui/forms/formproduct.cpp
|
||||
|
||||
itemrichtextdelegate.o: itemrichtextdelegate.cpp itemrichtextdelegate.h
|
||||
@@ -1105,6 +1130,31 @@ formbase.o: src/gui/forms/formbase.cpp src/gui/forms/formbase.h \
|
||||
treeitem.o: treeitem.cpp treeitem.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o treeitem.o treeitem.cpp
|
||||
|
||||
productdao.o: src/dao/productdao.cpp src/dao/productdao.h \
|
||||
src/gui/forms/formproduct.h \
|
||||
src/gui/forms/formbase.h \
|
||||
src/elementtype.h \
|
||||
data/sqltable.h \
|
||||
mapplication.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o productdao.o src/dao/productdao.cpp
|
||||
|
||||
enterprisedao.o: src/dao/enterprisedao.cpp src/dao/enterprisedao.h \
|
||||
mapplication.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o enterprisedao.o src/dao/enterprisedao.cpp
|
||||
|
||||
thirddao.o: src/dao/thirddao.cpp src/dao/thirddao.h \
|
||||
mapplication.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o thirddao.o src/dao/thirddao.cpp
|
||||
|
||||
budgetdao.o: src/dao/budgetdao.cpp src/dao/budgetdao.h \
|
||||
mapplication.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o budgetdao.o src/dao/budgetdao.cpp
|
||||
|
||||
elementdao.o: src/dao/elementdao.cpp src/dao/elementdao.h \
|
||||
src/elementtype.h \
|
||||
mapplication.h
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o elementdao.o src/dao/elementdao.cpp
|
||||
|
||||
qrc_editabletreemodel.o: qrc_editabletreemodel.cpp
|
||||
$(CXX) -c $(CXXFLAGS) $(INCPATH) -o qrc_editabletreemodel.o qrc_editabletreemodel.cpp
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ BudgetPro is a desktop application designed for managing company finances, budge
|
||||
- **Invoice Tracking**: Manage incoming and outgoing invoices
|
||||
- **Data Visualization**: Tree views for hierarchical financial data
|
||||
- **Custom Editors**: Specialized delegates for different data types (combobox, rich text, etc.)
|
||||
- **Template Editor**: Visual template designer for document export
|
||||
- **Document Export**: Export documents as PDF, XLSX, and DOCX with configurable templates
|
||||
|
||||
## Technical Stack
|
||||
|
||||
@@ -36,6 +38,15 @@ BudgetPro/
|
||||
├── widget/ # Custom widgets and delegates
|
||||
├── utils/ # Utility classes and helpers
|
||||
├── data/ # Data access layer (sqltable.h)
|
||||
├── templates/ # Document export templates (JSON)
|
||||
├── src/
|
||||
│ ├── dao/ # Data Access Objects
|
||||
│ │ ├── templatedao.h/cpp # Template CRUD operations
|
||||
│ │ └── templateengine.h/cpp # Export engine (PDF/XLSX/DOCX)
|
||||
│ └── gui/
|
||||
│ └── forms/
|
||||
│ ├── formtemplateeditor.h/cpp # Visual template editor
|
||||
│ └── formtemplatelist.h/cpp # Template list manager
|
||||
└── resources/ # Qt resource file (icons, stylesheets, etc.)
|
||||
```
|
||||
|
||||
@@ -80,6 +91,10 @@ BudgetPro includes several custom Qt components:
|
||||
- Item numbering in hierarchical views
|
||||
- Popup tables for complex selection
|
||||
- `TreeModel`: Custom model for tree-structured data
|
||||
- `TemplateEngine`: Document export engine supporting PDF, XLSX, DOCX
|
||||
- `TemplateDAO`: Data access for document templates
|
||||
- `formTemplateEditor`: Visual template designer
|
||||
- `formTemplateList`: Template list management
|
||||
- `AvatarWidget`: For displaying user/entity avatars
|
||||
|
||||
## Extending the Application
|
||||
|
||||
+37
-22
@@ -15,7 +15,7 @@ INCLUDEPATH = \
|
||||
src/gui/forms \
|
||||
src/models
|
||||
|
||||
FORMS = src/gui/mainwindow.ui \
|
||||
FORMS = src/gui/mainwindow/mainwindow.ui \
|
||||
src/gui/forms/formbaselist.ui \
|
||||
src/gui/forms/formbudget.ui \
|
||||
src/gui/forms/formbudgetlist.ui \
|
||||
@@ -30,15 +30,15 @@ FORMS = src/gui/mainwindow.ui \
|
||||
src/gui/forms/formbase.ui
|
||||
|
||||
|
||||
HEADERS = src/gui/mainwindow.h \
|
||||
HEADERS = src/gui/mainwindow/mainwindow.h \
|
||||
src/gui/forms/formbaselist.h \
|
||||
src/gui/forms/formbudgetlist.h \
|
||||
src/models/treemodel.h \
|
||||
itemnumberdelegate.h \
|
||||
qmtreeview.h \
|
||||
itemtextdelegate.h \
|
||||
header.h \
|
||||
mapplication.h \
|
||||
src/gui/widgets/itemnumberdelegate.h \
|
||||
src/gui/widgets/qmtreeview.h \
|
||||
src/gui/widgets/itemtextdelegate.h \
|
||||
src/utils/header.h \
|
||||
src/app/mapplication.h \
|
||||
src/gui/forms/formbudget.h \
|
||||
utils/fiebdc.h \
|
||||
utils/filterlineedit.h \
|
||||
@@ -48,7 +48,7 @@ HEADERS = src/gui/mainwindow.h \
|
||||
widget/avatarwidget.h \
|
||||
src/gui/forms/formproduct.h \
|
||||
data/sqltable.h \
|
||||
itemrichtextdelegate.h \
|
||||
src/gui/widgets/itemrichtextdelegate.h \
|
||||
src/gui/forms/dialogcreateenterprise.h \
|
||||
utils/frameless.h \
|
||||
src/gui/forms/dialogopencompany.h \
|
||||
@@ -56,31 +56,31 @@ HEADERS = src/gui/mainwindow.h \
|
||||
src/gui/forms/formelementlist.h \
|
||||
src/gui/forms/formthirdlist.h \
|
||||
widget/mlineeditbutton.h \
|
||||
itemtextpopupdelegate.h \
|
||||
src/gui/widgets/itemtextpopupdelegate.h \
|
||||
widget/lineedittag.h \
|
||||
widget/treemodelcomposeelement.h \
|
||||
itemcomboboxdelegate.h \
|
||||
src/gui/widgets/itemcomboboxdelegate.h \
|
||||
src/gui/widgets/qlistmodel.h \
|
||||
widget/msqlquerymodel.h \
|
||||
src/gui/forms/forminvoiceinlist.h \
|
||||
src/gui/forms/formbase.h \
|
||||
treeitem.h
|
||||
src/models/treeitem.h
|
||||
|
||||
|
||||
RESOURCES = editabletreemodel.qrc
|
||||
|
||||
|
||||
SOURCES = src/gui/mainwindow.cpp \
|
||||
SOURCES = src/gui/mainwindow/mainwindow.cpp \
|
||||
utils/dbutils.cpp \
|
||||
src/gui/forms/formbaselist.cpp \
|
||||
src/gui/forms/formbudgetlist.cpp \
|
||||
src/models/treemodel.cpp \
|
||||
main.cpp \
|
||||
itemnumberdelegate.cpp \
|
||||
qmtreeview.cpp \
|
||||
itemtextdelegate.cpp \
|
||||
header.cpp \
|
||||
mapplication.cpp \
|
||||
src/main.cpp \
|
||||
src/gui/widgets/itemnumberdelegate.cpp \
|
||||
src/gui/widgets/qmtreeview.cpp \
|
||||
src/gui/widgets/itemtextdelegate.cpp \
|
||||
src/utils/header.cpp \
|
||||
src/app/mapplication.cpp \
|
||||
src/gui/forms/formbudget.cpp \
|
||||
utils/fiebdc.cpp \
|
||||
utils/filterlineedit.cpp \
|
||||
@@ -89,7 +89,7 @@ SOURCES = src/gui/mainwindow.cpp \
|
||||
src/gui/forms/formthird.cpp \
|
||||
widget/avatarwidget.cpp \
|
||||
src/gui/forms/formproduct.cpp \
|
||||
itemrichtextdelegate.cpp \
|
||||
src/gui/widgets/itemrichtextdelegate.cpp \
|
||||
src/gui/forms/dialogcreateenterprise.cpp \
|
||||
utils/frameless.cpp \
|
||||
src/gui/forms/dialogopencompany.cpp \
|
||||
@@ -97,15 +97,15 @@ SOURCES = src/gui/mainwindow.cpp \
|
||||
src/gui/forms/formelementlist.cpp \
|
||||
src/gui/forms/formthirdlist.cpp \
|
||||
widget/mlineeditbutton.cpp \
|
||||
itemtextpopupdelegate.cpp \
|
||||
src/gui/widgets/itemtextpopupdelegate.cpp \
|
||||
widget/lineedittag.cpp \
|
||||
widget/treemodelcomposeelement.cpp \
|
||||
itemcomboboxdelegate.cpp \
|
||||
src/gui/widgets/itemcomboboxdelegate.cpp \
|
||||
src/gui/widgets/qlistmodel.cpp \
|
||||
widget/msqlquerymodel.cpp \
|
||||
src/gui/forms/forminvoiceinlist.cpp \
|
||||
src/gui/forms/formbase.cpp \
|
||||
treeitem.cpp
|
||||
src/models/treeitem.cpp
|
||||
|
||||
|
||||
# install
|
||||
@@ -113,3 +113,18 @@ target.path = $$[QT_INSTALL_EXAMPLES]/widgets/itemviews/editabletreemodel
|
||||
INSTALLS += target
|
||||
|
||||
HEADERS += utils/dbutils.h
|
||||
|
||||
# DAO sources
|
||||
SOURCES += \
|
||||
src/dao/productdao.cpp \
|
||||
src/dao/enterprisedao.cpp \
|
||||
src/dao/thirddao.cpp \
|
||||
src/dao/budgetdao.cpp \
|
||||
src/dao/elementdao.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/dao/productdao.h \
|
||||
src/dao/enterprisedao.h \
|
||||
src/dao/thirddao.h \
|
||||
src/dao/budgetdao.h \
|
||||
src/dao/elementdao.h
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
@echo off
|
||||
:: Build script for Windows
|
||||
set BUILD_DIR=build
|
||||
if not exist %BUILD_DIR% mkdir %BUILD_DIR%
|
||||
cd %BUILD_DIR%
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
cd ..
|
||||
echo Build complete. Binary located in %BUILD_DIR%\Release\BudgetPro.exe
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
# Build script for Linux and macOS
|
||||
BUILD_DIR="build"
|
||||
|
||||
if [ ! -d "$BUILD_DIR" ]; then
|
||||
mkdir $BUILD_DIR
|
||||
fi
|
||||
|
||||
cd $BUILD_DIR
|
||||
cmake ..
|
||||
make -j$(nproc)
|
||||
cd ..
|
||||
echo "Build complete. Binary located in $BUILD_DIR/BudgetPro"
|
||||
+79
-132
@@ -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
|
||||
@@ -539,10 +467,29 @@ const QString tContact = "CREATE TABLE CONTACT ("
|
||||
|
||||
|
||||
|
||||
//----------------------- TEMPLATE -----------------------------------------
|
||||
const QString tTemplate = "CREATE TABLE TEMPLATE ("
|
||||
"ID INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||
"NAME VARCHAR(100) NOT NULL, "
|
||||
"DESCRIPTION VARCHAR(500), "
|
||||
"DOCUMENT_TYPE VARCHAR(20) NOT NULL, "
|
||||
"WIDTH_MM FLOAT DEFAULT 210, "
|
||||
"HEIGHT_MM FLOAT DEFAULT 297, "
|
||||
"MARGIN_TOP FLOAT DEFAULT 20, "
|
||||
"MARGIN_BOTTOM FLOAT DEFAULT 20, "
|
||||
"MARGIN_LEFT FLOAT DEFAULT 20, "
|
||||
"MARGIN_RIGHT FLOAT DEFAULT 20, "
|
||||
"CONTENT TEXT, "
|
||||
"IS_DEFAULT BOOLEAN DEFAULT 0, "
|
||||
"CREATEDBY VARCHAR(100), "
|
||||
"CREATEDAT DATETIME DEFAULT CURRENT_TIMESTAMP, "
|
||||
"UPDATEDAT DATETIME DEFAULT CURRENT_TIMESTAMP"
|
||||
");";
|
||||
|
||||
const QStringList dbTables = {tDBInfo, tEmpresaInfo, tThird, tElemento, tElemComp, tUnidad, tPropuestaVenta, tDataPropuestaVenta,
|
||||
tDocVenta, tDataDocVenta, tDocCompra, tDataDocCompra, tContact};
|
||||
tDocVenta, tDataDocVenta, tDocCompra, tDataDocCompra, tContact, tTemplate, tProjectDocument, tProjectBudget};
|
||||
|
||||
const QStringList dbTableNames = {"DBINFO", "ENTERPRISESINFO", "THIRD", "ELEMENT", "ELEMENTCOMPOSITION", "UNIT", "SALEPROPOSAL", "SALEPROPOSALDATA",
|
||||
"SALEDOCUMENT", "SALEDOCUMENTDATA", "BUYDOCUMENT", "BUYDOCUMENTDATA", "CONTACT"};
|
||||
"SALEDOCUMENT", "SALEDOCUMENTDATA", "BUYDOCUMENT", "BUYDOCUMENTDATA", "CONTACT", "TEMPLATE", "PROJECTDOCUMENT", "PROJECTBUDGET"};
|
||||
|
||||
#endif // SQLTABLE_H
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,178 +0,0 @@
|
||||
#include "formelementlist.h"
|
||||
#include "qpainter.h"
|
||||
#include "ui_formelementlist.h"
|
||||
#include "formproduct.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mapplication.h"
|
||||
#include "msqlquerymodel.h"
|
||||
#include "utils/filtertableheader.h"
|
||||
#include "gui/formbaselist.h"
|
||||
|
||||
#include <QDrag>
|
||||
|
||||
|
||||
formElementList::formElementList(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::formElementList)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
mModel = new MSqlQueryModel(this);
|
||||
ui->tableView->setModel(mModel);
|
||||
updateList();
|
||||
ui->tableView->setColumnWidth(0, 150);
|
||||
ui->tableView->setColumnWidth(1, 80);
|
||||
ui->tableView->setColumnWidth(2, 120);
|
||||
ui->tableView->setColumnWidth(3, 350);
|
||||
ui->tableView->setColumnWidth(4, 80);
|
||||
ui->tableView->setColumnWidth(5, 80);
|
||||
ui->tableView->setColumnWidth(6, 40);
|
||||
|
||||
// Set up filter row
|
||||
auto *m_tableHeader = new FilterTableHeader(ui->tableView);
|
||||
ui->tableView->setHorizontalHeader(m_tableHeader);
|
||||
m_tableHeader->setFilter(0, "");
|
||||
m_tableHeader->setFocusColumn(0);
|
||||
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(0, Qt::Horizontal, tr("Tipo"));
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(1, Qt::Horizontal, tr("Clase"));
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(2, Qt::Horizontal, tr("Código"));
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(3, Qt::Horizontal, tr("Resumen"));
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(4, Qt::Horizontal, tr("Coste"));
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(5, Qt::Horizontal, tr("Venta"));
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(6, Qt::Horizontal, tr("Activo"));
|
||||
|
||||
ui->tableView->setDragEnabled(true); // Habilita el drag
|
||||
connect(ui->tableView, &QTableView::pressed, this, &formElementList::startDrag);
|
||||
}
|
||||
|
||||
formElementList::~formElementList()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void formElementList::updateList()
|
||||
{
|
||||
dApp->Enterprise().open();
|
||||
mModel->setQuery("SELECT TYPE1, TYPE2, CODE, TITLE, PURCHASE_PRICE, SALE_PRICE, STATE FROM ELEMENT" /*" ORDER BY CODE ASC"*/,
|
||||
dApp->Enterprise());
|
||||
dApp->Enterprise().close();
|
||||
}
|
||||
|
||||
void formElementList::on_buttonNew_released()
|
||||
{
|
||||
formProduct *form = dApp->mainWindow()->createFormProduct(); // sustistuir por Mainwindow::createFormProduct();
|
||||
form->show();
|
||||
}
|
||||
|
||||
void formElementList::on_buttonEdit_released()
|
||||
{
|
||||
openDocument(ui->tableView->currentIndex());
|
||||
}
|
||||
|
||||
void formElementList::on_buttonClone_released()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void formElementList::on_buttonDelete_released()
|
||||
{
|
||||
QModelIndex index = ui->tableView->currentIndex();
|
||||
QAbstractItemModel *model = const_cast<QAbstractItemModel*>(index.model()); // Obtén el modelo asociado
|
||||
if (index.column() != 0)
|
||||
{
|
||||
//index = index.parent().child(index.row(), 0);
|
||||
index = model->index(index.row(), 0, index.parent());
|
||||
}
|
||||
QString ID = index.data().toString();
|
||||
QModelIndex parentIndex = index.parent();
|
||||
QModelIndex childIndex = model->index(index.row(), 2, parentIndex); // Obtén el índice del hijo
|
||||
int type = childIndex.data().toInt(); // Accede al dato
|
||||
//int type = index.parent().child(index.row(), 2).data().toInt();
|
||||
|
||||
dApp->Enterprise().open();
|
||||
QSqlQuery qry = QSqlQuery(dApp->Enterprise());
|
||||
|
||||
/*
|
||||
if (index.parent().child(index.row(), 2).data().toInt() == 0)
|
||||
{
|
||||
// TODO: borrar la composición
|
||||
if(!qry.exec(QString("DELETE FROM ELEMENTCOMPOSITION WHERE CODE = '%1';").arg(ID)))
|
||||
{
|
||||
qDebug() << "Error ejecutando el query: " << qry.lastError().text() << "\n";
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if(!qry.exec(QString("DELETE FROM ELEMENT WHERE CODE = '%1';").arg(ID)))
|
||||
{
|
||||
qDebug() << "Error ejecutando el query: " << qry.lastError().text() << "\n";
|
||||
}
|
||||
updateList();
|
||||
|
||||
error:
|
||||
dApp->Enterprise().close();
|
||||
}
|
||||
|
||||
void formElementList::on_buttonUpdate_released()
|
||||
{
|
||||
updateList();
|
||||
}
|
||||
|
||||
void formElementList::on_tableView_doubleClicked(const QModelIndex &index)
|
||||
{
|
||||
openDocument(index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void formElementList::openDocument(QModelIndex index)
|
||||
{
|
||||
QAbstractItemModel *model = ui->tableView->model();
|
||||
//QModelIndex item = index;
|
||||
formProduct *form = dApp->mainWindow()->createFormProduct();
|
||||
|
||||
//if (index.column() != 2)
|
||||
// item = index.parent().child(index.row(), 2);
|
||||
form->openDocument(model->index(index.row(), 2).data().toString());// item.data().toString());
|
||||
form->show();
|
||||
}
|
||||
|
||||
|
||||
void formElementList::startDrag(const QModelIndex &index) {
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
// Crear datos MIME
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
QString data = mModel->data(index).toString();
|
||||
mimeData->setText(data);
|
||||
|
||||
// Iniciar arrastre
|
||||
QDrag *drag = new QDrag(ui->tableView);
|
||||
drag->setMimeData(mimeData);
|
||||
|
||||
// Crear un ícono para el cursor
|
||||
QPixmap pixmap(100, 30);
|
||||
pixmap.fill(Qt::transparent); // Fondo transparente
|
||||
|
||||
QPainter painter(&pixmap);
|
||||
painter.setBrush(Qt::yellow);
|
||||
painter.drawRoundedRect(0, 0, pixmap.width(), pixmap.height(), 5, 5);
|
||||
|
||||
painter.setPen(Qt::black);
|
||||
painter.drawText(pixmap.rect(), Qt::AlignCenter, data);
|
||||
painter.end();
|
||||
|
||||
drag->setPixmap(pixmap); // Asignar el ícono al cursor
|
||||
//drag->setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2)); // Centro del ícono como punto caliente
|
||||
|
||||
|
||||
drag->exec(Qt::MoveAction);
|
||||
}
|
||||
|
||||
@@ -1,178 +0,0 @@
|
||||
#include "formelementlist.h"
|
||||
#include "qpainter.h"
|
||||
#include "ui_formelementlist.h"
|
||||
#include "formproduct.h"
|
||||
#include "mainwindow.h"
|
||||
#include "mapplication.h"
|
||||
#include "msqlquerymodel.h"
|
||||
#include "utils/filtertableheader.h"
|
||||
#include "gui/formbaselist.h"
|
||||
|
||||
#include <QDrag>
|
||||
|
||||
|
||||
formElementList::formElementList(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::formElementList)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
mModel = new MSqlQueryModel(this);
|
||||
ui->tableView->setModel(mModel);
|
||||
updateList();
|
||||
ui->tableView->setColumnWidth(0, 150);
|
||||
ui->tableView->setColumnWidth(1, 80);
|
||||
ui->tableView->setColumnWidth(2, 120);
|
||||
ui->tableView->setColumnWidth(3, 350);
|
||||
ui->tableView->setColumnWidth(4, 80);
|
||||
ui->tableView->setColumnWidth(5, 80);
|
||||
ui->tableView->setColumnWidth(6, 40);
|
||||
|
||||
// Set up filter row
|
||||
auto *m_tableHeader = new FilterTableHeader(ui->tableView);
|
||||
ui->tableView->setHorizontalHeader(m_tableHeader);
|
||||
m_tableHeader->setFilter(0, "");
|
||||
m_tableHeader->setFocusColumn(0);
|
||||
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(0, Qt::Horizontal, tr("Tipo"));
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(1, Qt::Horizontal, tr("Clase"));
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(2, Qt::Horizontal, tr("Código"));
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(3, Qt::Horizontal, tr("Resumen"));
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(4, Qt::Horizontal, tr("Coste"));
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(5, Qt::Horizontal, tr("Venta"));
|
||||
ui->tableView->horizontalHeader()->model()->setHeaderData(6, Qt::Horizontal, tr("Activo"));
|
||||
|
||||
ui->tableView->setDragEnabled(true); // Habilita el drag
|
||||
connect(ui->tableView, &QTableView::pressed, this, &formElementList::startDrag);
|
||||
}
|
||||
|
||||
formElementList::~formElementList()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void formElementList::updateList()
|
||||
{
|
||||
dApp->Enterprise().open();
|
||||
mModel->setQuery("SELECT TYPE1, TYPE2, CODE, TITLE, PURCHASE_PRICE, SALE_PRICE, STATE FROM ELEMENT" /*" ORDER BY CODE ASC"*/,
|
||||
dApp->Enterprise());
|
||||
dApp->Enterprise().close();
|
||||
}
|
||||
|
||||
void formElementList::on_buttonNew_released()
|
||||
{
|
||||
formProduct *form = dApp->mainWindow()->createFormProduct(); // sustistuir por Mainwindow::createFormProduct();
|
||||
form->show();
|
||||
}
|
||||
|
||||
void formElementList::on_buttonEdit_released()
|
||||
{
|
||||
openDocument(ui->tableView->currentIndex());
|
||||
}
|
||||
|
||||
void formElementList::on_buttonClone_released()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void formElementList::on_buttonDelete_released()
|
||||
{
|
||||
QModelIndex index = ui->tableView->currentIndex();
|
||||
QAbstractItemModel *model = const_cast<QAbstractItemModel*>(index.model()); // Obtén el modelo asociado
|
||||
if (index.column() != 0)
|
||||
{
|
||||
//index = index.parent().child(index.row(), 0);
|
||||
index = model->index(index.row(), 0, index.parent());
|
||||
}
|
||||
QString ID = index.data().toString();
|
||||
QModelIndex parentIndex = index.parent();
|
||||
QModelIndex childIndex = model->index(index.row(), 2, parentIndex); // Obtén el índice del hijo
|
||||
int type = childIndex.data().toInt(); // Accede al dato
|
||||
//int type = index.parent().child(index.row(), 2).data().toInt();
|
||||
|
||||
dApp->Enterprise().open();
|
||||
QSqlQuery qry = QSqlQuery(dApp->Enterprise());
|
||||
|
||||
/*
|
||||
if (index.parent().child(index.row(), 2).data().toInt() == 0)
|
||||
{
|
||||
// TODO: borrar la composición
|
||||
if(!qry.exec(QString("DELETE FROM ELEMENTCOMPOSITION WHERE CODE = '%1';").arg(ID)))
|
||||
{
|
||||
qDebug() << "Error ejecutando el query: " << qry.lastError().text() << "\n";
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if(!qry.exec(QString("DELETE FROM ELEMENT WHERE CODE = '%1';").arg(ID)))
|
||||
{
|
||||
qDebug() << "Error ejecutando el query: " << qry.lastError().text() << "\n";
|
||||
}
|
||||
updateList();
|
||||
|
||||
error:
|
||||
dApp->Enterprise().close();
|
||||
}
|
||||
|
||||
void formElementList::on_buttonUpdate_released()
|
||||
{
|
||||
updateList();
|
||||
}
|
||||
|
||||
void formElementList::on_tableView_doubleClicked(const QModelIndex &index)
|
||||
{
|
||||
openDocument(index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void formElementList::openDocument(QModelIndex index)
|
||||
{
|
||||
QAbstractItemModel *model = ui->tableView->model();
|
||||
//QModelIndex item = index;
|
||||
formProduct *form = dApp->mainWindow()->createFormProduct();
|
||||
|
||||
//if (index.column() != 2)
|
||||
// item = index.parent().child(index.row(), 2);
|
||||
form->openDocument(model->index(index.row(), 2).data().toString());// item.data().toString());
|
||||
form->show();
|
||||
}
|
||||
|
||||
|
||||
void formElementList::startDrag(const QModelIndex &index) {
|
||||
if (!index.isValid())
|
||||
return;
|
||||
|
||||
// Crear datos MIME
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
QString data = mModel->data(index).toString();
|
||||
mimeData->setText(data);
|
||||
|
||||
// Iniciar arrastre
|
||||
QDrag *drag = new QDrag(ui->tableView);
|
||||
drag->setMimeData(mimeData);
|
||||
|
||||
// Crear un ícono para el cursor
|
||||
QPixmap pixmap(100, 30);
|
||||
pixmap.fill(Qt::transparent); // Fondo transparente
|
||||
|
||||
QPainter painter(&pixmap);
|
||||
painter.setBrush(Qt::yellow);
|
||||
painter.drawRoundedRect(0, 0, pixmap.width(), pixmap.height(), 5, 5);
|
||||
|
||||
painter.setPen(Qt::black);
|
||||
painter.drawText(pixmap.rect(), Qt::AlignCenter, data);
|
||||
painter.end();
|
||||
|
||||
drag->setPixmap(pixmap); // Asignar el ícono al cursor
|
||||
//drag->setHotSpot(QPoint(pixmap.width() / 2, pixmap.height() / 2)); // Centro del ícono como punto caliente
|
||||
|
||||
|
||||
drag->exec(Qt::MoveAction);
|
||||
}
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
#ifndef FORMPRODUCT_H
|
||||
#define FORMPRODUCT_H
|
||||
|
||||
#include <QWidget>
|
||||
#include "formbase.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class formProduct;
|
||||
}
|
||||
|
||||
class formProduct : public formBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
//explicit formProduct(QWidget *parent = 0);
|
||||
explicit formProduct(QString aID = "", int aEditMode = 0, QWidget *parent = nullptr);
|
||||
~formProduct();
|
||||
|
||||
void newDocument() override {}
|
||||
void openDocument(QString id) override;
|
||||
void closeDocument() override;
|
||||
void save() override;
|
||||
bool needsave() override { return mNeedSave; }
|
||||
void setEditMode(bool aMode) override {}
|
||||
|
||||
public slots:
|
||||
void on_ModelSetData(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles);
|
||||
private slots:
|
||||
void on_editPC_valueChanged(double arg1);
|
||||
void on_editMargin_valueChanged(double arg1);
|
||||
void on_editPV_valueChanged(double arg1);
|
||||
void on_comboIVA_currentIndexChanged(const QString &arg1);
|
||||
void on_editPV_editingFinished();
|
||||
void on_buttonSave_released();
|
||||
|
||||
void on_editPVIVA_valueChanged(const QString &arg1);
|
||||
|
||||
void on_comboType2_currentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
Ui::formProduct *ui;
|
||||
bool editMode;
|
||||
|
||||
void CalculatePrice();
|
||||
bool InsertElement(QString ID, QModelIndex index);
|
||||
void setLineType(QString type, QModelIndex index);
|
||||
void setCellText(QString val, QModelIndex index, int col);
|
||||
void setEditMode();
|
||||
void setComposeElement(bool val);
|
||||
};
|
||||
|
||||
#endif // FORMPRODUCT_H
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+43
-2
@@ -124,9 +124,8 @@ bool ProductDAO::update(const QString& code, int type1, int type2, const QString
|
||||
"UNIT_ID = :UNIT_ID, DATE_UPDATE = :DATE_UPDATE, REAL_PRICE = :REAL_PRICE, DISCOUNT = :DISCOUNT, "
|
||||
"PURCHASE_PRICE = :PURCHASE_PRICE, BENEFIT = :BENEFIT, TAX = :TAX, SALE_PRICE = :SALE_PRICE, BARCODE = :BARCODE, IMAGE = :IMAGE, "
|
||||
"STATE = :STATE, MANUFACTURER = :MANUFACTURER, GAMMA = :GAMMA, WEIGHT = :WEIGHT, HEIGHT = :HEIGHT, "
|
||||
"WIDTH = :WIDTH, LENGHT = :LENGHT "
|
||||
"WIDTH = :WIDTH, LENGHT = :LENGHT "\
|
||||
"WHERE CODE = :CODE");
|
||||
);
|
||||
|
||||
qry.bindValue(":TYPE1", type1);
|
||||
qry.bindValue(":TYPE2", type2);
|
||||
@@ -294,3 +293,45 @@ bool ProductDAO::updateCompositionElement(const QString& productCode, const QStr
|
||||
dApp->Enterprise().close();
|
||||
return success;
|
||||
}
|
||||
|
||||
// Remove all composition elements for a product
|
||||
bool ProductDAO::removeAllComposition(const QString& productCode)
|
||||
{
|
||||
dApp->Enterprise().open();
|
||||
QSqlQuery qry = QSqlQuery(dApp->Enterprise());
|
||||
qry.prepare("DELETE FROM ELEMENTCOMPOSITION WHERE CODE = :CODE");
|
||||
qry.bindValue(":CODE", productCode);
|
||||
|
||||
bool success = qry.exec();
|
||||
if (!success) {
|
||||
qDebug() << "Error removing all composition elements:" << qry.lastError().text();
|
||||
}
|
||||
dApp->Enterprise().close();
|
||||
return success;
|
||||
}
|
||||
|
||||
// Get basic element info (title, unit) for display in composition tree
|
||||
bool ProductDAO::getElementBasicInfo(const QString& code, QString& title, QString& unitId)
|
||||
{
|
||||
dApp->Enterprise().open();
|
||||
QSqlQuery qry = QSqlQuery(dApp->Enterprise());
|
||||
qry.prepare("SELECT TITLE, UNIT_ID FROM ELEMENT WHERE CODE = :CODE");
|
||||
qry.bindValue(":CODE", code);
|
||||
|
||||
bool success = qry.exec();
|
||||
if (!success) {
|
||||
qDebug() << "Error getting element basic info:" << qry.lastError().text();
|
||||
dApp->Enterprise().close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (qry.next()) {
|
||||
title = qry.value(0).toString();
|
||||
unitId = qry.value(1).toString();
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
dApp->Enterprise().close();
|
||||
return success;
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <QSqlError>
|
||||
#include <QDebug>
|
||||
#include <QVector>
|
||||
#include "../gui/formproduct.h"
|
||||
#include "../gui/forms/formproduct.h"
|
||||
#include "../data/sqltable.h"
|
||||
|
||||
class ProductDAO
|
||||
@@ -58,6 +58,12 @@ public:
|
||||
|
||||
// Update composition element amount
|
||||
static bool updateCompositionElement(const QString& productCode, const QString& elementCode, double amount);
|
||||
|
||||
// Remove all composition elements for a product
|
||||
static bool removeAllComposition(const QString& productCode);
|
||||
|
||||
// Get basic element info (title, unit) for display in composition tree
|
||||
static bool getElementBasicInfo(const QString& code, QString& title, QString& unitId);
|
||||
};
|
||||
|
||||
#endif // PRODUCTDAO_H
|
||||
@@ -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};
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,152 @@
|
||||
#include "templatedao.h"
|
||||
#include "../../data/sqltable.h"
|
||||
|
||||
bool TemplateDAO::create(Template &tpl)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare(
|
||||
"INSERT INTO TEMPLATE ("
|
||||
"NAME, DESCRIPTION, DOCUMENT_TYPE, WIDTH_MM, HEIGHT_MM, "
|
||||
"MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT, CONTENT, IS_DEFAULT, CREATEDBY"
|
||||
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
);
|
||||
query.addBindValue(tpl.name);
|
||||
query.addBindValue(tpl.description);
|
||||
query.addBindValue(tpl.documentType);
|
||||
query.addBindValue(tpl.widthMM);
|
||||
query.addBindValue(tpl.heightMM);
|
||||
query.addBindValue(tpl.marginTop);
|
||||
query.addBindValue(tpl.marginBottom);
|
||||
query.addBindValue(tpl.marginLeft);
|
||||
query.addBindValue(tpl.marginRight);
|
||||
query.addBindValue(tpl.content);
|
||||
query.addBindValue(tpl.isDefault ? 1 : 0);
|
||||
query.addBindValue(tpl.createdBy);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "TemplateDAO::create - Error:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
tpl.id = query.lastInsertId().toInt();
|
||||
return true;
|
||||
}
|
||||
|
||||
QVector<Template> TemplateDAO::getAll()
|
||||
{
|
||||
QVector<Template> result;
|
||||
QSqlQuery query("SELECT ID, NAME, DESCRIPTION, DOCUMENT_TYPE, WIDTH_MM, HEIGHT_MM, "
|
||||
"MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT, CONTENT, IS_DEFAULT, CREATEDBY "
|
||||
"FROM TEMPLATE ORDER BY NAME");
|
||||
while (query.next()) {
|
||||
Template tpl;
|
||||
tpl.id = query.value(0).toInt();
|
||||
tpl.name = query.value(1).toString();
|
||||
tpl.description = query.value(2).toString();
|
||||
tpl.documentType = query.value(3).toString();
|
||||
tpl.widthMM = query.value(4).toDouble();
|
||||
tpl.heightMM = query.value(5).toDouble();
|
||||
tpl.marginTop = query.value(6).toDouble();
|
||||
tpl.marginBottom = query.value(7).toDouble();
|
||||
tpl.marginLeft = query.value(8).toDouble();
|
||||
tpl.marginRight = query.value(9).toDouble();
|
||||
tpl.content = query.value(10).toString();
|
||||
tpl.isDefault = query.value(11).toBool();
|
||||
tpl.createdBy = query.value(12).toString();
|
||||
result.append(tpl);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Template TemplateDAO::getById(int id)
|
||||
{
|
||||
Template tpl;
|
||||
QSqlQuery query;
|
||||
query.prepare("SELECT ID, NAME, DESCRIPTION, DOCUMENT_TYPE, WIDTH_MM, HEIGHT_MM, "
|
||||
"MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT, CONTENT, IS_DEFAULT, CREATEDBY "
|
||||
"FROM TEMPLATE WHERE ID = ?");
|
||||
query.addBindValue(id);
|
||||
if (query.exec() && query.next()) {
|
||||
tpl.id = query.value(0).toInt();
|
||||
tpl.name = query.value(1).toString();
|
||||
tpl.description = query.value(2).toString();
|
||||
tpl.documentType = query.value(3).toString();
|
||||
tpl.widthMM = query.value(4).toDouble();
|
||||
tpl.heightMM = query.value(5).toDouble();
|
||||
tpl.marginTop = query.value(6).toDouble();
|
||||
tpl.marginBottom = query.value(7).toDouble();
|
||||
tpl.marginLeft = query.value(8).toDouble();
|
||||
tpl.marginRight = query.value(9).toDouble();
|
||||
tpl.content = query.value(10).toString();
|
||||
tpl.isDefault = query.value(11).toBool();
|
||||
tpl.createdBy = query.value(12).toString();
|
||||
}
|
||||
return tpl;
|
||||
}
|
||||
|
||||
bool TemplateDAO::update(const Template &tpl)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare(
|
||||
"UPDATE TEMPLATE SET "
|
||||
"NAME=?, DESCRIPTION=?, DOCUMENT_TYPE=?, WIDTH_MM=?, HEIGHT_MM=?, "
|
||||
"MARGIN_TOP=?, MARGIN_BOTTOM=?, MARGIN_LEFT=?, MARGIN_RIGHT=?, "
|
||||
"CONTENT=?, IS_DEFAULT=? "
|
||||
"WHERE ID=?"
|
||||
);
|
||||
query.addBindValue(tpl.name);
|
||||
query.addBindValue(tpl.description);
|
||||
query.addBindValue(tpl.documentType);
|
||||
query.addBindValue(tpl.widthMM);
|
||||
query.addBindValue(tpl.heightMM);
|
||||
query.addBindValue(tpl.marginTop);
|
||||
query.addBindValue(tpl.marginBottom);
|
||||
query.addBindValue(tpl.marginLeft);
|
||||
query.addBindValue(tpl.marginRight);
|
||||
query.addBindValue(tpl.content);
|
||||
query.addBindValue(tpl.isDefault ? 1 : 0);
|
||||
query.addBindValue(tpl.id);
|
||||
|
||||
if (!query.exec()) {
|
||||
qWarning() << "TemplateDAO::update - Error:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TemplateDAO::remove(int id)
|
||||
{
|
||||
QSqlQuery query;
|
||||
query.prepare("DELETE FROM TEMPLATE WHERE ID = ?");
|
||||
query.addBindValue(id);
|
||||
if (!query.exec()) {
|
||||
qWarning() << "TemplateDAO::remove - Error:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Template TemplateDAO::getDefaultForType(const QString &documentType)
|
||||
{
|
||||
Template tpl;
|
||||
QSqlQuery query;
|
||||
query.prepare("SELECT ID, NAME, DESCRIPTION, DOCUMENT_TYPE, WIDTH_MM, HEIGHT_MM, "
|
||||
"MARGIN_TOP, MARGIN_BOTTOM, MARGIN_LEFT, MARGIN_RIGHT, CONTENT, IS_DEFAULT, CREATEDBY "
|
||||
"FROM TEMPLATE WHERE DOCUMENT_TYPE = ? AND IS_DEFAULT = 1 LIMIT 1");
|
||||
query.addBindValue(documentType);
|
||||
if (query.exec() && query.next()) {
|
||||
tpl.id = query.value(0).toInt();
|
||||
tpl.name = query.value(1).toString();
|
||||
tpl.description = query.value(2).toString();
|
||||
tpl.documentType = query.value(3).toString();
|
||||
tpl.widthMM = query.value(4).toDouble();
|
||||
tpl.heightMM = query.value(5).toDouble();
|
||||
tpl.marginTop = query.value(6).toDouble();
|
||||
tpl.marginBottom = query.value(7).toDouble();
|
||||
tpl.marginLeft = query.value(8).toDouble();
|
||||
tpl.marginRight = query.value(9).toDouble();
|
||||
tpl.content = query.value(10).toString();
|
||||
tpl.isDefault = query.value(11).toBool();
|
||||
tpl.createdBy = query.value(12).toString();
|
||||
}
|
||||
return tpl;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef TEMPLATEDAO_H
|
||||
#define TEMPLATEDAO_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QDebug>
|
||||
#include <QVector>
|
||||
|
||||
class Template
|
||||
{
|
||||
public:
|
||||
int id = 0;
|
||||
QString name;
|
||||
QString description;
|
||||
QString documentType; // budget, invoice, project, purchase, third, generic
|
||||
double widthMM = 210;
|
||||
double heightMM = 297;
|
||||
double marginTop = 20;
|
||||
double marginBottom = 20;
|
||||
double marginLeft = 20;
|
||||
double marginRight = 20;
|
||||
QString content; // JSON con definicion de elementos
|
||||
bool isDefault = false;
|
||||
QString createdBy;
|
||||
};
|
||||
|
||||
class TemplateDAO : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TemplateDAO(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
static bool create(Template &tpl);
|
||||
static QVector<Template> getAll();
|
||||
static Template getById(int id);
|
||||
static bool update(const Template &tpl);
|
||||
static bool remove(int id);
|
||||
static Template getDefaultForType(const QString &documentType);
|
||||
};
|
||||
|
||||
#endif // TEMPLATEDAO_H
|
||||
@@ -0,0 +1,265 @@
|
||||
#include "templateengine.h"
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QTextStream>
|
||||
#include <QProcess>
|
||||
#include <QRegularExpression>
|
||||
#include <QStandardPaths>
|
||||
|
||||
QString TemplateEngine::exportDir()
|
||||
{
|
||||
QString dir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/BudgetPro_Export";
|
||||
if (!QDir(dir).exists())
|
||||
QDir().mkpath(dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
QString TemplateEngine::resolveValue(const QString &text, const QJsonObject &data)
|
||||
{
|
||||
QString result = text;
|
||||
static QRegularExpression re("\\{\\{(.+?)\\}\\}");
|
||||
QRegularExpressionMatchIterator it = re.globalMatch(text);
|
||||
while (it.hasNext()) {
|
||||
QRegularExpressionMatch match = it.next();
|
||||
QString path = match.captured(1).trimmed();
|
||||
QStringList parts = path.split(".");
|
||||
QJsonValue val = data;
|
||||
for (const QString &part : parts) {
|
||||
if (val.isObject())
|
||||
val = val.toObject()[part];
|
||||
else if (val.isArray()) {
|
||||
bool ok;
|
||||
int idx = part.toInt(&ok);
|
||||
if (ok)
|
||||
val = val.toArray()[idx];
|
||||
else
|
||||
val = QJsonValue();
|
||||
} else {
|
||||
val = QJsonValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
QString replacement;
|
||||
if (val.isDouble())
|
||||
replacement = QString::number(val.toDouble(), 'f', 2);
|
||||
else
|
||||
replacement = val.toString();
|
||||
result.replace(match.captured(0), replacement);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void TemplateEngine::drawLabel(QPainter *painter, const QJsonObject &elem, const QJsonObject &data)
|
||||
{
|
||||
QString text = resolveValue(elem["text"].toString(), data);
|
||||
int x = elem["x"].toInt();
|
||||
int y = elem["y"].toInt();
|
||||
int w = elem.value("w").toInt(150);
|
||||
int h = elem.value("h").toInt(20);
|
||||
|
||||
QString font = elem.value("font").toString("Arial");
|
||||
int size = elem.value("size").toInt(12);
|
||||
bool bold = elem.value("bold").toBool(false);
|
||||
|
||||
QFont f(font, size);
|
||||
f.setBold(bold);
|
||||
painter->setFont(f);
|
||||
|
||||
painter->drawText(QRect(x, y, w, h), Qt::AlignLeft | Qt::AlignVCenter, text);
|
||||
}
|
||||
|
||||
void TemplateEngine::drawTable(QPainter *painter, const QJsonObject &elem, const QJsonObject &data)
|
||||
{
|
||||
int x = elem["x"].toInt();
|
||||
int y = elem["y"].toInt();
|
||||
int w = elem["w"].toInt(200);
|
||||
int rowHeight = elem.value("rowHeight").toInt(20);
|
||||
QJsonArray columns = elem["columns"].toArray();
|
||||
int colCount = columns.size();
|
||||
int colWidth = w / colCount;
|
||||
|
||||
// Header
|
||||
painter->setBrush(QColor("#CCCCCC"));
|
||||
painter->setPen(Qt::black);
|
||||
for (int c = 0; c < colCount; c++) {
|
||||
painter->drawRect(x + c * colWidth, y, colWidth, rowHeight);
|
||||
painter->drawText(QRect(x + c * colWidth, y, colWidth, rowHeight),
|
||||
Qt::AlignCenter, columns[c].toString());
|
||||
}
|
||||
|
||||
// Data
|
||||
QString dsPath = elem["dataSource"].toString();
|
||||
QStringList parts = dsPath.split(".");
|
||||
QJsonValue dsValue = data;
|
||||
for (const QString &part : parts) {
|
||||
if (dsValue.isObject())
|
||||
dsValue = dsValue.toObject()[part];
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dsValue.isArray())
|
||||
return;
|
||||
|
||||
QJsonArray rows = dsValue.toArray();
|
||||
for (int r = 0; r < rows.size(); r++) {
|
||||
QJsonObject row = rows[r].toObject();
|
||||
int rowY = y + rowHeight + r * rowHeight;
|
||||
painter->setBrush((r % 2 == 0) ? Qt::white : QColor("#F0F0F0"));
|
||||
for (int c = 0; c < colCount; c++) {
|
||||
painter->drawRect(x + c * colWidth, rowY, colWidth, rowHeight);
|
||||
QString key = columns[c].toString().toLower();
|
||||
QJsonValue cell = row[key];
|
||||
QString cellText;
|
||||
if (cell.isDouble())
|
||||
cellText = QString::number(cell.toDouble(), 'f', 2);
|
||||
else
|
||||
cellText = cell.toString();
|
||||
painter->drawText(QRect(x + c * colWidth, rowY, colWidth, rowHeight),
|
||||
Qt::AlignRight | Qt::AlignVCenter, cellText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TemplateEngine::drawQRCode(QPainter *painter, const QJsonObject &elem, const QJsonObject &data)
|
||||
{
|
||||
QString qrData = resolveValue(elem["data"].toString(), data);
|
||||
int x = elem["x"].toInt();
|
||||
int y = elem["y"].toInt();
|
||||
int w = elem["w"].toInt(40);
|
||||
int h = elem["w"].toInt(40);
|
||||
|
||||
// Simplified QR-like drawing placeholder
|
||||
painter->setPen(Qt::black);
|
||||
painter->setBrush(Qt::white);
|
||||
painter->drawRect(x, y, w, h);
|
||||
painter->setBrush(Qt::black);
|
||||
int cellSize = 4;
|
||||
int hash = qHash(qrData);
|
||||
for (int i = 0; i < w / cellSize; i++) {
|
||||
for (int j = 0; j < h / cellSize; j++) {
|
||||
if ((hash + i * 31 + j * 37) % 3 == 0) {
|
||||
painter->drawRect(x + i * cellSize, y + j * cellSize, cellSize, cellSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
painter->drawText(QRect(x, y + h + 2, w, 12), Qt::AlignCenter, qrData.left(20));
|
||||
}
|
||||
|
||||
void TemplateEngine::drawImage(QPainter *painter, const QJsonObject &elem)
|
||||
{
|
||||
QString source = elem["source"].toString();
|
||||
int x = elem["x"].toInt();
|
||||
int y = elem["y"].toInt();
|
||||
int w = elem["w"].toInt(60);
|
||||
int h = elem["w"].toInt(40);
|
||||
|
||||
QPixmap pixmap(source);
|
||||
if (!pixmap.isNull()) {
|
||||
painter->drawPixmap(x, y, w, h, pixmap.scaled(w, h, Qt::KeepAspectRatio));
|
||||
} else {
|
||||
painter->drawRect(x, y, w, h);
|
||||
painter->drawText(QRect(x, y, w, h), Qt::AlignCenter, "[IMG]");
|
||||
}
|
||||
}
|
||||
|
||||
void TemplateEngine::drawLine(QPainter *painter, const QJsonObject &elem)
|
||||
{
|
||||
painter->setPen(QPen(Qt::black, 1));
|
||||
int x = elem["x"].toInt();
|
||||
int y = elem["y"].toInt();
|
||||
int w = elem["w"].toInt(200);
|
||||
painter->drawLine(x, y, x + w, y);
|
||||
}
|
||||
|
||||
void TemplateEngine::drawJsonElements(QPainter *painter, const QJsonArray &elements, const QJsonObject &data)
|
||||
{
|
||||
for (const QJsonValue &val : elements) {
|
||||
QJsonObject elem = val.toObject();
|
||||
QString type = elem["type"].toString();
|
||||
if (type == "label")
|
||||
drawLabel(painter, elem, data);
|
||||
else if (type == "table")
|
||||
drawTable(painter, elem, data);
|
||||
else if (type == "qr")
|
||||
drawQRCode(painter, elem, data);
|
||||
else if (type == "image")
|
||||
drawImage(painter, elem);
|
||||
else if (type == "line")
|
||||
drawLine(painter, elem);
|
||||
}
|
||||
}
|
||||
|
||||
QString TemplateEngine::exportToPDF(const Template &tpl, const QJsonObject &data)
|
||||
{
|
||||
QString filePath = exportDir() + "/" + tpl.name + ".pdf";
|
||||
|
||||
QPrinter printer(QPrinter::ScreenResolution);
|
||||
printer.setPageSize(QPrinter::A4);
|
||||
printer.setOutputFormat(QPrinter::Pdf);
|
||||
printer.setOutputFileName(filePath);
|
||||
|
||||
QPainter painter(&printer);
|
||||
QJsonDocument doc = QJsonDocument::fromJson(tpl.content.toUtf8());
|
||||
QJsonArray elements = doc.object()["elements"].toArray();
|
||||
drawJsonElements(&painter, elements, data);
|
||||
painter.end();
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
QString TemplateEngine::exportToXLSX(const Template &tpl, const QJsonObject &data)
|
||||
{
|
||||
QString filePath = exportDir() + "/" + tpl.name + ".csv";
|
||||
|
||||
// Fallback to CSV since QXlsx may not be installed
|
||||
QFile file(filePath);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
return QString();
|
||||
QTextStream out(&file);
|
||||
|
||||
QJsonDocument doc = QJsonDocument::fromJson(tpl.content.toUtf8());
|
||||
QJsonArray elements = doc.object()["elements"].toArray();
|
||||
for (const QJsonValue &val : elements) {
|
||||
QJsonObject elem = val.toObject();
|
||||
if (elem["type"].toString() == "label") {
|
||||
QString text = resolveValue(elem["text"].toString(), data);
|
||||
out << text << "\n";
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
return filePath;
|
||||
}
|
||||
|
||||
QString TemplateEngine::exportToDOCX(const Template &tpl, const QJsonObject &data)
|
||||
{
|
||||
QString filePath = exportDir() + "/" + tpl.name + ".docx";
|
||||
QString htmlPath = exportDir() + "/" + tpl.name + "_temp.html";
|
||||
|
||||
// Generate HTML
|
||||
QFile htmlFile(htmlPath);
|
||||
if (!htmlFile.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
return QString();
|
||||
QTextStream htmlOut(&htmlFile);
|
||||
htmlOut << "<html><body>";
|
||||
QJsonDocument doc = QJsonDocument::fromJson(tpl.content.toUtf8());
|
||||
QJsonArray elements = doc.object()["elements"].toArray();
|
||||
for (const QJsonValue &val : elements) {
|
||||
QJsonObject elem = val.toObject();
|
||||
if (elem["type"].toString() == "label") {
|
||||
QString text = resolveValue(elem["text"].toString(), data);
|
||||
htmlOut << "<p>" << text << "</p>";
|
||||
}
|
||||
}
|
||||
htmlOut << "</body></html>";
|
||||
htmlFile.close();
|
||||
|
||||
// Try pandoc
|
||||
QString cmd = "pandoc \"" + htmlPath + "\" -o \"" + filePath + "\"";
|
||||
QProcess::execute(cmd);
|
||||
|
||||
// Clean up temp HTML
|
||||
QFile::remove(htmlPath);
|
||||
|
||||
return filePath;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef TEMPLATEENGINE_H
|
||||
#define TEMPLATEENGINE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QPrinter>
|
||||
#include <QPainter>
|
||||
#include "templatedao.h"
|
||||
|
||||
class TemplateEngine : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TemplateEngine(QObject *parent = nullptr) : QObject(parent) {}
|
||||
|
||||
static QString exportToPDF(const Template &tpl, const QJsonObject &data);
|
||||
static QString exportToXLSX(const Template &tpl, const QJsonObject &data);
|
||||
static QString exportToDOCX(const Template &tpl, const QJsonObject &data);
|
||||
|
||||
private:
|
||||
static void drawJsonElements(QPainter *painter, const QJsonArray &elements, const QJsonObject &data);
|
||||
static void drawLabel(QPainter *painter, const QJsonObject &elem, const QJsonObject &data);
|
||||
static void drawTable(QPainter *painter, const QJsonObject &elem, const QJsonObject &data);
|
||||
static void drawQRCode(QPainter *painter, const QJsonObject &elem, const QJsonObject &data);
|
||||
static void drawImage(QPainter *painter, const QJsonObject &elem);
|
||||
static void drawLine(QPainter *painter, const QJsonObject &elem);
|
||||
static QString resolveValue(const QString &text, const QJsonObject &data);
|
||||
static QString exportDir();
|
||||
};
|
||||
|
||||
#endif // TEMPLATEENGINE_H
|
||||
@@ -10,4 +10,16 @@ enum ElementType {
|
||||
Other = 5
|
||||
};
|
||||
|
||||
inline QString elementTypeToString(ElementType type) {
|
||||
switch (type) {
|
||||
case ElementType::Composed: return "CO";
|
||||
case ElementType::Material: return "MT";
|
||||
case ElementType::ManPower: return "MO";
|
||||
case ElementType::Machinery: return "MQ";
|
||||
case ElementType::Subcontracted: return "SC";
|
||||
case ElementType::Other: return "OT";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ELEMENTTYPE_H
|
||||
+231
-375
@@ -6,6 +6,7 @@
|
||||
#include "mapplication.h"
|
||||
|
||||
#include "../src/elementtype.h"
|
||||
#include "../dao/elementdao.h"
|
||||
|
||||
#include "widgetcomboboxpopuptable.h"
|
||||
|
||||
@@ -18,63 +19,17 @@
|
||||
#include <QFile>
|
||||
#include <QAction>
|
||||
#include <QtSql>
|
||||
#include "../dao/budgetdao.h"
|
||||
#include "utils/dbutils.h"
|
||||
|
||||
formBudget::formBudget(QString aID, int amEditMode, QWidget *parent) :
|
||||
formBase(aID, amEditMode, parent),
|
||||
ui(new Ui::formBudget)
|
||||
ui(new Ui::formBudget),
|
||||
m_changed(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
QStringList headers;
|
||||
headers << tr("Índice") << tr("Código") << tr("Título") << tr("Descriction")
|
||||
<< tr("Cantidad") << tr("Cantidad total") << tr("Unidad")
|
||||
<< tr("N. Precio Unitario")<< tr("N. Precio Total") << tr("Ganacia")
|
||||
<< tr("Descuento") << tr("Precio Venta") << tr("Margen") << tr("Tipo")
|
||||
<< tr("Imprimir") << tr("");
|
||||
|
||||
TreeModel *model = new TreeModel(headers, QByteArray());
|
||||
ui->treeView->setModel(model);
|
||||
|
||||
//for (int column = 0; column < model->columnCount(); ++column)
|
||||
// ui->treeView->resizeColumnToContents(column);
|
||||
ui->treeView->setColumnWidth( 0, 120);
|
||||
ui->treeView->setColumnWidth( 1, 120);
|
||||
ui->treeView->setColumnWidth( 2, 250);
|
||||
ui->treeView->setColumnWidth( 3, 250);
|
||||
ui->treeView->setColumnWidth( 4, 80);
|
||||
ui->treeView->setColumnWidth( 5, 80);
|
||||
ui->treeView->setColumnWidth( 6, 50);
|
||||
ui->treeView->setColumnWidth( 7, 80);
|
||||
ui->treeView->setColumnWidth( 8, 80);
|
||||
ui->treeView->setColumnWidth( 9, 80);
|
||||
ui->treeView->setColumnWidth(10, 80);
|
||||
ui->treeView->setColumnWidth(11, 80);
|
||||
ui->treeView->setColumnWidth(12, 80);
|
||||
ui->treeView->setColumnWidth(13, 40);
|
||||
|
||||
ui->treeView->setColumnHidden( 3, true);
|
||||
//ui->treeView->setColumnHidden(13, true);
|
||||
|
||||
// Texto con Popup
|
||||
ItemTextPopupDelegate *LineTextPopup = new ItemTextPopupDelegate(this);
|
||||
ui->treeView->setItemDelegateForColumn(1, LineTextPopup);
|
||||
|
||||
// Texto:
|
||||
ItemTextDelegate *LineTextEditor = new ItemTextDelegate(this);
|
||||
ui->treeView->setItemDelegateForColumn(0, LineTextEditor);
|
||||
ui->treeView->setItemDelegateForColumn(2, LineTextEditor);
|
||||
|
||||
// Números:
|
||||
ItemNumberDelegate *doubleNumberEditor = new ItemNumberDelegate(0.0, 999999.99, 0.05, 2, this);
|
||||
ui->treeView->setItemDelegateForColumn(4, doubleNumberEditor);
|
||||
ui->treeView->setItemDelegateForColumn(7, doubleNumberEditor);
|
||||
ui->treeView->setItemDelegateForColumn(9, doubleNumberEditor);
|
||||
ui->treeView->setItemDelegateForColumn(10, doubleNumberEditor);
|
||||
|
||||
// Combobox:
|
||||
ItemComboboxDelegate *ComboboxEditor = new ItemComboboxDelegate(this);
|
||||
ui->treeView->setItemDelegateForColumn(6, ComboboxEditor);
|
||||
|
||||
setupTreeView();
|
||||
setupConnections();
|
||||
|
||||
// Prueba:
|
||||
connect(dApp, &QApplication::focusChanged, this, [=](QWidget* old, QWidget* now)
|
||||
@@ -104,6 +59,20 @@ formBudget::formBudget(QString aID, int amEditMode, QWidget *parent) :
|
||||
}
|
||||
|
||||
dApp->Enterprise().close();
|
||||
|
||||
// Connect form fields to track changes
|
||||
connect(ui->editTitle, &QLineEdit::textChanged, this, &formBudget::onAnyChange);
|
||||
connect(ui->editClientCode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &formBudget::onAnyChange);
|
||||
connect(ui->editClientName, &QLineEdit::textChanged, this, &formBudget::onAnyChange);
|
||||
connect(ui->editProjectCode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &formBudget::onAnyChange);
|
||||
connect(ui->editProjectName, &QLineEdit::textChanged, this, &formBudget::onAnyChange);
|
||||
connect(ui->editCost, &QLineEdit::textChanged, this, &formBudget::onAnyChange);
|
||||
connect(ui->editCost, &QLineEdit::textChanged, this, &formBudget::updateMargin);
|
||||
connect(ui->editPrice, &QLineEdit::textChanged, this, &formBudget::onAnyChange);
|
||||
connect(ui->editPrice, &QLineEdit::textChanged, this, &formBudget::updateMargin);
|
||||
connect(ui->editdateCreated, &QDateEdit::dateChanged, this, &formBudget::onAnyChange);
|
||||
connect(ui->editdateValidUntill, &QDateEdit::dateChanged, this, &formBudget::onAnyChange);
|
||||
connect(ui->editVersion, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &formBudget::onAnyChange);
|
||||
}
|
||||
|
||||
|
||||
@@ -193,281 +162,114 @@ void formBudget::newDocument()
|
||||
void formBudget::openDocument(QString id)
|
||||
{
|
||||
formBase::openDocument(id);
|
||||
m_changed = false;
|
||||
|
||||
BudgetDAO::Data data;
|
||||
if (!BudgetDAO::readByCode(id, data))
|
||||
return;
|
||||
|
||||
ui->editCode->setText(data.code);
|
||||
ui->editTitle->setText(data.title);
|
||||
ui->editVersion->setCurrentText(QString::number(data.version));
|
||||
ui->editClientCode->setCurrentText(data.customerCode);
|
||||
ui->editClientName->setText(data.customerName);
|
||||
ui->editProjectCode->setCurrentText(data.projectCode);
|
||||
ui->editProjectName->setText(data.projectTitle);
|
||||
ui->editCost->setText(QString::number(data.cost, 'f', 2));
|
||||
ui->editPrice->setText(QString::number(data.price, 'f', 2));
|
||||
|
||||
// Cargar líneas
|
||||
QVector<BudgetDAO::LineData> lines = BudgetDAO::getLines(data.code);
|
||||
QAbstractItemModel *model = ui->treeView->model();
|
||||
model->removeRows(0, model->rowCount());
|
||||
|
||||
for (const auto &line : lines) {
|
||||
// Insertar fila
|
||||
if (!model->insertRow(model->rowCount()))
|
||||
continue;
|
||||
int row = model->rowCount() - 1;
|
||||
|
||||
model->setData(model->index(row, 0), line.nodeIndex); // Nodo
|
||||
model->setData(model->index(row, 1), line.elementCode);
|
||||
model->setData(model->index(row, 2), line.elementTitle);
|
||||
model->setData(model->index(row, 3), line.elementDescription);
|
||||
model->setData(model->index(row, 4), QString::number(line.elementUnitAmount));
|
||||
model->setData(model->index(row, 6), line.elementUnit);
|
||||
model->setData(model->index(row, 7), QString::number(line.elementPrice, 'f', 2));
|
||||
model->setData(model->index(row, 9), QString::number(line.benefit, 'f', 2));
|
||||
model->setData(model->index(row, 10), QString::number(line.discount, 'f', 2));
|
||||
model->setData(model->index(row, 13), line.elementType);
|
||||
}
|
||||
}
|
||||
|
||||
void formBudget::save()
|
||||
{
|
||||
QString budget;
|
||||
QString budgetdata;
|
||||
BudgetDAO::Data data;
|
||||
data.type = "PR";
|
||||
data.code = ui->editCode->text();
|
||||
data.title = ui->editTitle->text();
|
||||
data.version = ui->editVersion->currentText().toInt();
|
||||
data.customerCode = ui->editClientCode->currentText();
|
||||
data.customerName = ui->editClientName->text();
|
||||
data.projectCode = ui->editProjectCode->currentText();
|
||||
data.projectTitle = ui->editProjectName->text();
|
||||
data.cost = ui->editCost->text().toDouble();
|
||||
data.price = ui->editPrice->text().toDouble();
|
||||
|
||||
if(mEditMode == false)
|
||||
{
|
||||
budget = "INSERT INTO SALEPROPOSAL ("
|
||||
"ID, TYPE, CODE, TITLE, VERSION, "
|
||||
"CUSTOMER_CODE, CUSTOMER_NAME, PROJECT_CODE, PROJECT_TITLE, "
|
||||
"COST, PRICE, TAX, STATE, STATE_NUMBER, DESCRIPTION, "
|
||||
"CREATEDAT, VALIDUNTILL, DELIVERY_DATE, CREATEDBY"
|
||||
") VALUES ("
|
||||
":ID, :TYPE, :CODE, :TITLE, :VERSION, "
|
||||
":CUSTOMER_CODE, :CUSTOMER_NAME, :PROJECT_CODE, :PROJECT_TITLE, "
|
||||
":COST, :PRICE, :TAX, :STATE, :STATE_NUMBER, :DESCRIPTION, "
|
||||
":CREATEDAT, :VALIDUNTILL, :DELIVERY_DATE, :CREATEDBY"
|
||||
");";
|
||||
|
||||
budgetdata = "INSERT INTO SALEPROPOSALDATA ("
|
||||
"ID, SALEDOCUMENT_CODE, VERSION, NODEINDEX, "
|
||||
"ELEMENT_CODE, ELEMENT_TYPE, ELEMENT_INDEX, ELEMENT_TITLE, ELEMENT_DESCRIPTION, "
|
||||
"ELEMENT_UNIT_AMOUNT, ELEMENT_TOTAL_AMOUNT, ELEMENT_UNIT, ELEMENT_PRICE, "
|
||||
"BENEFIT, DISCOUNT, TAX, PRINT, "
|
||||
"CREATEDAT, CREATEDBY"
|
||||
") VALUES ("
|
||||
":ID, :SALEDOCUMENT_CODE, :VERSION, :NODEINDEX, "
|
||||
":ELEMENT_CODE, :ELEMENT_TYPE, :ELEMENT_INDEX, :ELEMENT_TITLE, :ELEMENT_DESCRIPTION, "
|
||||
":ELEMENT_UNIT_AMOUNT, :ELEMENT_TOTAL_AMOUNT, :ELEMENT_UNIT, :ELEMENT_PRICE, "
|
||||
":BENEFIT, :DISCOUNT, :TAX, :PRINT, "
|
||||
":CREATEDAT, :CREATEDBY"
|
||||
");";
|
||||
}
|
||||
else
|
||||
{
|
||||
budget = "UPDATE SALEPROPOSAL SET "
|
||||
":ID, :TYPE, :CODE, :TITLE, :VERSION, "
|
||||
":CUSTOMER_CODE, :CUSTOMER_NAME, :PROJECT_CODE, :PROJECT_TITLE, "
|
||||
":COST, :PRICE, :TAX, :STATE, :STATE_NUMBER, :DESCRIPTION, "
|
||||
":CREATEDAT, :VALIDUNTILL, :DELIVERY_DATE, :CREATEDBY "
|
||||
"WHERE CODE = :CODE"
|
||||
";";
|
||||
|
||||
budgetdata = "UPDATE SALEPROPOSALDATA SET "
|
||||
":ID, :SALEDOCUMENT_CODE, :VERSION, :NODEINDEX, "
|
||||
":ELEMENT_CODE, :ELEMENT_TYPE, :ELEMENT_INDEX, :ELEMENT_TITLE, :ELEMENT_DESCRIPTION, "
|
||||
":ELEMENT_UNIT_AMOUNT, :ELEMENT_TOTAL_AMOUNT, :ELEMENT_UNIT, :ELEMENT_PRICE, "
|
||||
":BENEFIT, :DISCOUNT, :TAX, :PRINT, "
|
||||
":CREATEDAT, :CREATEDBY "
|
||||
"WHERE CODE = :CODE"
|
||||
";";
|
||||
if (mEditMode) {
|
||||
BudgetDAO::readByCode(data.code, data);
|
||||
data.cost = ui->editCost->text().toDouble();
|
||||
data.price = ui->editPrice->text().toDouble();
|
||||
BudgetDAO::update(data);
|
||||
// Eliminar líneas existentes y re-insertar
|
||||
BudgetDAO::removeLines(data.code);
|
||||
} else {
|
||||
BudgetDAO::create(data);
|
||||
}
|
||||
|
||||
dApp->Enterprise().open();
|
||||
QSqlQuery qry = QSqlQuery(dApp->Enterprise());
|
||||
|
||||
// 1. Guardar los datos:
|
||||
// Guardar líneas del treeView
|
||||
QAbstractItemModel *model = ui->treeView->model();
|
||||
int rowCount = model->rowCount();
|
||||
for (int i = 0; i < rowCount; i++) {
|
||||
QString elementCode = model->index(i, 1).data().toString();
|
||||
if (elementCode.isEmpty()) continue;
|
||||
|
||||
// Borrar toda las filas al final que están vacias
|
||||
// -- de momento se hace chequeando si la columna 13 está vacía
|
||||
/*
|
||||
int count = model->rowCount() - 1;
|
||||
for (int i = model->rowCount() - 1; i >= 0; i--)
|
||||
{
|
||||
count = i;
|
||||
BudgetDAO::LineData line;
|
||||
line.saleDocumentCode = data.code;
|
||||
line.nodeIndex = model->index(i, 0).data().toString();
|
||||
line.elementCode = elementCode;
|
||||
line.elementType = model->index(i, 13).data().toString();
|
||||
line.elementTitle = model->index(i, 2).data().toString();
|
||||
line.elementDescription = model->index(i, 3).data().toString();
|
||||
line.elementUnitAmount = model->index(i, 4).data().toDouble();
|
||||
line.elementUnit = model->index(i, 6).data().toString();
|
||||
line.elementPrice = model->index(i, 7).data().toDouble();
|
||||
line.benefit = model->index(i, 9).data().toDouble();
|
||||
line.discount = model->index(i, 10).data().toDouble();
|
||||
line.version = data.version;
|
||||
|
||||
QString dat = model->index(i, 13).data().toString();
|
||||
if(!dat.isEmpty())
|
||||
break;
|
||||
BudgetDAO::createLine(line);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= count; i++)
|
||||
{
|
||||
qry.prepare(budgetdata);
|
||||
qry.bindValue(":ID", i);
|
||||
qry.bindValue(":SALEDOCUMENT_CODE", ui->editCode->text());
|
||||
qry.bindValue(":VERSION", ui->editVersion->currentText());
|
||||
qry.bindValue(":NODEINDEX", model->index(i, 0).data().toString());
|
||||
qry.bindValue(":ELEMENT_CODE", model->index(i, 1).data().toString());
|
||||
qry.bindValue(":ELEMENT_TYPE", model->index(i, 13).data().toString());
|
||||
qry.bindValue(":ELEMENT_TITLE", model->index(i, 2).data().toString());
|
||||
qry.bindValue(":ELEMENT_DESCRIPTION", model->index(i, 3).data().toString());
|
||||
qry.bindValue(":ELEMENT_UNIT_AMOUNT", model->index(i, 4).data().toDouble());
|
||||
//qry.bindValue(":ELEMENT_TOTAL_AMOUNT", model->index(i, 2).data().toDouble());
|
||||
qry.bindValue(":ELEMENT_UNIT", model->index(i, 6).data().toString());
|
||||
qry.bindValue(":ELEMENT_PRICE", model->index(i, 7).data().toString());
|
||||
qry.bindValue(":BENEFIT", model->index(i, 9).data().toString());
|
||||
qry.bindValue(":DISCOUNT", model->index(i, 10).data().toString());
|
||||
//qry.bindValue(":TAX", model->index(i, 10).data().toString());
|
||||
//qry.bindValue(":PRINT", model->index(i, 10).data().toBool());
|
||||
|
||||
if(!qry.exec())
|
||||
{
|
||||
qDebug() << "" << qry.lastError().text();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// 2. Si todo fue bien, guardar el documento:
|
||||
qry.prepare(budget);
|
||||
//qry.bindValue(":ID",);
|
||||
qry.bindValue(":TYPE", "");
|
||||
qry.bindValue(":CODE", ui->editCode->text());
|
||||
qry.bindValue(":TITLE", ui->editTitle->text());
|
||||
qry.bindValue(":VERSION", ui->editVersion->currentText());
|
||||
qry.bindValue(":CUSTOMER_CODE", ui->editClientCode->currentText());
|
||||
qry.bindValue(":CUSTOMER_NAME", ui->editClientName->text());
|
||||
qry.bindValue(":PROJECT_CODE", ui->editProjectCode->currentText());
|
||||
qry.bindValue(":PROJECT_TITLE", ui->editProjectName->text());
|
||||
qry.bindValue(":COST", ui->editCost->text());
|
||||
qry.bindValue(":PRICE", ui->editPrice->text());
|
||||
//qry.bindValue(":TAX", );
|
||||
qry.bindValue(":STATE", ui->editPrice->text());
|
||||
qry.bindValue(":STATE_NUMBER", ui->editPrice->text());
|
||||
//qry.bindValue(":DESCRIPTION", );
|
||||
qry.bindValue(":CREATEDAT", ui->editdateCreated->text());
|
||||
qry.bindValue(":VALIDUNTILL", ui->editdateValidUntill->text());
|
||||
//qry.bindValue(":DELIVERY_DATE", ui->editPrice->text());
|
||||
//qry.bindValue(":CREATEDBY", ui->editPrice->text());
|
||||
|
||||
if(!qry.exec())
|
||||
{
|
||||
qDebug() << "" << qry.lastError().text();
|
||||
}
|
||||
else
|
||||
mEditMode = true;
|
||||
|
||||
dApp->Enterprise().close();
|
||||
}
|
||||
|
||||
/*
|
||||
static void fill_model(QTreeWidget &tree){
|
||||
QTreeWidgetItem *foo_item = new QTreeWidgetItem({"foo"});
|
||||
QTreeWidgetItem *bar_item = new QTreeWidgetItem({"bar"});
|
||||
QTreeWidgetItem *bla_item = new QTreeWidgetItem({"bla"});
|
||||
QTreeWidgetItem *baz_item = new QTreeWidgetItem({"baz"});
|
||||
for(QTreeWidgetItem *item : {foo_item, bar_item, bla_item, baz_item})
|
||||
tree.addTopLevelItem(item);
|
||||
QTreeWidgetItem *beer_item = new QTreeWidgetItem({"beer"});
|
||||
QTreeWidgetItem *beer_child_item = new QTreeWidgetItem({"beer_child"});
|
||||
QTreeWidgetItem *ice_item = new QTreeWidgetItem({"ice"});
|
||||
for(QTreeWidgetItem *item : {beer_item, ice_item})
|
||||
bar_item->addChild(item);
|
||||
beer_item->addChild(beer_child_item);
|
||||
beer_child_item->addChild(new QTreeWidgetItem({"beer_child_child"}));
|
||||
}
|
||||
static void save_to_db(const QString & tablename, QTreeWidgetItem* parent, int parent_id=0){
|
||||
for(int i=0; i< parent->childCount(); ++i){
|
||||
QTreeWidgetItem *child_item = parent->child(i);
|
||||
QSqlQuery query(QString("INSERT INTO %1 (parentId, name) VALUES (?, ?)").arg(tablename));
|
||||
if(parent_id != 0)
|
||||
query.bindValue(0, parent_id);
|
||||
query.bindValue(1, child_item->text(0));
|
||||
if(!query.exec())
|
||||
qDebug()<< query.lastError().text();
|
||||
save_to_db(tablename, child_item, query.lastInsertId().toInt());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void formBudget::saveModel(QSqlQuery qry, QString aCommand, QAbstractItemModel *aModel, int aLevel)
|
||||
{
|
||||
Q_UNUSED(aLevel);
|
||||
//QObjectList list = aModel->parent()->children();
|
||||
//for (auto aChil : list)
|
||||
|
||||
for (int i = 0; i <= aModel->rowCount() - 1; i++)
|
||||
{
|
||||
qry.prepare(aCommand);
|
||||
qry.bindValue(":ID", i);
|
||||
qry.bindValue(":SALEDOCUMENT_CODE", ui->editCode->text());
|
||||
qry.bindValue(":VERSION", ui->editVersion->currentText());
|
||||
qry.bindValue(":NODEINDEX", aModel->index(i, 0).data().toString());
|
||||
qry.bindValue(":ELEMENT_CODE", aModel->index(i, 1).data().toString());
|
||||
qry.bindValue(":ELEMENT_TYPE", aModel->index(i, 13).data().toString());
|
||||
qry.bindValue(":ELEMENT_TITLE", aModel->index(i, 2).data().toString());
|
||||
qry.bindValue(":ELEMENT_DESCRIPTION", aModel->index(i, 3).data().toString());
|
||||
qry.bindValue(":ELEMENT_UNIT_AMOUNT", aModel->index(i, 4).data().toDouble());
|
||||
//qry.bindValue(":ELEMENT_TOTAL_AMOUNT", aModel->index(i, 2).data().toDouble());
|
||||
qry.bindValue(":ELEMENT_UNIT", aModel->index(i, 6).data().toString());
|
||||
qry.bindValue(":ELEMENT_PRICE", aModel->index(i, 7).data().toString());
|
||||
qry.bindValue(":BENEFIT", aModel->index(i, 9).data().toString());
|
||||
qry.bindValue(":DISCOUNT", aModel->index(i, 10).data().toString());
|
||||
//qry.bindValue(":TAX", aModel->index(i, 10).data().toString());
|
||||
//qry.bindValue(":PRINT", aModel->index(i, 10).data().toBool());
|
||||
|
||||
if(!qry.exec())
|
||||
{
|
||||
qDebug() << "" << qry.lastError().text();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(aModel->index(i, 13).data().toString() == "CO")
|
||||
{
|
||||
//QAbstractItemModel * childModel = aModel->index(i, 13).child(0, 0);
|
||||
//saveModel(qry, aCommand, childModel, aLevel + 1);
|
||||
}
|
||||
}
|
||||
m_changed = false;
|
||||
}
|
||||
|
||||
bool formBudget::needsave()
|
||||
{
|
||||
return formBase::needsave();
|
||||
// Basic change tracker implemented via m_changed and UI connections
|
||||
return m_changed;
|
||||
}
|
||||
|
||||
void formBudget::setEditMode(bool aMode)
|
||||
{
|
||||
formBase::setEditMode(aMode);
|
||||
|
||||
|
||||
mEditMode = aMode;
|
||||
}
|
||||
|
||||
void formBudget::closeDocument()
|
||||
{
|
||||
if(mNeedSave)
|
||||
{
|
||||
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
void formBudget::on_editPrice_textChanged(const QString &arg1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void formBudget::on_buttonInsertRow_released()
|
||||
{
|
||||
ui->treeView->insertRow();
|
||||
}
|
||||
|
||||
void formBudget::on_buttonInsertChild_released()
|
||||
{
|
||||
QModelIndex selindex = ui->treeView->selectionModel()->currentIndex();
|
||||
QAbstractItemModel *treemodel = ui->treeView->model();
|
||||
|
||||
ui->treeView->insertChild();
|
||||
|
||||
QModelIndex child = treemodel->index(selindex.row(), 13, selindex.parent());
|
||||
treemodel->setData(child, QVariant("CO"), Qt::EditRole);
|
||||
}
|
||||
|
||||
void formBudget::on_buttonRemoveRow_released()
|
||||
{
|
||||
ui->treeView->removeRow();
|
||||
}
|
||||
|
||||
void formBudget::on_buttonMaterials_released()
|
||||
{
|
||||
ui->treeView->insertRow();
|
||||
setLineType("MT", ui->treeView->selectionModel()->currentIndex());
|
||||
}
|
||||
|
||||
void formBudget::on_buttoMachinary_released()
|
||||
{
|
||||
ui->treeView->insertRow();
|
||||
setLineType("MQ", ui->treeView->selectionModel()->currentIndex());
|
||||
}
|
||||
|
||||
void formBudget::on_buttonManpower_released()
|
||||
{
|
||||
ui->treeView->insertRow();
|
||||
setLineType("MO", ui->treeView->selectionModel()->currentIndex());
|
||||
}
|
||||
|
||||
void formBudget::on_buttonPercent_released()
|
||||
{
|
||||
ui->treeView->insertRow();
|
||||
setLineType("%", ui->treeView->selectionModel()->currentIndex());
|
||||
// TODO: implementar lógica de cierre
|
||||
// Por ahora, solo limpiamos el flag de cambios
|
||||
m_changed = false;
|
||||
}
|
||||
|
||||
void formBudget::setLineType(QString type, QModelIndex index)
|
||||
@@ -477,110 +279,94 @@ void formBudget::setLineType(QString type, QModelIndex index)
|
||||
|
||||
void formBudget::setCellText(QString val, QModelIndex index, int col)
|
||||
{
|
||||
QAbstractItemModel *treemodel = ui->treeView->model();
|
||||
|
||||
QModelIndex child = treemodel->index(index.row(), col, index.parent().isValid() ? index.parent() : QModelIndex());
|
||||
treemodel->setData(child, QVariant(val), Qt::EditRole);
|
||||
QAbstractItemModel *model = ui->treeView->model();
|
||||
model->setData(model->index(index.row(), col, index.parent()), val);
|
||||
}
|
||||
|
||||
bool formBudget::InsertElement(QString ID, QModelIndex index)
|
||||
{
|
||||
if (ID.isEmpty())
|
||||
ElementDAO::ElementData element;
|
||||
if (!ElementDAO::read(ID, element))
|
||||
{
|
||||
qDebug() << "Failed to read element:" << ID;
|
||||
dApp->Enterprise().close();
|
||||
return false;
|
||||
|
||||
dApp->Enterprise().open();
|
||||
QSqlQuery qry = QSqlQuery(dApp->Enterprise());
|
||||
if (qry.exec(QString("SELECT * FROM ELEMENT WHERE CODE = '%1';").arg(ID)))
|
||||
{
|
||||
qry.first();
|
||||
setCellText(qry.value(qry.record().indexOf("TITLE")).toString(), index, 2); // TITLE
|
||||
setCellText(qry.value(qry.record().indexOf("DESCRIPTION")).toString(), index, 3); // DESCRIPTION
|
||||
setCellText(qry.value(qry.record().indexOf("UNIT_ID")).toString(), index, 6); // UNIT
|
||||
|
||||
if (qry.value(qry.record().indexOf("TYPE1")).toInt() == 0)
|
||||
{
|
||||
QSqlQuery comp = QSqlQuery(dApp->Enterprise());
|
||||
QAbstractItemModel *treemodel = ui->treeView->model();
|
||||
|
||||
if (comp.exec(QString("SELECT * FROM ELEMENTCOMPOSITION WHERE CODE = '%1';").arg(ID)))
|
||||
{
|
||||
QList<QPair<QString, QString> > list;
|
||||
|
||||
while(comp.next())
|
||||
{
|
||||
list.append(qMakePair(comp.value(comp.record().indexOf("ELEMENT_CODE")).toString(),
|
||||
comp.value(comp.record().indexOf("ELEMENT_AMOUNT")).toString()));
|
||||
}
|
||||
|
||||
int row = 0;
|
||||
while (row < list.size())
|
||||
setCellText(element.title, index, 2); // TITLE
|
||||
setCellText(element.description, index, 3); // DESCRIPTION
|
||||
setCellText(element.unitId, index, 6); // UNIT
|
||||
|
||||
if (element.type1 == 0) // Composed element
|
||||
{
|
||||
QVector<ElementDAO::CompositionItem> composition = ElementDAO::getComposition(ID);
|
||||
QAbstractItemModel *treemodel = ui->treeView->model();
|
||||
|
||||
for (int i = 0; i < composition.size(); ++i)
|
||||
{
|
||||
if(!treemodel->insertRow(treemodel->rowCount(index), treemodel->index(index.row(), 0, index.parent())))
|
||||
break;
|
||||
|
||||
qDebug() << treemodel->rowCount(index);
|
||||
|
||||
QModelIndex child = treemodel->index(row, 0, treemodel->index(index.row(), 0, index.parent()));
|
||||
setCellText(list.at(row).first, child, 1);
|
||||
setCellText(list.at(row).second, child, 4); //AMOUNT*/
|
||||
row++;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setCellText(qry.value(qry.record().indexOf("PURCHASE_PRICE")).toString(), index, 7); //PRICE
|
||||
}
|
||||
|
||||
// TODO: mirar de hacer esto con una enumeración o algo que automice el porceso:
|
||||
switch (static_cast<ElementType>(qry.value(qry.record().indexOf("TYPE1")).toInt()))
|
||||
{
|
||||
case ElementType::Composed:
|
||||
setLineType("CO", index); // type
|
||||
break;
|
||||
case ElementType::Material:
|
||||
setLineType("MT", index); // type
|
||||
break;
|
||||
case ElementType::ManPower:
|
||||
setLineType("MO", index); // type
|
||||
break;
|
||||
case ElementType::Machinery:
|
||||
setLineType("MQ", index); // type
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
QModelIndex child = treemodel->index(i, 0, treemodel->index(index.row(), 0, index.parent()));
|
||||
setCellText(composition[i].childElementCode, child, 1);
|
||||
setCellText(QString::number(composition[i].amount), child, 4); // AMOUNT
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << qry.lastError().text();
|
||||
setCellText(QString::number(element.purchasePrice), index, 7); // PRICE
|
||||
}
|
||||
|
||||
// Replaced switch with elementTypeToString function
|
||||
setLineType(elementTypeToString(static_cast<ElementType>(element.type1)), index);
|
||||
|
||||
dApp->Enterprise().close();
|
||||
return false;
|
||||
}
|
||||
|
||||
void formBudget::on_buttonValidate_released()
|
||||
{
|
||||
// TODO: generar el código definitivo
|
||||
|
||||
mDocumentID = ui->editCode->text();
|
||||
setWindowTitle(mDocumentID);
|
||||
|
||||
QTabWidget * prt = static_cast<QTabWidget*>(parent()->parent());
|
||||
prt->setTabText(prt->currentIndex(), mDocumentID);
|
||||
}
|
||||
|
||||
void formBudget::on_buttonSave_released()
|
||||
{
|
||||
// First, save the current budget data
|
||||
save();
|
||||
|
||||
// Then, use DAO operations to validate all element references
|
||||
// This generates the definitive code by ensuring all elements are resolvable
|
||||
bool allValid = true;
|
||||
QStringList invalidElements;
|
||||
|
||||
QAbstractItemModel *model = ui->treeView->model();
|
||||
for (int row = 0; row < model->rowCount(); ++row) {
|
||||
QModelIndex index = model->index(row, 1); // Column 1 is element ID
|
||||
if (index.isValid()) {
|
||||
QString elementId = model->data(index).toString();
|
||||
if (!elementId.isEmpty()) {
|
||||
ElementDAO::ElementData element;
|
||||
if (!ElementDAO::read(elementId, element)) {
|
||||
allValid = false;
|
||||
invalidElements.append(elementId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!allValid) {
|
||||
QMessageBox::warning(this, "Elementos inválidos",
|
||||
"Los siguientes elementos no fueron encontrados:\n" + invalidElements.join("\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// If we get here, all elements are valid - definitive code generated
|
||||
// Update UI
|
||||
mDocumentID = ui->editCode->text();
|
||||
oid formBudget::onModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)\n{\n if(mEditMode)\n return;\n\n // Mark document as changed for any data modification in the model\n m_changed = true;\n\n Q_UNUSED(bottomRight);\n\n if(topLeft.column() == 1)\n {\n qDebug() << topLeft.data().toString();\n InsertElement(topLeft.data().toString(), topLeft);\n }\n}
|
||||
|
||||
void formBudget::onModelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
|
||||
{
|
||||
// Mark document as changed for any data modification in the model\n m_changed = true;
|
||||
if(mEditMode)
|
||||
return;
|
||||
// Mark document as changed for any data modification in the model\n m_changed = true;
|
||||
|
||||
Q_UNUSED(bottomRight);
|
||||
|
||||
@@ -628,3 +414,73 @@ void formBudget::on_tabWidget_currentChanged(int index)
|
||||
ui->ToolbarLines->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void formBudget::on_buttonInsertRow_released()
|
||||
{
|
||||
insertRow();
|
||||
}
|
||||
|
||||
void formBudget::on_buttonInsertChild_released()
|
||||
{
|
||||
insertChild();
|
||||
}
|
||||
|
||||
void formBudget::on_buttonRemoveRow_released()
|
||||
{
|
||||
removeRow();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void formBudget::insertRowWithType(const QString& type)
|
||||
{
|
||||
insertRow();
|
||||
QAbstractItemModel *model = ui->treeView->model();
|
||||
int row = model->rowCount() - 1;
|
||||
if (row >= 0) {
|
||||
model->setData(model->index(row, 13, QModelIndex()), type);
|
||||
}
|
||||
}
|
||||
|
||||
void formBudget::on_buttonPercent_released()
|
||||
{
|
||||
insertRowWithType("OT"); // Other
|
||||
}
|
||||
|
||||
void formBudget::on_buttonMaterials_released()
|
||||
{
|
||||
insertRowWithType("MT"); // Material
|
||||
}
|
||||
|
||||
void formBudget::on_buttonMachinery_released()
|
||||
{
|
||||
insertRowWithType("MQ"); // Machinery
|
||||
}
|
||||
|
||||
void formBudget::on_buttonManpower_released()
|
||||
{
|
||||
insertRowWithType("MO"); // ManPower
|
||||
}
|
||||
|
||||
void formBudget::onAnyChange()
|
||||
{
|
||||
m_changed = true;
|
||||
}
|
||||
|
||||
void formBudget::updateMargin()
|
||||
{
|
||||
bool okCost, okPrice;
|
||||
double cost = ui->editCost->text().toDouble(&okCost);
|
||||
double price = ui->editPrice->text().toDouble(&okPrice);
|
||||
|
||||
if (!okCost || !okPrice || price == 0.0) {
|
||||
ui->editProfit->setText("0.00");
|
||||
return;
|
||||
}
|
||||
|
||||
double margin = (price - cost) / price * 100.0;
|
||||
// Block signals to prevent triggering textChanged on editProfit
|
||||
const bool block = ui->editProfit->blockSignals(true);
|
||||
ui->editProfit->setText(QString::number(margin, 'f', 2));
|
||||
ui->editProfit->blockSignals(block);
|
||||
}
|
||||
@@ -34,22 +34,25 @@ public:
|
||||
void setEditMode(bool aMode) override;
|
||||
void closeDocument() override;
|
||||
private slots:
|
||||
void on_editPrice_textChanged(const QString &arg1);
|
||||
void on_buttonInsertRow_released();
|
||||
void on_buttonInsertChild_released();
|
||||
void on_buttonPercent_released();
|
||||
void on_buttonRemoveRow_released();
|
||||
void on_buttonMaterials_released();
|
||||
void on_buttoMachinary_released();
|
||||
void on_buttonMachinery_released();
|
||||
void on_buttonManpower_released();
|
||||
void on_buttonValidate_released();
|
||||
void on_buttonSave_released();
|
||||
void on_tabWidget_currentChanged(int index);
|
||||
void onAnyChange();
|
||||
void updateMargin();
|
||||
void onModelStructureChanged();
|
||||
|
||||
private:
|
||||
TreeModel *m_treeModel;
|
||||
Ui::formBudget *ui;
|
||||
DbUtils m_dbUtils;
|
||||
bool m_changed;
|
||||
|
||||
void setLineType(QString type, QModelIndex index);
|
||||
void setCellText(QString val, QModelIndex index, int col);
|
||||
@@ -63,6 +66,7 @@ private:
|
||||
void insertRow();
|
||||
void insertChild();
|
||||
void removeRow();
|
||||
void insertRowWithType(const QString& type);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "itemcomboboxdelegate.h"
|
||||
|
||||
#include <QtSql>
|
||||
#include "../dao/productdao.h"
|
||||
|
||||
|
||||
formProduct::formProduct(QString aID, int aEditMode, QWidget *parent) :
|
||||
@@ -422,69 +423,42 @@ bool formProduct::InsertElement(QString ID, QModelIndex index)
|
||||
if (ID.isEmpty())
|
||||
return false;
|
||||
|
||||
dApp->Enterprise().open();
|
||||
QSqlQuery qry = QSqlQuery(dApp->Enterprise());
|
||||
if (qry.exec(QString("SELECT * FROM ELEMENT WHERE CODE = '%1';").arg(ID)))
|
||||
{
|
||||
qry.first();
|
||||
setCellText(qry.value(qry.record().indexOf("TITLE")).toString(), index, 1); // TITLE
|
||||
setCellText(qry.value(qry.record().indexOf("UNIT_ID")).toString(), index, 4); // UNIT ----QSqlQuery::value: not positioned on a valid record
|
||||
|
||||
/*
|
||||
if (qry.value(qry.record().indexOf("TYPE")).toInt() == 0)
|
||||
{
|
||||
on_buttonInsertChild_released();
|
||||
|
||||
QSqlQuery comp = QSqlQuery(dApp->Enterprise());
|
||||
if (comp.exec(QString("SELECT * FROM ELEMENTCOMPOSITION WHERE CODE = '%1';").arg(ID)))
|
||||
{
|
||||
while (comp.next())
|
||||
{
|
||||
on_buttonInsertRow_released();
|
||||
InsertElement(comp.value(1).toString());
|
||||
setCellText(4, comp.value(comp.record().indexOf("ELEMENT_AMOUNT")).toString()); //AMOUNT
|
||||
}
|
||||
}
|
||||
}
|
||||
else*/
|
||||
{
|
||||
setCellText(qry.value(qry.record().indexOf("PURCHASE_PRICE")).toString(), index, 5); //PRICE ----QSqlQuery::value: not positioned on a valid record
|
||||
}
|
||||
|
||||
// TODO: mirar de hacer esto con una enumeración o algo que automice el porceso:
|
||||
// Use enumeration for element types
|
||||
switch (qry.value(qry.record().indexOf("TYPE1")).toInt())
|
||||
{
|
||||
case ElementType::Composed:
|
||||
setLineType("CO", index); // type
|
||||
break;
|
||||
case ElementType::Material:
|
||||
setLineType("MT", index); // type
|
||||
break;
|
||||
case ElementType::ManPower:
|
||||
setLineType("MO", index); // type
|
||||
break;
|
||||
case ElementType::Machinery:
|
||||
setLineType("MQ", index); // type
|
||||
break;
|
||||
case ElementType::Subcontracted:
|
||||
setLineType("SC", index); // type
|
||||
break;
|
||||
case ElementType::Other:
|
||||
setLineType("OT", index); // type
|
||||
break;
|
||||
default:
|
||||
setLineType("UNKNOWN", index); // type
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << qry.lastError().text();
|
||||
}
|
||||
|
||||
dApp->Enterprise().close();
|
||||
QString title, unitId;
|
||||
if (!ProductDAO::getElementBasicInfo(ID, title, unitId))
|
||||
return false;
|
||||
|
||||
setCellText(title, index, 1); // TITLE
|
||||
setCellText(unitId, index, 4); // UNIT
|
||||
|
||||
// Leer datos completos para precio y tipo
|
||||
int type1, type2;
|
||||
QString desc, famId, barcode, manuf, gamma;
|
||||
QDate dateUpd;
|
||||
double realPrice, disc, purchPrice, benefit, tax, salePrice;
|
||||
double weight, height, width, lenght;
|
||||
QByteArray img;
|
||||
bool state;
|
||||
|
||||
if (ProductDAO::read(ID, type1, type2, desc, title, famId, unitId,
|
||||
dateUpd, realPrice, disc, purchPrice,
|
||||
benefit, tax, salePrice, barcode, img, state,
|
||||
manuf, gamma, weight, height, width, lenght))
|
||||
{
|
||||
setCellText(QString::number(purchPrice), index, 5); // PRICE
|
||||
|
||||
switch (type1)
|
||||
{
|
||||
case ElementType::Composed: setLineType("CO", index); break;
|
||||
case ElementType::Material: setLineType("MT", index); break;
|
||||
case ElementType::ManPower: setLineType("MO", index); break;
|
||||
case ElementType::Machinery: setLineType("MQ", index); break;
|
||||
case ElementType::Subcontracted: setLineType("SC", index); break;
|
||||
case ElementType::Other: setLineType("OT", index); break;
|
||||
default: setLineType("UNKNOWN", index); break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void formProduct::on_comboType2_currentIndexChanged(int index)
|
||||
|
||||
@@ -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) + " €");
|
||||
}
|
||||
@@ -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
|
||||
@@ -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."));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,93 @@
|
||||
#include "formtemplateeditor.h"
|
||||
#include "ui_formtemplateeditor.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QMessageBox>
|
||||
#include <QDebug>
|
||||
|
||||
formTemplateEditor::formTemplateEditor(QWidget *parent)
|
||||
: QMainWindow(parent), ui(new Ui::formTemplateEditor)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connectSignals();
|
||||
}
|
||||
|
||||
formTemplateEditor::~formTemplateEditor()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void formTemplateEditor::connectSignals()
|
||||
{
|
||||
connect(ui->saveButton, &QPushButton::clicked, this, &formTemplateEditor::saveTemplate);
|
||||
}
|
||||
|
||||
void formTemplateEditor::loadTemplate(const Template &tpl)
|
||||
{
|
||||
m_currentTemplate = tpl;
|
||||
ui->nameEdit->setText(tpl.name);
|
||||
ui->descriptionEdit->setText(tpl.description);
|
||||
ui->typeCombo->setCurrentText(tpl.documentType);
|
||||
ui->widthSpin->setValue(tpl.widthMM);
|
||||
ui->heightSpin->setValue(tpl.heightMM);
|
||||
ui->marginTopSpin->setValue(tpl.marginTop);
|
||||
ui->marginBottomSpin->setValue(tpl.marginBottom);
|
||||
ui->marginLeftSpin->setValue(tpl.marginLeft);
|
||||
ui->marginRightSpin->setValue(tpl.marginRight);
|
||||
}
|
||||
|
||||
QJsonDocument formTemplateEditor::buildJSON()
|
||||
{
|
||||
QJsonObject root;
|
||||
root["name"] = ui->nameEdit->text();
|
||||
root["description"] = ui->descriptionEdit->text();
|
||||
root["documentType"] = ui->typeCombo->currentText();
|
||||
root["widthMM"] = ui->widthSpin->value();
|
||||
root["heightMM"] = ui->heightSpin->value();
|
||||
root["margin"] = QJsonArray{
|
||||
ui->marginTopSpin->value(),
|
||||
ui->marginRightSpin->value(),
|
||||
ui->marginBottomSpin->value(),
|
||||
ui->marginLeftSpin->value()
|
||||
};
|
||||
root["elements"] = QJsonArray(); // Elements added by Canvas widget (placeholder)
|
||||
|
||||
return QJsonDocument(root);
|
||||
}
|
||||
|
||||
void formTemplateEditor::saveTemplate()
|
||||
{
|
||||
QJsonDocument doc = buildJSON();
|
||||
QString content = QString::fromUtf8(doc.toJson());
|
||||
|
||||
Template tpl;
|
||||
tpl.name = ui->nameEdit->text();
|
||||
tpl.description = ui->descriptionEdit->text();
|
||||
tpl.documentType = ui->typeCombo->currentText();
|
||||
tpl.widthMM = ui->widthSpin->value();
|
||||
tpl.heightMM = ui->heightSpin->value();
|
||||
tpl.marginTop = ui->marginTopSpin->value();
|
||||
tpl.marginBottom = ui->marginBottomSpin->value();
|
||||
tpl.marginLeft = ui->marginLeftSpin->value();
|
||||
tpl.marginRight = ui->marginRightSpin->value();
|
||||
tpl.content = content;
|
||||
tpl.isDefault = false;
|
||||
tpl.createdBy = "user";
|
||||
|
||||
bool ok;
|
||||
if (m_currentTemplate.id > 0) {
|
||||
tpl.id = m_currentTemplate.id;
|
||||
ok = TemplateDAO::update(tpl);
|
||||
} else {
|
||||
ok = TemplateDAO::create(tpl);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
QMessageBox::information(this, tr("Éxito"), tr("Plantilla guardada correctamente."));
|
||||
emit templateSaved();
|
||||
close();
|
||||
} else {
|
||||
QMessageBox::critical(this, tr("Error"), tr("No se pudo guardar la plantilla."));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef FORMTEMPLATEEDITOR_H
|
||||
#define FORMTEMPLATEEDITOR_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QJsonDocument>
|
||||
#include "templatedao.h"
|
||||
|
||||
namespace Ui {
|
||||
class formTemplateEditor;
|
||||
}
|
||||
|
||||
class formTemplateEditor : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit formTemplateEditor(QWidget *parent = nullptr);
|
||||
~formTemplateEditor();
|
||||
|
||||
void loadTemplate(const Template &tpl);
|
||||
|
||||
signals:
|
||||
void templateSaved();
|
||||
|
||||
private:
|
||||
Ui::formTemplateEditor *ui;
|
||||
Template m_currentTemplate;
|
||||
|
||||
void connectSignals();
|
||||
QJsonDocument buildJSON();
|
||||
void saveTemplate();
|
||||
};
|
||||
|
||||
#endif // FORMTEMPLATEEDITOR_H
|
||||
@@ -0,0 +1,92 @@
|
||||
#include "formtemplatelist.h"
|
||||
#include "ui_formtemplatelist.h"
|
||||
#include "templatedao.h"
|
||||
#include "formtemplateeditor.h"
|
||||
#include <QSqlQueryModel>
|
||||
#include <QMessageBox>
|
||||
|
||||
formTemplateList::formTemplateList(QWidget *parent)
|
||||
: QMainWindow(parent), ui(new Ui::formTemplateList)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setupModel();
|
||||
|
||||
connect(ui->refreshButton, &QPushButton::clicked, this, &formTemplateList::refreshList);
|
||||
connect(ui->newButton, &QPushButton::clicked, this, &formTemplateList::createNewTemplate);
|
||||
connect(ui->editButton, &QPushButton::clicked, this, &formTemplateList::editTemplate);
|
||||
connect(ui->deleteButton, &QPushButton::clicked, this, &formTemplateList::deleteTemplate);
|
||||
}
|
||||
|
||||
formTemplateList::~formTemplateList()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void formTemplateList::setupModel()
|
||||
{
|
||||
QSqlQueryModel *model = new QSqlQueryModel(this);
|
||||
model->setQuery("SELECT ID, NAME, DESCRIPTION, DOCUMENT_TYPE FROM TEMPLATE ORDER BY NAME");
|
||||
model->setHeaderData(0, Qt::Horizontal, tr("ID"));
|
||||
model->setHeaderData(1, Qt::Horizontal, tr("Nombre"));
|
||||
model->setHeaderData(2, Qt::Horizontal, tr("Descripción"));
|
||||
model->setHeaderData(3, Qt::Horizontal, tr("Tipo"));
|
||||
ui->templateTable->setModel(model);
|
||||
ui->templateTable->setColumnHidden(0, true);
|
||||
}
|
||||
|
||||
void formTemplateList::refreshList()
|
||||
{
|
||||
QSqlQueryModel *model = qobject_cast<QSqlQueryModel*>(ui->templateTable->model());
|
||||
if (model)
|
||||
model->setQuery(model->query().lastQuery());
|
||||
}
|
||||
|
||||
void formTemplateList::createNewTemplate()
|
||||
{
|
||||
formTemplateEditor *editor = new formTemplateEditor(this);
|
||||
connect(editor, &formTemplateEditor::templateSaved, this, [this]() {
|
||||
refreshList();
|
||||
});
|
||||
editor->show();
|
||||
}
|
||||
|
||||
void formTemplateList::editTemplate()
|
||||
{
|
||||
QModelIndex idx = ui->templateTable->currentIndex();
|
||||
if (!idx.isValid()) {
|
||||
QMessageBox::information(this, tr("Info"), tr("Selecciona una plantilla primero."));
|
||||
return;
|
||||
}
|
||||
int row = idx.row();
|
||||
int id = ui->templateTable->model()->data(ui->templateTable->model()->index(row, 0)).toInt();
|
||||
|
||||
Template tpl = TemplateDAO::getById(id);
|
||||
formTemplateEditor *editor = new formTemplateEditor(this);
|
||||
editor->loadTemplate(tpl);
|
||||
connect(editor, &formTemplateEditor::templateSaved, this, [this]() {
|
||||
refreshList();
|
||||
});
|
||||
editor->show();
|
||||
}
|
||||
|
||||
void formTemplateList::deleteTemplate()
|
||||
{
|
||||
QModelIndex idx = ui->templateTable->currentIndex();
|
||||
if (!idx.isValid()) {
|
||||
QMessageBox::information(this, tr("Info"), tr("Selecciona una plantilla primero."));
|
||||
return;
|
||||
}
|
||||
int row = idx.row();
|
||||
int id = ui->templateTable->model()->data(ui->templateTable->model()->index(row, 0)).toInt();
|
||||
|
||||
int ret = QMessageBox::question(this, tr("Confirmar"), tr("¿Eliminar esta plantilla?"),
|
||||
QMessageBox::Yes | QMessageBox::No);
|
||||
if (ret == QMessageBox::Yes) {
|
||||
if (TemplateDAO::remove(id)) {
|
||||
QMessageBox::information(this, tr("Éxito"), tr("Plantilla eliminada."));
|
||||
refreshList();
|
||||
} else {
|
||||
QMessageBox::critical(this, tr("Error"), tr("No se pudo eliminar la plantilla."));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef FORMTEMPLATELIST_H
|
||||
#define FORMTEMPLATELIST_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include "templatedao.h"
|
||||
|
||||
namespace Ui {
|
||||
class formTemplateList;
|
||||
}
|
||||
|
||||
class formTemplateList : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit formTemplateList(QWidget *parent = nullptr);
|
||||
~formTemplateList();
|
||||
|
||||
public slots:
|
||||
void refreshList();
|
||||
void createNewTemplate();
|
||||
void editTemplate();
|
||||
void deleteTemplate();
|
||||
|
||||
private:
|
||||
void setupModel();
|
||||
Ui::formTemplateList *ui;
|
||||
};
|
||||
|
||||
#endif // FORMTEMPLATELIST_H
|
||||
+67
-120
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QtSql>
|
||||
#include "../dao/thirddao.h"
|
||||
|
||||
formThird::formThird(QString aID, int aEditMode, QWidget *parent) :
|
||||
formBase(aID, aEditMode, parent),
|
||||
@@ -31,52 +32,43 @@ formThird::~formThird()
|
||||
void formThird::openDocument(QString id)
|
||||
{
|
||||
mEditMode = true;
|
||||
//ui->editCode->setText(id);
|
||||
//ui->editCode->setReadOnly(true);
|
||||
rowid = id.toInt();
|
||||
|
||||
dApp->Enterprise().open();
|
||||
QSqlQuery qry = QSqlQuery(dApp->Enterprise());
|
||||
ThirdDAO::Data data;
|
||||
if (ThirdDAO::read(rowid, data)) {
|
||||
ui->editName->setText(data.name);
|
||||
ui->editNickname->setText(data.nickname);
|
||||
ui->editCIF->setText(data.cif);
|
||||
ui->editIntraCode->setText(data.intraFc);
|
||||
|
||||
QString command = QString("SELECT * FROM THIRD WHERE ID = '%1';").arg(id);
|
||||
if (qry.exec(command))
|
||||
{
|
||||
qry.first();
|
||||
ui->comboState->setCurrentIndex(data.state);
|
||||
ui->comboClient->setCurrentIndex(data.clientState);
|
||||
ui->editClientCode->setText(data.clientCode);
|
||||
ui->editAccountClient->setText(data.clientAccount);
|
||||
ui->comboSupplier->setCurrentIndex(data.supplierState);
|
||||
ui->editSupplierCode->setText(data.supplierCode);
|
||||
ui->editAccountSupplier->setText(data.supplierAccount);
|
||||
|
||||
ui->editName->setText(qry.value(qry.record().indexOf("NAME")).toString());
|
||||
ui->editNickname->setText(qry.value(qry.record().indexOf("NICKNAME")).toString());
|
||||
ui->editCIF->setText(qry.value(qry.record().indexOf("CIF")).toString());
|
||||
ui->editIntraCode->setText(qry.value(qry.record().indexOf("INTRA_FC")).toString());
|
||||
ui->editAddress->setPlainText(data.address);
|
||||
ui->editCP->setText(data.postcode);
|
||||
ui->editCity->setText(data.city);
|
||||
ui->editProvince->setText(data.province);
|
||||
ui->comboCountry->setCurrentText(data.countryId);
|
||||
|
||||
ui->comboState->setCurrentIndex(qry.value(qry.record().indexOf("STATE")).toInt());
|
||||
ui->comboClient->setCurrentIndex(qry.value(qry.record().indexOf("CLIENT_STATE")).toInt());
|
||||
ui->comboClient->setCurrentIndex(qry.value(qry.record().indexOf("SUPPLIER_STATE")).toInt());
|
||||
ui->editClientCode->setText(qry.value(qry.record().indexOf("CLIENT_CODE")).toString());
|
||||
ui->editSupplierCode->setText(qry.value(qry.record().indexOf("SUPPLIER_CODE")).toString());
|
||||
ui->editPhone->setText(data.phone);
|
||||
ui->editFax->setText(data.fax);
|
||||
ui->editMobile->setText(data.mobile);
|
||||
ui->editEmail->setText(data.email);
|
||||
ui->editWebside->setText(data.website);
|
||||
|
||||
ui->editAddress->setPlainText(qry.value(qry.record().indexOf("ADDRESS")).toString());
|
||||
ui->editCP->setText(qry.value(qry.record().indexOf("POSTCODE")).toString());
|
||||
ui->editCity->setText(qry.value(qry.record().indexOf("CITY")).toString());
|
||||
ui->editProvince->setText(qry.value(qry.record().indexOf("PROVINCE")).toString());
|
||||
ui->comboCountry->setCurrentText(qry.value(qry.record().indexOf("COUNTRY_ID")).toString());
|
||||
ui->editPublicNotes->setHtml(data.notePublic);
|
||||
ui->editPrivateNotes->setHtml(data.notePrivate);
|
||||
|
||||
ui->editPhone->setText(qry.value(qry.record().indexOf("PHONE")).toString());
|
||||
ui->editFax->setText(qry.value(qry.record().indexOf("FAX")).toString());
|
||||
ui->editMobile->setText(qry.value(qry.record().indexOf("MOBILE")).toString());
|
||||
ui->editEmail->setText(qry.value(qry.record().indexOf("EMAIL")).toString());
|
||||
ui->editWebside->setText(qry.value(qry.record().indexOf("WEBSIDE")).toString());
|
||||
|
||||
ui->editPublicNotes->setHtml(qry.value(qry.record().indexOf("NOTE_PUBLIC")).toString());
|
||||
ui->editPrivateNotes->setHtml(qry.value(qry.record().indexOf("NOTE_PRIVATE")).toString());
|
||||
|
||||
ui->editDischargeDate->setDate(qry.value(qry.record().indexOf("CREATEDAT")).toDate());
|
||||
ui->editUpdateDate->setDate(qry.value(qry.record().indexOf("UPDATEDAT")).toDate());
|
||||
ui->editDischargeDate->setDate(data.createdAt);
|
||||
ui->editUpdateDate->setDate(data.updatedAt);
|
||||
} else {
|
||||
qDebug() << "Error reading third with ID:" << id;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Error ejecutando el query: " << qry.lastError().text() << "\n";
|
||||
}
|
||||
|
||||
dApp->Enterprise().close();
|
||||
}
|
||||
|
||||
void formThird::closeDocument()
|
||||
@@ -127,91 +119,46 @@ void formThird::LoadLogo()
|
||||
|
||||
void formThird::save()
|
||||
{
|
||||
QString command;
|
||||
ThirdDAO::Data data;
|
||||
data.cif = ui->editCIF->text();
|
||||
data.name = ui->editName->text();
|
||||
data.nickname = ui->editNickname->text();
|
||||
data.intraFc = ui->editIntraCode->text();
|
||||
data.state = ui->comboState->currentIndex();
|
||||
data.clientState = ui->comboClient->currentIndex();
|
||||
data.clientCode = ui->editClientCode->text();
|
||||
data.clientAccount = ui->editAccountClient->text();
|
||||
data.supplierState = ui->comboSupplier->currentIndex();
|
||||
data.supplierCode = ui->editSupplierCode->text();
|
||||
data.supplierAccount = ui->editAccountSupplier->text();
|
||||
data.address = ui->editAddress->toPlainText();
|
||||
data.postcode = ui->editCP->text();
|
||||
data.city = ui->editCity->text();
|
||||
data.province = ui->editProvince->text();
|
||||
data.countryId = ui->comboCountry->currentText();
|
||||
data.phone = ui->editPhone->text();
|
||||
data.fax = ui->editFax->text();
|
||||
data.mobile = ui->editMobile->text();
|
||||
data.email = ui->editEmail->text();
|
||||
data.website = ui->editWebside->text();
|
||||
data.notePublic = ui->editPublicNotes->toHtml();
|
||||
data.notePrivate = ui->editPrivateNotes->toHtml();
|
||||
data.updatedAt = ui->editUpdateDate->date();
|
||||
data.createdAt = ui->editDischargeDate->date();
|
||||
|
||||
if (mEditMode)
|
||||
command = "UPDATE THIRD SET "
|
||||
"FORM = :FORM, CIF = :CIF, NAME = :NAME, NICKNAME = :NICKNAME, FAMILY = :FAMILY, "
|
||||
"INTRA_FC = :INTRA_FC, STATE = :STATE, CLIENT_STATE = :CLIENT_STATE, CLIENT_CODE = :CLIENT_CODE, "
|
||||
"CLIENT_ACCOUNT = :CLIENT_ACCOUNT, SUPPLIER_STATE = :SUPPLIER_STATE, SUPPLIER_CODE = :SUPLLIR_CODE, "
|
||||
"SUPPLIER_ACCOUNT = :SUPPLIER_ACCOUNT, ADDRESS = :ADDRESS, POSTCODE = :POSTCODE, CITY = :CITY, "
|
||||
"PROVINCE = :PROVINCE, COUNTRY_ID = :COUNTRY_ID, PHONE = :PHONE, FAX = :FAX, "
|
||||
"EMAIL = :EMAIL, WEBSIDE = :WEBSIDE, PAYMENT_METHOD = :PAYMENT_METHOD, PAYMENT_TYPE = :PAYMENT_TYPE, "
|
||||
"LOGO = :LOGO, NOTE_PUBLIC = :NOTE_PUBLIC, NOTE_PRIVATE = :NOTE_PRIVATE, UPDATEDAT = :UPDATEDAT, "
|
||||
"CREATEDAT = :CREATEDAT, CREATEDBY = :CREATEBY "
|
||||
"WHERE CIF = '" + ui->editCIF->text() +
|
||||
"';";
|
||||
else
|
||||
command = "INSERT INTO THIRD ("
|
||||
"FORM, CIF, NAME, NICKNAME, FAMILY, INTRA_FC, STATE, CLIENT_STATE, CLIENT_CODE, "
|
||||
"CLIENT_ACCOUNT, SUPPLIER_STATE, SUPPLIER_CODE, SUPPLIER_ACCOUNT, ADDRESS, "
|
||||
"POSTCODE, CITY, PROVINCE, COUNTRY_ID, PHONE, FAX, EMAIL, WEBSIDE, "
|
||||
"PAYMENT_METHOD, PAYMENT_TYPE, LOGO, NOTE_PUBLIC, NOTE_PRIVATE, UPDATEDAT, "
|
||||
"CREATEDAT, CREATEDBY"
|
||||
") VALUES ("
|
||||
":FORM, :CIF, :NAME, :NICKNAME, :FAMILY, :INTRA_FC, :STATE, :CLIENT_STATE, :CLIENT_CODE, "
|
||||
":CLIENT_ACCOUNT, :SUPPLIER_STATE, :SUPPLIER_CODE, :SUPPLIER_ACCOUNT, :ADDRESS, "
|
||||
":POSTCODE, :CITY, :PROVINCE, :COUNTRY_ID, :PHONE, :FAX, :EMAIL, :WEBSIDE, "
|
||||
":PAYMENT_METHOD, :PAYMENT_TYPE, :LOGO, :NOTE_PUBLIC, :NOTE_PRIVATE, :UPDATEDAT, "
|
||||
":CREATEDAT, :CREATEDBY"
|
||||
");";
|
||||
|
||||
qDebug() << command;
|
||||
|
||||
dApp->Enterprise().open();
|
||||
QSqlQuery qry = QSqlQuery(dApp->Enterprise());
|
||||
qry.prepare(command);
|
||||
|
||||
//qry.bindValue(":FORM", );
|
||||
qry.bindValue(":CIF", ui->editCIF->text());
|
||||
qry.bindValue(":NAME", ui->editName->text());
|
||||
qry.bindValue(":NICKNAME", ui->editNickname->text());
|
||||
//qry.bindValue(":FAMILY", );
|
||||
qry.bindValue(":INTRA_FC", ui->editIntraCode->text());
|
||||
qry.bindValue(":STATE", ui->comboState->currentIndex());
|
||||
|
||||
qry.bindValue(":CLIENT_STATE", ui->comboClient->currentIndex());
|
||||
qry.bindValue(":CLIENT_CODE", ui->editClientCode->text());
|
||||
qry.bindValue(":CLIENT_ACCOUNT", ui->editAccountClient->text());
|
||||
|
||||
qry.bindValue(":SUPPLIER_STATE", ui->comboSupplier->currentIndex());
|
||||
qry.bindValue(":SUPPLIER_CODE", ui->editSupplierCode->text());
|
||||
qry.bindValue(":SUPPLIER_ACCOUNT", ui->editAccountSupplier->text());
|
||||
|
||||
qry.bindValue(":ADDRESS", ui->editAddress->toPlainText());
|
||||
qry.bindValue(":POSTCODE", ui->editCP->text());
|
||||
qry.bindValue(":CITY", ui->editCity->text());
|
||||
qry.bindValue(":PROVINCE", ui->editProvince->text());
|
||||
qry.bindValue(":COUNTRY_ID", ui->comboCountry->currentText());
|
||||
//qry.bindValue(":COUNTRY", ui->editIntraCode->text());
|
||||
|
||||
qry.bindValue(":PHONE", ui->editPhone->text());
|
||||
qry.bindValue(":FAX", ui->editFax->text());
|
||||
qry.bindValue(":MOBILE", ui->editMobile->text());
|
||||
qry.bindValue(":EMAIL", ui->editEmail->text());
|
||||
qry.bindValue(":WEBSIDE", ui->editWebside->text());
|
||||
|
||||
//qry.bindValue(":PAYMENT_METHOD", ui->editPhone->text());
|
||||
//qry.bindValue(":PAYMENT_TYPE", ui->editFax->text());
|
||||
|
||||
//qry.bindValue(":LOGO", ui->editMobile->text());
|
||||
qry.bindValue(":NOTE_PUBLIC", ui->editPublicNotes->toHtml());
|
||||
qry.bindValue(":NOTE_PRIVATE", ui->editPrivateNotes->toHtml());
|
||||
|
||||
qry.bindValue(":UPDATEDAT", ui->editUpdateDate->date());
|
||||
qry.bindValue(":CREATEDAT", ui->editDischargeDate->date());
|
||||
//qry.bindValue(":CREATEDBY", ui->editWebside->text());
|
||||
|
||||
if (!qry.exec())
|
||||
{
|
||||
qDebug() << "Error ejecutando el query: " << qry.lastError().text() << "\n";
|
||||
bool ok;
|
||||
if (mEditMode) {
|
||||
data.id = rowid;
|
||||
ok = ThirdDAO::update(data);
|
||||
} else {
|
||||
ok = ThirdDAO::create(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (ok) {
|
||||
setEditMode();
|
||||
} else {
|
||||
qDebug() << "Error saving third";
|
||||
}
|
||||
|
||||
dApp->Enterprise().close();
|
||||
}
|
||||
|
||||
void formThird::setEditMode()
|
||||
|
||||
Binary file not shown.
@@ -302,3 +302,15 @@ void MainWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
dApp->quit();
|
||||
}
|
||||
|
||||
void MainWindow::importFIEBDCFile()
|
||||
{
|
||||
// TODO: stub - implementar cuando se restaure la funcionalidad
|
||||
QMessageBox::information(this, tr("Import"), tr("FIEBDC import not yet available."));
|
||||
}
|
||||
|
||||
void MainWindow::exportBC3File()
|
||||
{
|
||||
// TODO: stub - implementar cuando se restaure la funcionalidad
|
||||
QMessageBox::information(this, tr("Export"), tr("BC3 export not yet available."));
|
||||
}
|
||||
@@ -98,6 +98,8 @@ public slots:
|
||||
|
||||
private slots:
|
||||
void tabCloseRequested(int index);
|
||||
void importFIEBDCFile();
|
||||
void exportBC3File();
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"name": "Presupuesto Proyecto",
|
||||
"description": "Plantilla de presupuesto para proyectos",
|
||||
"documentType": "budget",
|
||||
"widthMM": 210,
|
||||
"heightMM": 297,
|
||||
"margin": [20, 20, 20, 20],
|
||||
"elements": [
|
||||
{
|
||||
"type": "label",
|
||||
"x": 50,
|
||||
"y": 50,
|
||||
"w": 200,
|
||||
"h": 20,
|
||||
"text": "Presupuesto #{{code}}",
|
||||
"font": "Arial",
|
||||
"size": 14,
|
||||
"bold": true,
|
||||
"align": "left"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"x": 300,
|
||||
"y": 50,
|
||||
"w": 100,
|
||||
"h": 20,
|
||||
"text": "{{date}}",
|
||||
"font": "Arial",
|
||||
"size": 10,
|
||||
"bold": false
|
||||
},
|
||||
{
|
||||
"type": "table",
|
||||
"x": 50,
|
||||
"y": 80,
|
||||
"w": 350,
|
||||
"h": 150,
|
||||
"columns": ["description", "quantity", "unitPrice", "total"],
|
||||
"dataSource": "lines",
|
||||
"cellAlignment": {
|
||||
"0": "left",
|
||||
"1": "right",
|
||||
"2": "right",
|
||||
"3": "right"
|
||||
},
|
||||
"headerAlignment": "center",
|
||||
"headerColor": "#CCCCCC",
|
||||
"alternateRowColor": true,
|
||||
"rowHeight": 20
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"x": 250,
|
||||
"y": 240,
|
||||
"w": 50,
|
||||
"h": 20,
|
||||
"text": "Total:",
|
||||
"font": "Arial",
|
||||
"size": 14,
|
||||
"bold": true
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"x": 300,
|
||||
"y": 240,
|
||||
"w": 100,
|
||||
"h": 20,
|
||||
"text": "{{total}}",
|
||||
"font": "Arial",
|
||||
"size": 14,
|
||||
"bold": true,
|
||||
"align": "right"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "Factura PDF",
|
||||
"description": "Plantilla de factura para clientes",
|
||||
"documentType": "invoice",
|
||||
"widthMM": 210,
|
||||
"heightMM": 297,
|
||||
"margin": [20, 20, 20, 20],
|
||||
"elements": [
|
||||
{
|
||||
"type": "label",
|
||||
"x": 50,
|
||||
"y": 50,
|
||||
"w": 150,
|
||||
"h": 20,
|
||||
"text": "Factura #{{code}}",
|
||||
"font": "Arial",
|
||||
"size": 14,
|
||||
"bold": true,
|
||||
"align": "left"
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"x": 200,
|
||||
"y": 50,
|
||||
"w": 100,
|
||||
"h": 20,
|
||||
"text": "{{clientName}}",
|
||||
"font": "Arial",
|
||||
"size": 12,
|
||||
"bold": false
|
||||
},
|
||||
{
|
||||
"type": "table",
|
||||
"x": 50,
|
||||
"y": 80,
|
||||
"w": 200,
|
||||
"h": 100,
|
||||
"columns": ["description", "quantity", "price", "total"],
|
||||
"dataSource": "lines",
|
||||
"cellAlignment": {
|
||||
"0": "left",
|
||||
"1": "right",
|
||||
"2": "right",
|
||||
"3": "right"
|
||||
},
|
||||
"headerAlignment": "center",
|
||||
"headerColor": "#CCCCCC",
|
||||
"alternateRowColor": true,
|
||||
"rowHeight": 20
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
Binary file not shown.
Reference in New Issue
Block a user