diff --git a/.clang-format b/.clang-format index b8140ac..2c120cc 100644 --- a/.clang-format +++ b/.clang-format @@ -1,58 +1,43 @@ ---- Language: Cpp # BasedOnStyle: LLVM -AccessModifierOffset: -4 +AccessModifierOffset: -2 AlignAfterOpenBracket: Align -AlignArrayOfStructures: None -AlignConsecutiveMacros: None -AlignConsecutiveAssignments: None -AlignConsecutiveBitFields: None -AlignConsecutiveDeclarations: None +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false AlignEscapedNewlines: Right -AlignOperands: Align +AlignOperands: true AlignTrailingComments: true -AllowAllArgumentsOnNextLine: true -AllowAllConstructorInitializersOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true -AllowShortEnumsOnASingleLine: true -AllowShortBlocksOnASingleLine: Never +AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: All -AllowShortLambdasOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Never +AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: MultiLine -AttributeMacros: - - __capability +AlwaysBreakTemplateDeclarations: false BinPackArguments: true BinPackParameters: true -BraceWrapping: - AfterCaseLabel: false +BraceWrapping: AfterClass: true - AfterControlStatement: Never + AfterControlStatement: false AfterEnum: false - AfterFunction: true - AfterNamespace: true + AfterFunction: false + AfterNamespace: false AfterObjCDeclaration: false AfterStruct: false AfterUnion: false AfterExternBlock: false BeforeCatch: false BeforeElse: false - BeforeLambdaBody: false - BeforeWhile: false IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true BreakBeforeBinaryOperators: None -BreakBeforeConceptDeclarations: true -BreakBeforeBraces: Custom +BreakBeforeBraces: Linux BreakBeforeInheritanceComma: false -BreakInheritanceList: BeforeColon BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon @@ -65,56 +50,35 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true -DeriveLineEnding: true DerivePointerAlignment: false DisableFormat: false -EmptyLineAfterAccessModifier: Never -EmptyLineBeforeAccessModifier: LogicalBlock ExperimentalAutoDetectBinPacking: false FixNamespaceComments: true -ForEachMacros: +ForEachMacros: - foreach - Q_FOREACH - BOOST_FOREACH -IfMacros: - - KJ_IF_MAYBE IncludeBlocks: Preserve -IncludeCategories: +IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 - SortPriority: 0 - CaseSensitive: false - Regex: '^(<|"(gtest|gmock|isl|json)/)' Priority: 3 - SortPriority: 0 - CaseSensitive: false - Regex: '.*' Priority: 1 - SortPriority: 0 - CaseSensitive: false IncludeIsMainRegex: '(Test)?$' -IncludeIsMainSourceRegex: '' -IndentAccessModifiers: false IndentCaseLabels: false -IndentCaseBlocks: false -IndentGotoLabels: true IndentPPDirectives: None -IndentExternBlock: AfterExternBlock -IndentRequires: false IndentWidth: 4 IndentWrappedFunctionNames: false -InsertTrailingCommas: None JavaScriptQuotes: Leave JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: true -LambdaBodyIndentation: Signature MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None -ObjCBinPackProtocolList: Auto ObjCBlockIndentWidth: 2 -ObjCBreakBeforeNestedBlockParam: true ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: true PenaltyBreakAssignment: 2 @@ -122,57 +86,24 @@ PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 -PenaltyIndentedWhitespace: 0 -PointerAlignment: Right -PPIndentWidth: -1 -ReferenceAlignment: Pointer +PointerAlignment: Left ReflowComments: true -ShortNamespaceLines: 1 -SortIncludes: CaseSensitive -SortJavaStaticImport: Before +SortIncludes: true SortUsingDeclarations: true SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true -SpaceBeforeCaseColon: false -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements -SpaceAroundPointerQualifiers: Default -SpaceBeforeRangeBasedForLoopColon: true -SpaceInEmptyBlock: false SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 -SpacesInAngles: Never -SpacesInConditionalStatement: false +SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false -SpacesInLineCommentPrefix: - Minimum: 1 - Maximum: -1 SpacesInParentheses: false SpacesInSquareBrackets: false -SpaceBeforeSquareBrackets: false -BitFieldColonSpacing: Both -Standard: Latest -StatementAttributeLikeMacros: - - Q_EMIT -StatementMacros: - - Q_UNUSED - - QT_REQUIRE_VERSION +Standard: Auto TabWidth: 8 -UseCRLF: false UseTab: Never -WhitespaceSensitiveMacros: - - STRINGIZE - - PP_STRINGIZE - - BOOST_PP_STRINGIZE - - NS_SWIFT_NAME - - CF_SWIFT_NAME -... diff --git a/.gitignore b/.gitignore index 6e490ea..c795b05 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1 @@ -build -.vscode/ipch/* -.kdev4 -.cache \ No newline at end of file +build \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index e69de29..1cec96a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "3rdparty/nlohmann_json"] + path = 3rdparty/nlohmann_json + url = https://github.com/nlohmann/json.git diff --git a/.vscode/launch.json b/.vscode/launch.json index fb0e8c6..17dfcc6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -21,8 +21,7 @@ "text": "-enable-pretty-printing", "ignoreFailures": true } - ], - "visualizerFile": "/home/brodbemn/.config/Code - OSS/User/workspaceStorage/d64ec049841ecb3d43e402bb3c167cb5/tonka3000.qtvsctools/qt.natvis.xml" + ] } ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 41f34ac..0b81f37 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -65,47 +65,9 @@ "condition_variable": "cpp", "mutex": "cpp", "hash_map": "cpp", - "future": "cpp", - "bit": "cpp", - "compare": "cpp", - "concepts": "cpp", - "forward_list": "cpp", - "map": "cpp", - "set": "cpp", - "string": "cpp", - "unordered_set": "cpp", - "iterator": "cpp", - "memory_resource": "cpp", - "random": "cpp", - "semaphore": "cpp", - "stop_token": "cpp", - "__bit_reference": "cpp", - "__bits": "cpp", - "__config": "cpp", - "__debug": "cpp", - "__errc": "cpp", - "__hash_table": "cpp", - "__locale": "cpp", - "__mutex_base": "cpp", - "__node_handle": "cpp", - "__split_buffer": "cpp", - "__threading_support": "cpp", - "__tree": "cpp", - "__tuple": "cpp", - "__verbose_abort": "cpp", - "format": "cpp", - "ios": "cpp", - "locale": "cpp" + "future": "cpp" }, "C_Cpp.clang_format_path": "/usr/bin/clang-format", "cmake.configureOnOpen": true, - "C_Cpp.configurationWarnings": "Disabled", - "files.watcherExclude": { - "**/.git/objects/**": true, - "**/.git/subtree-cache/**": true, - "**/node_modules/*/**": true, - "**/.hg/store/**": true, - ".flatpak/**": true, - "_build/**": true - } + "C_Cpp.configurationWarnings": "Disabled" } \ No newline at end of file diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt new file mode 100644 index 0000000..ad35ca6 --- /dev/null +++ b/3rdparty/CMakeLists.txt @@ -0,0 +1,4 @@ +if(NOT KIMA2_USE_EXTERNAL_JSON) + set(JSON_BuildTests OFF CACHE INTERNAL "") + add_subdirectory(nlohmann_json EXCLUDE_FROM_ALL) +endif() diff --git a/3rdparty/nlohmann_json b/3rdparty/nlohmann_json new file mode 160000 index 0000000..f1768a5 --- /dev/null +++ b/3rdparty/nlohmann_json @@ -0,0 +1 @@ +Subproject commit f1768a540a7b7c5cc30cdcd6be9e9ef91083719b diff --git a/CMakeLists.txt b/CMakeLists.txt index 86b072a..7bbd98b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,24 +1,21 @@ -cmake_minimum_required(VERSION 3.30) +cmake_minimum_required(VERSION 3.8) -project(kima2 VERSION 1.9.2) +project(kima2 VERSION 0.13.1) -set(CMAKE_MODULE_PATH "${CMAKE_HOME_DIRECTORY}/cmake") +set(CMAKE_MODULE_PATH "${CMAKE_HOME_DIRECTORY}/cmake" ${CMAKE_MODULE_PATH}) -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -# For SingleApplication and nlohmann_json -include(FetchContent) +#include(InstallRequiredSystemLibraries) if(MSVC) add_compile_options(/W4 /WX) else() - #add_compile_options(-Wall -Wextra -pedantic -Woverloaded-virtual -Wredundant-decls -Wshadow) - add_compile_options(-Wall -Wextra) + add_compile_options(-Wall -Wextra -pedantic -Woverloaded-virtual -Wredundant-decls -Wshadow) endif() configure_file(config.h.in ${PROJECT_BINARY_DIR}/config.h) -configure_file(de.rustysoft.kima2.metainfo.xml.in ${PROJECT_BINARY_DIR}/de.rustysoft.kima2.metainfo.xml) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) @@ -30,13 +27,14 @@ if(KIMA2_USE_EXTERNAL_JSON) find_package(nlohmann_json REQUIRED) endif() +add_subdirectory(3rdparty) add_subdirectory(src) -#if(NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE MATCHES Debug) -# include(CTest) -# enable_testing() -# add_subdirectory(test) -#endif() +if(NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE MATCHES Debug) + include(CTest) + enable_testing() + add_subdirectory(test) +endif() # CPack @@ -80,8 +78,6 @@ else(WIN32 AND NOT UNIX) DESTINATION share/${PROJECT_NAME}) install(FILES "${CMAKE_SOURCE_DIR}/misc/kima2.svg" DESTINATION share/icons/hicolor/scalable/apps) - install(FILES de.rustysoft.kima2.metainfo.xml - DESTINATION share/metainfo) endif (WIN32 AND NOT UNIX) if( MINGW ) @@ -90,19 +86,18 @@ if( MINGW ) set( CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS ${MINGW_PATH}/libstdc++-6.dll ${MINGW_PATH}/libgcc_s_seh-1.dll - ${MINGW_PATH}/Qt6Core.dll - ${MINGW_PATH}/Qt6Gui.dll - ${MINGW_PATH}/Qt6Widgets.dll - ${MINGW_PATH}/Qt6PrintSupport.dll - ${MINGW_PATH}/Qt6Network.dll + ${MINGW_PATH}/Qt5Core.dll + ${MINGW_PATH}/Qt5Gui.dll + ${MINGW_PATH}/Qt5Widgets.dll + ${MINGW_PATH}/Qt5PrintSupport.dll ${MINGW_PATH}/libwinpthread-1.dll ${MINGW_PATH}/libsqlite3-0.dll ${MINGW_PATH}/libusb-1.0.dll - ${MINGW_PATH}/libicuuc76.dll - ${MINGW_PATH}/libicuin76.dll - ${MINGW_PATH}/libicudt76.dll + ${MINGW_PATH}/libxlnt.dll + ${MINGW_PATH}/libicuuc62.dll + ${MINGW_PATH}/libicuin62.dll + ${MINGW_PATH}/libicudt62.dll ${MINGW_PATH}/libpcre2-16-0.dll - ${MINGW_PATH}/libpcre2-8-0.dll ${MINGW_PATH}/zlib1.dll ${MINGW_PATH}/libharfbuzz-0.dll ${MINGW_PATH}/libpng16-16.dll @@ -111,26 +106,21 @@ if( MINGW ) ${MINGW_PATH}/libgraphite2.dll ${MINGW_PATH}/libbz2-1.dll ${MINGW_PATH}/libintl-8.dll - ${MINGW_PATH}/libdouble-conversion.dll - ${MINGW_PATH}/libzstd.dll - ${MINGW_PATH}/libmd4c.dll - ${MINGW_PATH}/libbrotlicommon.dll - ${MINGW_PATH}/libbrotlidec.dll - #${MINGW_PATH}/libfmt.dll - ${MINGW_PATH}/libb2-1.dll + ${MINGW_PATH}/libpcre-1.dll ${MINGW_PATH}/libiconv-2.dll) - install(FILES ${MINGW_PATH}/../share/qt6/plugins/platforms/qwindows.dll - ${MINGW_PATH}/../share/qt6/plugins/platforms/qminimal.dll + install(FILES ${MINGW_PATH}/../share/qt5/plugins/platforms/qwindows.dll + ${MINGW_PATH}/../share/qt5/plugins/platforms/qminimal.dll DESTINATION bin/platforms) - #install(FILES ${MINGW_PATH}/../share/qt6/plugins/printsupport/windowsprintersupport.dll - # DESTINATION bin/printsupport) - install(FILES ${MINGW_PATH}/../share/qt6/translations/qtbase_de.qm - ${MINGW_PATH}/../share/qt6/translations/qt_de.qm - ${MINGW_PATH}/../share/qt6/translations/qt_help_de.qm - ${MINGW_PATH}/../share/qt6/translations/qtmultimedia_de.qm - DESTINATION bin/share/qt6/translations) - install(FILES ${MINGW_PATH}/../share/qt6/plugins/styles/qmodernwindowsstyle.dll - DESTINATION bin/styles) + install(FILES ${MINGW_PATH}/../share/qt5/plugins/printsupport/windowsprintersupport.dll + DESTINATION bin/printsupport) + install(FILES ${MINGW_PATH}/../share/qt5/translations/qtbase_de.qm + ${MINGW_PATH}/../share/qt5/translations/qt_de.qm + ${MINGW_PATH}/../share/qt5/translations/qt_help_de.qm + ${MINGW_PATH}/../share/qt5/translations/qtmultimedia_de.qm + ${MINGW_PATH}/../share/qt5/translations/qtquick1_de.qm + ${MINGW_PATH}/../share/qt5/translations/qtscript_de.qm + ${MINGW_PATH}/../share/qt5/translations/qtxmlpatterns_de.qm + DESTINATION bin/translations) endif( MINGW ) include(InstallRequiredSystemLibraries) diff --git a/LICENSE b/LICENSE index 0b127da..082cdac 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright © 2018-2025 Martin Brodbeck +Copyright © 2018 Martin Brodbeck Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis erteilt, diff --git a/README.md b/README.md index 3c0dd87..7e2bc98 100644 --- a/README.md +++ b/README.md @@ -13,16 +13,19 @@ Verkaufsdaten nach dem Verkaufsende auszutauschen. Ebenso können über einen ESC/POS-Drucker Quittungen ausgestellt werden. ## Installation -Auf [rustysoft.de](https://www.rustysoft.de/software/kima2/) werden die Installationsmöglichkeiten (Flatpak, Windows-Installer) erläutert. Bitte die Hinweise dort beachten. +Auf [rustysoft.de](https://www.rustysoft.de/?01_kima2) werden verschiedene Installationspakete (Arch Linux, +Ubuntu, Windows) angeboten. Bitte die Hinweise dort beachten. -## Selbst compilieren +### Selbst compilieren KIMA2 benötigt folgende Libraries: -* Qt 6 -* boost >= 1.80 +* Qt5 +* boost >= 1.62 * libusb-1.0 +* xlnt >= 1.3.0 * nlohmann-json (als 3rdparty submodule vorhanden) -Da Features aus C++20 sowie von neueren Compilern verwendet werden, sollte als Compiler mindestens GCC 14 verwendet werden. +Da Features aus C++17 verwendet werden sowie std::filesystem, sollte als Compiler mindestens +GCC 8 verwendet werden. Die Installationsschritte unter Linux sind wie folgt: ``` @@ -34,4 +37,4 @@ sudo make install ``` Unter Windows muss vorab MinGW eingerichtet werden (z. B. MSYS2). Nach der Compilierung kann mit -`cpack -G NSIS` ein Installationspaket erstellt werden. +`cpack -G NSIS` ein Installationspaket erstellt werden. \ No newline at end of file diff --git a/de.rustysoft.kima2.metainfo.xml.in b/de.rustysoft.kima2.metainfo.xml.in deleted file mode 100644 index 9f228f7..0000000 --- a/de.rustysoft.kima2.metainfo.xml.in +++ /dev/null @@ -1,27 +0,0 @@ - - - de.rustysoft.kima2 - - KIMA2 - A small cash point program for children’s stuff markets - - MIT - GPL-3.0-or-later - - - - - - -

- A small cash point program for children's stuff markets. German language only. -

-
- - de.rustysoft.kima2.desktop - - - https://rustysoft.de/images/software/kima2/screenshot.png - - -
diff --git a/kima2.kdev4 b/kima2.kdev4 deleted file mode 100644 index 44cdfff..0000000 --- a/kima2.kdev4 +++ /dev/null @@ -1,4 +0,0 @@ -[Project] -CreatedFrom=CMakeLists.txt -Manager=KDevCMakeManager -Name=kima2 diff --git a/manual/Benutzerhandbuch.odt b/manual/Benutzerhandbuch.odt index c2defc2..a3c4466 100644 Binary files a/manual/Benutzerhandbuch.odt and b/manual/Benutzerhandbuch.odt differ diff --git a/manual/Benutzerhandbuch.pdf b/manual/Benutzerhandbuch.pdf index 793f996..bd34ffc 100644 Binary files a/manual/Benutzerhandbuch.pdf and b/manual/Benutzerhandbuch.pdf differ diff --git a/misc/PKGBUILD b/misc/PKGBUILD index a50410c..8681fc0 100644 --- a/misc/PKGBUILD +++ b/misc/PKGBUILD @@ -1,35 +1,29 @@ # Maintainer: Martin Brodbeck pkgname=kima2 -pkgver=1.7.1 +pkgver=0.13.0 pkgrel=1 pkgdesc="A small cash point program for children's things markets (German only)" arch=('i686' 'x86_64') -url="http://www.rustysoft.de/software/kima2" +url="http://www.rustysoft.de/?01_kima2" license=('custom') -depends=('glibc' 'libusb' 'qt6-base' 'sqlite3') +depends=('glibc' 'libusb' 'qt5-base' 'sqlite3' 'xlnt') makedepends=('boost>=1.62') -source=(git+https://git.rustysoft.de/martin/kima2) -sha256sums=('SKIP') +source=($pkgname-$pkgver.tar.gz) +md5sums=('') build() { - cd $pkgname - - git checkout v$pkgver - git submodule init - git submodule update - - if [ -d build ]; then - rm -rf build + if [ ! -d $pkgname/build ]; then + mkdir $pkgname/build fi - mkdir build && cd build + cd $pkgname/build - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DKIMA2_USE_EXTERNAL_JSON=OFF .. + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$pkgdir/usr -DKIMA2_USE_EXTERNAL_JSON=ON .. make } package() { cd $pkgname/build - make DESTDIR="$pkgdir" install + make install cd .. install -D -m644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" } diff --git a/misc/kima2.desktop b/misc/kima2.desktop index becabdf..004ab5f 100644 --- a/misc/kima2.desktop +++ b/misc/kima2.desktop @@ -3,8 +3,8 @@ Type=Application Name=KIMA2 GenericName=Cash Point Program GenericName[de]=Kassenprogramm -Comment=A small cash point program for children's stuff markets -Comment[de]=Ein kleines Kassenprogramm für Kindersachenmärkte +Comment=A small cash point program +Comment[de]=Ein kleines Kassenprogramm Exec=kima2 Icon=kima2 Categories=Office; diff --git a/misc/kima2.spec b/misc/kima2.spec deleted file mode 100644 index 2c586a8..0000000 --- a/misc/kima2.spec +++ /dev/null @@ -1,43 +0,0 @@ -Name: kima2 -Version: 1.6.0 -Release: 1%{?dist} -Summary: A small cash point program for children's things markets -License: custom - -Source0: %{name}-%{version}.tar.gz - -BuildRequires: meson -BuildRequires: gcc-c++ -#BuildRequires: pkgconfig(nlohmann_json) -BuildRequires: boost-date-time -BuildRequires: sqlite-devel -BuildRequires: libusb-devel -BuildRequires: qt5-qtdeclarative-devel -#BuildRequires: pkgconfig(pthreads) - -%description - -%prep -%autosetup - -%build -%meson -%meson_build - -%install -%meson_install - -%check -%meson_test - -%files -%{_bindir}/kima2 -%{_datadir}/applications/kima2.desktop -%{_datadir}/icons/hicolor/scalable/apps/kima2.svg -%{_datadir}/kima2/Benutzerhandbuch.pdf - - -%changelog -* Fri Oct 11 2019 Martin Brodbeck - dev builds -- - diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 681cf5c..cb0d4c1 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,32 +1,34 @@ set(Boost_USE_STATIC_LIBS ON) -find_package(Boost 1.78 REQUIRED) +find_package(Boost 1.62 COMPONENTS date_time REQUIRED) find_package(SQLite3 REQUIRED) -FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz) -FetchContent_MakeAvailable(json) +if (MINGW) + find_package(XLNT REQUIRED STATIC) +else (MINGW) + find_package(PkgConfig REQUIRED) + pkg_check_modules(XLNT REQUIRED xlnt>=1.3) +endif (MINGW) -add_library(core STATIC) - -target_sources(core PRIVATE +set(CORE_SOURCES database.cpp entity.cpp - entityint.cpp - entityuuid.cpp seller.cpp article.cpp sale.cpp marketplace.cpp - csvreader.cpp + excelreader.cpp jsonutil.cpp utils.cpp ) +add_library(core STATIC ${CORE_SOURCES}) + if (WIN32) - target_link_libraries(core PRIVATE sqlite3 nlohmann_json::nlohmann_json) + target_link_libraries(core PRIVATE printer Boost::boost Boost::date_time sqlite3 nlohmann_json::nlohmann_json ${XLNT_LIBRARY}) target_link_libraries(core PRIVATE bcrypt) else() - target_link_libraries(core PRIVATE sqlite3 nlohmann_json::nlohmann_json) + target_link_libraries(core PRIVATE printer Boost::boost Boost::date_time sqlite3 nlohmann_json::nlohmann_json ${XLNT_LIBRARIES}) endif() -target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..) +target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/core/article.cpp b/src/core/article.cpp index 6137549..0715d93 100644 --- a/src/core/article.cpp +++ b/src/core/article.cpp @@ -1,38 +1,44 @@ #include "article.h" -#include "seller.h" #include "utils.h" #include #include -Article::Article(int price) : m_price(price) {} +// Article::Article() : Entity() {} -void Article::setArticleNo(int articleNo) { m_articleNo = articleNo; } +Article::Article(int price) : price_(price) {} -void Article::setPrice(int price) { m_price = price; } +// Article::Article(std::shared_ptr sellerPtr) : Entity() { sellerPtr_ = sellerPtr; } -void Article::setDescription(const std::string &description) { m_description = description; } +void Article::setArticleNo(int articleNo) { articleNo_ = articleNo; } -void Article::setSale(Sale *salePtr) { m_salePtr = salePtr; } +void Article::setPrice(int price) { price_ = price; } -void Article::setSeller(Seller *sellerPtr) { m_sellerPtr = sellerPtr; } +void Article::setDescription(const std::string& description) { description_ = description; } -bool Article::isSold() { return m_salePtr ? true : false; } +void Article::setSale(Sale* salePtr) { salePtr_ = salePtr; } -std::string Article::getDescription() { return m_description; } +void Article::setSeller(Seller* sellerPtr) { sellerPtr_ = sellerPtr; } -Seller *Article::getSeller() { return m_sellerPtr; } -Sale *Article::getSale() { return m_salePtr; } +bool Article::isSold() { return salePtr_ ? true : false; } -int Article::getPrice() const { return m_price; } +std::string Article::getDescription() { return description_; } -std::string Article::getPriceAsString() const { return formatCentAsEuroString(m_price); } +Seller* Article::getSeller() { return sellerPtr_; } +Sale* Article::getSale() { return salePtr_; } -int Article::getArticleNo() const { return m_articleNo; } +int Article::getPrice() const { return price_; } + +std::string Article::getPriceAsString() const +{ + return formatCentAsEuroString(price_); +} + +int Article::getArticleNo() const { return articleNo_; } std::string Article::getCompleteArticleNo() const { std::stringstream artNoStream; - artNoStream << m_sourceNo << "K" << std::setfill('0') << std::setw(5) << m_articleNo; + artNoStream << sourceNo_ << "K" << std::setfill('0') << std::setw(5) << articleNo_; return artNoStream.str(); -} +} \ No newline at end of file diff --git a/src/core/article.h b/src/core/article.h index c9be086..a497242 100644 --- a/src/core/article.h +++ b/src/core/article.h @@ -1,7 +1,9 @@ #ifndef ARTICLE_H #define ARTICLE_H -#include "entityuuid.h" +#include "entity.h" +//#include "sale.h" +//#include "seller.h" #include #include @@ -9,35 +11,34 @@ class Seller; class Sale; -class Article : public EntityUuid +class Article : public Entity { -public: + public: Article() = default; Article(int price); - Article(const Article &) = delete; - virtual ~Article() = default; + //virtual ~Article() = default; void setArticleNo(int articleNo); void setPrice(int price); - void setDescription(const std::string &description); + void setDescription(const std::string& description); bool isSold(); - void setSale(Sale *salePtr); - void setSeller(Seller *sellerPtr); + void setSale(Sale* salePtr); + void setSeller(Seller* sellerPtr); int getArticleNo() const; std::string getCompleteArticleNo() const; std::string getDescription(); - Seller *getSeller(); - Sale *getSale(); + Seller* getSeller(); + Sale* getSale(); int getPrice() const; std::string getPriceAsString() const; -private: - Seller *m_sellerPtr{}; - Sale *m_salePtr{}; - int m_articleNo{}; - int m_price{}; - std::string m_description{}; + private: + Seller* sellerPtr_{}; + Sale* salePtr_{}; + int articleNo_{}; + int price_{}; + std::string description_{}; }; -#endif +#endif \ No newline at end of file diff --git a/src/core/csvreader.cpp b/src/core/csvreader.cpp deleted file mode 100644 index 6c2cdf6..0000000 --- a/src/core/csvreader.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "csvreader.h" -#include "utils.h" - -#include - -// #include -#include - -#ifdef DELETE -#undef DELETE -#endif - -namespace fs = std::filesystem; - -std::size_t CsvReader::readSellersFromFile(const fs::path &filePath, Marketplace *market) -{ - -#if defined(_WIN64) || defined(_WIN32) - // Windows: Somhow this is necessary in order to open file names with umlauts - auto wide = filePath.wstring(); - std::string fileName(wide.begin(), wide.end()); - - std::ifstream infile(fileName); -#else - // csv::CSVReader csvReader(filePath.string(), format); - std::ifstream infile(filePath.string()); -#endif - - for (auto &seller : market->getSellers()) { - seller->setState(Seller::State::DELETE); - } - - market->storeToDb(true); - - std::string line; - - while (getline(infile, line)) { - std::vector strs; - boost::split(strs, line, boost::is_any_of(";")); - - auto seller = std::make_unique(); - - try { - int sellerNo = std::stoi(strs[0]); - seller->setSellerNo(sellerNo); - } catch (std::invalid_argument const &ex) { - continue; - } - - if (isNumber(strs[1])) - seller->setNumArticlesOffered(std::stoi(strs[1])); - else - seller->setNumArticlesOffered(0); - - // If both, first name and last name, are empty, use N. N. - // Else, use the real values. - if (strs[2].empty() && strs[2].empty()) { - seller->setFirstName("N."); - seller->setLastName("N."); - } else { - std::string firstName = strs[2]; - seller->setFirstName(trim(firstName)); - std::string lastName = strs[3]; - seller->setLastName(trim(lastName)); - } - - market->getSellers().push_back(std::move(seller)); - } - - // Add one additional seller "RESERVE RESERVE" - auto seller = std::make_unique(); - seller->setSellerNo(market->getNextSellerNo()); - seller->setFirstName("RESERVE"); - seller->setLastName("RESERVE"); - market->getSellers().push_back(std::move(seller)); - - // If there was no special seller "Sonderkonto" in import data, then create one - auto specialSeller = market->findSellerWithSellerNo(0); - if (!specialSeller) { - auto seller = std::make_unique(); - seller->setSellerNo(0); - seller->setLastName("Sonderkonto"); - seller->setFirstName("Sonderkonto"); - seller->setNumArticlesOffered(0); - market->getSellers().push_back(std::move(seller)); - } - - market->sortSellers(); - market->storeToDb(); - - return market->getSellers().size() - 1; // minus 1 because we don't count the "special" seller -} diff --git a/src/core/csvreader.h b/src/core/csvreader.h deleted file mode 100644 index ff1901a..0000000 --- a/src/core/csvreader.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef CSV_READER_H -#define CSV_READER_H - -#include "marketplace.h" -#include "seller.h" - -#include -#include -#include -#include - -class CsvReader -{ -public: - static std::size_t readSellersFromFile(const std::filesystem::path &filePath, - Marketplace *market); -}; - -#endif \ No newline at end of file diff --git a/src/core/database.cpp b/src/core/database.cpp index d6b7384..123c467 100644 --- a/src/core/database.cpp +++ b/src/core/database.cpp @@ -1,13 +1,13 @@ #include "database.h" -#include #include -#include #include #include #include -Database::Database(const std::string &dbname) +#include "boost/date_time/posix_time/posix_time.hpp" + +Database::Database(const std::string& dbname) { dbname_ = dbname; init(); @@ -28,7 +28,7 @@ Database::Database() if (!fs::exists(dbpath)) { try { fs::create_directories(dbpath); - } catch (fs::filesystem_error &err) { + } catch (fs::filesystem_error& err) { throw err; } } @@ -45,11 +45,8 @@ void Database::newDb() fs::path sourcePath = dbname_; fs::path destPath = sourcePath.parent_path() / sourcePath.stem(); - - auto chronoTime = std::chrono::system_clock::now(); - std::string timeString = std::format("{0:%FT%H-%M-%S}", chronoTime); - - destPath += std::string("_") += timeString += ".db"; + destPath += std::string("_") += + boost::posix_time::to_iso_string(boost::posix_time::second_clock::local_time()) += ".db"; fs::copy_file(sourcePath, destPath, fs::copy_options::overwrite_existing); @@ -60,13 +57,13 @@ void Database::newDb() Database::~Database() { sqlite3_close(db_); } -void Database::exec(const std::string &sql) +void Database::exec(const std::string& sql) { - char *errMsg; + char* errMsg; const int errCode = sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &errMsg); if (errCode) { std::string errMsgString(errMsg); // Make a C++ string of the errMsg, so that we can call - // sqlite3_free() before throwing the exception + // sqlite3_free() before throwing the exception sqlite3_free(errMsg); throw std::runtime_error("Error in SQL execution: " + errMsgString); } @@ -78,10 +75,11 @@ void Database::createNew() std::string sqlCreateKima2{"CREATE TABLE IF NOT EXISTS kima2 (" "version INTEGER NOT NULL);" - "INSERT INTO kima2 (version) VALUES (3);"}; + "INSERT INTO kima2 (version) VALUES (2);"}; sqlStrings.push_back(sqlCreateKima2); std::string sqlCreateSellers{"CREATE TABLE IF NOT EXISTS sellers (" - "seller_no INTEGER PRIMARY KEY NOT NULL, " + "id TEXT PRIMARY KEY NOT NULL, " + "seller_no INTEGER, " "first_name TEXT, " "last_name TEXT, " "num_offered_articles INTEGER, " @@ -91,13 +89,13 @@ void Database::createNew() std::string sqlCreateArticles{ "CREATE TABLE IF NOT EXISTS articles (" "id TEXT PRIMARY KEY NOT NULL, " - "seller_no TEXT NOT NULL, " + "seller_id TEXT NOT NULL, " "source_no INTEGER NOT NULL, " "article_no INTEGER NOT NULL, " "description TEXT, " "price INTEGER NOT NULL, " "UNIQUE (source_no, article_no), " - "FOREIGN KEY (seller_no) REFERENCES sellers(seller_no) ON DELETE CASCADE, " + "FOREIGN KEY (seller_id) REFERENCES sellers(id) ON DELETE CASCADE, " "CHECK (article_no BETWEEN 0 AND 99999)" ");"}; sqlStrings.push_back(sqlCreateArticles); @@ -117,13 +115,13 @@ void Database::createNew() sqlStrings.push_back(sqlCreateSalesItems); std::string sqlInitialEntries{ - "INSERT OR IGNORE INTO sellers (seller_no, first_name, last_name, " + "INSERT OR IGNORE INTO sellers (id, seller_no, first_name, last_name, " "num_offered_articles) VALUES " - "(0, 'Sonderkonto', 'Sonderkonto', 0)"}; + "('11111111-1111-1111-1111-111111111111', 0, 'Sonderkonto', 'Sonderkonto', 0)"}; sqlStrings.push_back(sqlInitialEntries); beginTransaction(); - for (const auto &sql : sqlStrings) { + for (const auto& sql : sqlStrings) { exec(sql); } endTransaction(); @@ -132,15 +130,13 @@ void Database::createNew() void Database::updateDbToVer2() { beginTransaction(); - exec("INSERT OR IGNORE INTO sellers (seller_no, first_name, last_name, " + exec("INSERT OR IGNORE INTO sellers (id, seller_no, first_name, last_name, " "num_offered_articles) VALUES " - "(0, 'Sonderkonto', 'Sonderkonto', 0)"); - exec("UPDATE kima2 SET version = 3"); + "('11111111-1111-1111-1111-111111111111', 0, 'Sonderkonto', 'Sonderkonto', 0)"); + exec("UPDATE kima2 SET version = 2"); endTransaction(); } -void Database::updateDbToVer3() { newDb(); } - void Database::init() { const int errCode = sqlite3_open(dbname_.c_str(), &db_); @@ -156,19 +152,12 @@ void Database::init() switch (version) { case 0: createNew(); - initResult_ = InitResult::OK; break; case 1: - updateDbToVer3(); - initResult_ = InitResult::OUTDATED_REPLACED; - break; - case 2: - updateDbToVer3(); - initResult_ = InitResult::OUTDATED_REPLACED; + updateDbToVer2(); break; default: // Do nothing because we are up-to-date. - initResult_ = InitResult::OK; break; } } @@ -176,7 +165,7 @@ void Database::init() int Database::getVersion() { int retCode{}; - sqlite3_stmt *stmt; + sqlite3_stmt* stmt; // Check if there's already a kima2 table available. // If not, return version == 0. @@ -223,26 +212,29 @@ void Database::beginTransaction() { exec("BEGIN TRANSACTION"); } void Database::endTransaction() { exec("END TRANSACTION"); } -unsigned int Database::storeSellers(std::vector> &sellers, bool onlyDelete) +unsigned int Database::storeSellers(std::vector>& sellers, bool onlyDelete) { int retCode{}; int count{}; - sqlite3_stmt *stmt; + sqlite3_stmt* stmt; beginTransaction(); - for (auto &seller : sellers) { + for (auto& seller : sellers) { if (seller->getState() == Seller::State::NEW && !onlyDelete) { retCode = sqlite3_prepare_v2( db_, "INSERT INTO sellers" - " (seller_no, first_name, last_name, num_offered_articles)" - " VALUES (:seller_no, :first_name, :last_name, :num_offered_articles)", + " (id, seller_no, first_name, last_name, num_offered_articles)" + " VALUES (:uuid, :seller_no, :first_name, :last_name, :num_offered_articles)", -1, &stmt, nullptr); if (retCode != SQLITE_OK) throw std::runtime_error(sqlite3_errmsg(db_)); + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":uuid"), + boost::uuids::to_string(seller->getUuid()).c_str(), -1, + SQLITE_TRANSIENT); sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":seller_no"), seller->getSellerNo()); sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":first_name"), @@ -268,13 +260,15 @@ unsigned int Database::storeSellers(std::vector> &seller "UPDATE sellers SET" " seller_no = :seller_no, first_name = :first_name," " last_name = :last_name, num_offered_articles = :num_offered_articles" - " WHERE seller_no = :id", + " WHERE id = :uuid", -1, &stmt, nullptr); if (retCode != SQLITE_OK) throw std::runtime_error(sqlite3_errmsg(db_)); - sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":id"), seller->getId()); + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":uuid"), + boost::uuids::to_string(seller->getUuid()).c_str(), -1, + SQLITE_TRANSIENT); sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":seller_no"), seller->getSellerNo()); sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":first_name"), @@ -297,13 +291,15 @@ unsigned int Database::storeSellers(std::vector> &seller } else if (seller->getState() == Seller::State::DELETE) { count += static_cast(seller->getArticles(false).size()); - retCode = sqlite3_prepare_v2(db_, "DELETE FROM sellers WHERE seller_no = :id", -1, - &stmt, nullptr); + retCode = + sqlite3_prepare_v2(db_, "DELETE FROM sellers WHERE id = :uuid", -1, &stmt, nullptr); if (retCode != SQLITE_OK) throw std::runtime_error(sqlite3_errmsg(db_)); - sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":id"), seller->getId()); + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":uuid"), + boost::uuids::to_string(seller->getUuid()).c_str(), -1, + SQLITE_TRANSIENT); retCode = sqlite3_step(stmt); @@ -326,12 +322,12 @@ unsigned int Database::storeSellers(std::vector> &seller // Everything went fine, so we can now update our objects sellers.erase(std::remove_if(sellers.begin(), sellers.end(), - [](const std::unique_ptr &seller) { + [](const std::unique_ptr& seller) { return (seller->getState() == Seller::State::DELETE); }), sellers.end()); - for (auto &seller : sellers) { + for (auto& seller : sellers) { seller->cleanupArticles(); seller->setState(Seller::State::OK); } @@ -339,18 +335,18 @@ unsigned int Database::storeSellers(std::vector> &seller return count; } -unsigned int Database::storeArticles(std::vector
articles) +unsigned int Database::storeArticles(std::vector articles) { int retCode{}; int count{}; - sqlite3_stmt *stmt; + sqlite3_stmt* stmt; - for (auto &article : articles) { + for (auto& article : articles) { if (article->getState() == Article::State::NEW) { retCode = sqlite3_prepare_v2( db_, "INSERT INTO articles" - " (id, seller_no, source_no, article_no, description, price)" + " (id, seller_id, source_no, article_no, description, price)" " VALUES (:uuid, :seller_id, :source_no, :article_no, :desc, :price)", -1, &stmt, nullptr); @@ -360,8 +356,9 @@ unsigned int Database::storeArticles(std::vector
articles) sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":uuid"), boost::uuids::to_string(article->getUuid()).c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":seller_id"), - article->getSeller()->getId()); + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":seller_id"), + boost::uuids::to_string(article->getSeller()->getUuid()).c_str(), -1, + SQLITE_TRANSIENT); sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":source_no"), article->getSourceNo()); sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":article_no"), @@ -385,7 +382,7 @@ unsigned int Database::storeArticles(std::vector
articles) retCode = sqlite3_prepare_v2( db_, "UPDATE articles SET" - " seller_no = :seller_id, source_no = :source_no, article_no = :article_no," + " seller_id = seller_id, source_no = :source_no, article_no = :article_no," " description = :desc, price = :price" " WHERE id = :uuid", -1, &stmt, nullptr); @@ -396,8 +393,9 @@ unsigned int Database::storeArticles(std::vector
articles) sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":uuid"), boost::uuids::to_string(article->getUuid()).c_str(), -1, SQLITE_TRANSIENT); - sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":seller_id"), - article->getSeller()->getId()); + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":seller_id"), + boost::uuids::to_string(article->getSeller()->getUuid()).c_str(), -1, + SQLITE_TRANSIENT); sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":source_no"), article->getSourceNo()); sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":article_no"), @@ -444,18 +442,18 @@ unsigned int Database::storeArticles(std::vector
articles) return count; } -unsigned int Database::storeSales(std::vector> &sales) +unsigned int Database::storeSales(std::vector>& sales) { int retCode{}; int count{}; - sqlite3_stmt *stmt; + sqlite3_stmt* stmt; if (sales.size() == 0) return 0; beginTransaction(); - for (auto &sale : sales) { + for (auto& sale : sales) { if (sale->getState() == Sale::State::NEW) { retCode = sqlite3_prepare_v2(db_, "INSERT INTO sales" @@ -485,7 +483,7 @@ unsigned int Database::storeSales(std::vector> &sales) ++count; sqlite3_finalize(stmt); - for (const auto &article : sale->getArticles()) { + for (const auto& article : sale->getArticles()) { retCode = sqlite3_prepare_v2(db_, "INSERT INTO sales_items" " (sale_id, article_id)" @@ -538,24 +536,24 @@ unsigned int Database::storeSales(std::vector> &sales) // Everything went fine, so we can now update our objects sales.erase( std::remove_if(sales.begin(), sales.end(), - [](const auto &sale) { return (sale->getState() == Sale::State::DELETE); }), + [](const auto& sale) { return (sale->getState() == Sale::State::DELETE); }), sales.end()); - for (auto &sale : sales) { + for (auto& sale : sales) { sale->setState(Sale::State::OK); } return count; } -unsigned int Database::loadSellers(std::vector> &sellers) +unsigned int Database::loadSellers(std::vector>& sellers) { int retCode{}; int count{}; - sqlite3_stmt *stmt; + sqlite3_stmt* stmt; retCode = sqlite3_prepare_v2(db_, - "SELECT seller_no, first_name, last_name, " + "SELECT id, seller_no, first_name, last_name, " "num_offered_articles FROM sellers ORDER BY seller_no", -1, &stmt, nullptr); if (retCode != SQLITE_OK) @@ -568,10 +566,11 @@ unsigned int Database::loadSellers(std::vector> &sellers while (retCode != SQLITE_DONE) { ++count; auto seller = std::make_unique(); - seller->setSellerNo(sqlite3_column_int(stmt, 0)); - seller->setFirstName(reinterpret_cast(sqlite3_column_text(stmt, 1))); - seller->setLastName(reinterpret_cast(sqlite3_column_text(stmt, 2))); - seller->setNumArticlesOffered(sqlite3_column_int(stmt, 3)); + seller->setUuidFromString(reinterpret_cast(sqlite3_column_text(stmt, 0))); + seller->setSellerNo(sqlite3_column_int(stmt, 1)); + seller->setFirstName(reinterpret_cast(sqlite3_column_text(stmt, 2))); + seller->setLastName(reinterpret_cast(sqlite3_column_text(stmt, 3))); + seller->setNumArticlesOffered(sqlite3_column_int(stmt, 4)); seller->setState(Seller::State::OK); sellers.push_back(std::move(seller)); @@ -580,29 +579,29 @@ unsigned int Database::loadSellers(std::vector> &sellers sqlite3_finalize(stmt); - for (auto &seller : sellers) { + for (auto& seller : sellers) { retCode = sqlite3_prepare_v2(db_, "SELECT id, source_no, article_no, description, price" " FROM articles" - " WHERE seller_no = :seller_id" + " WHERE seller_id = :seller_uuid" " ORDER BY article_no", -1, &stmt, nullptr); if (retCode != SQLITE_OK) throw std::runtime_error(sqlite3_errmsg(db_)); - sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":seller_id"), seller->getId()); + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":seller_uuid"), + boost::uuids::to_string(seller->getUuid()).c_str(), -1, SQLITE_TRANSIENT); retCode = sqlite3_step(stmt); while (retCode != SQLITE_DONE) { ++count; auto article = std::make_unique
(); - article->setUuidFromString( - reinterpret_cast(sqlite3_column_text(stmt, 0))); + article->setUuidFromString(reinterpret_cast(sqlite3_column_text(stmt, 0))); article->setSeller(seller.get()); article->setSourceNo(sqlite3_column_int(stmt, 1)); article->setArticleNo(sqlite3_column_int(stmt, 2)); - article->setDescription(reinterpret_cast(sqlite3_column_text(stmt, 3))); + article->setDescription(reinterpret_cast(sqlite3_column_text(stmt, 3))); article->setPrice(sqlite3_column_int(stmt, 4)); article->setState(Article::State::OK); @@ -617,12 +616,12 @@ unsigned int Database::loadSellers(std::vector> &sellers return count; } -unsigned int Database::loadSales(std::vector> &sales, - std::vector> &sellers) +unsigned int Database::loadSales(std::vector>& sales, + std::vector>& sellers) { int retCode{}; int count{}; - sqlite3_stmt *stmt; + sqlite3_stmt* stmt; retCode = sqlite3_prepare_v2(db_, "SELECT id, source_no, sold_at" @@ -635,13 +634,13 @@ unsigned int Database::loadSales(std::vector> &sales, sales.clear(); - std::map saleMap; + std::map saleMap; while (retCode != SQLITE_DONE) { ++count; auto sale = std::make_unique(); - sale->setUuidFromString(reinterpret_cast(sqlite3_column_text(stmt, 0))); + sale->setUuidFromString(reinterpret_cast(sqlite3_column_text(stmt, 0))); sale->setSourceNo(sqlite3_column_int(stmt, 1)); - sale->setTimestamp(reinterpret_cast(sqlite3_column_text(stmt, 2))); + sale->setTimestamp(reinterpret_cast(sqlite3_column_text(stmt, 2))); sale->setState(Sale::State::OK); saleMap.insert(std::make_pair(sale->getUuidAsString(), sale.get())); sales.push_back(std::move(sale)); @@ -651,8 +650,8 @@ unsigned int Database::loadSales(std::vector> &sales, sqlite3_finalize(stmt); - std::map artMap; - for (const auto &seller : sellers) { + std::map artMap; + for (const auto& seller : sellers) { for (const auto article : seller->getArticles(false)) { artMap.insert(std::make_pair(article->getUuidAsString(), article)); } @@ -668,8 +667,8 @@ unsigned int Database::loadSales(std::vector> &sales, retCode = sqlite3_step(stmt); while (retCode != SQLITE_DONE) { - saleMap[reinterpret_cast(sqlite3_column_text(stmt, 0))]->addArticle( - artMap[reinterpret_cast(sqlite3_column_text(stmt, 1))]); + saleMap[reinterpret_cast(sqlite3_column_text(stmt, 0))]->addArticle( + artMap[reinterpret_cast(sqlite3_column_text(stmt, 1))]); retCode = sqlite3_step(stmt); } @@ -682,7 +681,7 @@ unsigned int Database::loadSales(std::vector> &sales, void Database::updateCashPointNo(int oldCashPointNo, int newCashPointNo) { int retCode{}; - sqlite3_stmt *stmt; + sqlite3_stmt* stmt; // Check if the new no ist already in use retCode = sqlite3_prepare_v2(db_, "SELECT COUNT() FROM articles WHERE source_no = :source_no", @@ -747,4 +746,4 @@ void Database::updateCashPointNo(int oldCashPointNo, int newCashPointNo) sqlite3_finalize(stmt); endTransaction(); -} +} \ No newline at end of file diff --git a/src/core/database.h b/src/core/database.h index af39f23..661d433 100644 --- a/src/core/database.h +++ b/src/core/database.h @@ -10,36 +10,32 @@ class Database { -public: - enum class InitResult { OK, OUTDATED_REPLACED }; - explicit Database(const std::string &dbname); + public: + explicit Database(const std::string& dbname); Database(); ~Database(); - Database(const Database &) = delete; - Database &operator=(const Database &) = delete; - void exec(const std::string &sql); - unsigned int storeSellers(std::vector> &sellers, + Database(const Database&) = delete; + Database& operator=(const Database&) = delete; + void exec(const std::string& sql); + unsigned int storeSellers(std::vector>& sellers, bool onlyDelete = false); - unsigned int loadSellers(std::vector> &sellers); - unsigned int storeSales(std::vector> &sales); - unsigned int loadSales(std::vector> &sales, - std::vector> &sellers); + unsigned int loadSellers(std::vector>& sellers); + unsigned int storeSales(std::vector>& sales); + unsigned int loadSales(std::vector>& sales, + std::vector>& sellers); void updateCashPointNo(int oldCashPointNo, int newCashPointNo); void newDb(); - InitResult getInitResult() { return initResult_; } -private: - sqlite3 *db_{nullptr}; + private: + sqlite3* db_{nullptr}; std::string dbname_; void init(); void beginTransaction(); void endTransaction(); void createNew(); int getVersion(); - unsigned int storeArticles(std::vector
articles); + unsigned int storeArticles(std::vector articles); void updateDbToVer2(); - void updateDbToVer3(); - InitResult initResult_{InitResult::OK}; }; -#endif // DATABASE_H +#endif // DATABASE_H \ No newline at end of file diff --git a/src/core/entity.cpp b/src/core/entity.cpp index 9f07489..8caa834 100644 --- a/src/core/entity.cpp +++ b/src/core/entity.cpp @@ -1,3 +1,33 @@ #include "entity.h" -Entity::State Entity::getState() const { return m_state; } +#include + +#include +#include + +Entity::~Entity() = default; + +void Entity::createUuid() +{ + static boost::uuids::random_generator generator{}; + uuid_ = generator(); +} + +void Entity::setUuidFromString(const std::string& uuidString) +{ + boost::uuids::string_generator generator{}; + uuid_ = generator(uuidString); +} + +Entity::State Entity::getState() const +{ + return state_; +} + +void Entity::setSourceNo(int sourceNo) { + sourceNo_ = sourceNo; +} + +int Entity::getSourceNo() const { + return sourceNo_; +} \ No newline at end of file diff --git a/src/core/entity.h b/src/core/entity.h index 3b049ba..017b6e0 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -1,16 +1,35 @@ #ifndef ENTITY_H #define ENTITY_H +#include + +#include +#include + class Entity { -public: + public: enum class State { NEW, UPDATE, DELETE, OK }; - virtual ~Entity() = default; - void setState(State state) { m_state = state; } - virtual State getState() const; -private: - State m_state{State::NEW}; + // Entity() = default; + virtual ~Entity() = 0; + + void createUuid(); + void setUuidFromString(const std::string& uuidString); + void setState(State state) { state_ = state; } + void setSourceNo(int sourceNo); + + const boost::uuids::uuid& getUuid() const { return uuid_; }; + std::string getUuidAsString() const { return boost::uuids::to_string(uuid_); } + virtual State getState() const; + virtual int getSourceNo() const; + + protected: + int sourceNo_{}; + + private: + boost::uuids::uuid uuid_{}; + State state_{State::NEW}; }; -#endif // ENTITY_H +#endif // ENTITY_H \ No newline at end of file diff --git a/src/core/entityint.cpp b/src/core/entityint.cpp deleted file mode 100644 index 2d0f6af..0000000 --- a/src/core/entityint.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "entityint.h" - -EntityInt::EntityInt(int id) { m_id = id; } - -void EntityInt::setId(int id) { m_id = id; } diff --git a/src/core/entityint.h b/src/core/entityint.h deleted file mode 100644 index 82fac50..0000000 --- a/src/core/entityint.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ENTITY_INT_H -#define ENTITY_INT_H - -#include "entity.h" - -class EntityInt : public Entity -{ -public: - EntityInt() = default; - virtual ~EntityInt() = default; - EntityInt(int id); - void setId(int id); - int getId() const { return m_id; }; - -protected: - int m_id{}; -}; - -#endif // ENTITY_INT_H diff --git a/src/core/entityuuid.cpp b/src/core/entityuuid.cpp deleted file mode 100644 index eade2ac..0000000 --- a/src/core/entityuuid.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "entityuuid.h" - -#include - -#include -#include - -void EntityUuid::createUuid() -{ - static boost::uuids::random_generator generator{}; - m_uuid = generator(); -} - -void EntityUuid::setUuidFromString(const std::string &uuidString) -{ - boost::uuids::string_generator generator{}; - m_uuid = generator(uuidString); -} - -void EntityUuid::setSourceNo(int sourceNo) { m_sourceNo = sourceNo; } - -int EntityUuid::getSourceNo() const { return m_sourceNo; } diff --git a/src/core/entityuuid.h b/src/core/entityuuid.h deleted file mode 100644 index 11b99d5..0000000 --- a/src/core/entityuuid.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef ENTITY_UUID_H -#define ENTITY_UUID_H - -#include "entity.h" - -#include - -#include -#include - -class EntityUuid : public Entity -{ -public: - EntityUuid() = default; - virtual ~EntityUuid() = default; - - void createUuid(); - void setUuidFromString(const std::string &uuidString); - void setSourceNo(int sourceNo); - - const boost::uuids::uuid &getUuid() const { return m_uuid; }; - std::string getUuidAsString() const { return boost::uuids::to_string(m_uuid); } - virtual int getSourceNo() const; - -protected: - int m_sourceNo{}; - -private: - boost::uuids::uuid m_uuid{}; -}; - -#endif // ENTITY_UUID_H diff --git a/src/core/excelreader.cpp b/src/core/excelreader.cpp new file mode 100644 index 0000000..37e2d80 --- /dev/null +++ b/src/core/excelreader.cpp @@ -0,0 +1,63 @@ +#include "excelreader.h" + +#include +#include + +namespace fs = std::filesystem; + +void ExcelReader::readSellersFromFile(const fs::path& filePath, Marketplace* market) +{ + xlnt::workbook wb; + std::ifstream mystream(filePath, std::ios::binary); + if(!mystream.is_open()) { + throw std::runtime_error("Could not open ecxel file"); + } + wb.load(mystream); + + for (auto& seller : market->getSellers()) { + seller->setState(Seller::State::DELETE); + } + + market->storeToDb(true); + auto ws = wb.sheet_by_index(0); + + const int START_ROW = 5; + const int END_ROW = 350; + + int rowCount{}; + for (const auto& row : ws.rows(false)) { + if (rowCount < START_ROW) { + ++rowCount; + continue; + } else if (rowCount > END_ROW) { + break; + } + if (row[2].value().empty() && row[3].value().empty()) { + ++rowCount; + continue; + } + auto seller = std::make_unique(); + seller->createUuid(); + seller->setSellerNo(row[0].value()); + seller->setNumArticlesOffered(row[1].value()); + seller->setFirstName(row[2].value()); + seller->setLastName(row[3].value()); + market->getSellers().push_back(std::move(seller)); + rowCount++; + } + + // If there was no special seller "Sonderkonto" in import data, then create one + auto specialSeller = market->findSellerWithUuid("11111111-1111-1111-1111-111111111111"); + if (!specialSeller) { + auto seller = std::make_unique(); + seller->setUuidFromString("11111111-1111-1111-1111-111111111111"); + seller->setSellerNo(0); + seller->setLastName("Sonderkonto"); + seller->setFirstName("Sonderkonto"); + seller->setNumArticlesOffered(0); + market->getSellers().push_back(std::move(seller)); + } + + market->sortSellers(); + market->storeToDb(); +} diff --git a/src/core/excelreader.h b/src/core/excelreader.h new file mode 100644 index 0000000..8071e04 --- /dev/null +++ b/src/core/excelreader.h @@ -0,0 +1,18 @@ +#ifndef EXCEL_READER_H +#define EXCEL_READER_H + +#include "marketplace.h" +#include "seller.h" + +#include +#include +#include +#include + +class ExcelReader +{ + public: + static void readSellersFromFile(const std::filesystem::path& filePath, Marketplace* market); +}; + +#endif \ No newline at end of file diff --git a/src/core/jsonutil.cpp b/src/core/jsonutil.cpp index 095a7b0..dddf79a 100644 --- a/src/core/jsonutil.cpp +++ b/src/core/jsonutil.cpp @@ -5,15 +5,17 @@ #include +namespace fs = std::filesystem; using json = nlohmann::json; -void JsonUtil::exportSellers(const std::filesystem::path &filePath, Marketplace *market) +void JsonUtil::exportSellers(const std::filesystem::path& filePath, Marketplace* market) { json root; std::ofstream file(filePath); - for (const auto &seller : market->getSellers()) { + for (const auto& seller : market->getSellers()) { json newEntry; + newEntry["uuid"] = seller->getUuidAsString(); newEntry["seller_no"] = seller->getSellerNo(); newEntry["last_name"] = seller->getLastName(); newEntry["first_name"] = seller->getFirstName(); @@ -24,9 +26,9 @@ void JsonUtil::exportSellers(const std::filesystem::path &filePath, Marketplace file << root.dump(4) << std::endl; } -std::size_t JsonUtil::importSellers(const std::filesystem::path &filePath, Marketplace *market) +void JsonUtil::importSellers(const std::filesystem::path& filePath, Marketplace* market) { - for (auto &seller : market->getSellers()) { + for (auto& seller : market->getSellers()) { seller->setState(Seller::State::DELETE); } market->storeToDb(true); @@ -36,6 +38,7 @@ std::size_t JsonUtil::importSellers(const std::filesystem::path &filePath, Marke for (auto val : jsonValues["sellers"]) { auto seller = std::make_unique(); + seller->setUuidFromString(val["uuid"]); seller->setSellerNo(val["seller_no"]); seller->setLastName(val["last_name"]); seller->setFirstName(val["first_name"]); @@ -44,9 +47,10 @@ std::size_t JsonUtil::importSellers(const std::filesystem::path &filePath, Marke } // If there was no special seller "Sonderkonto" in import data, then create one - auto specialSeller = market->findSellerWithSellerNo(0); + auto specialSeller = market->findSellerWithUuid("11111111-1111-1111-1111-111111111111"); if (!specialSeller) { auto seller = std::make_unique(); + seller->setUuidFromString("11111111-1111-1111-1111-111111111111"); seller->setSellerNo(0); seller->setLastName("Sonderkonto"); seller->setFirstName("Sonderkonto"); @@ -55,20 +59,18 @@ std::size_t JsonUtil::importSellers(const std::filesystem::path &filePath, Marke } market->sortSellers(); - market->storeToDb(); - return market->getSellers().size() - 1; // minus 1 because we don't count the "special" seller + market->storeToDb(); } -void JsonUtil::exportSales(const std::filesystem::path &filePath, Marketplace *market, - int cashPointNo) +void JsonUtil::exportSales(const std::filesystem::path& filePath, Marketplace* market, int cashPointNo) { json root; std::ofstream file(filePath); root["source_no"] = cashPointNo; - for (const auto &sale : market->getSales()) { + for (const auto& sale : market->getSales()) { if (sale->getSourceNo() != cashPointNo) continue; @@ -76,10 +78,10 @@ void JsonUtil::exportSales(const std::filesystem::path &filePath, Marketplace *m newSale["uuid"] = sale->getUuidAsString(); newSale["timestamp"] = sale->getTimestamp(); - for (const auto &article : sale->getArticles()) { + for (const auto& article : sale->getArticles()) { json newArticle; newArticle["uuid"] = article->getUuidAsString(); - newArticle["seller_no"] = article->getSeller()->getSellerNo(); + newArticle["seller_uuid"] = article->getSeller()->getUuidAsString(); newArticle["desc"] = article->getDescription(); newArticle["price"] = article->getPrice(); // newArticle["source_no"] = article->getSourceNo(); @@ -94,36 +96,33 @@ void JsonUtil::exportSales(const std::filesystem::path &filePath, Marketplace *m file << root.dump(4) << std::endl; } -void JsonUtil::importSales(const std::filesystem::path &filePath, Marketplace *market, - int cashPointNo) +void JsonUtil::importSales(const std::filesystem::path& filePath, Marketplace* market, int cashPointNo) { std::ifstream file(filePath); json jsonValues = json::parse(file); int source_no = jsonValues["source_no"]; if (source_no == cashPointNo) { - std::string ret = "Die Kassen-Nr. "; - ret += std::to_string(source_no); - ret += " der zu imporierenden Daten wird von dieser Kasse hier bereits verwendet."; - throw std::runtime_error(ret); + throw std::runtime_error("Die Kassen-Nr. der zu imporierenden Daten wird von dieser Kasse " + "hier bereits verwendet."); } market->setSalesToDelete(jsonValues["source_no"]); market->storeToDb(); - for (const auto &valSale : jsonValues["sales"]) { + for (const auto& valSale : jsonValues["sales"]) { auto sale = std::make_unique(); sale->setUuidFromString(valSale["uuid"]); sale->setSourceNo(jsonValues["source_no"]); sale->setTimestamp(valSale["timestamp"]); - for (const auto &valArticle : valSale["articles"]) { + for (const auto& valArticle : valSale["articles"]) { auto article = std::make_unique
(); article->setUuidFromString(valArticle["uuid"]); article->setSourceNo(jsonValues["source_no"]); article->setArticleNo(valArticle["article_no"]); article->setDescription(valArticle["desc"]); article->setPrice(valArticle["price"]); - auto seller = market->findSellerWithSellerNo(valArticle["seller_no"]); + auto seller = market->findSellerWithUuid(valArticle["seller_uuid"]); if (seller == nullptr) { throw std::runtime_error( "Die zu importierenden Daten verweisen auf einen nicht vorhandenen Verkäufer. " @@ -137,4 +136,4 @@ void JsonUtil::importSales(const std::filesystem::path &filePath, Marketplace *m } market->storeToDb(); -} +} \ No newline at end of file diff --git a/src/core/jsonutil.h b/src/core/jsonutil.h index 37190a0..3663dcc 100644 --- a/src/core/jsonutil.h +++ b/src/core/jsonutil.h @@ -3,18 +3,16 @@ #include "marketplace.h" -#include #include +#include class JsonUtil { -public: - static void exportSellers(const std::filesystem::path &filePath, Marketplace *market); - static std::size_t importSellers(const std::filesystem::path &filePath, Marketplace *market); - static void exportSales(const std::filesystem::path &filePath, Marketplace *market, - int cashPointNo); - static void importSales(const std::filesystem::path &filePath, Marketplace *market, - int cashPointNo); + public: + static void exportSellers(const std::filesystem::path& filePath, Marketplace* market); + static void importSellers(const std::filesystem::path& filePath, Marketplace* market); + static void exportSales(const std::filesystem::path& filePath, Marketplace* market, int cashPointNo); + static void importSales(const std::filesystem::path& filePath, Marketplace* market, int cashPointNo); }; #endif \ No newline at end of file diff --git a/src/core/marketplace.cpp b/src/core/marketplace.cpp index a68242b..302981a 100644 --- a/src/core/marketplace.cpp +++ b/src/core/marketplace.cpp @@ -3,19 +3,19 @@ #include "utils.h" #include -#include #include #include #include #include +#include namespace fs = std::filesystem; Marketplace::Marketplace() { - /*auto seller = std::make_unique("Max", "Mustermann"); + auto seller = std::make_unique("Max", "Mustermann"); seller->createUuid(); - sellers_.push_back(std::move(seller)); */ + sellers_.push_back(std::move(seller)); } void Marketplace::storeToDb(bool onlyDelete) @@ -25,23 +25,22 @@ void Marketplace::storeToDb(bool onlyDelete) db.storeSales(sales_); } -Database::InitResult Marketplace::loadFromDb() +void Marketplace::loadFromDb() { Database db; db.loadSellers(sellers_); db.loadSales(sales_, sellers_); - return db.getInitResult(); } -SellersVec &Marketplace::getSellers() { return sellers_; } +SellersVec& Marketplace::getSellers() { return sellers_; } -SalesVec &Marketplace::getSales() { return sales_; } +SalesVec& Marketplace::getSales() { return sales_; } int Marketplace::getNextSellerNo() { auto iter = std::max_element( sellers_.begin(), sellers_.end(), - [](const auto &a, const auto &b) -> bool { return a->getSellerNo() < b->getSellerNo(); }); + [](const auto& a, const auto& b) -> bool { return a->getSellerNo() < b->getSellerNo(); }); if (iter == sellers_.end()) return 1; return (*iter)->getSellerNo() + 1; @@ -53,14 +52,14 @@ int Marketplace::getNextArticleNo() int maxArtNoInBasket{0}; auto iter = std::max_element(sellers_.begin(), sellers_.end(), - [](const auto &a, const auto &b) -> bool { + [](const auto& a, const auto& b) -> bool { return a->getMaxArticleNo() < b->getMaxArticleNo(); }); if (iter != sellers_.end()) maxArtNoInDb = (*iter)->getMaxArticleNo(); auto iter2 = - std::max_element(basket_.begin(), basket_.end(), [](const auto &a, const auto &b) -> bool { + std::max_element(basket_.begin(), basket_.end(), [](const auto& a, const auto& b) -> bool { return a->getArticleNo() < b->getArticleNo(); }); @@ -73,13 +72,13 @@ int Marketplace::getNextArticleNo() int Marketplace::getNumSellersDelete() { int count = std::count_if(sellers_.begin(), sellers_.end(), - [](const auto &a) { return a->getState() == Seller::State::DELETE; }); + [](const auto& a) { return a->getState() == Seller::State::DELETE; }); return count; } int Marketplace::getNumArticlesSold() { - int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, [](int a, const auto &seller) { + int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, [](int a, const auto& seller) { return a + seller->numArticlesSold(); }); return sum; @@ -87,7 +86,7 @@ int Marketplace::getNumArticlesSold() int Marketplace::getNumArticlesOffered() { - int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, [](int a, const auto &seller) { + int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, [](int a, const auto& seller) { return a + seller->numArticlesOffered(); }); return sum; @@ -95,10 +94,19 @@ int Marketplace::getNumArticlesOffered() void Marketplace::sortSellers() { std::sort(sellers_.begin(), sellers_.end()); } -Seller *Marketplace::findSellerWithSellerNo(int sellerNo) +Seller* Marketplace::findSellerWithSellerNo(int sellerNo) { auto iter = std::find_if(sellers_.begin(), sellers_.end(), - [sellerNo](const auto &a) { return a->getSellerNo() == sellerNo; }); + [sellerNo](const auto& a) { return a->getSellerNo() == sellerNo; }); + if (iter == sellers_.end()) + return nullptr; + return (*iter).get(); +} + +Seller* Marketplace::findSellerWithUuid(const std::string& uuid) +{ + auto iter = std::find_if(sellers_.begin(), sellers_.end(), + [uuid](const auto& a) { return a->getUuidAsString() == uuid; }); if (iter == sellers_.end()) return nullptr; return (*iter).get(); @@ -106,8 +114,7 @@ Seller *Marketplace::findSellerWithSellerNo(int sellerNo) void Marketplace::addArticleToBasket(std::unique_ptr
article) { - basket_.insert(basket_.begin(), - std::move(article)); // article to the beginning of the basket vector + basket_.insert(basket_.begin(), std::move(article)); // article to the beginning of the basket vector } size_t Marketplace::basketSize() { return basket_.size(); } @@ -129,12 +136,12 @@ void Marketplace::finishCurrentSale(std::unique_ptr sale) storeToDb(); } -BasketVec &Marketplace::getBasket() { return basket_; } +BasketVec& Marketplace::getBasket() { return basket_; } int Marketplace::getBasketSumInCent() { int sum = std::accumulate(basket_.begin(), basket_.end(), 0, - [](int a, const auto &b) { return a + b->getPrice(); }); + [](int a, const auto& b) { return a + b->getPrice(); }); return sum; } @@ -148,40 +155,39 @@ std::string Marketplace::getBasketSumAsString() void Marketplace::removeSale(boost::uuids::uuid uuid) { sales_.erase(std::remove_if(sales_.begin(), sales_.end(), - [&uuid](const auto &a) { return a->getUuid() == uuid; }), + [&uuid](const auto& a) { return a->getUuid() == uuid; }), sales_.end()); } void Marketplace::setSalesToDelete(int cashPointNo) { - std::for_each(sales_.begin(), sales_.end(), [cashPointNo](auto &sale) { + std::for_each(sales_.begin(), sales_.end(), [cashPointNo](auto& sale) { if (sale->getSourceNo() == cashPointNo) { sale->setState(Sale::State::DELETE); - for (auto &article : sale->getArticles()) { + for (auto& article : sale->getArticles()) { article->setState(Article::State::DELETE); } } }); } -void Marketplace::exportReportToCSV(const fs::path &filePath, int feeInPercent, int maxFeeInEuro) +void Marketplace::exportReportToCSV(const fs::path& filePath, int feeInPercent, int maxFeeInEuro) { - const char delimiter = ';'; + const char delimiter = ','; std::ofstream file(filePath); file << "Verk.Nr." << delimiter << "Nachname" << delimiter << "Vorname" << delimiter << "Anz. gemeldet" << delimiter << "Anz. verkauft" << delimiter << "Umsatz" << delimiter << "Auszahlung\n"; - for (const auto &seller : sellers_) { + for (const auto& seller : sellers_) { file << seller->getSellerNo() << delimiter << escapeCsvValue(seller->getLastName(), delimiter) << delimiter << escapeCsvValue(seller->getFirstName(), delimiter) << delimiter << seller->numArticlesOffered() << delimiter << seller->numArticlesSold() << delimiter << escapeCsvValue(seller->sumAsString(), delimiter) << delimiter - << escapeCsvValue( - paymentAsString(seller->sumInCents(), feeInPercent, maxFeeInEuro * 100), - delimiter) + << escapeCsvValue(paymentAsString(seller->sumInCents(), feeInPercent, maxFeeInEuro * 100), + delimiter) << "\n"; } } @@ -189,7 +195,7 @@ void Marketplace::exportReportToCSV(const fs::path &filePath, int feeInPercent, int Marketplace::getOverallSumInCent() { int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, - [](int a, const auto &b) { return a + b->sumInCents(); }); + [](int a, const auto& b) { return a + b->sumInCents(); }); return sum; } @@ -202,7 +208,7 @@ std::string Marketplace::getOverallSumAsString() int Marketplace::getOverallPaymentInCent(int percent, int maxFee) { int sum = std::accumulate( - sellers_.begin(), sellers_.end(), 0, [percent, maxFee](int a, const auto &b) { + sellers_.begin(), sellers_.end(), 0, [percent, maxFee](int a, const auto& b) { return a + b->sumInCents() - marketFee(b->sumInCents(), percent, maxFee); }); return sum; @@ -240,7 +246,7 @@ std::string paymentAsString(int sumInCent, int percent, int maxFeeInCent) return formatCentAsEuroString(sumInCent - marketFee(sumInCent, percent, maxFeeInCent)); } -std::string escapeCsvValue(const std::string &value, const char delimiter) +std::string escapeCsvValue(const std::string& value, const char delimiter) { std::stringstream output; bool containsDelim{false}; @@ -250,7 +256,7 @@ std::string escapeCsvValue(const std::string &value, const char delimiter) output << '"'; } - for (auto &symbol : value) { + for (auto& symbol : value) { if (symbol == '"') { output << '"' << symbol; } else { @@ -283,4 +289,4 @@ void Marketplace::clear() Database db; db.newDb(); loadFromDb(); -} +} \ No newline at end of file diff --git a/src/core/marketplace.h b/src/core/marketplace.h index 71a7aa6..758f758 100644 --- a/src/core/marketplace.h +++ b/src/core/marketplace.h @@ -2,7 +2,6 @@ #define MARKETPLACE_H #include "article.h" -#include "database.h" #include "sale.h" #include "seller.h" @@ -20,26 +19,26 @@ using BasketVec = std::vector>; class Marketplace { -public: + public: Marketplace(); void storeToDb(bool onlyDelete = false); - Database::InitResult loadFromDb(); + void loadFromDb(); - SellersVec &getSellers(); - SalesVec &getSales(); + SellersVec& getSellers(); + SalesVec& getSales(); int getNextSellerNo(); int getNextArticleNo(); int getNumSellersDelete(); int getNumArticlesSold(); int getNumArticlesOffered(); - BasketVec &getBasket(); + BasketVec& getBasket(); int getBasketSumInCent(); std::string getBasketSumAsString(); void sortSellers(); - Seller *findSellerWithSellerNo(int sellerNo); - Seller *findSellerWithUuid(const std::string &uuid); + Seller* findSellerWithSellerNo(int sellerNo); + Seller* findSellerWithUuid(const std::string& uuid); void addArticleToBasket(std::unique_ptr
article); size_t basketSize(); void finishCurrentSale(std::unique_ptr sale); @@ -54,12 +53,12 @@ public: void clear(); - void exportReportToCSV(const std::filesystem::path &filePath, int feeInPercent, + void exportReportToCSV(const std::filesystem::path& filePath, int feeInPercent, int maxFeeInEuro); friend class ExcelReader; -private: + private: SellersVec sellers_; SalesVec sales_; BasketVec basket_; @@ -68,6 +67,6 @@ private: double marketFee(int sumInCent, int percent, int maxFeeInCent); std::string marketFeeAsString(int sumInCent, int percent, int maxFeeInCent); std::string paymentAsString(int sumInCent, int percent, int maxFeeInCent); -std::string escapeCsvValue(const std::string &value, const char delimiter); +std::string escapeCsvValue(const std::string& value, const char delimiter); -#endif +#endif \ No newline at end of file diff --git a/src/core/sale.cpp b/src/core/sale.cpp index 60e041a..ae3f143 100644 --- a/src/core/sale.cpp +++ b/src/core/sale.cpp @@ -3,41 +3,43 @@ #include -void Sale::addArticle(Article *articlePtr) +void Sale::addArticle(Article* articlePtr) { articlePtr->setSale(this); - m_articles.push_back(articlePtr); + articles_.push_back(articlePtr); } -ArticlesVec &Sale::getArticles() { return m_articles; } +ArticlesVec& Sale::getArticles() { return articles_; } -void Sale::removeArticle(const Article *articlePtr) +void Sale::removeArticle(const Article* articlePtr) { - auto it = std::find(m_articles.begin(), m_articles.end(), articlePtr); + /* auto it = std::find_if(articles_.begin(), articles_.end(), + [&articlePtr](auto art) { return art.get() == articlePtr; }); */ + auto it = std::find(articles_.begin(), articles_.end(), articlePtr); - if (it != m_articles.end()) { + if (it != articles_.end()) { (*it)->setSale(nullptr); (*it)->setState( Article::State::DELETE); // since we only have ad-hoc articles, that have all been sold - m_articles.erase(it); + articles_.erase(it); } } int Sale::sumInCents() { - int sum = std::accumulate(m_articles.begin(), m_articles.end(), 0, - [](int a, const Article *b) { return a + b->getPrice(); }); + int sum = std::accumulate(articles_.begin(), articles_.end(), 0, + [](int a, const Article* b) { return a + b->getPrice(); }); return sum; } std::string Sale::sumAsString() { return formatCentAsEuroString(sumInCents()); } -std::string Sale::getTimestamp() const { return m_timestamp; } +std::string Sale::getTimestamp() const { return timestamp_; } -void Sale::setTimestamp(const std::string ×tamp) { m_timestamp = timestamp; } +void Sale::setTimestamp(const std::string& timestamp) { timestamp_ = timestamp; } std::string Sale::getTimestampFormatted() const { - boost::posix_time::ptime time = boost::posix_time::from_iso_extended_string(m_timestamp); + boost::posix_time::ptime time = boost::posix_time::from_iso_extended_string(timestamp_); return boost::posix_time::to_simple_string(time); } diff --git a/src/core/sale.h b/src/core/sale.h index dd54f58..c6de317 100644 --- a/src/core/sale.h +++ b/src/core/sale.h @@ -11,30 +11,27 @@ namespace { -using ArticlesVec = std::vector
; +using ArticlesVec = std::vector; } -class Sale : public EntityUuid +class Sale : public Entity { -public: - Sale() = default; - Sale(const Sale &) = delete; - virtual ~Sale() = default; - void addArticle(Article *articlePtr); - void setTimestamp(const std::string ×tamp); + public: + void addArticle(Article* articlePtr); + void setTimestamp(const std::string& timestamp); - ArticlesVec &getArticles(); + ArticlesVec& getArticles(); std::string getTimestamp() const; std::string getTimestampFormatted() const; int sumInCents(); std::string sumAsString(); - void removeArticle(const Article *articlePtr); + void removeArticle(const Article* articlePtr); -private: - std::string m_timestamp{ + private: + std::string timestamp_{ boost::posix_time::to_iso_extended_string(boost::posix_time::second_clock::local_time())}; - mutable ArticlesVec m_articles{}; + mutable ArticlesVec articles_{}; }; -#endif +#endif \ No newline at end of file diff --git a/src/core/seller.cpp b/src/core/seller.cpp index 9cbb88d..9147934 100644 --- a/src/core/seller.cpp +++ b/src/core/seller.cpp @@ -5,49 +5,50 @@ #include #include -Seller::Seller(const std::string &firstName, const std::string &lastName, int sellerNo, +Seller::Seller(const std::string& firstName, const std::string& lastName, int sellerNo, int numArticlesOffered) - : EntityInt(sellerNo) + : Entity() { - m_firstName = firstName; - m_lastName = lastName; - m_numArticlesOffered = numArticlesOffered; + firstName_ = firstName; + lastName_ = lastName; + sellerNo_ = sellerNo; + numArticlesOffered_ = numArticlesOffered; } -void Seller::setSellerNo(int seller_no) { setId(seller_no); } +void Seller::setSellerNo(int seller_no) { sellerNo_ = seller_no; } -void Seller::setFirstName(const std::string &firstName) { m_firstName = firstName; } +void Seller::setFirstName(const std::string& firstName) { firstName_ = firstName; } -void Seller::setLastName(const std::string &lastName) { m_lastName = lastName; } +void Seller::setLastName(const std::string& lastName) { lastName_ = lastName; } -void Seller::setNumArticlesOffered(int number) { m_numArticlesOffered = number; } +void Seller::setNumArticlesOffered(int number) { numArticlesOffered_ = number; } void Seller::addArticle(std::unique_ptr
article) { article->setSeller(this); - m_articles.push_back(std::move(article)); + articles_.push_back(std::move(article)); } -std::string Seller::getFirstName() const { return m_firstName; } +std::string Seller::getFirstName() const { return firstName_; } -std::string Seller::getLastName() const { return m_lastName; } +std::string Seller::getLastName() const { return lastName_; } -int Seller::getSellerNo() const { return getId(); } +int Seller::getSellerNo() const { return sellerNo_; } std::string Seller::getSellerNoAsString() const { std::stringstream selNoStr; - selNoStr << std::setfill('0') << std::setw(3) << m_id; + selNoStr << std::setfill('0') << std::setw(3) << sellerNo_; return selNoStr.str(); ; } -std::vector
Seller::getArticles(bool onlySold) const +std::vector Seller::getArticles(bool onlySold) const { - std::vector
articles; - for (const auto &article : m_articles) { + std::vector articles; + for (const auto& article : articles_) { if (onlySold && article->isSold()) { articles.push_back(article.get()); } else if (!onlySold) { @@ -57,54 +58,54 @@ std::vector
Seller::getArticles(bool onlySold) const return articles; } -Article *Seller::getArticleByUuid(const std::string &uuidString) +Article* Seller::getArticleByUuid(const std::string& uuidString) { - auto iter = std::find_if(m_articles.begin(), m_articles.end(), [&uuidString](const auto &art) { + auto iter = std::find_if(articles_.begin(), articles_.end(), [&uuidString](const auto& art) { return art->getUuidAsString() == uuidString; }); - if (iter == m_articles.end()) + if (iter == articles_.end()) return nullptr; return (*iter).get(); } int Seller::numArticlesSold() const { return static_cast(getArticles(true).size()); } -int Seller::numArticlesOffered() const { return m_numArticlesOffered; } +int Seller::numArticlesOffered() const { return numArticlesOffered_; } int Seller::getMaxArticleNo() const { auto iter = std::max_element( - m_articles.begin(), m_articles.end(), - [](const auto &a, const auto &b) -> bool { return a->getArticleNo() < b->getArticleNo(); }); - if (iter == m_articles.end()) + articles_.begin(), articles_.end(), + [](const auto& a, const auto& b) -> bool { return a->getArticleNo() < b->getArticleNo(); }); + if (iter == articles_.end()) return 0; return (*iter)->getArticleNo(); } void Seller::cleanupArticles() { - m_articles.erase(std::remove_if(m_articles.begin(), m_articles.end(), - [](const auto &article) { + articles_.erase(std::remove_if(articles_.begin(), articles_.end(), + [](const auto& article) { return article->getState() == Article::State::DELETE; }), - m_articles.end()); + articles_.end()); - for (auto &article : m_articles) { + for (auto& article : articles_) { article->setState(Article::State::OK); } } int Seller::sumInCents() { - int sum = std::accumulate(m_articles.begin(), m_articles.end(), 0, - [](int a, const auto &b) { return a + b->getPrice(); }); + int sum = std::accumulate(articles_.begin(), articles_.end(), 0, + [](int a, const auto& b) { return a + b->getPrice(); }); return sum; } std::string Seller::sumAsString() { return formatCentAsEuroString(sumInCents()); } -bool operator<(const Seller &li, const Seller &re) { return li.m_id < re.m_id; } -bool operator<(const std::unique_ptr &li, const std::unique_ptr &re) +bool operator<(const Seller& li, const Seller& re) { return li.sellerNo_ < re.sellerNo_; } +bool operator<(const std::unique_ptr& li, const std::unique_ptr& re) { - return li->m_id < re->m_id; -} + return li->sellerNo_ < re->sellerNo_; +} \ No newline at end of file diff --git a/src/core/seller.h b/src/core/seller.h index f71b1eb..db44a0f 100644 --- a/src/core/seller.h +++ b/src/core/seller.h @@ -2,7 +2,7 @@ #define SELLER_H #include "article.h" -#include "entityint.h" +#include "entity.h" #include #include @@ -10,18 +10,17 @@ // class Article; -class Seller : public EntityInt +class Seller : public Entity { -public: + public: Seller() = default; - Seller(const Seller &) = delete; - virtual ~Seller() = default; - Seller(const std::string &firstName, const std::string &lastName, int sellerNo = 0, + // virtual ~Seller() = default; + Seller(const std::string& firstName, const std::string& lastName, int sellerNo = 0, int numArticlesOffered = 0); void setSellerNo(int sellerNo); - void setFirstName(const std::string &firstName); - void setLastName(const std::string &lastName); + void setFirstName(const std::string& firstName); + void setLastName(const std::string& lastName); void setNumArticlesOffered(int number); void addArticle(std::unique_ptr
article); void cleanupArticles(); @@ -32,20 +31,22 @@ public: std::string getSellerNoAsString() const; int numArticlesOffered() const; int numArticlesSold() const; - std::vector
getArticles(bool onlySold = true) const; - Article *getArticleByUuid(const std::string &uuidString); + // int numArticlesTotal() const; + std::vector getArticles(bool onlySold = true) const; + Article* getArticleByUuid(const std::string& uuidString); int getMaxArticleNo() const; int sumInCents(); std::string sumAsString(); - friend bool operator<(const Seller &li, const Seller &re); - friend bool operator<(const std::unique_ptr &li, const std::unique_ptr &re); + friend bool operator<(const Seller& li, const Seller& re); + friend bool operator<(const std::unique_ptr& li, const std::unique_ptr& re); -private: - int m_numArticlesOffered{}; - std::string m_firstName{}; - std::string m_lastName{}; - std::vector> m_articles{}; + private: + int sellerNo_{-1}; + int numArticlesOffered_{}; + std::string firstName_{}; + std::string lastName_{}; + std::vector> articles_{}; }; -#endif +#endif \ No newline at end of file diff --git a/src/core/utils.cpp b/src/core/utils.cpp index 1725924..b983423 100644 --- a/src/core/utils.cpp +++ b/src/core/utils.cpp @@ -1,70 +1,46 @@ #include "utils.h" -#include -#include -#include #include #include -#include - -//using namespace fmt; - std::string formatCentAsEuroString(const int cent, int width) { - /*std::stringstream currStream; + std::stringstream currStream; try { std::locale myLocale("de_DE.utf8"); currStream.imbue(myLocale); - std::cout << ">>> " << fmt::format(myLocale, "{:6.2Lf}", 1.12345) << '\n'; currStream << std::right << std::setw(width) << std::showbase << std::put_money(cent, false); - } catch (std::runtime_error &err) { + } catch (std::runtime_error& err) { currStream << std::fixed << std::setw(width >= 4 ? width - 4 : width) << std::setprecision(2) << cent / 100.0L << " €"; } - return currStream.str();*/ - -#if defined(_WIN64) || defined(_WIN32) - std::locale myLocale; -#else - std::locale myLocale{"de_DE.utf8"}; -#endif - return std::format(myLocale, "{:{}.2Lf} €", cent / 100.0L, width); + return currStream.str(); } -std::string <rim(std::string &str, const std::string &chars) +std::optional convertToPosPrinterDevice(const std::string& device, + const std::string& endpoint) { - str.erase(0, str.find_first_not_of(chars)); - return str; -} + if (device.empty()) { + return std::nullopt; + } -std::string &rtrim(std::string &str, const std::string &chars) -{ - str.erase(str.find_last_not_of(chars) + 1); - return str; -} + PrinterDevice printerDevice; + std::string delimiter = ":"; + try { + printerDevice.idVendor = std::stoi(device.substr(0, device.find(delimiter)), 0, 16); + printerDevice.idProduct = std::stoi(device.substr(device.find(delimiter) + 1), 0, 16); + if (endpoint.empty()) { + printerDevice.endpoint = 0x03; + } else { + printerDevice.endpoint = std::stoi(endpoint, 0, 16); + } -std::string &trim(std::string &str, const std::string &chars) -{ - return ltrim(rtrim(str, chars), chars); -} + } catch (std::exception& ex) { + throw ex; + } -bool case_insensitive_match(std::string s1, std::string s2) -{ - // convert s1 and s2 into lower case strings - transform(s1.begin(), s1.end(), s1.begin(), ::tolower); - transform(s2.begin(), s2.end(), s2.begin(), ::tolower); - if (s1.compare(s2) == 0) - return true; // The strings are same - return false; // not matched + return printerDevice; } - -bool isNumber(const std::string &str) -{ - return !str.empty() && std::find_if(str.begin(), str.end(), [](unsigned char c) { - return !std::isdigit(c); - }) == str.end(); -} \ No newline at end of file diff --git a/src/core/utils.h b/src/core/utils.h index 0adfd75..ff15359 100644 --- a/src/core/utils.h +++ b/src/core/utils.h @@ -1,15 +1,14 @@ -#ifndef CORE_UTILS_H -#define CORE_UTILS_H +#ifndef UTILS_H +#define UTILS_H + +#include "posprinter.h" #include #include #include -std::string formatCentAsEuroString(const int cent, int width = 6); -std::string <rim(std::string &str, const std::string &chars = "\t\n\v\f\r "); -std::string &rtrim(std::string &str, const std::string &chars = "\t\n\v\f\r "); -std::string &trim(std::string &str, const std::string &chars = "\t\n\v\f\r "); -bool case_insensitive_match(std::string s1, std::string s2); -bool isNumber(const std::string &str); +std::string formatCentAsEuroString(const int cent, int width = 10); +std::optional convertToPosPrinterDevice(const std::string& vendor, + const std::string& endpoint); #endif diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index edd2102..b66b5c1 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -8,45 +8,31 @@ set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) # Find the QtWidgets library -find_package(Qt6 COMPONENTS Widgets Network PrintSupport CONFIG REQUIRED) +find_package(Qt5Widgets CONFIG REQUIRED) +find_package(Qt5PrintSupport CONFIG REQUIRED) -# For SingleApplication: -set(QT_DEFAULT_MAJOR_VERSION 6 CACHE STRING "Qt version to use, defaults to 6") -set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication") -FetchContent_Declare( - SingleApplication - GIT_REPOSITORY https://github.com/itay-grudev/SingleApplication - GIT_TAG v3.5.2 -) -FetchContent_MakeAvailable(SingleApplication) -add_compile_definitions(QAPPLICATION_CLASS=${QAPPLICATION_CLASS}) - -add_executable(kima2) - -target_sources(kima2 PRIVATE - kima2.cpp - mainwindow.cpp - mainwindow.ui - sellerdialog.cpp - sellerdialog.ui - sellermodel.cpp - pricedialog.cpp - pricedialog.ui - basketmodel.cpp - salemodel.cpp - reportdialog.cpp - reportdialog.ui - reportmodel.cpp - settingsdialog.cpp - settingsdialog.ui - ../../kima2.qrc - kima2.rc +set(GUI_SOURCES + kima2.cpp + mainwindow.cpp + mainwindow.ui + sellerdialog.cpp + sellerdialog.ui + sellermodel.cpp + pricedialog.cpp + pricedialog.ui + basketmodel.cpp + salemodel.cpp + reportdialog.cpp + reportdialog.ui + reportmodel.cpp + settingsdialog.cpp + settingsdialog.ui + ../../kima2.qrc ) +add_executable(kima2 ${GUI_SOURCES} kima2.rc) target_include_directories(kima2 PRIVATE ${PROJECT_BINARY_DIR}) - -target_link_libraries(kima2 core printer Qt::Core Qt::PrintSupport Qt::Network SingleApplication::SingleApplication) - +target_link_libraries(kima2 core printer Qt5::Widgets Qt5::PrintSupport stdc++fs) if(WIN32) set_target_properties(kima2 PROPERTIES LINK_FLAGS "-mwindows") endif(WIN32) diff --git a/src/gui/basketmodel.cpp b/src/gui/basketmodel.cpp index 789d64b..2ac1931 100644 --- a/src/gui/basketmodel.cpp +++ b/src/gui/basketmodel.cpp @@ -1,17 +1,17 @@ #include "basketmodel.h" #include -#include #include +#include BasketModel::BasketModel(Marketplace* market, QObject* parent) - : QAbstractTableModel(parent), m_marketplace(market) + : QAbstractTableModel(parent), marketplace_(market) { } int BasketModel::rowCount([[maybe_unused]] const QModelIndex& parent) const { - return static_cast(m_marketplace->basketSize()); + return static_cast(marketplace_->basketSize()); } int BasketModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 4; } @@ -22,7 +22,7 @@ QVariant BasketModel::data(const QModelIndex& index, int role) const QFont myFont; QFont myFixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); - if (myFixedFont.fixedPitch() == false) { + if (myFixedFont.fixedPitch() == false) { myFixedFont.setFamily("monospace"); } @@ -46,10 +46,10 @@ QVariant BasketModel::data(const QModelIndex& index, int role) const if (role != Qt::DisplayRole) return QVariant(); - if (m_marketplace->basketSize() == 0) + if (marketplace_->basketSize() == 0) return QVariant(); - Article* article = m_marketplace->getBasket().at(index.row()).get(); + Article* article = marketplace_->getBasket().at(index.row()).get(); switch (index.column()) { case 0: @@ -92,45 +92,45 @@ QVariant BasketModel::headerData(int section, Qt::Orientation orientation, int r void BasketModel::addArticle(Seller* seller, int price, const std::string& desc) { - emit beginInsertRows(QModelIndex(), m_marketplace->getBasket().size(), - m_marketplace->getBasket().size()); + emit beginInsertRows(QModelIndex(), marketplace_->getBasket().size(), + marketplace_->getBasket().size()); auto article = std::make_unique
(price); article->createUuid(); article->setDescription(desc); - article->setArticleNo(m_marketplace->getNextArticleNo()); + article->setArticleNo(marketplace_->getNextArticleNo()); article->setSourceNo(QSettings().value("global/cashPointNo").toInt()); article->setSeller(seller); - m_marketplace->addArticleToBasket(std::move(article)); + marketplace_->addArticleToBasket(std::move(article)); emit endInsertRows(); } void BasketModel::finishSale() { - emit beginRemoveRows(QModelIndex(), 0, m_marketplace->getBasket().size() - 1); + emit beginRemoveRows(QModelIndex(), 0, marketplace_->getBasket().size() - 1); auto sale = std::make_unique(); sale->createUuid(); sale->setSourceNo(QSettings().value("global/cashPointNo").toInt()); - m_marketplace->finishCurrentSale(std::move(sale)); + marketplace_->finishCurrentSale(std::move(sale)); emit endRemoveRows(); emit basketDataChanged(); } void BasketModel::cancelSale() { - emit beginRemoveRows(QModelIndex(), 0, m_marketplace->getBasket().size() - 1); - m_marketplace->getBasket().clear(); + emit beginRemoveRows(QModelIndex(), 0, marketplace_->getBasket().size() - 1); + marketplace_->getBasket().clear(); emit endRemoveRows(); } bool BasketModel::removeRows(int row, int count, const QModelIndex& parent) { - auto article = m_marketplace->getBasket().at(row).get(); + auto article = marketplace_->getBasket().at(row).get(); emit beginRemoveRows(parent, row, row + count - 1); - m_marketplace->getBasket().erase( - std::remove_if(m_marketplace->getBasket().begin(), m_marketplace->getBasket().end(), + marketplace_->getBasket().erase( + std::remove_if(marketplace_->getBasket().begin(), marketplace_->getBasket().end(), [&article](const auto& a) { return a->getUuid() == article->getUuid(); }), - m_marketplace->getBasket().end()); + marketplace_->getBasket().end()); emit endRemoveRows(); return true; } diff --git a/src/gui/basketmodel.h b/src/gui/basketmodel.h index 81ad858..2a9b7fc 100644 --- a/src/gui/basketmodel.h +++ b/src/gui/basketmodel.h @@ -1,13 +1,13 @@ #ifndef BASKET_MODEL_H #define BASKET_MODEL_H -#include +#include #include class BasketModel : public QAbstractTableModel { - Q_OBJECT + Q_OBJECT public: explicit BasketModel(Marketplace* market, QObject* parent = nullptr); @@ -15,16 +15,19 @@ class BasketModel : public QAbstractTableModel virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + //virtual Qt::ItemFlags flags(const QModelIndex& index) const override; + //virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; + //virtual bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; void addArticle(Seller* seller, int price, const std::string& desc); void finishSale(); void cancelSale(); virtual bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; - signals: + signals: void basketDataChanged(); private: - Marketplace* m_marketplace; + Marketplace* marketplace_; }; -#endif +#endif \ No newline at end of file diff --git a/src/gui/kima2.cpp b/src/gui/kima2.cpp index d2826bd..f286e66 100644 --- a/src/gui/kima2.cpp +++ b/src/gui/kima2.cpp @@ -6,29 +6,26 @@ #include #include #include -#include -#include #include -#include -#include - -using namespace Qt::Literals::StringLiterals; - -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { - SingleApplication kimaApp(argc, argv, false, SingleApplication::Mode::User | SingleApplication::ExcludeAppPath | SingleApplication::ExcludeAppVersion); + QApplication kimaApp{argc, argv}; // QCoreApplication::setOrganizationName("RustySoft"); QCoreApplication::setOrganizationDomain("rustysoft.de"); QCoreApplication::setApplicationName("kima2"); - QTranslator qtTranslator; - - if (qtTranslator.load(QLocale::system(), u"qtbase"_s, u"_"_s, - QLibraryInfo::path(QLibraryInfo::TranslationsPath))) { - kimaApp.installTranslator(&qtTranslator); - } + QTranslator qTranslator; + QLocale german(QLocale::German); +#ifdef __linux__ + qTranslator.load("qt_" + german.name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); +#endif +#ifdef _WIN32 + qTranslator.load("qt_" + german.name(), + QApplication::applicationDirPath() + QDir::separator() + "translations"); +#endif + kimaApp.installTranslator(&qTranslator); QSettings settings{}; while (!settings.contains("global/cashPointNo")) { diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index ca9031e..7f1e9c8 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -1,23 +1,22 @@ #include "mainwindow.h" #include "basketmodel.h" +#include "config.h" +#include "jsonutil.h" #include "pricedialog.h" #include "reportdialog.h" #include "salemodel.h" #include "sellerdialog.h" #include "settingsdialog.h" -#include -#include -#include -#include -#include -#include +#include + +#include +#include #include #include #include -#include #include #include @@ -31,31 +30,23 @@ constexpr int STATUSBAR_TIMEOUT = 5000; MainWindow::MainWindow() { - m_ui.setupUi(this); + ui_.setupUi(this); - m_marketplace = std::make_unique(); - Database::InitResult res = m_marketplace->loadFromDb(); - if (res == Database::InitResult::OUTDATED_REPLACED) { - QMessageBox(QMessageBox::Icon::Information, "Datenbankinformation", - "Es wurde eine veraltete Datenbankdatei erkannt.
Diese wurde " - "umbenannt und eine neue Datei wurde erstellt.") - .exec(); - } + marketplace_ = std::make_unique(); + marketplace_->loadFromDb(); statusBar()->showMessage("Gespeicherte Daten wurden geladen.", STATUSBAR_TIMEOUT); - BasketModel *model = new BasketModel(getMarketplace(), m_ui.basketView); - m_ui.basketView->setModel(model); - m_ui.basketView->setColumnHidden(0, true); // hide the uuid + BasketModel* model = new BasketModel(getMarketplace(), ui_.basketView); + ui_.basketView->setModel(model); + ui_.basketView->setColumnHidden(0, true); // hide the uuid setWindowTitle("KIMA2 - Kasse Nr. " + QSettings().value("global/cashPointNo").toString()); - m_ui.salesView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); setSaleModel(); - connect(m_ui.actionQuit, &QAction::triggered, qApp, QApplication::closeAllWindows, - Qt::QueuedConnection); - connect(m_ui.newAction, &QAction::triggered, this, [this]() { - if (m_marketplace->getSellers().size() == 0 && m_marketplace->getSales().size() == 0) { + connect(ui_.actionQuit, &QAction::triggered, qApp, QApplication::quit); + connect(ui_.newAction, &QAction::triggered, this, [=]() { + if (marketplace_->getSellers().size() == 0 && marketplace_->getSales().size() == 0) { return; } auto dlgResult = @@ -67,45 +58,46 @@ MainWindow::MainWindow() if (dlgResult == QMessageBox::No) return; - delete m_ui.salesView->model(); - dynamic_cast(m_ui.basketView->model())->cancelSale(); - m_marketplace->clear(); + delete ui_.salesView->model(); + dynamic_cast(ui_.basketView->model())->cancelSale(); + marketplace_->clear(); setSaleModel(); updateStatLabel(); }); - m_ui.sellerNoEdit->installEventFilter(this); - m_ui.givenSpinBox->installEventFilter(this); + ui_.sellerNoEdit->installEventFilter(this); + ui_.givenSpinBox->installEventFilter(this); - connect(m_ui.actionEditSeller, &QAction::triggered, this, + connect(ui_.actionEditSeller, &QAction::triggered, this, &MainWindow::onActionEditSellerTriggered); - connect(m_ui.paidButton, &QPushButton::clicked, this, &MainWindow::onPaidButtonTriggered); - connect(m_ui.givenSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), this, + connect(ui_.paidButton, &QPushButton::clicked, this, &MainWindow::onPaidButtonTriggered); + connect(ui_.givenSpinBox, QOverload::of(&QDoubleSpinBox::valueChanged), this, &MainWindow::onGivenSpinBoxValueChanged); - connect(m_ui.basketView->selectionModel(), &QItemSelectionModel::selectionChanged, this, + connect(ui_.basketView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::onBasketViewSelectionChanged); - connect(m_ui.cancelArticleButton, &QPushButton::clicked, this, + connect(ui_.cancelArticleButton, &QPushButton::clicked, this, &MainWindow::onCancelArticleButtonClicked); - connect(m_ui.cancelSaleButton, &QPushButton::clicked, this, + connect(ui_.cancelSaleButton, &QPushButton::clicked, this, &MainWindow::onCancelSaleButtonClicked); - connect(m_ui.printSaleReceiptButton, &QPushButton::clicked, this, + connect(ui_.printSaleReceiptButton, &QPushButton::clicked, this, &MainWindow::onPrintSaleReceiptButtonClicked); - connect(m_ui.cancelAllArticlesButton, &QPushButton::clicked, this, + connect(ui_.cancelAllArticlesButton, &QPushButton::clicked, this, &MainWindow::onCancelAllArticlesButtonClicked); - connect(m_ui.aboutQtAction, &QAction::triggered, this, &MainWindow::onAboutQt); - connect(m_ui.aboutAction, &QAction::triggered, this, &MainWindow::onAbout); - connect(m_ui.openManualAction, &QAction::triggered, this, []() { - auto locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); + connect(ui_.aboutQtAction, &QAction::triggered, this, &MainWindow::onAboutQt); + connect(ui_.aboutAction, &QAction::triggered, this, &MainWindow::onAbout); + connect(ui_.openManualAction, &QAction::triggered, this, []() { + auto locations = QStandardPaths::standardLocations(QStandardPaths::DataLocation); for (auto location : locations) { if (QFile::exists(location + QString("/Benutzerhandbuch.pdf"))) { QDesktopServices::openUrl( - QUrl::fromLocalFile(location + QString("/Benutzerhandbuch.pdf"))); + QUrl(QString("file:///") + location + QString("/Benutzerhandbuch.pdf"), + QUrl::TolerantMode)); } } }); - connect(m_ui.licenseAction, &QAction::triggered, this, [this]() { + connect(ui_.licenseAction, &QAction::triggered, this, [=]() { QString licenseText( - "Copyright © 2018-2025 Martin Brodbeck\n\n" + "Copyright © 2018 Martin Brodbeck\n\n" "Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der " "zugehörigen Dokumentationen (die \"Software\") erhält, die Erlaubnis erteilt, " "sie uneingeschränkt zu nutzen, inklusive und ohne Ausnahme mit dem Recht, " @@ -124,30 +116,32 @@ MainWindow::MainWindow() "SOFTWARE ODER SONSTIGER VERWENDUNG DER SOFTWARE ENTSTANDEN."); QMessageBox::information(this, "Lizenzinformation", licenseText); }); - connect(m_ui.reportAction, &QAction::triggered, this, [this]() { ReportDialog(this).exec(); }); - connect(m_ui.configAction, &QAction::triggered, this, [this]() { + connect(ui_.reportAction, &QAction::triggered, this, [=]() { ReportDialog(this).exec(); }); + connect(ui_.configAction, &QAction::triggered, this, [=]() { int result = SettingsDialog(this).exec(); if (result == QDialog::Accepted) { - delete m_ui.salesView->model(); - m_marketplace->loadFromDb(); + delete ui_.salesView->model(); + marketplace_->loadFromDb(); setSaleModel(); } this->setWindowTitle("KIMA2 - Kasse Nr. " + QSettings().value("global/cashPointNo").toString()); }); - connect(m_ui.importSellerAction, &QAction::triggered, this, - &MainWindow::onImportSellerActionTriggered); - connect(m_ui.exportSalesJsonAction, &QAction::triggered, this, + connect(ui_.importSellerExcelAction, &QAction::triggered, this, + &MainWindow::onImportSellerExcelActionTriggered); + connect(ui_.importSellerJsonAction, &QAction::triggered, this, + &MainWindow::onImportSellerJsonActionTriggered); + connect(ui_.exportSellerJsonAction, &QAction::triggered, this, + &MainWindow::onExportSellerJsonActionTriggered); + connect(ui_.exportSalesJsonAction, &QAction::triggered, this, &MainWindow::onExportSalesJsonActionTriggered); - connect(m_ui.importSalesJsonAction, &QAction::triggered, this, + connect(ui_.importSalesJsonAction, &QAction::triggered, this, &MainWindow::onImportSalesJsonActionTriggered); readGeometry(); setWindowIcon(QIcon(":/misc/kima2.ico")); updateStatLabel(); - m_ui.lastPriceLabel1->setText(formatCentAsEuroString(0).c_str()); - m_ui.lastPriceLabel2->setText(formatCentAsEuroString(0).c_str()); } void MainWindow::onActionEditSellerTriggered() @@ -155,11 +149,11 @@ void MainWindow::onActionEditSellerTriggered() auto dialog = std::make_unique(this); int retCode = dialog->exec(); - delete m_ui.salesView->model(); + delete ui_.salesView->model(); if (retCode == QDialog::Accepted) { - m_marketplace->sortSellers(); - m_marketplace->storeToDb(); + marketplace_->sortSellers(); + marketplace_->storeToDb(); statusBar()->showMessage("Änderungen an den Verkäufer-Stammdaten gespeichert.", STATUSBAR_TIMEOUT); } else { @@ -173,44 +167,43 @@ void MainWindow::onActionEditSellerTriggered() void MainWindow::setSaleModel() { - m_ui.salesView->setModel(new SaleModel(getMarketplace(), m_ui.salesView)); - m_ui.salesView->setColumnHidden(2, true); - m_ui.salesView->resizeColumnToContents(0); - m_ui.salesView->resizeColumnToContents(1); + ui_.salesView->setModel(new SaleModel(getMarketplace(), ui_.salesView)); + ui_.salesView->setColumnHidden(2, true); + ui_.salesView->resizeColumnToContents(0); - m_ui.printSaleReceiptButton->setEnabled(false); - m_ui.cancelSaleButton->setEnabled(false); + ui_.printSaleReceiptButton->setEnabled(false); + ui_.cancelSaleButton->setEnabled(false); - connect(static_cast(m_ui.basketView->model()), &BasketModel::basketDataChanged, - static_cast(m_ui.salesView->model()), &SaleModel::onBasketDataChanged); - connect(m_ui.salesView->selectionModel(), &QItemSelectionModel::selectionChanged, this, + connect(static_cast(ui_.basketView->model()), &BasketModel::basketDataChanged, + static_cast(ui_.salesView->model()), &SaleModel::onBasketDataChanged); + connect(ui_.salesView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::onSalesViewSelectionChanged); } void MainWindow::onPaidButtonTriggered() { - if (m_marketplace->basketSize() > 0) { - QString lastPrice{m_marketplace->getBasketSumAsString().c_str()}; - dynamic_cast(m_ui.basketView->model())->finishSale(); - m_ui.salesView->resizeColumnToContents(0); - m_ui.lastPriceLabel1->setText(lastPrice); - m_ui.lastPriceLabel2->setText(lastPrice); - m_ui.basketSumLabel->setText(formatCentAsEuroString(0).c_str()); - m_ui.drawbackLabel->setText(formatCentAsEuroString(0).c_str()); - m_ui.drawbackContainerWidget->setEnabled(false); - m_ui.sellerNoEdit->setFocus(); + if (marketplace_->basketSize() > 0) { + QString lastPrice{marketplace_->getBasketSumAsString().c_str()}; + dynamic_cast(ui_.basketView->model())->finishSale(); + ui_.salesView->resizeColumnToContents(0); + ui_.lastPriceLabel1->setText(lastPrice); + ui_.lastPriceLabel2->setText(lastPrice); + ui_.basketSumLabel->setText(formatCentAsEuroString(0).c_str()); + ui_.drawbackLabel->setText(formatCentAsEuroString(0).c_str()); + ui_.drawbackContainerWidget->setEnabled(false); + ui_.sellerNoEdit->setFocus(); statusBar()->showMessage("Verkaufsvorgang erfolgreich durchgeführt.", STATUSBAR_TIMEOUT); updateStatLabel(); } } -bool MainWindow::eventFilter(QObject *target, QEvent *event) +bool MainWindow::eventFilter(QObject* target, QEvent* event) { - if (target == m_ui.sellerNoEdit) { + if (target == ui_.sellerNoEdit) { if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); + QKeyEvent* keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key::Key_Enter || keyEvent->key() == Qt::Key::Key_Return) { - if (keyEvent->modifiers() & Qt::ControlModifier) { + if (keyEvent->modifiers() == Qt::ControlModifier) { checkSellerNo(true); } else { checkSellerNo(false); @@ -219,18 +212,18 @@ bool MainWindow::eventFilter(QObject *target, QEvent *event) return true; } } - } else if (target == m_ui.givenSpinBox) { + } else if (target == ui_.givenSpinBox) { if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); + QKeyEvent* keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key::Key_Enter || keyEvent->key() == Qt::Key::Key_Return) { - if (keyEvent->modifiers() & Qt::ControlModifier) { + if (keyEvent->modifiers() == Qt::ControlModifier) { onPaidButtonTriggered(); return true; } } else if (keyEvent->key() == Qt::Key::Key_Escape) { - m_ui.drawbackLabel->setText(formatCentAsEuroString(0).c_str()); - m_ui.drawbackContainerWidget->setEnabled(false); - m_ui.sellerNoEdit->setFocus(); + ui_.drawbackLabel->setText(formatCentAsEuroString(0).c_str()); + ui_.drawbackContainerWidget->setEnabled(false); + ui_.sellerNoEdit->setFocus(); } } } @@ -241,15 +234,15 @@ void MainWindow::checkSellerNo(bool ctrlPressed) { using std::regex, std::regex_match, std::smatch; - auto inputText = m_ui.sellerNoEdit->text().toStdString(); + auto inputText = ui_.sellerNoEdit->text().toStdString(); if (inputText.empty()) { if (ctrlPressed == false) { onPaidButtonTriggered(); - } else if (m_marketplace->getBasket().size() > 0) { - m_ui.drawbackContainerWidget->setEnabled(true); - m_ui.givenSpinBox->setFocus(); - m_ui.givenSpinBox->selectAll(); + } else if (marketplace_->getBasket().size() > 0) { + ui_.drawbackContainerWidget->setEnabled(true); + ui_.givenSpinBox->setFocus(); + ui_.givenSpinBox->selectAll(); } return; } @@ -258,13 +251,13 @@ void MainWindow::checkSellerNo(bool ctrlPressed) smatch result; if (!regex_match(inputText, result, pattern)) { - m_ui.sellerNoEdit->clear(); + ui_.sellerNoEdit->clear(); return; } int sellerNo = std::stoi(result[0]); - auto seller = m_marketplace->findSellerWithSellerNo(sellerNo); + auto seller = marketplace_->findSellerWithSellerNo(sellerNo); if (seller) { PriceDialog priceDialog(this); if (sellerNo == 0) { @@ -274,52 +267,52 @@ void MainWindow::checkSellerNo(bool ctrlPressed) if (dialogResult == QDialog::Accepted) { int price = priceDialog.getPrice(); std::string desc = priceDialog.getDescription(); - dynamic_cast(m_ui.basketView->model())->addArticle(seller, price, desc); - m_ui.basketView->resizeColumnToContents(1); - m_ui.basketSumLabel->setText(m_marketplace->getBasketSumAsString().c_str()); + dynamic_cast(ui_.basketView->model())->addArticle(seller, price, desc); + ui_.basketView->resizeColumnToContents(1); + ui_.basketSumLabel->setText(marketplace_->getBasketSumAsString().c_str()); } } - m_ui.sellerNoEdit->clear(); + ui_.sellerNoEdit->clear(); } void MainWindow::onGivenSpinBoxValueChanged(double value) { int givenInCent = std::round(value * 100); - int basketSumInCent = m_marketplace->getBasketSumInCent(); + int basketSumInCent = marketplace_->getBasketSumInCent(); int drawback = givenInCent - basketSumInCent; - m_ui.drawbackLabel->setText(formatCentAsEuroString(drawback).c_str()); + ui_.drawbackLabel->setText(formatCentAsEuroString(drawback).c_str()); } -void MainWindow::onBasketViewSelectionChanged(const QItemSelection &selected, - [[maybe_unused]] const QItemSelection &deselected) +void MainWindow::onBasketViewSelectionChanged(const QItemSelection& selected, + [[maybe_unused]] const QItemSelection& deselected) { if (selected.size() > 0) { - m_ui.cancelArticleButton->setEnabled(true); + ui_.cancelArticleButton->setEnabled(true); } else { - m_ui.cancelArticleButton->setEnabled(false); + ui_.cancelArticleButton->setEnabled(false); } } -void MainWindow::onSalesViewSelectionChanged(const QItemSelection &selected, - [[maybe_unused]] const QItemSelection &deselected) +void MainWindow::onSalesViewSelectionChanged(const QItemSelection& selected, + [[maybe_unused]] const QItemSelection& deselected) { if (selected.size() > 0) { - m_ui.cancelSaleButton->setEnabled(true); + ui_.cancelSaleButton->setEnabled(true); if (!selected.indexes()[0].parent().isValid()) - m_ui.printSaleReceiptButton->setEnabled(true); + ui_.printSaleReceiptButton->setEnabled(true); else - m_ui.printSaleReceiptButton->setEnabled(false); + ui_.printSaleReceiptButton->setEnabled(false); } else { - m_ui.cancelSaleButton->setEnabled(false); - m_ui.printSaleReceiptButton->setEnabled(false); + ui_.cancelSaleButton->setEnabled(false); + ui_.printSaleReceiptButton->setEnabled(false); } } void MainWindow::onCancelArticleButtonClicked([[maybe_unused]] bool checked) { - auto selModel = m_ui.basketView->selectionModel(); + auto selModel = ui_.basketView->selectionModel(); if (selModel->hasSelection() == false) return; @@ -336,23 +329,22 @@ void MainWindow::onCancelArticleButtonClicked([[maybe_unused]] bool checked) // Deleting the rows, beginning with the last one! for (auto iter = indexes.constEnd() - 1; iter >= indexes.constBegin(); --iter) { - m_ui.basketView->model()->removeRow(iter->row()); + ui_.basketView->model()->removeRow(iter->row()); } - m_ui.basketSumLabel->setText( - m_marketplace->getBasketSumAsString().c_str()); // Update basket sum - m_ui.sellerNoEdit->setFocus(); + ui_.basketSumLabel->setText(marketplace_->getBasketSumAsString().c_str()); // Update basket sum + ui_.sellerNoEdit->setFocus(); } void MainWindow::onCancelSaleButtonClicked([[maybe_unused]] bool checked) { - auto selModel = m_ui.salesView->selectionModel(); + auto selModel = ui_.salesView->selectionModel(); if (selModel->hasSelection() == false) return; auto dlgResult = QMessageBox(QMessageBox::Icon::Warning, "Sind Sie sicher?", - "Möchten Sie wirklich aus abgeschlossenen Verkäufen stornieren?", + "Möchten Sie wirklich stornieren?", QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, this) .exec(); if (dlgResult == QMessageBox::No) @@ -363,25 +355,16 @@ void MainWindow::onCancelSaleButtonClicked([[maybe_unused]] bool checked) // Deleting the rows, beginning with the last one! for (auto iter = indexes.constEnd() - 1; iter >= indexes.constBegin(); --iter) { - m_ui.salesView->model()->removeRow(iter->row(), iter->parent()); + ui_.salesView->model()->removeRow(iter->row(), iter->parent()); } - m_ui.salesView->collapseAll(); - - QString lastPriceValue(formatCentAsEuroString(0).c_str()); - if (m_ui.salesView->model()->rowCount() > 0) { - lastPriceValue = - m_ui.salesView->model()->data(m_ui.salesView->model()->index(0, 1)).toString(); - } - m_ui.lastPriceLabel1->setText(lastPriceValue); - m_ui.lastPriceLabel2->setText(lastPriceValue); - + ui_.salesView->collapseAll(); updateStatLabel(); } void MainWindow::onPrintSaleReceiptButtonClicked([[maybe_unused]] bool checked) { - auto selModel = m_ui.salesView->selectionModel(); + auto selModel = ui_.salesView->selectionModel(); if (selModel->hasSelection() == false) return; @@ -390,7 +373,7 @@ void MainWindow::onPrintSaleReceiptButtonClicked([[maybe_unused]] bool checked) QString posPrinterEndpoint = settings.value("global/posPrinterEndpoint", "").toString(); auto indexes = selModel->selectedRows(); - auto &sale = m_marketplace->getSales().at(indexes[0].row()); + auto& sale = marketplace_->getSales().at(indexes[0].row()); auto printerDevice = convertToPosPrinterDevice(posPrinterDevice.toStdString(), posPrinterEndpoint.toStdString()); @@ -404,13 +387,12 @@ void MainWindow::onPrintSaleReceiptButtonClicked([[maybe_unused]] bool checked) } if (printer->isValid()) - printer->printSaleReceipt( - sale.get(), settings.value("global/commune", "Dettingen").toString().toStdString()); + printer->printSaleReceipt(sale.get(), settings.value("global/commune", "Dettingen").toString().toStdString()); } void MainWindow::onCancelAllArticlesButtonClicked([[maybe_unused]] bool checked) { - if (m_ui.basketView->model()->rowCount() == 0) + if (ui_.basketView->model()->rowCount() == 0) return; auto dlgResult = @@ -421,11 +403,10 @@ void MainWindow::onCancelAllArticlesButtonClicked([[maybe_unused]] bool checked) if (dlgResult == QMessageBox::No) return; - dynamic_cast(m_ui.basketView->model())->cancelSale(); + dynamic_cast(ui_.basketView->model())->cancelSale(); - m_ui.basketSumLabel->setText( - m_marketplace->getBasketSumAsString().c_str()); // Update basket sum - m_ui.sellerNoEdit->setFocus(); + ui_.basketSumLabel->setText(marketplace_->getBasketSumAsString().c_str()); // Update basket sum + ui_.sellerNoEdit->setFocus(); } void MainWindow::onAboutQt() { QMessageBox::aboutQt(this); } @@ -441,9 +422,9 @@ void MainWindow::onAbout() ">info@rustysoft.de>

"); } -void MainWindow::onImportSellerActionTriggered() +void MainWindow::onImportSellerExcelActionTriggered() { - if (!m_marketplace->getSales().empty()) { + if (!marketplace_->getSales().empty()) { QMessageBox(QMessageBox::Icon::Information, "Import nicht möglich", "Der Import ist nicht möglich, da schon Verkäufe getätigt wurden.", QMessageBox::StandardButton::Ok, this) @@ -451,31 +432,59 @@ void MainWindow::onImportSellerActionTriggered() return; } - auto filename = - QFileDialog::getOpenFileName(this, "Verkäufer importieren", QString(), - "Alle unterstützte Dateien (*.csv);;CSV Dateien (*.csv)"); + QMessageBox( + QMessageBox::Icon::Information, "Bitte beachten", + "Achtung: Importieren Sie die Verkäuferdaten nur auf einer (!) " + "KIMA2-Installation.
" + "Verteilen Sie die Daten auf die anderen Installationen unbedingt über eine JSON-Datei!", + QMessageBox::StandardButton::Ok, this) + .exec(); + + auto filename = QFileDialog::getOpenFileName(this, "Verkäufer importieren", QString(), + "Excel Dateien (*.xlsx *.xls)"); if (filename.isEmpty()) return; -#if defined(_WIN64) || defined(_WIN32) fs::path filePath(filename.toStdWString()); -#else - fs::path filePath(filename.toStdString()); -#endif - - std::size_t numImported{}; - numImported = CsvReader::readSellersFromFile(filePath, m_marketplace.get()); + ExcelReader::readSellersFromFile(filePath, marketplace_.get()); updateStatLabel(); +} - using namespace std::string_literals; - std::ostringstream msg; - msg << "Aus der CSV-Datei wurden "s << std::to_string(numImported) - << " Verkäufer importiert."; - QMessageBox(QMessageBox::Icon::Information, "Verkäufer erfolgreich importiert", - msg.str().c_str(), QMessageBox::StandardButton::Ok, this) - .exec(); +void MainWindow::onImportSellerJsonActionTriggered() +{ + if (!marketplace_->getSales().empty()) { + QMessageBox(QMessageBox::Icon::Information, "Import nicht möglich", + "Der Import ist nicht möglich, da schon Verkäufe getätigt wurden.", + QMessageBox::StandardButton::Ok, this) + .exec(); + return; + } + + auto filename = QFileDialog::getOpenFileName(this, "Verkäufer importieren", QString(), + "JSON Dateien (*.json)"); + + if (filename.isEmpty()) + return; + + fs::path filePath(filename.toStdWString()); + + JsonUtil::importSellers(filePath, marketplace_.get()); + updateStatLabel(); +} + +void MainWindow::onExportSellerJsonActionTriggered() +{ + auto filename = QFileDialog::getSaveFileName( + this, "Verkäufer exportieren", QString("kima2_verkaeufer.json"), "JSON Dateien (*.json)"); + + if (filename.isEmpty()) + return; + + fs::path filePath(filename.toStdWString()); + + JsonUtil::exportSellers(filePath, marketplace_.get()); } void MainWindow::onExportSalesJsonActionTriggered() @@ -490,13 +499,9 @@ void MainWindow::onExportSalesJsonActionTriggered() if (filename.isEmpty()) return; -#if defined(_WIN64) || defined(_WIN32) fs::path filePath(filename.toStdWString()); -#else - fs::path filePath(filename.toStdString()); -#endif - JsonUtil::exportSales(filePath, m_marketplace.get(), + JsonUtil::exportSales(filePath, marketplace_.get(), settings.value("global/cashPointNo").toInt()); } @@ -504,30 +509,23 @@ void MainWindow::onImportSalesJsonActionTriggered() { QSettings settings; - auto filenames = QFileDialog::getOpenFileNames(this, "Umsätze/Transaktionen importieren", + auto filename = QFileDialog::getOpenFileName(this, "Umsätze/Transaktionen importieren", QString(), "JSON Dateien (*.json)"); - if (filenames.isEmpty()) + if (filename.isEmpty()) return; - for(auto filename: filenames) { -#if defined(_WIN64) || defined(_WIN32) - fs::path filePath(filename.toStdWString()); -#else - fs::path filePath(filename.toStdString()); -#endif + fs::path filePath(filename.toStdWString()); - delete m_ui.salesView->model(); - try { - JsonUtil::importSales(filePath, m_marketplace.get(), - settings.value("global/cashPointNo").toInt()); - } catch (std::runtime_error &err) { - QMessageBox(QMessageBox::Icon::Warning, "Import nicht möglich", err.what(), QMessageBox::Ok, - this) - .exec(); - } + delete ui_.salesView->model(); + try { + JsonUtil::importSales(filePath, marketplace_.get(), + settings.value("global/cashPointNo").toInt()); + } catch (std::runtime_error& err) { + QMessageBox(QMessageBox::Icon::Warning, "Import nicht möglich", err.what(), QMessageBox::Ok, + this) + .exec(); } - setSaleModel(); updateStatLabel(); } @@ -552,7 +550,7 @@ void MainWindow::readGeometry() settings.endGroup(); } -void MainWindow::closeEvent(QCloseEvent *event) +void MainWindow::closeEvent(QCloseEvent* event) { writeGeometry(); event->accept(); @@ -562,9 +560,9 @@ void MainWindow::updateStatLabel() { std::string statistics("KIMA2 - Version "); statistics += PROJECT_VERSION; - statistics += "
Verkäufer: " + std::to_string(m_marketplace->getSellers().size() - 1); - statistics += "
Kunden: " + std::to_string(m_marketplace->getSales().size()); - statistics += "
Umsatz: " + m_marketplace->getOverallSumAsString(); + statistics += "
Verkäufer: " + std::to_string(marketplace_->getSellers().size() - 1); + statistics += "
Kunden: " + std::to_string(marketplace_->getSales().size()); + statistics += "
Umsatz: " + marketplace_->getOverallSumAsString(); - m_ui.statLabel->setText(statistics.c_str()); -} + ui_.statLabel->setText(statistics.c_str()); +} \ No newline at end of file diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index 42ac25f..755faa0 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -3,7 +3,7 @@ #include "ui_mainwindow.h" -#include +#include #include #include @@ -16,7 +16,7 @@ class MainWindow : public QMainWindow public: MainWindow(); - Marketplace* getMarketplace() { return m_marketplace.get(); } + Marketplace* getMarketplace() { return marketplace_.get(); } private slots: void onBasketViewSelectionChanged(const QItemSelection& selected, @@ -29,7 +29,7 @@ class MainWindow : public QMainWindow void onCancelAllArticlesButtonClicked(bool checked); void onAboutQt(); void onAbout(); - virtual bool eventFilter(QObject* target, QEvent* event) override; + virtual bool eventFilter(QObject *target, QEvent *event) override; protected: virtual void closeEvent(QCloseEvent* event) override; @@ -39,7 +39,9 @@ class MainWindow : public QMainWindow void checkSellerNo(bool ctrlPressed = false); void onPaidButtonTriggered(); void onGivenSpinBoxValueChanged(double value); - void onImportSellerActionTriggered(); + void onImportSellerExcelActionTriggered(); + void onImportSellerJsonActionTriggered(); + void onExportSellerJsonActionTriggered(); void onExportSalesJsonActionTriggered(); void onImportSalesJsonActionTriggered(); void setSaleModel(); @@ -47,8 +49,8 @@ class MainWindow : public QMainWindow void readGeometry(); void updateStatLabel(); - Ui::MainWindow m_ui; - std::unique_ptr m_marketplace; + Ui::MainWindow ui_; + std::unique_ptr marketplace_; }; -#endif +#endif \ No newline at end of file diff --git a/src/gui/mainwindow.ui b/src/gui/mainwindow.ui index 49ba0fc..d686bf4 100644 --- a/src/gui/mainwindow.ui +++ b/src/gui/mainwindow.ui @@ -112,11 +112,7 @@ - - - 999.990000000000009 - - + @@ -440,8 +436,16 @@ drucken
&Verkäufer + + + Importieren + + + + - + + @@ -505,9 +509,9 @@ drucken Exportieren für andere Kasse (JSON) - + - Aus CSV-Datei (initial) + Aus Excel-Datei (initial) @@ -540,11 +544,6 @@ drucken Lizenz - - - Importieren (aus CSV-Datei) - - diff --git a/src/gui/pricedialog.cpp b/src/gui/pricedialog.cpp index 46546c8..f28f190 100644 --- a/src/gui/pricedialog.cpp +++ b/src/gui/pricedialog.cpp @@ -6,31 +6,34 @@ PriceDialog::PriceDialog(QWidget* parent, bool forceDesc, Qt::WindowFlags f) : QDialog(parent, f) { - m_forceDesc = forceDesc; - m_ui.setupUi(this); - m_ui.priceSpinBox->setFocus(); + forceDesc_ = forceDesc; + ui_.setupUi(this); + ui_.priceSpinBox->setFocus(); } -int PriceDialog::getPrice() const { return static_cast(m_ui.priceSpinBox->value() * 100); } +int PriceDialog::getPrice() const { return static_cast(ui_.priceSpinBox->value() * 100); } -std::string PriceDialog::getDescription() const { return m_ui.descEdit->text().toStdString(); } +std::string PriceDialog::getDescription() const { return ui_.descEdit->text().toStdString(); } void PriceDialog::accept() { - if (static_cast(std::round(m_ui.priceSpinBox->value() * 100.0L)) % 50 != 0) { + if (static_cast(std::round(ui_.priceSpinBox->value() * 100.0L)) % 50 != 0) { QMessageBox(QMessageBox::Icon::Warning, "Falsche Preiseingabe", "Es sind nur 0,50 Cent-Schritte erlaubt.", QMessageBox::StandardButton::Ok, this) .exec(); - } else if (m_forceDesc && m_ui.descEdit->text().trimmed().isEmpty()) { + } else if (forceDesc_ && ui_.descEdit->text().trimmed().isEmpty()) { QMessageBox(QMessageBox::Icon::Warning, "Artikelbeschreibung fehlt", "Da Sie auf das Sonderkonto buchen ist eine Artikelbeschreibung erforderlich.", QMessageBox::StandardButton::Ok, this) .exec(); - m_ui.descEdit->setFocus(); + ui_.descEdit->setFocus(); } else { QDialog::accept(); } } -void PriceDialog::setForceDesc(bool force) { m_forceDesc = force; } \ No newline at end of file +void PriceDialog::setForceDesc(bool force) +{ + forceDesc_ = force; +} \ No newline at end of file diff --git a/src/gui/pricedialog.h b/src/gui/pricedialog.h index 5d9cbdf..229d2f3 100644 --- a/src/gui/pricedialog.h +++ b/src/gui/pricedialog.h @@ -19,8 +19,8 @@ class PriceDialog : public QDialog private: void on_model_duplicateSellerNo(const QString& message); virtual void accept() override; - Ui::PriceDialog m_ui; - bool m_forceDesc; + Ui::PriceDialog ui_; + bool forceDesc_; }; #endif \ No newline at end of file diff --git a/src/gui/pricedialog.ui b/src/gui/pricedialog.ui index 7e99c7c..f35c6f0 100644 --- a/src/gui/pricedialog.ui +++ b/src/gui/pricedialog.ui @@ -6,8 +6,8 @@ 0 0 - 266 - 128 + 201 + 127 @@ -18,11 +18,6 @@ - - - 16 - - Preis @@ -33,11 +28,6 @@ - - - 16 - - -999.990000000000009 @@ -61,18 +51,6 @@ - - - 0 - 0 - - - - - 200 - 0 - - (optional) diff --git a/src/gui/reportdialog.cpp b/src/gui/reportdialog.cpp index 2c13baf..3a84ec4 100644 --- a/src/gui/reportdialog.cpp +++ b/src/gui/reportdialog.cpp @@ -2,9 +2,8 @@ #include "mainwindow.h" -#include -#include -#include +#include +#include #include @@ -17,22 +16,22 @@ namespace fs = std::filesystem; -ReportDialog::ReportDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f) +ReportDialog::ReportDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f) { - m_ui.setupUi(this); - m_market = dynamic_cast(parent)->getMarketplace(); - m_model = std::make_unique(m_market, m_ui.reportView); - m_ui.reportView->setModel(m_model.get()); - m_ui.reportView->hideColumn(0); - m_ui.reportView->setRowHidden(0, true); // hide the special "Sonderkonto" user + ui_.setupUi(this); + market_ = dynamic_cast(parent)->getMarketplace(); + model_ = std::make_unique(market_, ui_.reportView); + ui_.reportView->setModel(model_.get()); + ui_.reportView->hideColumn(0); + ui_.reportView->setRowHidden(0, true); // hide the special "Sonderkonto" user - connect(m_ui.exportCsvButton, &QPushButton::clicked, this, + connect(ui_.exportCsvButton, &QPushButton::clicked, this, &ReportDialog::onExportCsvButtonClicked); - connect(m_ui.printReportButton, &QPushButton::clicked, this, + connect(ui_.printReportButton, &QPushButton::clicked, this, &ReportDialog::onPrintReportButtonClicked); - connect(m_ui.printSellerReceiptButton, &QPushButton::clicked, this, + connect(ui_.printSellerReceiptButton, &QPushButton::clicked, this, &ReportDialog::onPrintSellerReceiptButtonClicked); - connect(m_ui.reportView->selectionModel(), &QItemSelectionModel::selectionChanged, this, + connect(ui_.reportView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ReportDialog::onReportViewSelectionChanged); } @@ -48,13 +47,9 @@ void ReportDialog::onExportCsvButtonClicked() if (filename.isEmpty()) return; -#if defined(_WIN64) || defined(_WIN32) fs::path filePath(filename.toStdWString()); -#else - fs::path filePath(filename.toStdString()); -#endif - m_market->exportReportToCSV(filePath, feeInPercent, maxFeeInEuro); + market_->exportReportToCSV(filePath, feeInPercent, maxFeeInEuro); } void ReportDialog::onPrintReportButtonClicked() @@ -75,8 +70,8 @@ void ReportDialog::onPrintReportButtonClicked() QPainter painter; int height = printer.height(); int width = printer.width(); - const double ENTRIES_PER_PAGE = 45; - const auto &sellers = m_market->getSellers(); + const double ENTRIES_PER_PAGE = 51; + const auto& sellers = market_->getSellers(); unsigned int numPages = std::ceil(sellers.size() / ENTRIES_PER_PAGE); painter.begin(&printer); @@ -107,7 +102,7 @@ void ReportDialog::onPrintReportButtonClicked() for (unsigned int j = 0; j < ENTRIES_PER_PAGE && (i - 1) * ENTRIES_PER_PAGE + j < sellers.size(); ++j) { int idx = (i - 1) * ENTRIES_PER_PAGE + j; - if (sellers.at(idx)->getId() == 0) { + if (sellers.at(idx)->getUuidAsString() == "11111111-1111-1111-1111-111111111111") { continue; } content += QString("%1 %2 %3 %4 %5 %6 %7\n") @@ -126,7 +121,7 @@ void ReportDialog::onPrintReportButtonClicked() } // pieces booked on the special account "Sonderkonto" - const auto specialSeller = m_market->findSellerWithSellerNo(0); + const auto specialSeller = market_->findSellerWithUuid("11111111-1111-1111-1111-111111111111"); if (specialSeller && specialSeller->numArticlesSold() > 0) { printer.newPage(); painter.setFont(QFont("Arial", 16, QFont::Bold)); @@ -136,7 +131,7 @@ void ReportDialog::onPrintReportButtonClicked() QString content("Einzelteile ohne Nummer\n=======================\n\n"); unsigned int lines{0}; unsigned int pages{1}; - for (const auto &article : specialSeller->getArticles(true)) { + for (const auto& article : specialSeller->getArticles(true)) { content += QString("- %1:").arg(article->getDescription().substr(0, 45).c_str(), -45); content += QString("%1\n").arg(article->getPriceAsString().c_str(), 11); ++lines; @@ -163,8 +158,8 @@ void ReportDialog::onPrintReportButtonClicked() "Auswertung Kindersachenmarkt"); painter.setFont(fixedFont); QString content("Gesamtstatistik\n===============\n\n"); - int numArticlesOffered = m_market->getNumArticlesOffered(); - int numArticlesSold = m_market->getNumArticlesSold(); + int numArticlesOffered = market_->getNumArticlesOffered(); + int numArticlesSold = market_->getNumArticlesSold(); double percentArticlesSold = (static_cast(numArticlesSold) / static_cast(numArticlesOffered)) * 100; content += QString("Registrierte Verkäufer: %1\n").arg(sellers.size() - 1, 6); @@ -172,14 +167,14 @@ void ReportDialog::onPrintReportButtonClicked() content += QString("Verkaufte Artikel: %1 (%L2 %)\n") .arg(numArticlesSold, 6) .arg(percentArticlesSold, 0, 'f', 2); - content += QString("Anzahl Kunden: %1\n\n").arg(m_market->getSales().size(), 6); - content += QString("Gesamtumsatz: %1\n").arg(m_market->getOverallSumAsString().c_str(), 10); + content += QString("Anzahl Kunden: %1\n\n").arg(market_->getSales().size(), 6); + content += QString("Gesamtumsatz: %1\n").arg(market_->getOverallSumAsString().c_str(), 10); content += QString("Ausgezahlt: %1\n") - .arg(m_market->getOverallPaymentAsString(feeInPercent, maxFeeInEuro * 100).c_str(), 10); + .arg(market_->getOverallPaymentAsString(feeInPercent, maxFeeInEuro * 100).c_str(), 10); content += QString("Verbleibend: %1\n\n") - .arg(m_market->getOverallRevenueAsString(feeInPercent, maxFeeInEuro * 100).c_str(), 10); + .arg(market_->getOverallRevenueAsString(feeInPercent, maxFeeInEuro * 100).c_str(), 10); content += QString("(Einbehaltener Prozentsatz: %1 %)\n").arg(feeInPercent, 3); content += QString("(Maximal einbehaltener Betrag: %1 €)\n").arg(maxFeeInEuro, 3); @@ -196,12 +191,12 @@ void ReportDialog::onPrintSellerReceiptButtonClicked() QString posPrinterDevice = settings.value("global/posPrinterDevice", "").toString(); QString posPrinterEndpoint = settings.value("global/posPrinterEndpoint", "").toString(); - auto selModel = m_ui.reportView->selectionModel(); + auto selModel = ui_.reportView->selectionModel(); if (selModel->hasSelection() == false) return; auto indexes = selModel->selectedRows(); - std::ranges::sort(indexes); + auto& seller = market_->getSellers().at(indexes[0].row()); auto printerDevice = convertToPosPrinterDevice(posPrinterDevice.toStdString(), posPrinterEndpoint.toStdString()); @@ -214,22 +209,18 @@ void ReportDialog::onPrintSellerReceiptButtonClicked() printer = std::make_unique(); } - if (printer->isValid()) { - for (const auto &index : indexes) { - auto &seller = m_market->getSellers().at(index.row()); - printer->printSellerReceipt( - seller.get(), feeInPercent, maxFeeInEuro * 100, - settings.value("global/commune", "Dettingen").toString().toStdString()); - } - } + if (printer->isValid()) + printer->printSellerReceipt( + seller.get(), feeInPercent, maxFeeInEuro * 100, + settings.value("global/commune", "Dettingen").toString().toStdString()); } -void ReportDialog::onReportViewSelectionChanged(const QItemSelection &selected, - [[maybe_unused]] const QItemSelection &deselected) +void ReportDialog::onReportViewSelectionChanged(const QItemSelection& selected, + [[maybe_unused]] const QItemSelection& deselected) { if (selected.size() > 0) { - m_ui.printSellerReceiptButton->setEnabled(true); + ui_.printSellerReceiptButton->setEnabled(true); } else { - m_ui.printSellerReceiptButton->setEnabled(false); + ui_.printSellerReceiptButton->setEnabled(false); } } diff --git a/src/gui/reportdialog.h b/src/gui/reportdialog.h index 33713d8..64edc5c 100644 --- a/src/gui/reportdialog.h +++ b/src/gui/reportdialog.h @@ -5,7 +5,7 @@ #include "reportmodel.h" -#include +#include #include @@ -24,10 +24,9 @@ class ReportDialog : public QDialog void onReportViewSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); - private: - Ui::ReportDialog m_ui; - Marketplace* m_market; - std::unique_ptr m_model; + private : Ui::ReportDialog ui_; + Marketplace* market_; + std::unique_ptr model_; }; -#endif +#endif \ No newline at end of file diff --git a/src/gui/reportdialog.ui b/src/gui/reportdialog.ui index 5ac21c8..d5d27b6 100644 --- a/src/gui/reportdialog.ui +++ b/src/gui/reportdialog.ui @@ -19,7 +19,7 @@ - QAbstractItemView::ExtendedSelection + QAbstractItemView::SingleSelection QAbstractItemView::SelectRows diff --git a/src/gui/reportmodel.cpp b/src/gui/reportmodel.cpp index 20acadd..888430b 100644 --- a/src/gui/reportmodel.cpp +++ b/src/gui/reportmodel.cpp @@ -5,16 +5,16 @@ #include ReportModel::ReportModel(Marketplace* market, QObject* parent) - : QAbstractTableModel(parent), m_market(market) + : QAbstractTableModel(parent), market_(market) { QSettings settings; - m_feeInPercent = settings.value("global/feeInPercent").toInt(); - m_maxFeeInCent = settings.value("global/maxFeeInEuro").toInt() * 100; + feeInPercent_ = settings.value("global/feeInPercent").toInt(); + maxFeeInCent_ = settings.value("global/maxFeeInEuro").toInt() * 100; } int ReportModel::rowCount([[maybe_unused]] const QModelIndex& parent) const { - return static_cast(m_market->getSellers().size()); + return static_cast(market_->getSellers().size()); } int ReportModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 7; } @@ -52,14 +52,14 @@ QVariant ReportModel::data(const QModelIndex& index, int role) const if (role != Qt::DisplayRole) return QVariant(); - if (m_market->getSellers().size() == 0) + if (market_->getSellers().size() == 0) return QVariant(); - Seller* seller = m_market->getSellers().at(index.row()).get(); + Seller* seller = market_->getSellers().at(index.row()).get(); switch (index.column()) { case 0: - return seller->getId(); + return seller->getUuidAsString().c_str(); case 1: return seller->getSellerNo(); case 2: @@ -71,7 +71,7 @@ QVariant ReportModel::data(const QModelIndex& index, int role) const case 5: return seller->sumAsString().c_str(); case 6: - return paymentAsString(seller->sumInCents(), m_feeInPercent, m_maxFeeInCent).c_str(); + return paymentAsString(seller->sumInCents(), feeInPercent_, maxFeeInCent_).c_str(); default: return "???"; } @@ -104,4 +104,4 @@ QVariant ReportModel::headerData(int section, Qt::Orientation orientation, int r // return QStringLiteral("%1").arg(section); } else return ""; -} +} \ No newline at end of file diff --git a/src/gui/reportmodel.h b/src/gui/reportmodel.h index 1bb8d3c..6509d2f 100644 --- a/src/gui/reportmodel.h +++ b/src/gui/reportmodel.h @@ -1,7 +1,7 @@ #ifndef REPORT_MODEL_H #define REPORT_MODEL_H -#include +#include #include @@ -15,9 +15,9 @@ class ReportModel : public QAbstractTableModel virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; private: - Marketplace* m_market; - int m_feeInPercent{}; - int m_maxFeeInCent{}; + Marketplace* market_; + int feeInPercent_{}; + int maxFeeInCent_{}; }; -#endif +#endif \ No newline at end of file diff --git a/src/gui/salemodel.cpp b/src/gui/salemodel.cpp index 71dfae9..0476b24 100644 --- a/src/gui/salemodel.cpp +++ b/src/gui/salemodel.cpp @@ -1,6 +1,6 @@ #include "salemodel.h" -#include +#include #include @@ -9,7 +9,7 @@ SaleModel::SaleModel(Marketplace* market, QObject* parent) : QAbstractItemModel(parent) { - m_marketplace = market; + marketplace_ = market; } QModelIndex SaleModel::index(int row, int column, const QModelIndex& parent) const @@ -18,7 +18,7 @@ QModelIndex SaleModel::index(int row, int column, const QModelIndex& parent) con return QModelIndex(); if (!parent.isValid()) { - Sale* sale = m_marketplace->getSales().at(row).get(); + Sale* sale = marketplace_->getSales().at(row).get(); return createIndex(row, column, sale); } else if (!parent.parent().isValid()) { Sale* sale = static_cast(parent.internalPointer()); @@ -44,15 +44,15 @@ QModelIndex SaleModel::parent(const QModelIndex& index) const Sale* sale{}; Article* article{}; - EntityUuid* ent = static_cast(index.internalPointer()); + Entity* ent = static_cast(index.internalPointer()); sale = dynamic_cast(ent); if (sale) { - if (sale == m_rootItem.get()) + if (sale == rootItem.get()) return QModelIndex(); else { - return createIndex(-1, 0, m_rootItem.get()); + return createIndex(-1, 0, rootItem.get()); } } else { article = dynamic_cast(ent); @@ -80,7 +80,7 @@ QVariant SaleModel::data(const QModelIndex& index, int role) const if (role == Qt::FontRole) { QFont myFont; QFont myFixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont); - if (myFixedFont.fixedPitch() == false) { + if (myFixedFont.fixedPitch() == false) { myFixedFont.setFamily("monospace"); } @@ -113,9 +113,7 @@ QVariant SaleModel::data(const QModelIndex& index, int role) const Article* article = static_cast(index.internalPointer()); switch (index.column()) { case 0: - return (std::string("Verk. ") + article->getSeller()->getSellerNoAsString() + " (" + - article->getCompleteArticleNo() + ")") - .c_str(); + return (std::string("Verk. ") + article->getSeller()->getSellerNoAsString() + " (" + article->getCompleteArticleNo() + ")").c_str(); case 1: return article->getPriceAsString().c_str(); case 2: @@ -132,7 +130,7 @@ int SaleModel::rowCount(const QModelIndex& parent) const return 0; if (!parent.isValid()) { - return m_marketplace->getSales().size(); + return marketplace_->getSales().size(); } else if (!parent.parent().isValid()) { Sale* sale = static_cast(parent.internalPointer()); return sale->getArticles().size(); @@ -167,7 +165,7 @@ QVariant SaleModel::headerData(int section, Qt::Orientation orientation, int rol void SaleModel::onBasketDataChanged() { emit beginResetModel(); - auto& sales = m_marketplace->getSales(); + auto& sales = marketplace_->getSales(); std::sort(sales.begin(), sales.end(), [](const auto& lhs, const auto& rhs) { return lhs->getTimestamp() > rhs->getTimestamp(); }); @@ -179,11 +177,11 @@ bool SaleModel::removeRows(int row, int count, const QModelIndex& parent) if (!parent.isValid()) { // remove complete sale emit beginRemoveRows(parent, row, row + count - 1); - auto& sale = m_marketplace->getSales().at(row); + auto& sale = marketplace_->getSales().at(row); sale->setState(Sale::State::DELETE); std::for_each(sale->getArticles().begin(), sale->getArticles().end(), [](auto& a) { a->setState(Article::State::DELETE); }); - m_marketplace->storeToDb(); + marketplace_->storeToDb(); emit endRemoveRows(); } else if (!parent.parent().isValid()) { @@ -199,7 +197,7 @@ bool SaleModel::removeRows(int row, int count, const QModelIndex& parent) sale->setState(Sale::State::DELETE); } emit beginRemoveRows(parent.parent(), 0, 0); - m_marketplace->storeToDb(); + marketplace_->storeToDb(); emit endRemoveRows(); } diff --git a/src/gui/salemodel.h b/src/gui/salemodel.h index 29a13bf..91190e9 100644 --- a/src/gui/salemodel.h +++ b/src/gui/salemodel.h @@ -1,7 +1,7 @@ #ifndef SALEMODEL_H #define SALEMODEL_H -#include +#include #include @@ -12,7 +12,7 @@ class SaleModel : public QAbstractItemModel public: explicit SaleModel(Marketplace* market, QObject* parent = nullptr); virtual QModelIndex index(int row, int column, - const QModelIndex& parent = QModelIndex()) const override; + const QModelIndex& parent = QModelIndex()) const override; virtual QModelIndex parent(const QModelIndex& index) const override; virtual QVariant data(const QModelIndex& index, int role) const override; virtual int rowCount(const QModelIndex& parent) const override; @@ -24,8 +24,8 @@ class SaleModel : public QAbstractItemModel void onBasketDataChanged(); private: - Marketplace* m_marketplace; - std::unique_ptr m_rootItem{new Sale()}; + Marketplace* marketplace_; + std::unique_ptr rootItem{new Sale()}; }; -#endif +#endif \ No newline at end of file diff --git a/src/gui/sellerdialog.cpp b/src/gui/sellerdialog.cpp index 0b678fd..1c4ef97 100644 --- a/src/gui/sellerdialog.cpp +++ b/src/gui/sellerdialog.cpp @@ -7,25 +7,25 @@ SellerDialog::SellerDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f) { - m_ui.setupUi(this); - m_ui.editButton->setVisible(false); - m_market = dynamic_cast(parent)->getMarketplace(); - m_model = std::make_unique(m_market, m_ui.tableView); - m_ui.tableView->setModel(m_model.get()); - m_ui.tableView->setColumnHidden(0, true); // hide the uuid - m_ui.tableView->setRowHidden(0, true); // hide the special "Sonderkonto" user - connect(m_ui.newButton, &QPushButton::clicked, this, &SellerDialog::on_newButton_clicked); - connect(m_ui.deleteButton, &QPushButton::clicked, this, &SellerDialog::on_deleteButton_clicked); - connect(m_model.get(), &SellerModel::duplicateSellerNo, this, + ui_.setupUi(this); + ui_.editButton->setVisible(false); + market_ = dynamic_cast(parent)->getMarketplace(); + model_ = std::make_unique(market_, ui_.tableView); + ui_.tableView->setModel(model_.get()); + ui_.tableView->setColumnHidden(0, true); // hide the uuid + ui_.tableView->setRowHidden(0, true); // hide the special "Sonderkonto" user + connect(ui_.newButton, &QPushButton::clicked, this, &SellerDialog::on_newButton_clicked); + connect(ui_.deleteButton, &QPushButton::clicked, this, &SellerDialog::on_deleteButton_clicked); + connect(model_.get(), &SellerModel::duplicateSellerNo, this, &SellerDialog::on_model_duplicateSellerNo); - connect(m_ui.tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, + connect(ui_.tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &SellerDialog::onSellerViewSelectionChanged); } void SellerDialog::on_newButton_clicked() { // Don't allow new seller if market has already started - if (m_market->getSales().size() > 0) { + if (market_->getSales().size() > 0) { QMessageBox(QMessageBox::Icon::Warning, "Hinweis", "Da die Verkaufsphase schon begonnen hat (Artikel wurden bereits verkauft) " "können Sie keine Verkäufer mehr hinzufügen.", @@ -34,22 +34,22 @@ void SellerDialog::on_newButton_clicked() return; } - m_ui.tableView->reset(); - m_ui.tableView->model()->insertRows(m_ui.tableView->model()->rowCount(), 1); - m_ui.tableView->scrollToBottom(); - m_ui.tableView->selectRow(m_ui.tableView->model()->rowCount() - 1); - QModelIndex idx = m_ui.tableView->model()->index(m_ui.tableView->model()->rowCount() - 1, 2); - m_ui.tableView->setCurrentIndex(idx); - m_ui.tableView->edit(idx); + ui_.tableView->reset(); + ui_.tableView->model()->insertRows(ui_.tableView->model()->rowCount(), 1); + ui_.tableView->scrollToBottom(); + ui_.tableView->selectRow(ui_.tableView->model()->rowCount() - 1); + QModelIndex idx = ui_.tableView->model()->index(ui_.tableView->model()->rowCount() - 1, 2); + ui_.tableView->setCurrentIndex(idx); + ui_.tableView->edit(idx); } void SellerDialog::on_deleteButton_clicked() { - auto selModel = m_ui.tableView->selectionModel(); + auto selModel = ui_.tableView->selectionModel(); if (selModel->hasSelection() == false) return; - if (m_market->getSales().size() > 0) { + if (market_->getSales().size() > 0) { QMessageBox(QMessageBox::Icon::Warning, "Hinweis", "Da die Verkaufsphase schon begonnen hat (Artikel wurden bereits verkauft) " "können Sie keine Verkäufer mehr löschen.", @@ -60,8 +60,7 @@ void SellerDialog::on_deleteButton_clicked() auto dlgResult = QMessageBox(QMessageBox::Icon::Warning, "Sind Sie sicher?", - "Löschen wirkt sich sofort auf die Datenbank aus. Sie können den " - "Vorgang nicht rückgängig machen. Möchten Sie fortfahren?", + "Löschen wirkt sich direkt auf die Datenbank aus. Möchten Sie fortfahren?", QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No, this) .exec(); if (dlgResult == QMessageBox::No) @@ -72,7 +71,7 @@ void SellerDialog::on_deleteButton_clicked() // Deleting the rows, beginning with the last one! for (auto iter = indexes.constEnd() - 1; iter >= indexes.constBegin(); --iter) { - m_ui.tableView->model()->removeRow(iter->row()); + ui_.tableView->model()->removeRow(iter->row()); } } @@ -102,8 +101,8 @@ void SellerDialog::onSellerViewSelectionChanged(const QItemSelection& selected, [[maybe_unused]] const QItemSelection& deselected) { if (selected.size() > 0) { - m_ui.deleteButton->setEnabled(true); + ui_.deleteButton->setEnabled(true); } else { - m_ui.deleteButton->setEnabled(false); + ui_.deleteButton->setEnabled(false); } } \ No newline at end of file diff --git a/src/gui/sellerdialog.h b/src/gui/sellerdialog.h index ea87d4d..63e53fb 100644 --- a/src/gui/sellerdialog.h +++ b/src/gui/sellerdialog.h @@ -26,9 +26,9 @@ class SellerDialog : public QDialog void on_deleteButton_clicked(); void on_model_duplicateSellerNo(const QString& message); virtual void accept() override; - Ui::SellerDialog m_ui; - Marketplace* m_market; - std::unique_ptr m_model; + Ui::SellerDialog ui_; + Marketplace* market_; + std::unique_ptr model_; }; #endif \ No newline at end of file diff --git a/src/gui/sellermodel.cpp b/src/gui/sellermodel.cpp index a93f2ba..7ec2356 100644 --- a/src/gui/sellermodel.cpp +++ b/src/gui/sellermodel.cpp @@ -5,13 +5,13 @@ #include SellerModel::SellerModel(Marketplace* market, QObject* parent) - : QAbstractTableModel(parent), m_marketplace(market) + : QAbstractTableModel(parent), marketplace_(market) { } int SellerModel::rowCount([[maybe_unused]] const QModelIndex& parent) const { - return m_marketplace->getSellers().size(); + return marketplace_->getSellers().size(); } int SellerModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 5; } @@ -21,14 +21,17 @@ QVariant SellerModel::data(const QModelIndex& index, int role) const if (role != Qt::DisplayRole) return QVariant(); - if (m_marketplace->getSellers().size() == 0) + if (marketplace_->getSellers().size() == 0) return QVariant(); - Seller* seller = m_marketplace->getSellers().at(index.row()).get(); + Seller* seller = marketplace_->getSellers().at(index.row()).get(); + /* if (seller->getState() == Seller::State::DELETE) + return QVariant(); + */ switch (index.column()) { case 0: - return seller->getId(); + return seller->getUuidAsString().c_str(); case 1: return seller->getSellerNo(); case 2: @@ -78,21 +81,21 @@ bool SellerModel::setData(const QModelIndex& index, const QVariant& value, int r if (role != Qt::EditRole) return false; - Seller* seller = m_marketplace->getSellers().at(index.row()).get(); + Seller* seller = marketplace_->getSellers().at(index.row()).get(); switch (index.column()) { case 0: - seller->setId(value.toInt()); + seller->setUuidFromString(value.toString().toStdString()); break; case 1: { if (value.toInt() < 0) return false; auto iter = - std::find_if(m_marketplace->getSellers().begin(), m_marketplace->getSellers().end(), + std::find_if(marketplace_->getSellers().begin(), marketplace_->getSellers().end(), [&value](const std::unique_ptr& s) { return value.toInt() == s->getSellerNo(); }); - if (iter != m_marketplace->getSellers().end()) { + if (iter != marketplace_->getSellers().end()) { emit duplicateSellerNo( "Die Verkäufernummer muss eindeutig sein.\n(Möglicherweise wird die Nummer von " "einem (ausgeblendeten) Eintrag, der zum Löschen vorgemerkt ist, verwendet.)"); @@ -123,8 +126,9 @@ bool SellerModel::insertRows(int row, int count, const QModelIndex& parent) { emit beginInsertRows(parent, row, row + count - 1); auto seller = std::make_unique(); - seller->setSellerNo(m_marketplace->getNextSellerNo()); - m_marketplace->getSellers().push_back(std::move(seller)); + seller->createUuid(); + seller->setSellerNo(marketplace_->getNextSellerNo()); + marketplace_->getSellers().push_back(std::move(seller)); emit endInsertRows(); return true; @@ -132,24 +136,24 @@ bool SellerModel::insertRows(int row, int count, const QModelIndex& parent) bool SellerModel::removeRows(int row, int count, const QModelIndex& parent) { - auto seller = m_marketplace->getSellers().at(row).get(); + auto seller = marketplace_->getSellers().at(row).get(); if (seller->getState() == Seller::State::NEW) { emit beginRemoveRows(parent, row, row + count - 1); - m_marketplace->getSellers().erase( - std::remove_if(m_marketplace->getSellers().begin(), m_marketplace->getSellers().end(), + marketplace_->getSellers().erase( + std::remove_if(marketplace_->getSellers().begin(), marketplace_->getSellers().end(), [&seller](const std::unique_ptr& a) { - return a->getId() == seller->getId(); + return a->getUuid() == seller->getUuid(); }), - m_marketplace->getSellers().end()); + marketplace_->getSellers().end()); emit endRemoveRows(); return true; } else { emit beginRemoveRows(parent, row, row + count - 1); seller->setState(Seller::State::DELETE); - m_marketplace->storeToDb(true); + marketplace_->storeToDb(true); emit endRemoveRows(); return true; } return false; -} +} \ No newline at end of file diff --git a/src/gui/sellermodel.h b/src/gui/sellermodel.h index 52b99a7..5449bfb 100644 --- a/src/gui/sellermodel.h +++ b/src/gui/sellermodel.h @@ -1,31 +1,30 @@ #ifndef SELLER_MODEL_H #define SELLER_MODEL_H -#include +#include #include class SellerModel : public QAbstractTableModel { - Q_OBJECT + Q_OBJECT -public: - explicit SellerModel(Marketplace *market, QObject *parent = nullptr); - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override; - virtual int columnCount(const QModelIndex &parent = QModelIndex()) const override; - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + public: + explicit SellerModel(Marketplace* market, QObject* parent = nullptr); + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; + virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; - virtual Qt::ItemFlags flags(const QModelIndex &index) const override; - virtual bool setData(const QModelIndex &index, const QVariant &value, - int role = Qt::EditRole) override; - virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; - virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; + virtual Qt::ItemFlags flags(const QModelIndex& index) const override; + virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; + virtual bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; + virtual bool removeRows(int row, int count, const QModelIndex& parent = QModelIndex()) override; -signals: - void duplicateSellerNo(const QString &message); + signals: + void duplicateSellerNo(const QString& message); -private: - Marketplace *m_marketplace; + private: + Marketplace* marketplace_; }; -#endif +#endif \ No newline at end of file diff --git a/src/gui/settingsdialog.cpp b/src/gui/settingsdialog.cpp index 7dfee89..ac3a7a4 100644 --- a/src/gui/settingsdialog.cpp +++ b/src/gui/settingsdialog.cpp @@ -2,10 +2,9 @@ #include "mainwindow.h" -#include -#include -#include -#include +#include +#include +#include #include #include @@ -13,9 +12,9 @@ #include #include -SettingsDialog::SettingsDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f) +SettingsDialog::SettingsDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f) { - m_ui.setupUi(this); + ui_.setupUi(this); QSettings settings{}; int cashPointNo = settings.value("global/cashPointNo").toInt(); @@ -26,25 +25,25 @@ SettingsDialog::SettingsDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(par int maxFeeInEuro = settings.value("global/maxFeeInEuro").toInt(); if (parent) - m_market = dynamic_cast(parent)->getMarketplace(); + market_ = dynamic_cast(parent)->getMarketplace(); - m_ui.cashPointNoSpinBox->setValue(cashPointNo); - m_ui.communeEdit->setText(commune); - m_ui.posPrinterDeviceEdit->setText(posPrinterDevice); - m_ui.posPrinterEndpointEdit->setText(posPrinterEndpoint); - m_ui.feePercentSpinBox->setValue(feeInPercent); - m_ui.maxFeeSpinBox->setValue(maxFeeInEuro); + ui_.cashPointNoSpinBox->setValue(cashPointNo); + ui_.communeEdit->setText(commune); + ui_.posPrinterDeviceEdit->setText(posPrinterDevice); + ui_.posPrinterEndpointEdit->setText(posPrinterEndpoint); + ui_.feePercentSpinBox->setValue(feeInPercent); + ui_.maxFeeSpinBox->setValue(maxFeeInEuro); - connect(m_ui.testPosPrinterButton, &QPushButton::clicked, this, [this]() { + connect(ui_.testPosPrinterButton, &QPushButton::clicked, this, [=]() { using namespace std::string_literals; try { - if (m_ui.posPrinterDeviceEdit->text().isEmpty()) { + if (ui_.posPrinterDeviceEdit->text().isEmpty()) { PosPrinter printer; printer.printTest(); } else { - std::string posPrinterDeviceString = m_ui.posPrinterDeviceEdit->text().toStdString(); + std::string posPrinterDeviceString = ui_.posPrinterDeviceEdit->text().toStdString(); std::string posPrinterEndpointString = - m_ui.posPrinterEndpointEdit->text().toStdString(); + ui_.posPrinterEndpointEdit->text().toStdString(); try { auto printerDevice = @@ -55,7 +54,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(par printer.printTest(); } - } catch (std::exception &) { + } catch (std::exception&) { QMessageBox(QMessageBox::Icon::Warning, "Falsche Eingabe", QString("Eingabeformat für Device (hexadezimale IDs): " ":\nBeispiel: 0416:5011\n " @@ -65,7 +64,7 @@ SettingsDialog::SettingsDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(par return; } } - } catch (std::runtime_error &err) { + } catch (std::runtime_error& err) { QMessageBox(QMessageBox::Icon::Warning, "Bondrucker Fehler", QString("Test schlug fehl: ") + err.what(), QMessageBox::StandardButton::Ok, this) @@ -80,17 +79,17 @@ void SettingsDialog::accept() QSettings settings; int oldCashPointNo = settings.value("global/cashPointNo").toInt(); - int newCashPointNo = m_ui.cashPointNoSpinBox->value(); + int newCashPointNo = ui_.cashPointNoSpinBox->value(); - settings.setValue("global/commune", m_ui.communeEdit->text().trimmed()); - settings.setValue("global/posPrinterDevice", m_ui.posPrinterDeviceEdit->text().trimmed()); - settings.setValue("global/posPrinterEndpoint", m_ui.posPrinterEndpointEdit->text().trimmed()); - settings.setValue("global/feeInPercent", m_ui.feePercentSpinBox->value()); - settings.setValue("global/maxFeeInEuro", m_ui.maxFeeSpinBox->value()); + settings.setValue("global/commune", ui_.communeEdit->text().trimmed()); + settings.setValue("global/posPrinterDevice", ui_.posPrinterDeviceEdit->text().trimmed()); + settings.setValue("global/posPrinterEndpoint", ui_.posPrinterEndpointEdit->text().trimmed()); + settings.setValue("global/feeInPercent", ui_.feePercentSpinBox->value()); + settings.setValue("global/maxFeeInEuro", ui_.maxFeeSpinBox->value()); if (oldCashPointNo != newCashPointNo) { int result{0}; - if (m_market && m_market->getSales().size() > 0) { + if (market_ && market_->getSales().size() > 0) { result = QMessageBox(QMessageBox::Icon::Question, "Sind Sie sicher?", "Möchten Sie die Kassen-Nr wirklich ändern? Diese muss über alle " "Installationen hinweg eindeutig sein.", @@ -103,7 +102,7 @@ void SettingsDialog::accept() if (result == QMessageBox::Yes) { try { Database().updateCashPointNo(oldCashPointNo, newCashPointNo); - } catch (std::exception &ex) { + } catch (std::exception& ex) { std::string errMsg("Das Ändern der Kassen-Nr. ist fehlgeschlagen: "); errMsg.append(ex.what()); QMessageBox(QMessageBox::Icon::Critical, "Fehler", errMsg.c_str(), @@ -112,9 +111,9 @@ void SettingsDialog::accept() QDialog::accept(); return; } - settings.setValue("global/cashPointNo", m_ui.cashPointNoSpinBox->value()); + settings.setValue("global/cashPointNo", ui_.cashPointNoSpinBox->value()); } } QDialog::accept(); -} +} \ No newline at end of file diff --git a/src/gui/settingsdialog.h b/src/gui/settingsdialog.h index 541cc80..39e3086 100644 --- a/src/gui/settingsdialog.h +++ b/src/gui/settingsdialog.h @@ -3,14 +3,12 @@ #include "ui_settingsdialog.h" -#include +#include #include class SettingsDialog : public QDialog { - Q_OBJECT - public: SettingsDialog(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowTitleHint | Qt::WindowSystemMenuHint); @@ -19,8 +17,8 @@ class SettingsDialog : public QDialog void accept() override; private: - Ui::SettingsDialog m_ui; - Marketplace* m_market{}; + Ui::SettingsDialog ui_; + Marketplace* market_{}; }; -#endif +#endif \ No newline at end of file diff --git a/src/printer/CMakeLists.txt b/src/printer/CMakeLists.txt index 6205d41..84c58a6 100644 --- a/src/printer/CMakeLists.txt +++ b/src/printer/CMakeLists.txt @@ -1,6 +1,6 @@ set(Boost_USE_STATIC_LIBS ON) -find_package(Boost 1.78 REQUIRED) +find_package(Boost 1.62 REQUIRED) if(WIN32) find_package(LIBUSB REQUIRED) @@ -9,15 +9,14 @@ else() pkg_check_modules(LibUSB REQUIRED libusb-1.0) endif() -add_library(printer STATIC) -target_sources(printer PRIVATE - posprinter.cpp - utils.cpp +set(PRINTER_SOURCES + posprinter.cpp ) +add_library(printer STATIC ${PRINTER_SOURCES}) if(WIN32) target_link_libraries(printer core ${LIBUSB_1_LIBRARIES}) else() target_link_libraries(printer core ${LibUSB_LIBRARIES}) endif() -target_include_directories(printer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/.. ${Boost_INCLUDE_DIRS}) +target_include_directories(printer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/printer/posprinter.cpp b/src/printer/posprinter.cpp index 61926fc..43a900f 100644 --- a/src/printer/posprinter.cpp +++ b/src/printer/posprinter.cpp @@ -1,6 +1,6 @@ #include "posprinter.h" -#include +#include #include @@ -19,8 +19,6 @@ const std::string PosPrinter::Command::RIGHT_ALIGN = {0x1b, 0x61, 0x02}; const std::string PosPrinter::Command::FONT_SIZE_BIG = {0x1b, 0x21, 0x10}; const std::string PosPrinter::Command::FONT_SIZE_NORMAL = {0x1b, 0x21, 0x00}; const std::string PosPrinter::Command::FEED = {0x1b, 0x64, 0x03}; -const std::string PosPrinter::Command::PARTIAL_CUT = {0x1b, 0x69}; -const std::string PosPrinter::Command::FULL_CUT = {0x1b, 0x6d}; PosPrinter::PosPrinter() : PosPrinter(PrinterDevice()) {} @@ -204,7 +202,7 @@ void PosPrinter::printSellerReceipt(Seller* seller, const int percent, const int << marketFeeAsString(seller->sumInCents(), percent, maxFeeInCent) << "\n"; commandStream << "\nAuszahlung............. " << paymentAsString(seller->sumInCents(), percent, maxFeeInCent) << "\n"; - commandStream << Command::FEED << Command::FEED; + commandStream << Command::FEED; write(commandStream.str()); } @@ -215,4 +213,4 @@ bool PosPrinter::isValid() return true; else return false; -} +} \ No newline at end of file diff --git a/src/printer/posprinter.h b/src/printer/posprinter.h index 1cdbff6..8ede494 100644 --- a/src/printer/posprinter.h +++ b/src/printer/posprinter.h @@ -1,8 +1,8 @@ #ifndef POS_PRINTER_H #define POS_PRINTER_H -#include -#include +#include +#include #include @@ -36,8 +36,7 @@ class PosPrinter void printHeader(const std::string& commune = "Musterhausen"); void printTest(); void printSaleReceipt(Sale* sale, const std::string& commune = "Dettingen"); - void printSellerReceipt(Seller* seller, const int percent, const int maxFeeInCent, - const std::string& commune = "Dettingen"); + void printSellerReceipt(Seller* seller, const int percent, const int maxFeeInCent, const std::string& commune = "Dettingen"); bool isValid(); struct Command { @@ -49,8 +48,6 @@ class PosPrinter static const std::string FONT_SIZE_BIG; static const std::string FONT_SIZE_NORMAL; static const std::string FEED; - static const std::string PARTIAL_CUT; - static const std::string FULL_CUT; }; private: diff --git a/src/printer/utils.cpp b/src/printer/utils.cpp deleted file mode 100644 index 10cb4ed..0000000 --- a/src/printer/utils.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "utils.h" - -std::optional convertToPosPrinterDevice(const std::string& device, - const std::string& endpoint) -{ - if (device.empty()) { - return std::nullopt; - } - - PrinterDevice printerDevice; - std::string delimiter = ":"; - try { - printerDevice.idVendor = std::stoi(device.substr(0, device.find(delimiter)), 0, 16); - printerDevice.idProduct = std::stoi(device.substr(device.find(delimiter) + 1), 0, 16); - if (endpoint.empty()) { - printerDevice.endpoint = 0x03; - } else { - printerDevice.endpoint = std::stoi(endpoint, 0, 16); - } - - } catch (std::exception& ex) { - throw ex; - } - - return printerDevice; -} diff --git a/src/printer/utils.h b/src/printer/utils.h deleted file mode 100644 index 4429ae9..0000000 --- a/src/printer/utils.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef PRINTER_UTILS_H -#define PRINTER_UTILS_H - -#include "posprinter.h" - -#include -#include - -std::optional convertToPosPrinterDevice(const std::string& vendor, - const std::string& endpoint); - -#endif diff --git a/test/test_seller.cpp b/test/test_seller.cpp index 7d07b5b..45a41d6 100644 --- a/test/test_seller.cpp +++ b/test/test_seller.cpp @@ -9,14 +9,14 @@ BOOST_AUTO_TEST_CASE(create_uuid_nil) { Seller seller{}; - BOOST_TEST(seller.getId().is_nil() == true); + BOOST_TEST(seller.getUuid().is_nil() == true); } BOOST_AUTO_TEST_CASE(create_uuid) { Seller seller{}; seller.createUuid(); - BOOST_TEST(seller.getId().is_nil() == false); + BOOST_TEST(seller.getUuid().is_nil() == false); } BOOST_AUTO_TEST_CASE(create_many) @@ -25,7 +25,7 @@ BOOST_AUTO_TEST_CASE(create_many) std::array sellers; for (unsigned i = 0; i < sellers.size(); i++) { sellers[i] = Seller(); - //sellers[i].createUuid(); + sellers[i].createUuid(); } } @@ -37,4 +37,4 @@ BOOST_AUTO_TEST_CASE(with_article) { BOOST_TEST((article == nullptr)); BOOST_TEST(seller.getArticles(false).at(0)->getDescription() == "Test article"); BOOST_TEST(seller.numArticlesSold() == 0); -} +} \ No newline at end of file