Compare commits

...

110 Commits

Author SHA1 Message Date
Martin Brodbeck 0c7f071b9d include dir for boost added. 2024-03-05 14:38:02 +01:00
Martin Brodbeck d0c50c9b9a qsingleapplication version bumped 2024-01-23 11:25:07 +01:00
Martin Brodbeck a17cb22e05 2023 → 2024 2024-01-23 11:22:51 +01:00
Martin Brodbeck 205dac5326 nlohmann updateted to 3.11.3 2024-01-23 11:20:39 +01:00
Martin Brodbeck b0d2d6b284 update to version 1.8 2024-01-23 10:46:49 +01:00
Martin Brodbeck 7f11ba4e5d new version 1.8.0 2024-01-23 10:42:04 +01:00
Martin Brodbeck 32d0ec7749 Allow import of multiple sales at once. 2024-01-23 10:39:43 +01:00
Martin Brodbeck 54e5c70447 Changed minimum versions 2024-01-23 10:06:01 +01:00
Martin Brodbeck 379fd4a73c Lib references for Windows updated 2023-09-21 15:00:18 +02:00
Martin Brodbeck 8a94b53379 Push boost version. 2023-05-02 11:07:15 +02:00
Martin Brodbeck d9b13d0e1a README updated. 2023-05-02 11:03:22 +02:00
Martin Brodbeck 6f885dd64e more on metainfo 2023-04-28 10:29:39 +02:00
Martin Brodbeck 1a698a6cd2 metainfo added 2023-04-28 10:12:10 +02:00
Martin Brodbeck ac9ae8b34e Add metainfo 2023-04-28 10:08:02 +02:00
Martin Brodbeck 4385624988 Merge branch 'master' of ssh://git.rustysoft.de/martin/kima2 2023-04-26 12:47:45 +02:00
Martin Brodbeck 4cfd8d5572 2022 → 2023 2023-04-26 12:47:41 +02:00
Martin Brodbeck 528ae1ff31 use QUrl::fromLocalFile 2023-04-26 12:46:35 +02:00
Martin Brodbeck 649c26db4b Updated for Windows installation 2023-04-26 08:53:13 +02:00
Martin Brodbeck 13a1d26d96 description updated 2023-04-26 08:36:03 +02:00
Martin Brodbeck f898844c7c remove obsolete lstdc++fs flag 2023-04-25 16:19:27 +02:00
Martin Brodbeck e6b71a7e4d Get rid of csv-parser 2023-04-25 16:11:34 +02:00
Martin Brodbeck f4b4ccbbea Revert "Remove fmt dependency"
This reverts commit 8efdf7b6fe.
2023-04-25 15:22:06 +02:00
Martin Brodbeck e79a81797c Increase version number 2023-04-21 21:35:46 +02:00
Martin Brodbeck 8efdf7b6fe Remove fmt dependency 2023-04-21 21:33:59 +02:00
Martin Brodbeck a46e8d89c9 remove xlnt stuff 2023-01-18 19:41:53 +01:00
Martin Brodbeck 3e293ba447 updated 2023-01-18 17:08:09 +01:00
Martin Brodbeck 245e41bbf0 Push to new version. 2023-01-18 17:06:02 +01:00
Martin Brodbeck b0444112a8 seller menu simplified. 2023-01-18 17:05:21 +01:00
Martin Brodbeck c4ccd43b45 Push to new version 2023-01-18 16:46:44 +01:00
Martin Brodbeck 16745a248c Update manual 2023-01-18 16:46:30 +01:00
Martin Brodbeck 19ea7f27de Excel stuff removed. 2023-01-18 16:35:28 +01:00
Martin Brodbeck 42bf036f85 Merge branch 'master' of ssh://git.rustysoft.de/martin/kima2 2022-09-27 09:01:55 +02:00
Martin Brodbeck 9d7492c745 Version 1.6.1 2022-09-27 09:01:27 +02:00
Martin Brodbeck 9fcfb8e3ba Loading translation improved. 2022-09-26 20:47:23 +02:00
Martin Brodbeck a23de4dcf0 README updated 2022-09-26 14:04:57 +02:00
Martin Brodbeck 77f45fa55f improved Arch Linux build file 2022-09-26 13:48:48 +02:00
Martin Brodbeck 7299ae7c66 Fix db filename 2022-09-26 12:40:21 +02:00
Martin Brodbeck 1720dbba8b cpack: dependency fix for Windows 2022-09-26 12:29:53 +02:00
Martin Brodbeck 66e2e69c3e LICENSE: 2021 -> 2022 2022-09-26 12:24:45 +02:00
Martin Brodbeck 78aafab63b cpack: dependency fix for Windows 2022-09-26 12:23:50 +02:00
Martin Brodbeck 72e1a69dae prepare for 1.6.0 2022-09-26 12:10:57 +02:00
Martin Brodbeck 7e38da7276 Update DLLs for Qt6 2022-09-26 11:22:11 +02:00
Martin Brodbeck 144f61d6d4 Do not use named locales on Windows. 2022-09-26 11:21:03 +02:00
Martin Brodbeck 85574ff08a replace boost date_time with chrono 2022-09-26 10:14:57 +02:00
Martin Brodbeck c44d8b352a manual updated 2022-09-26 09:09:15 +02:00
Martin Brodbeck be9a7be38d nlohmann_json and singleapplication updated 2022-09-26 09:05:38 +02:00
Martin Brodbeck 104464f781 2022-09-24 20:43:32 +02:00
Martin Brodbeck 3a132e69ae Add one additional seller.
fixes #24
2022-09-24 20:41:15 +02:00
Martin Brodbeck 01577d02a0 Do not ignore seller entries with empty names.
fixes #23
2022-09-24 20:25:33 +02:00
Martin Brodbeck ecd1111391 Externen Link aktualisiert. 2022-09-24 14:56:22 +02:00
Martin Brodbeck 944edc277a ReportDialog: Reduce lines per page
fixes #22
2022-09-24 14:41:14 +02:00
Martin Brodbeck 0427bd4077 move to qt6 2022-07-07 17:16:51 +02:00
Martin Brodbeck 2b6628bdf8 Using fmt for currency 2022-07-07 16:53:44 +02:00
Martin Brodbeck 6944051c31 code formatting 2022-07-07 15:37:33 +02:00
Martin Brodbeck 5f7d91a18e Copyright year updated 2022-07-07 15:32:13 +02:00
Martin Brodbeck 2b7c099f5e Adopt to C++20 2022-07-07 15:31:32 +02:00
Martin Brodbeck acc3095e60 code formatting 2022-07-07 15:21:46 +02:00
Martin Brodbeck d677dfd628 clang-format updated 2022-07-07 15:14:30 +02:00
Martin Brodbeck e0ffd47430 nlohmann_json: update to v3.10.5 2022-07-07 15:07:42 +02:00
Martin Brodbeck 3e6e587df8 member variables renamed 2022-07-07 15:03:39 +02:00
Martin Brodbeck 21571215bc 2022-07-07 15:03:13 +02:00
Martin Brodbeck 52e0f1636e Hide .cache (clangd) 2022-07-07 15:03:04 +02:00
Martin Brodbeck 38b8865cea push to new singleapplication version 2021-09-27 14:53:09 +02:00
Martin Brodbeck 20c7a99578 2021-09-22 07:54:53 +02:00
Martin Brodbeck 3572d22715 2021-09-22 07:53:19 +02:00
Martin Brodbeck 453fd8cdb5 cpack: new Windows dependencies added 2021-09-21 10:49:54 +02:00
Martin Brodbeck 911b05b487 cpack: new Windows dependencies added 2021-09-21 10:36:43 +02:00
Martin Brodbeck 9e511c684d subproject updated 2021-09-20 08:46:51 +02:00
Martin Brodbeck b9bb9f1a8c new version 1.5.3 2021-09-20 08:05:37 +02:00
Martin Brodbeck 329c3a1540 Manual updated 2021-09-20 08:04:39 +02:00
Martin Brodbeck 8feb122c11 subprojects updated 2021-09-20 07:44:22 +02:00
Martin Brodbeck d573aed916 Merge branch 'master' of ssh://brodbeck-online.de:60022/martin/kima2-cpp 2021-09-20 07:40:34 +02:00
Martin Brodbeck 83b6cd1d26 2021-09-20 07:40:05 +02:00
Martin Brodbeck 059ae5ca66 2020 → 2021 2021-09-20 07:39:37 +02:00
Martin Brodbeck edf9cb1a2c Revert "2020 → 2021"
This reverts commit b8b5d8b140.
2021-09-19 19:59:51 +02:00
Martin Brodbeck b8b5d8b140 2021 → 2021 2021-09-19 19:58:49 +02:00
Martin Brodbeck 072af76de1 ... 2021-09-19 19:53:20 +02:00
Martin Brodbeck 92ecc92bf7 Fix umlaut-crash on linux machines 2021-09-19 19:52:32 +02:00
Martin Brodbeck e48fbe82e0 csv-parser updated 2021-09-17 21:16:08 +02:00
Martin Brodbeck 8ef821dcc0 singleapplication updated 2021-09-17 21:13:21 +02:00
Martin Brodbeck c65e7be415 new version 1.5.2 2020-10-19 07:50:30 +02:00
Martin Brodbeck b9f09fcd4c ... 2020-10-15 16:50:37 +02:00
Martin Brodbeck a156c5331a Added warning message when Excel import fails. 2020-10-15 16:43:00 +02:00
Martin Brodbeck 9e6e2eb936 Merge branch 'master' of ssh://brodbeck-online.de:60022/martin/kima2-cpp into master 2020-10-15 15:49:02 +02:00
Martin Brodbeck 8b299bacc3 Set default style on Windows to "Fusion". 2020-10-15 15:47:05 +02:00
Martin Brodbeck eb5434f374 Merge branch 'master' of ssh://brodbeck-online.de:60022/martin/kima2-cpp into master 2020-09-04 09:52:57 +02:00
Martin Brodbeck a547b6f3c3 push csv-parser subproject 2020-08-28 19:10:01 +02:00
Martin Brodbeck 26804ba03e push singleapplication subproject 2020-08-28 19:07:16 +02:00
Martin Brodbeck 305d41f2e1 Added missing dlls to Windows deployment 2020-04-17 10:22:52 +02:00
Martin Brodbeck 8374175087 2019 -> 2020 2020-02-15 09:55:01 +01:00
Martin Brodbeck 01bf3c29a2 [Windows] undefine DELETE macro if defined 2020-02-12 16:13:16 +01:00
Martin Brodbeck ff9dc9b05e Fix cpack for windows (dlls) 2020-02-12 16:12:40 +01:00
Martin Brodbeck e41ce5a117 Push to version 1.5.1 2020-02-12 14:06:59 +01:00
Martin Brodbeck 2d06de9907 Fix Excel import 2020-02-12 14:04:15 +01:00
Martin Brodbeck 77791e142c more on build scripts 2019-10-17 16:03:12 +02:00
Martin Brodbeck a8181729f9 more on meson 2019-10-14 19:32:14 +02:00
Martin Brodbeck 5aa4e3a5f0 typo 2019-10-11 12:49:32 +02:00
Martin Brodbeck 77226f294b rpm builds now 2019-10-11 12:48:54 +02:00
Martin Brodbeck 03f1c7cca5 Initial commit of rpm spec file 2019-10-11 11:09:54 +02:00
Martin Brodbeck b9d4375f5a improved build instructions 2019-10-11 10:01:21 +02:00
Martin Brodbeck f37cd75502 using system json lib if available
(works on Arch Linux)
2019-10-11 09:09:18 +02:00
Martin Brodbeck b016452a06 adjust cmake files to changed filesystem 2019-10-10 15:00:09 +02:00
Martin Brodbeck 7ca04f79ce more on meson 2019-10-10 14:52:00 +02:00
Martin Brodbeck e987692c7a add files to be installed to meson 2019-10-10 14:42:11 +02:00
Martin Brodbeck d13f9d2824 meson is now working ... somehow 2019-10-10 13:36:48 +02:00
Martin Brodbeck 2faa2fa019 3rdparty renamed to subprojects 2019-10-10 13:36:18 +02:00
Martin Brodbeck fc308c644c Merge branch 'master' into meson 2019-10-10 08:13:30 +02:00
Martin Brodbeck e89728846c restructure libs 2019-10-10 08:09:16 +02:00
Martin Brodbeck ad895abd35 initial meson files added 2019-10-09 16:31:29 +02:00
Martin Brodbeck ec0b7cbf0d code cleanup 2019-10-09 10:36:51 +02:00
77 changed files with 1113 additions and 903 deletions

View File

@ -1,27 +1,38 @@
---
Language: Cpp Language: Cpp
# BasedOnStyle: LLVM # BasedOnStyle: LLVM
AccessModifierOffset: -2 AccessModifierOffset: -4
AlignAfterOpenBracket: Align AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false AlignArrayOfStructures: None
AlignConsecutiveDeclarations: false AlignConsecutiveMacros: None
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Right AlignEscapedNewlines: Right
AlignOperands: true AlignOperands: Align
AlignTrailingComments: true AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true BinPackArguments: true
BinPackParameters: true BinPackParameters: true
BraceWrapping: BraceWrapping:
AfterClass: true AfterCaseLabel: false
AfterControlStatement: false AfterClass: false
AfterControlStatement: Never
AfterEnum: false AfterEnum: false
AfterFunction: false AfterFunction: false
AfterNamespace: false AfterNamespace: false
@ -31,13 +42,21 @@ BraceWrapping:
AfterExternBlock: false AfterExternBlock: false
BeforeCatch: false BeforeCatch: false
BeforeElse: false BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false IndentBraces: false
SplitEmptyFunction: true SplitEmptyFunction: true
SplitEmptyRecord: true SplitEmptyRecord: true
SplitEmptyNamespace: true SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None BreakBeforeBinaryOperators: None
BreakBeforeBraces: Linux BreakBeforeConceptDeclarations: true
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: true
AfterFunction: true
AfterNamespace: true
BreakBeforeInheritanceComma: false BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon BreakConstructorInitializers: BeforeColon
@ -50,35 +69,56 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4 ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4
Cpp11BracedListStyle: true Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false DerivePointerAlignment: false
DisableFormat: false DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true FixNamespaceComments: true
ForEachMacros: ForEachMacros:
- foreach - foreach
- Q_FOREACH - Q_FOREACH
- BOOST_FOREACH - BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve IncludeBlocks: Preserve
IncludeCategories: IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2 Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)' - Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3 Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*' - Regex: '.*'
Priority: 1 Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$' IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseLabels: false IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentRequires: false
IndentWidth: 4 IndentWidth: 4
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave JavaScriptQuotes: Leave
JavaScriptWrapImports: true JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
MacroBlockBegin: '' MacroBlockBegin: ''
MacroBlockEnd: '' MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
NamespaceIndentation: None NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2 ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2 PenaltyBreakAssignment: 2
@ -86,24 +126,57 @@ PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300 PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120 PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000 PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000 PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60 PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left PenaltyIndentedWhitespace: 0
PointerAlignment: Right
PPIndentWidth: -1
ReferenceAlignment: Pointer
ReflowComments: true ReflowComments: true
SortIncludes: true ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true SortUsingDeclarations: true
SpaceAfterCStyleCast: false SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements SpaceBeforeParens: ControlStatements
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1 SpacesBeforeTrailingComments: 1
SpacesInAngles: false SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false SpacesInParentheses: false
SpacesInSquareBrackets: false SpacesInSquareBrackets: false
Standard: Auto SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8 TabWidth: 8
UseCRLF: false
UseTab: Never UseTab: Never
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME
...

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
build build
.vscode/ipch/* .vscode/ipch/*
.kdev4 .kdev4
.cache

13
.gitmodules vendored
View File

@ -1,9 +1,6 @@
[submodule "3rdparty/nlohmann_json"] [submodule "subprojects/nlohmann_json"]
path = 3rdparty/nlohmann_json path = subprojects/nlohmann_json
url = https://github.com/nlohmann/json.git url = https://github.com/nlohmann/json.git
[submodule "3rdparty/singleapplication"] [submodule "subprojects/singleapplication"]
path = 3rdparty/singleapplication path = subprojects/singleapplication/singleapplication.git
url = https://github.com/itay-grudev/SingleApplication.git url = https://github.com/itay-grudev/SingleApplication.git
[submodule "3rdparty/csv-parser"]
path = 3rdparty/csv-parser
url = https://github.com/vincentlaucsb/csv-parser.git

3
.vscode/launch.json vendored
View File

@ -21,7 +21,8 @@
"text": "-enable-pretty-printing", "text": "-enable-pretty-printing",
"ignoreFailures": true "ignoreFailures": true
} }
] ],
"visualizerFile": "/home/brodbemn/.config/Code - OSS/User/workspaceStorage/d64ec049841ecb3d43e402bb3c167cb5/tonka3000.qtvsctools/qt.natvis.xml"
} }
] ]
} }

42
.vscode/settings.json vendored
View File

@ -65,9 +65,47 @@
"condition_variable": "cpp", "condition_variable": "cpp",
"mutex": "cpp", "mutex": "cpp",
"hash_map": "cpp", "hash_map": "cpp",
"future": "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"
}, },
"C_Cpp.clang_format_path": "/usr/bin/clang-format", "C_Cpp.clang_format_path": "/usr/bin/clang-format",
"cmake.configureOnOpen": true, "cmake.configureOnOpen": true,
"C_Cpp.configurationWarnings": "Disabled" "C_Cpp.configurationWarnings": "Disabled",
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/node_modules/*/**": true,
"**/.hg/store/**": true,
".flatpak/**": true,
"_build/**": true
}
} }

1
3rdparty/csv-parser vendored

@ -1 +0,0 @@
Subproject commit e4a899dcafcfa14e448348e9b3c8c06d7697dbf8

@ -1 +0,0 @@
Subproject commit 53c3eefa2cf790a7130fed3e13a3be35c2f2ace2

@ -1 +0,0 @@
Subproject commit e18babe5598d53a9e51ac9263d5b62ea2c3276e6

View File

@ -1,10 +1,10 @@
cmake_minimum_required(VERSION 3.8) cmake_minimum_required(VERSION 3.10)
project(kima2 VERSION 1.5.0) project(kima2 VERSION 1.8.0)
set(CMAKE_MODULE_PATH "${CMAKE_HOME_DIRECTORY}/cmake") set(CMAKE_MODULE_PATH "${CMAKE_HOME_DIRECTORY}/cmake")
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
#include(InstallRequiredSystemLibraries) #include(InstallRequiredSystemLibraries)
@ -17,6 +17,7 @@ else()
endif() endif()
configure_file(config.h.in ${PROJECT_BINARY_DIR}/config.h) 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_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
@ -28,7 +29,7 @@ if(KIMA2_USE_EXTERNAL_JSON)
find_package(nlohmann_json REQUIRED) find_package(nlohmann_json REQUIRED)
endif() endif()
add_subdirectory(3rdparty) add_subdirectory(subprojects)
add_subdirectory(src) add_subdirectory(src)
#if(NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE MATCHES Debug) #if(NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE MATCHES Debug)
@ -79,6 +80,8 @@ else(WIN32 AND NOT UNIX)
DESTINATION share/${PROJECT_NAME}) DESTINATION share/${PROJECT_NAME})
install(FILES "${CMAKE_SOURCE_DIR}/misc/kima2.svg" install(FILES "${CMAKE_SOURCE_DIR}/misc/kima2.svg"
DESTINATION share/icons/hicolor/scalable/apps) DESTINATION share/icons/hicolor/scalable/apps)
install(FILES de.rustysoft.kima2.metainfo.xml
DESTINATION share/metainfo)
endif (WIN32 AND NOT UNIX) endif (WIN32 AND NOT UNIX)
if( MINGW ) if( MINGW )
@ -87,18 +90,19 @@ if( MINGW )
set( CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS set( CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS
${MINGW_PATH}/libstdc++-6.dll ${MINGW_PATH}/libstdc++-6.dll
${MINGW_PATH}/libgcc_s_seh-1.dll ${MINGW_PATH}/libgcc_s_seh-1.dll
${MINGW_PATH}/Qt5Core.dll ${MINGW_PATH}/Qt6Core.dll
${MINGW_PATH}/Qt5Gui.dll ${MINGW_PATH}/Qt6Gui.dll
${MINGW_PATH}/Qt5Widgets.dll ${MINGW_PATH}/Qt6Widgets.dll
${MINGW_PATH}/Qt5PrintSupport.dll ${MINGW_PATH}/Qt6PrintSupport.dll
${MINGW_PATH}/Qt6Network.dll
${MINGW_PATH}/libwinpthread-1.dll ${MINGW_PATH}/libwinpthread-1.dll
${MINGW_PATH}/libsqlite3-0.dll ${MINGW_PATH}/libsqlite3-0.dll
${MINGW_PATH}/libusb-1.0.dll ${MINGW_PATH}/libusb-1.0.dll
${MINGW_PATH}/libxlnt.dll ${MINGW_PATH}/libicuuc73.dll
${MINGW_PATH}/libicuuc64.dll ${MINGW_PATH}/libicuin73.dll
${MINGW_PATH}/libicuin64.dll ${MINGW_PATH}/libicudt73.dll
${MINGW_PATH}/libicudt64.dll
${MINGW_PATH}/libpcre2-16-0.dll ${MINGW_PATH}/libpcre2-16-0.dll
${MINGW_PATH}/libpcre2-8-0.dll
${MINGW_PATH}/zlib1.dll ${MINGW_PATH}/zlib1.dll
${MINGW_PATH}/libharfbuzz-0.dll ${MINGW_PATH}/libharfbuzz-0.dll
${MINGW_PATH}/libpng16-16.dll ${MINGW_PATH}/libpng16-16.dll
@ -108,19 +112,26 @@ if( MINGW )
${MINGW_PATH}/libbz2-1.dll ${MINGW_PATH}/libbz2-1.dll
${MINGW_PATH}/libintl-8.dll ${MINGW_PATH}/libintl-8.dll
${MINGW_PATH}/libpcre-1.dll ${MINGW_PATH}/libpcre-1.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}/libiconv-2.dll) ${MINGW_PATH}/libiconv-2.dll)
install(FILES ${MINGW_PATH}/../share/qt5/plugins/platforms/qwindows.dll install(FILES ${MINGW_PATH}/../share/qt6/plugins/platforms/qwindows.dll
${MINGW_PATH}/../share/qt5/plugins/platforms/qminimal.dll ${MINGW_PATH}/../share/qt6/plugins/platforms/qminimal.dll
DESTINATION bin/platforms) DESTINATION bin/platforms)
install(FILES ${MINGW_PATH}/../share/qt5/plugins/printsupport/windowsprintersupport.dll #install(FILES ${MINGW_PATH}/../share/qt6/plugins/printsupport/windowsprintersupport.dll
DESTINATION bin/printsupport) # DESTINATION bin/printsupport)
install(FILES ${MINGW_PATH}/../share/qt5/translations/qtbase_de.qm install(FILES ${MINGW_PATH}/../share/qt6/translations/qtbase_de.qm
${MINGW_PATH}/../share/qt5/translations/qt_de.qm ${MINGW_PATH}/../share/qt6/translations/qt_de.qm
${MINGW_PATH}/../share/qt5/translations/qt_help_de.qm ${MINGW_PATH}/../share/qt6/translations/qt_help_de.qm
${MINGW_PATH}/../share/qt5/translations/qtmultimedia_de.qm ${MINGW_PATH}/../share/qt6/translations/qtmultimedia_de.qm
${MINGW_PATH}/../share/qt5/translations/qtquickcontrols_de.qm #${MINGW_PATH}/../share/qt6/translations/qtquickcontrols_de.qm
${MINGW_PATH}/../share/qt5/translations/qtscript_de.qm #${MINGW_PATH}/../share/qt6/translations/qtscript_de.qm
${MINGW_PATH}/../share/qt5/translations/qtxmlpatterns_de.qm #${MINGW_PATH}/../share/qt6/translations/qtxmlpatterns_de.qm
DESTINATION bin/translations) DESTINATION bin/translations)
endif( MINGW ) endif( MINGW )

View File

@ -1,4 +1,4 @@
Copyright © 2018 Martin Brodbeck Copyright © 2018-2024 Martin Brodbeck
Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der
zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis erteilt, zugehörigen Dokumentationen (die "Software") erhält, die Erlaubnis erteilt,

View File

@ -13,19 +13,17 @@ Verkaufsdaten nach dem Verkaufsende auszutauschen.
Ebenso können über einen ESC/POS-Drucker Quittungen ausgestellt werden. Ebenso können über einen ESC/POS-Drucker Quittungen ausgestellt werden.
## Installation ## Installation
Auf [rustysoft.de](https://www.rustysoft.de/?01_kima2) werden verschiedene Installationspakete (Arch Linux, Auf [rustysoft.de](https://www.rustysoft.de/software/kima2/) werden verschiedene Installationspakete (Arch Linux,
Ubuntu, Windows) angeboten. Bitte die Hinweise dort beachten. Ubuntu, Windows) angeboten. Bitte die Hinweise dort beachten.
### Selbst compilieren ### Selbst compilieren
KIMA2 benötigt folgende Libraries: KIMA2 benötigt folgende Libraries:
* Qt5 * Qt 6
* boost >= 1.62 * boost >= 1.80
* libusb-1.0 * libusb-1.0
* xlnt >= 1.3.0
* nlohmann-json (als 3rdparty submodule vorhanden) * nlohmann-json (als 3rdparty submodule vorhanden)
Da Features aus C++17 verwendet werden sowie std::filesystem, sollte als Compiler mindestens Da Features aus C++20 verwendet werden, sollte als Compiler mindestens GCC 12 verwendet werden.
GCC 8 verwendet werden.
Die Installationsschritte unter Linux sind wie folgt: Die Installationsschritte unter Linux sind wie folgt:
``` ```
@ -37,4 +35,4 @@ sudo make install
``` ```
Unter Windows muss vorab MinGW eingerichtet werden (z. B. MSYS2). Nach der Compilierung kann mit 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.

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>de.rustysoft.kima2</id>
<name>KIMA2</name>
<summary>A small cash point program for childrens stuff markets</summary>
<metadata_license>MIT</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<releases>
<release version="@PROJECT_VERSION@" type="stable" date="2024-01-23" />
</releases>
<description>
<p>
A small cash point program for children's stuff markets. German language only.
</p>
</description>
<launchable type="desktop-id">de.rustysoft.kima2.desktop</launchable>
<screenshots>
<screenshot type="default">
<image>https://rustysoft.de/images/software/kima2/screenshot.png</image>
</screenshot>
</screenshots>
</component>

Binary file not shown.

Binary file not shown.

33
meson.build Normal file
View File

@ -0,0 +1,33 @@
project('kima2', 'cpp', default_options : ['cpp_std=c++20'], version : '1.8.0')
conf_data = configuration_data()
conf_data.set('PROJECT_VERSION', '"' + meson.project_version() + '"')
configure_file(output : 'config.h',
configuration : conf_data)
configuration_inc = include_directories('.')
#csv = cmake.subproject('csv-parser')
#csv_lib = csv.dependency('csv')
nlohmann_lib = dependency('nlohmann_json', version : '>=3.5.0', required : false)
if not nlohmann_lib.found()
nlohmann_inc = include_directories('subprojects/nlohmann_json/single_include')
nlohmann_lib = declare_dependency(include_directories : nlohmann_inc)
endif
csv_inc = include_directories('subprojects/csv-parser/single_include')
csv_dep = declare_dependency(include_directories : csv_inc)
singleapp_proj = subproject('singleapplication')
singleapp_lib = singleapp_proj.get_variable('singleapp_lib')
singleapp_dep = singleapp_proj.get_variable('singleapp_dep')
subdir('src')
if build_machine.system() == 'linux'
install_data('misc/kima2.svg', install_dir : get_option('datadir') / 'icons/hicolor/scalable/apps')
install_data('misc/kima2.desktop', install_dir : get_option('datadir') / 'applications')
install_data('manual/Benutzerhandbuch.pdf', install_dir : get_option('datadir') / 'kima2')
endif

View File

@ -1,23 +1,29 @@
# Maintainer: Martin Brodbeck <martin at brodbeck-online dot de> # Maintainer: Martin Brodbeck <martin at brodbeck-online dot de>
pkgname=kima2 pkgname=kima2
pkgver=1.1.0 pkgver=1.7.1
pkgrel=1 pkgrel=1
pkgdesc="A small cash point program for children's things markets (German only)" pkgdesc="A small cash point program for children's things markets (German only)"
arch=('i686' 'x86_64') arch=('i686' 'x86_64')
url="http://www.rustysoft.de/?01_kima2" url="http://www.rustysoft.de/software/kima2"
license=('custom') license=('custom')
depends=('glibc' 'libusb' 'qt5-base' 'sqlite3' 'xlnt') depends=('glibc' 'libusb' 'qt6-base' 'sqlite3')
makedepends=('boost>=1.62') makedepends=('boost>=1.62')
source=($pkgname-$pkgver.tar.gz) source=(git+https://git.rustysoft.de/martin/kima2)
md5sums=('') sha256sums=('SKIP')
build() { build() {
if [ ! -d $pkgname/build ]; then cd $pkgname
mkdir $pkgname/build
fi
cd $pkgname/build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DKIMA2_USE_EXTERNAL_JSON=ON .. git checkout v$pkgver
git submodule init
git submodule update
if [ -d build ]; then
rm -rf build
fi
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DKIMA2_USE_EXTERNAL_JSON=OFF ..
make make
} }

View File

@ -3,8 +3,8 @@ Type=Application
Name=KIMA2 Name=KIMA2
GenericName=Cash Point Program GenericName=Cash Point Program
GenericName[de]=Kassenprogramm GenericName[de]=Kassenprogramm
Comment=A small cash point program Comment=A small cash point program for children's stuff markets
Comment[de]=Ein kleines Kassenprogramm Comment[de]=Ein kleines Kassenprogramm für Kindersachenmärkte
Exec=kima2 Exec=kima2
Icon=kima2 Icon=kima2
Categories=Office; Categories=Office;

43
misc/kima2.spec Normal file
View File

@ -0,0 +1,43 @@
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 <infor@rustysoft.de> - dev builds
-

View File

@ -1,14 +1,11 @@
set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_LIBS ON)
find_package(Boost 1.62 COMPONENTS date_time REQUIRED) find_package(Boost 1.78 REQUIRED)
find_package(SQLite3 REQUIRED) find_package(SQLite3 REQUIRED)
if (MINGW) # Because csv-parser needs threads:
find_package(XLNT REQUIRED STATIC)
else (MINGW) find_package(fmt)
find_package(PkgConfig REQUIRED)
pkg_check_modules(XLNT REQUIRED xlnt>=1.3)
endif (MINGW)
set(CORE_SOURCES set(CORE_SOURCES
database.cpp database.cpp
@ -19,7 +16,6 @@ set(CORE_SOURCES
article.cpp article.cpp
sale.cpp sale.cpp
marketplace.cpp marketplace.cpp
excelreader.cpp
csvreader.cpp csvreader.cpp
jsonutil.cpp jsonutil.cpp
utils.cpp utils.cpp
@ -27,13 +23,12 @@ set(CORE_SOURCES
add_library(core STATIC ${CORE_SOURCES}) add_library(core STATIC ${CORE_SOURCES})
target_include_directories(core PRIVATE ${PROJECT_SOURCE_DIR}/3rdparty/csv-parser/include) #target_include_directories(core PRIVATE ${PROJECT_SOURCE_DIR}/subprojects/csv-parser/single_include)
if (WIN32) if (WIN32)
target_link_libraries(core PRIVATE printer Boost::boost Boost::date_time sqlite3 nlohmann_json::nlohmann_json ${XLNT_LIBRARY} csv) target_link_libraries(core PRIVATE sqlite3 nlohmann_json::nlohmann_json fmt::fmt)
target_link_libraries(core PRIVATE bcrypt) target_link_libraries(core PRIVATE bcrypt)
else() else()
target_link_libraries(core PRIVATE printer Boost::boost Boost::date_time sqlite3 nlohmann_json::nlohmann_json ${XLNT_LIBRARIES} csv) target_link_libraries(core PRIVATE sqlite3 nlohmann_json::nlohmann_json fmt::fmt)
endif() endif()
#target_include_directories(core PRIVATE ${PROJECT_SOURCE_DIR}/3rdparty/csv-parser) target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/..)
target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -1,37 +1,38 @@
#include "article.h" #include "article.h"
#include "seller.h"
#include "utils.h" #include "utils.h"
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
Article::Article(int price) : price_(price) {} Article::Article(int price) : m_price(price) {}
void Article::setArticleNo(int articleNo) { articleNo_ = articleNo; } void Article::setArticleNo(int articleNo) { m_articleNo = articleNo; }
void Article::setPrice(int price) { price_ = price; } void Article::setPrice(int price) { m_price = price; }
void Article::setDescription(const std::string& description) { description_ = description; } void Article::setDescription(const std::string &description) { m_description = description; }
void Article::setSale(Sale* salePtr) { salePtr_ = salePtr; } void Article::setSale(Sale *salePtr) { m_salePtr = salePtr; }
void Article::setSeller(Seller* sellerPtr) { sellerPtr_ = sellerPtr; } void Article::setSeller(Seller *sellerPtr) { m_sellerPtr = sellerPtr; }
bool Article::isSold() { return salePtr_ ? true : false; } bool Article::isSold() { return m_salePtr ? true : false; }
std::string Article::getDescription() { return description_; } std::string Article::getDescription() { return m_description; }
Seller* Article::getSeller() { return sellerPtr_; } Seller *Article::getSeller() { return m_sellerPtr; }
Sale* Article::getSale() { return salePtr_; } Sale *Article::getSale() { return m_salePtr; }
int Article::getPrice() const { return price_; } int Article::getPrice() const { return m_price; }
std::string Article::getPriceAsString() const { return formatCentAsEuroString(price_); } std::string Article::getPriceAsString() const { return formatCentAsEuroString(m_price); }
int Article::getArticleNo() const { return articleNo_; } int Article::getArticleNo() const { return m_articleNo; }
std::string Article::getCompleteArticleNo() const std::string Article::getCompleteArticleNo() const
{ {
std::stringstream artNoStream; std::stringstream artNoStream;
artNoStream << sourceNo_ << "K" << std::setfill('0') << std::setw(5) << articleNo_; artNoStream << m_sourceNo << "K" << std::setfill('0') << std::setw(5) << m_articleNo;
return artNoStream.str(); return artNoStream.str();
} }

View File

@ -2,8 +2,6 @@
#define ARTICLE_H #define ARTICLE_H
#include "entityuuid.h" #include "entityuuid.h"
//#include "sale.h"
//#include "seller.h"
#include <memory> #include <memory>
#include <string> #include <string>
@ -13,33 +11,33 @@ class Sale;
class Article : public EntityUuid class Article : public EntityUuid
{ {
public: public:
Article() = default; Article() = default;
Article(int price); Article(int price);
Article(const Article&) = delete; Article(const Article &) = delete;
virtual ~Article() = default; virtual ~Article() = default;
void setArticleNo(int articleNo); void setArticleNo(int articleNo);
void setPrice(int price); void setPrice(int price);
void setDescription(const std::string& description); void setDescription(const std::string &description);
bool isSold(); bool isSold();
void setSale(Sale* salePtr); void setSale(Sale *salePtr);
void setSeller(Seller* sellerPtr); void setSeller(Seller *sellerPtr);
int getArticleNo() const; int getArticleNo() const;
std::string getCompleteArticleNo() const; std::string getCompleteArticleNo() const;
std::string getDescription(); std::string getDescription();
Seller* getSeller(); Seller *getSeller();
Sale* getSale(); Sale *getSale();
int getPrice() const; int getPrice() const;
std::string getPriceAsString() const; std::string getPriceAsString() const;
private: private:
Seller* sellerPtr_{}; Seller *m_sellerPtr{};
Sale* salePtr_{}; Sale *m_salePtr{};
int articleNo_{}; int m_articleNo{};
int price_{}; int m_price{};
std::string description_{}; std::string m_description{};
}; };
#endif #endif

View File

@ -2,58 +2,78 @@
#include "utils.h" #include "utils.h"
#include <fstream> #include <fstream>
#include <csv.hpp>
// #include <csv.hpp>
#include <boost/algorithm/string.hpp>
#ifdef DELETE
#undef DELETE
#endif
namespace fs = std::filesystem; namespace fs = std::filesystem;
std::size_t CsvReader::readSellersFromFile(const fs::path& filePath, Marketplace* market) std::size_t CsvReader::readSellersFromFile(const fs::path &filePath, Marketplace *market)
{ {
csv::CSVFormat format;
format.delimiter(';');
#if defined(_WIN64) || defined(_WIN32) #if defined(_WIN64) || defined(_WIN32)
// Windows: Somhow this is necessary in order to open file names with umlauts // Windows: Somhow this is necessary in order to open file names with umlauts
auto wide = filePath.wstring(); auto wide = filePath.wstring();
std::string fileName(wide.begin(), wide.end()); std::string fileName(wide.begin(), wide.end());
csv::CSVReader csvReader(fileName, format); std::ifstream infile(fileName);
#else #else
csv::CSVReader csvReader(filePath.string(), format); // csv::CSVReader csvReader(filePath.string(), format);
std::ifstream infile(filePath.string());
#endif #endif
for (auto& seller : market->getSellers()) { for (auto &seller : market->getSellers()) {
seller->setState(Seller::State::DELETE); seller->setState(Seller::State::DELETE);
} }
market->storeToDb(true); market->storeToDb(true);
int rowCount{};
for (csv::CSVRow &row : csvReader) {
if (!row[0].is_int()) {
++rowCount;
continue;
}
if (row[2].get<std::string>().empty() && row[3].get<std::string>().empty()) { std::string line;
++rowCount;
continue; while (getline(infile, line)) {
} std::vector<std::string> strs;
boost::split(strs, line, boost::is_any_of(";"));
auto seller = std::make_unique<Seller>(); auto seller = std::make_unique<Seller>();
seller->setSellerNo(row[0].get<int>());
if (row[1].is_int()) { try {
seller->setNumArticlesOffered(row[1].get<int>()); int sellerNo = std::stoi(strs[0]);
} else { seller->setSellerNo(sellerNo);
seller->setNumArticlesOffered(0); } catch (std::invalid_argument const &ex) {
continue;
} }
std::string firstName = row[2].get<std::string>();
seller->setFirstName(trim(firstName)); if (isNumber(strs[1]))
std::string lastName = row[3].get<std::string>(); seller->setNumArticlesOffered(std::stoi(strs[1]));
seller->setLastName(trim(lastName)); 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)); market->getSellers().push_back(std::move(seller));
rowCount++;
} }
// Add one additional seller "RESERVE RESERVE"
auto seller = std::make_unique<Seller>();
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 // If there was no special seller "Sonderkonto" in import data, then create one
auto specialSeller = market->findSellerWithSellerNo(0); auto specialSeller = market->findSellerWithSellerNo(0);
if (!specialSeller) { if (!specialSeller) {

View File

@ -11,9 +11,9 @@
class CsvReader class CsvReader
{ {
public: public:
static std::size_t readSellersFromFile(const std::filesystem::path& filePath, static std::size_t readSellersFromFile(const std::filesystem::path &filePath,
Marketplace* market); Marketplace *market);
}; };
#endif #endif

View File

@ -1,13 +1,13 @@
#include "database.h" #include "database.h"
#include <chrono>
#include <filesystem> #include <filesystem>
#include <fmt/chrono.h>
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
#include "boost/date_time/posix_time/posix_time.hpp" Database::Database(const std::string &dbname)
Database::Database(const std::string& dbname)
{ {
dbname_ = dbname; dbname_ = dbname;
init(); init();
@ -28,7 +28,7 @@ Database::Database()
if (!fs::exists(dbpath)) { if (!fs::exists(dbpath)) {
try { try {
fs::create_directories(dbpath); fs::create_directories(dbpath);
} catch (fs::filesystem_error& err) { } catch (fs::filesystem_error &err) {
throw err; throw err;
} }
} }
@ -45,8 +45,11 @@ void Database::newDb()
fs::path sourcePath = dbname_; fs::path sourcePath = dbname_;
fs::path destPath = sourcePath.parent_path() / sourcePath.stem(); fs::path destPath = sourcePath.parent_path() / sourcePath.stem();
destPath += std::string("_") +=
boost::posix_time::to_iso_string(boost::posix_time::second_clock::local_time()) += ".db"; auto chronoTime = std::chrono::system_clock::now();
std::string timeString = fmt::format("{0:%FT%H-%M-%S}", chronoTime);
destPath += std::string("_") += timeString += ".db";
fs::copy_file(sourcePath, destPath, fs::copy_options::overwrite_existing); fs::copy_file(sourcePath, destPath, fs::copy_options::overwrite_existing);
@ -57,13 +60,13 @@ void Database::newDb()
Database::~Database() { sqlite3_close(db_); } 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); const int errCode = sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &errMsg);
if (errCode) { if (errCode) {
std::string errMsgString(errMsg); // Make a C++ string of the errMsg, so that we can call 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); sqlite3_free(errMsg);
throw std::runtime_error("Error in SQL execution: " + errMsgString); throw std::runtime_error("Error in SQL execution: " + errMsgString);
} }
@ -120,7 +123,7 @@ void Database::createNew()
sqlStrings.push_back(sqlInitialEntries); sqlStrings.push_back(sqlInitialEntries);
beginTransaction(); beginTransaction();
for (const auto& sql : sqlStrings) { for (const auto &sql : sqlStrings) {
exec(sql); exec(sql);
} }
endTransaction(); endTransaction();
@ -173,7 +176,7 @@ void Database::init()
int Database::getVersion() int Database::getVersion()
{ {
int retCode{}; int retCode{};
sqlite3_stmt* stmt; sqlite3_stmt *stmt;
// Check if there's already a kima2 table available. // Check if there's already a kima2 table available.
// If not, return version == 0. // If not, return version == 0.
@ -220,15 +223,15 @@ void Database::beginTransaction() { exec("BEGIN TRANSACTION"); }
void Database::endTransaction() { exec("END TRANSACTION"); } void Database::endTransaction() { exec("END TRANSACTION"); }
unsigned int Database::storeSellers(std::vector<std::unique_ptr<Seller>>& sellers, bool onlyDelete) unsigned int Database::storeSellers(std::vector<std::unique_ptr<Seller>> &sellers, bool onlyDelete)
{ {
int retCode{}; int retCode{};
int count{}; int count{};
sqlite3_stmt* stmt; sqlite3_stmt *stmt;
beginTransaction(); beginTransaction();
for (auto& seller : sellers) { for (auto &seller : sellers) {
if (seller->getState() == Seller::State::NEW && !onlyDelete) { if (seller->getState() == Seller::State::NEW && !onlyDelete) {
retCode = sqlite3_prepare_v2( retCode = sqlite3_prepare_v2(
db_, db_,
@ -323,12 +326,12 @@ unsigned int Database::storeSellers(std::vector<std::unique_ptr<Seller>>& seller
// Everything went fine, so we can now update our objects // Everything went fine, so we can now update our objects
sellers.erase(std::remove_if(sellers.begin(), sellers.end(), sellers.erase(std::remove_if(sellers.begin(), sellers.end(),
[](const std::unique_ptr<Seller>& seller) { [](const std::unique_ptr<Seller> &seller) {
return (seller->getState() == Seller::State::DELETE); return (seller->getState() == Seller::State::DELETE);
}), }),
sellers.end()); sellers.end());
for (auto& seller : sellers) { for (auto &seller : sellers) {
seller->cleanupArticles(); seller->cleanupArticles();
seller->setState(Seller::State::OK); seller->setState(Seller::State::OK);
} }
@ -336,13 +339,13 @@ unsigned int Database::storeSellers(std::vector<std::unique_ptr<Seller>>& seller
return count; return count;
} }
unsigned int Database::storeArticles(std::vector<Article*> articles) unsigned int Database::storeArticles(std::vector<Article *> articles)
{ {
int retCode{}; int retCode{};
int count{}; int count{};
sqlite3_stmt* stmt; sqlite3_stmt *stmt;
for (auto& article : articles) { for (auto &article : articles) {
if (article->getState() == Article::State::NEW) { if (article->getState() == Article::State::NEW) {
retCode = sqlite3_prepare_v2( retCode = sqlite3_prepare_v2(
db_, db_,
@ -441,18 +444,18 @@ unsigned int Database::storeArticles(std::vector<Article*> articles)
return count; return count;
} }
unsigned int Database::storeSales(std::vector<std::unique_ptr<Sale>>& sales) unsigned int Database::storeSales(std::vector<std::unique_ptr<Sale>> &sales)
{ {
int retCode{}; int retCode{};
int count{}; int count{};
sqlite3_stmt* stmt; sqlite3_stmt *stmt;
if (sales.size() == 0) if (sales.size() == 0)
return 0; return 0;
beginTransaction(); beginTransaction();
for (auto& sale : sales) { for (auto &sale : sales) {
if (sale->getState() == Sale::State::NEW) { if (sale->getState() == Sale::State::NEW) {
retCode = sqlite3_prepare_v2(db_, retCode = sqlite3_prepare_v2(db_,
"INSERT INTO sales" "INSERT INTO sales"
@ -482,7 +485,7 @@ unsigned int Database::storeSales(std::vector<std::unique_ptr<Sale>>& sales)
++count; ++count;
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
for (const auto& article : sale->getArticles()) { for (const auto &article : sale->getArticles()) {
retCode = sqlite3_prepare_v2(db_, retCode = sqlite3_prepare_v2(db_,
"INSERT INTO sales_items" "INSERT INTO sales_items"
" (sale_id, article_id)" " (sale_id, article_id)"
@ -535,21 +538,21 @@ unsigned int Database::storeSales(std::vector<std::unique_ptr<Sale>>& sales)
// Everything went fine, so we can now update our objects // Everything went fine, so we can now update our objects
sales.erase( sales.erase(
std::remove_if(sales.begin(), sales.end(), 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()); sales.end());
for (auto& sale : sales) { for (auto &sale : sales) {
sale->setState(Sale::State::OK); sale->setState(Sale::State::OK);
} }
return count; return count;
} }
unsigned int Database::loadSellers(std::vector<std::unique_ptr<Seller>>& sellers) unsigned int Database::loadSellers(std::vector<std::unique_ptr<Seller>> &sellers)
{ {
int retCode{}; int retCode{};
int count{}; int count{};
sqlite3_stmt* stmt; sqlite3_stmt *stmt;
retCode = sqlite3_prepare_v2(db_, retCode = sqlite3_prepare_v2(db_,
"SELECT seller_no, first_name, last_name, " "SELECT seller_no, first_name, last_name, "
@ -566,8 +569,8 @@ unsigned int Database::loadSellers(std::vector<std::unique_ptr<Seller>>& sellers
++count; ++count;
auto seller = std::make_unique<Seller>(); auto seller = std::make_unique<Seller>();
seller->setSellerNo(sqlite3_column_int(stmt, 0)); seller->setSellerNo(sqlite3_column_int(stmt, 0));
seller->setFirstName(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1))); seller->setFirstName(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)));
seller->setLastName(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2))); seller->setLastName(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 2)));
seller->setNumArticlesOffered(sqlite3_column_int(stmt, 3)); seller->setNumArticlesOffered(sqlite3_column_int(stmt, 3));
seller->setState(Seller::State::OK); seller->setState(Seller::State::OK);
sellers.push_back(std::move(seller)); sellers.push_back(std::move(seller));
@ -577,7 +580,7 @@ unsigned int Database::loadSellers(std::vector<std::unique_ptr<Seller>>& sellers
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
for (auto& seller : sellers) { for (auto &seller : sellers) {
retCode = sqlite3_prepare_v2(db_, retCode = sqlite3_prepare_v2(db_,
"SELECT id, source_no, article_no, description, price" "SELECT id, source_no, article_no, description, price"
" FROM articles" " FROM articles"
@ -594,11 +597,12 @@ unsigned int Database::loadSellers(std::vector<std::unique_ptr<Seller>>& sellers
while (retCode != SQLITE_DONE) { while (retCode != SQLITE_DONE) {
++count; ++count;
auto article = std::make_unique<Article>(); auto article = std::make_unique<Article>();
article->setUuidFromString(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))); article->setUuidFromString(
reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)));
article->setSeller(seller.get()); article->setSeller(seller.get());
article->setSourceNo(sqlite3_column_int(stmt, 1)); article->setSourceNo(sqlite3_column_int(stmt, 1));
article->setArticleNo(sqlite3_column_int(stmt, 2)); article->setArticleNo(sqlite3_column_int(stmt, 2));
article->setDescription(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3))); article->setDescription(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 3)));
article->setPrice(sqlite3_column_int(stmt, 4)); article->setPrice(sqlite3_column_int(stmt, 4));
article->setState(Article::State::OK); article->setState(Article::State::OK);
@ -613,12 +617,12 @@ unsigned int Database::loadSellers(std::vector<std::unique_ptr<Seller>>& sellers
return count; return count;
} }
unsigned int Database::loadSales(std::vector<std::unique_ptr<Sale>>& sales, unsigned int Database::loadSales(std::vector<std::unique_ptr<Sale>> &sales,
std::vector<std::unique_ptr<Seller>>& sellers) std::vector<std::unique_ptr<Seller>> &sellers)
{ {
int retCode{}; int retCode{};
int count{}; int count{};
sqlite3_stmt* stmt; sqlite3_stmt *stmt;
retCode = sqlite3_prepare_v2(db_, retCode = sqlite3_prepare_v2(db_,
"SELECT id, source_no, sold_at" "SELECT id, source_no, sold_at"
@ -631,13 +635,13 @@ unsigned int Database::loadSales(std::vector<std::unique_ptr<Sale>>& sales,
sales.clear(); sales.clear();
std::map<std::string, Sale*> saleMap; std::map<std::string, Sale *> saleMap;
while (retCode != SQLITE_DONE) { while (retCode != SQLITE_DONE) {
++count; ++count;
auto sale = std::make_unique<Sale>(); auto sale = std::make_unique<Sale>();
sale->setUuidFromString(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))); sale->setUuidFromString(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)));
sale->setSourceNo(sqlite3_column_int(stmt, 1)); sale->setSourceNo(sqlite3_column_int(stmt, 1));
sale->setTimestamp(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 2))); sale->setTimestamp(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 2)));
sale->setState(Sale::State::OK); sale->setState(Sale::State::OK);
saleMap.insert(std::make_pair(sale->getUuidAsString(), sale.get())); saleMap.insert(std::make_pair(sale->getUuidAsString(), sale.get()));
sales.push_back(std::move(sale)); sales.push_back(std::move(sale));
@ -647,8 +651,8 @@ unsigned int Database::loadSales(std::vector<std::unique_ptr<Sale>>& sales,
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
std::map<std::string, Article*> artMap; std::map<std::string, Article *> artMap;
for (const auto& seller : sellers) { for (const auto &seller : sellers) {
for (const auto article : seller->getArticles(false)) { for (const auto article : seller->getArticles(false)) {
artMap.insert(std::make_pair(article->getUuidAsString(), article)); artMap.insert(std::make_pair(article->getUuidAsString(), article));
} }
@ -664,8 +668,8 @@ unsigned int Database::loadSales(std::vector<std::unique_ptr<Sale>>& sales,
retCode = sqlite3_step(stmt); retCode = sqlite3_step(stmt);
while (retCode != SQLITE_DONE) { while (retCode != SQLITE_DONE) {
saleMap[reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0))]->addArticle( saleMap[reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0))]->addArticle(
artMap[reinterpret_cast<const char*>(sqlite3_column_text(stmt, 1))]); artMap[reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1))]);
retCode = sqlite3_step(stmt); retCode = sqlite3_step(stmt);
} }
@ -678,7 +682,7 @@ unsigned int Database::loadSales(std::vector<std::unique_ptr<Sale>>& sales,
void Database::updateCashPointNo(int oldCashPointNo, int newCashPointNo) void Database::updateCashPointNo(int oldCashPointNo, int newCashPointNo)
{ {
int retCode{}; int retCode{};
sqlite3_stmt* stmt; sqlite3_stmt *stmt;
// Check if the new no ist already in use // Check if the new no ist already in use
retCode = sqlite3_prepare_v2(db_, "SELECT COUNT() FROM articles WHERE source_no = :source_no", retCode = sqlite3_prepare_v2(db_, "SELECT COUNT() FROM articles WHERE source_no = :source_no",

View File

@ -10,33 +10,33 @@
class Database class Database
{ {
public: public:
enum class InitResult {OK, OUTDATED_REPLACED}; enum class InitResult { OK, OUTDATED_REPLACED };
explicit Database(const std::string& dbname); explicit Database(const std::string &dbname);
Database(); Database();
~Database(); ~Database();
Database(const Database&) = delete; Database(const Database &) = delete;
Database& operator=(const Database&) = delete; Database &operator=(const Database &) = delete;
void exec(const std::string& sql); void exec(const std::string &sql);
unsigned int storeSellers(std::vector<std::unique_ptr<Seller>>& sellers, unsigned int storeSellers(std::vector<std::unique_ptr<Seller>> &sellers,
bool onlyDelete = false); bool onlyDelete = false);
unsigned int loadSellers(std::vector<std::unique_ptr<Seller>>& sellers); unsigned int loadSellers(std::vector<std::unique_ptr<Seller>> &sellers);
unsigned int storeSales(std::vector<std::unique_ptr<Sale>>& sales); unsigned int storeSales(std::vector<std::unique_ptr<Sale>> &sales);
unsigned int loadSales(std::vector<std::unique_ptr<Sale>>& sales, unsigned int loadSales(std::vector<std::unique_ptr<Sale>> &sales,
std::vector<std::unique_ptr<Seller>>& sellers); std::vector<std::unique_ptr<Seller>> &sellers);
void updateCashPointNo(int oldCashPointNo, int newCashPointNo); void updateCashPointNo(int oldCashPointNo, int newCashPointNo);
void newDb(); void newDb();
InitResult getInitResult() {return initResult_;} InitResult getInitResult() { return initResult_; }
private: private:
sqlite3* db_{nullptr}; sqlite3 *db_{nullptr};
std::string dbname_; std::string dbname_;
void init(); void init();
void beginTransaction(); void beginTransaction();
void endTransaction(); void endTransaction();
void createNew(); void createNew();
int getVersion(); int getVersion();
unsigned int storeArticles(std::vector<Article*> articles); unsigned int storeArticles(std::vector<Article *> articles);
void updateDbToVer2(); void updateDbToVer2();
void updateDbToVer3(); void updateDbToVer3();
InitResult initResult_{InitResult::OK}; InitResult initResult_{InitResult::OK};

View File

@ -1,6 +1,3 @@
#include "entity.h" #include "entity.h"
Entity::State Entity::getState() const Entity::State Entity::getState() const { return m_state; }
{
return state_;
}

View File

@ -3,14 +3,14 @@
class Entity class Entity
{ {
public: public:
enum class State { NEW, UPDATE, DELETE, OK }; enum class State { NEW, UPDATE, DELETE, OK };
virtual ~Entity() = default; virtual ~Entity() = default;
void setState(State state) { state_ = state; } void setState(State state) { m_state = state; }
virtual State getState() const; virtual State getState() const;
private: private:
State state_{State::NEW}; State m_state{State::NEW};
}; };
#endif // ENTITY_H #endif // ENTITY_H

View File

@ -1,5 +1,5 @@
#include "entityint.h" #include "entityint.h"
EntityInt::EntityInt(int id) { id_ = id; } EntityInt::EntityInt(int id) { m_id = id; }
void EntityInt::setId(int id) { id_ = id; } void EntityInt::setId(int id) { m_id = id; }

View File

@ -5,15 +5,15 @@
class EntityInt : public Entity class EntityInt : public Entity
{ {
public: public:
EntityInt() = default; EntityInt() = default;
virtual ~EntityInt() = default; virtual ~EntityInt() = default;
EntityInt(int id); EntityInt(int id);
void setId(int id); void setId(int id);
int getId() const { return id_; }; int getId() const { return m_id; };
protected: protected:
int id_{}; int m_id{};
}; };
#endif // ENTITY_INT_H #endif // ENTITY_INT_H

View File

@ -8,15 +8,15 @@
void EntityUuid::createUuid() void EntityUuid::createUuid()
{ {
static boost::uuids::random_generator generator{}; static boost::uuids::random_generator generator{};
uuid_ = generator(); m_uuid = generator();
} }
void EntityUuid::setUuidFromString(const std::string& uuidString) void EntityUuid::setUuidFromString(const std::string &uuidString)
{ {
boost::uuids::string_generator generator{}; boost::uuids::string_generator generator{};
uuid_ = generator(uuidString); m_uuid = generator(uuidString);
} }
void EntityUuid::setSourceNo(int sourceNo) { sourceNo_ = sourceNo; } void EntityUuid::setSourceNo(int sourceNo) { m_sourceNo = sourceNo; }
int EntityUuid::getSourceNo() const { return sourceNo_; } int EntityUuid::getSourceNo() const { return m_sourceNo; }

View File

@ -10,23 +10,23 @@
class EntityUuid : public Entity class EntityUuid : public Entity
{ {
public: public:
EntityUuid() = default; EntityUuid() = default;
virtual ~EntityUuid() = default; virtual ~EntityUuid() = default;
void createUuid(); void createUuid();
void setUuidFromString(const std::string& uuidString); void setUuidFromString(const std::string &uuidString);
void setSourceNo(int sourceNo); void setSourceNo(int sourceNo);
const boost::uuids::uuid& getUuid() const { return uuid_; }; const boost::uuids::uuid &getUuid() const { return m_uuid; };
std::string getUuidAsString() const { return boost::uuids::to_string(uuid_); } std::string getUuidAsString() const { return boost::uuids::to_string(m_uuid); }
virtual int getSourceNo() const; virtual int getSourceNo() const;
protected: protected:
int sourceNo_{}; int m_sourceNo{};
private: private:
boost::uuids::uuid uuid_{}; boost::uuids::uuid m_uuid{};
}; };
#endif // ENTITY_UUID_H #endif // ENTITY_UUID_H

View File

@ -1,67 +0,0 @@
#include "excelreader.h"
#include "utils.h"
#include <fstream>
#include <xlnt/xlnt.hpp>
namespace fs = std::filesystem;
std::size_t 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 Excel 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 = 504;
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<std::string>().empty() && row[3].value<std::string>().empty()) {
++rowCount;
continue;
}
auto seller = std::make_unique<Seller>();
seller->setSellerNo(row[0].value<int>());
seller->setNumArticlesOffered(row[1].value<int>());
std::string firstName = row[2].value<std::string>();
seller->setFirstName(trim(firstName));
std::string lastName = row[3].value<std::string>();
seller->setLastName(trim(lastName));
market->getSellers().push_back(std::move(seller));
rowCount++;
}
// 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>();
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
}

View File

@ -1,19 +0,0 @@
#ifndef EXCEL_READER_H
#define EXCEL_READER_H
#include "marketplace.h"
#include "seller.h"
#include <filesystem>
#include <memory>
#include <string>
#include <vector>
class ExcelReader
{
public:
static std::size_t readSellersFromFile(const std::filesystem::path& filePath,
Marketplace* market);
};
#endif

View File

@ -5,15 +5,14 @@
#include <fstream> #include <fstream>
namespace fs = std::filesystem;
using json = nlohmann::json; 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; json root;
std::ofstream file(filePath); std::ofstream file(filePath);
for (const auto& seller : market->getSellers()) { for (const auto &seller : market->getSellers()) {
json newEntry; json newEntry;
newEntry["seller_no"] = seller->getSellerNo(); newEntry["seller_no"] = seller->getSellerNo();
newEntry["last_name"] = seller->getLastName(); newEntry["last_name"] = seller->getLastName();
@ -25,9 +24,9 @@ void JsonUtil::exportSellers(const std::filesystem::path& filePath, Marketplace*
file << root.dump(4) << std::endl; file << root.dump(4) << std::endl;
} }
std::size_t JsonUtil::importSellers(const std::filesystem::path& filePath, Marketplace* market) std::size_t JsonUtil::importSellers(const std::filesystem::path &filePath, Marketplace *market)
{ {
for (auto& seller : market->getSellers()) { for (auto &seller : market->getSellers()) {
seller->setState(Seller::State::DELETE); seller->setState(Seller::State::DELETE);
} }
market->storeToDb(true); market->storeToDb(true);
@ -61,7 +60,7 @@ std::size_t JsonUtil::importSellers(const std::filesystem::path& filePath, Marke
return market->getSellers().size() - 1; // minus 1 because we don't count the "special" seller return market->getSellers().size() - 1; // minus 1 because we don't count the "special" seller
} }
void JsonUtil::exportSales(const std::filesystem::path& filePath, Marketplace* market, void JsonUtil::exportSales(const std::filesystem::path &filePath, Marketplace *market,
int cashPointNo) int cashPointNo)
{ {
json root; json root;
@ -69,7 +68,7 @@ void JsonUtil::exportSales(const std::filesystem::path& filePath, Marketplace* m
root["source_no"] = cashPointNo; root["source_no"] = cashPointNo;
for (const auto& sale : market->getSales()) { for (const auto &sale : market->getSales()) {
if (sale->getSourceNo() != cashPointNo) if (sale->getSourceNo() != cashPointNo)
continue; continue;
@ -77,7 +76,7 @@ void JsonUtil::exportSales(const std::filesystem::path& filePath, Marketplace* m
newSale["uuid"] = sale->getUuidAsString(); newSale["uuid"] = sale->getUuidAsString();
newSale["timestamp"] = sale->getTimestamp(); newSale["timestamp"] = sale->getTimestamp();
for (const auto& article : sale->getArticles()) { for (const auto &article : sale->getArticles()) {
json newArticle; json newArticle;
newArticle["uuid"] = article->getUuidAsString(); newArticle["uuid"] = article->getUuidAsString();
newArticle["seller_no"] = article->getSeller()->getSellerNo(); newArticle["seller_no"] = article->getSeller()->getSellerNo();
@ -95,7 +94,7 @@ void JsonUtil::exportSales(const std::filesystem::path& filePath, Marketplace* m
file << root.dump(4) << std::endl; file << root.dump(4) << std::endl;
} }
void JsonUtil::importSales(const std::filesystem::path& filePath, Marketplace* market, void JsonUtil::importSales(const std::filesystem::path &filePath, Marketplace *market,
int cashPointNo) int cashPointNo)
{ {
std::ifstream file(filePath); std::ifstream file(filePath);
@ -103,19 +102,21 @@ void JsonUtil::importSales(const std::filesystem::path& filePath, Marketplace* m
int source_no = jsonValues["source_no"]; int source_no = jsonValues["source_no"];
if (source_no == cashPointNo) { if (source_no == cashPointNo) {
throw std::runtime_error("Die Kassen-Nr. der zu imporierenden Daten wird von dieser Kasse " std::string ret = "Die Kassen-Nr. ";
"hier bereits verwendet."); ret += std::to_string(source_no);
ret += " der zu imporierenden Daten wird von dieser Kasse hier bereits verwendet.";
throw std::runtime_error(ret);
} }
market->setSalesToDelete(jsonValues["source_no"]); market->setSalesToDelete(jsonValues["source_no"]);
market->storeToDb(); market->storeToDb();
for (const auto& valSale : jsonValues["sales"]) { for (const auto &valSale : jsonValues["sales"]) {
auto sale = std::make_unique<Sale>(); auto sale = std::make_unique<Sale>();
sale->setUuidFromString(valSale["uuid"]); sale->setUuidFromString(valSale["uuid"]);
sale->setSourceNo(jsonValues["source_no"]); sale->setSourceNo(jsonValues["source_no"]);
sale->setTimestamp(valSale["timestamp"]); sale->setTimestamp(valSale["timestamp"]);
for (const auto& valArticle : valSale["articles"]) { for (const auto &valArticle : valSale["articles"]) {
auto article = std::make_unique<Article>(); auto article = std::make_unique<Article>();
article->setUuidFromString(valArticle["uuid"]); article->setUuidFromString(valArticle["uuid"]);
article->setSourceNo(jsonValues["source_no"]); article->setSourceNo(jsonValues["source_no"]);

View File

@ -8,12 +8,12 @@
class JsonUtil class JsonUtil
{ {
public: public:
static void exportSellers(const std::filesystem::path& filePath, Marketplace* market); static void exportSellers(const std::filesystem::path &filePath, Marketplace *market);
static std::size_t importSellers(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, static void exportSales(const std::filesystem::path &filePath, Marketplace *market,
int cashPointNo); int cashPointNo);
static void importSales(const std::filesystem::path& filePath, Marketplace* market, static void importSales(const std::filesystem::path &filePath, Marketplace *market,
int cashPointNo); int cashPointNo);
}; };

View File

@ -33,15 +33,15 @@ Database::InitResult Marketplace::loadFromDb()
return db.getInitResult(); 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() int Marketplace::getNextSellerNo()
{ {
auto iter = std::max_element( auto iter = std::max_element(
sellers_.begin(), sellers_.end(), 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()) if (iter == sellers_.end())
return 1; return 1;
return (*iter)->getSellerNo() + 1; return (*iter)->getSellerNo() + 1;
@ -53,14 +53,14 @@ int Marketplace::getNextArticleNo()
int maxArtNoInBasket{0}; int maxArtNoInBasket{0};
auto iter = std::max_element(sellers_.begin(), sellers_.end(), 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(); return a->getMaxArticleNo() < b->getMaxArticleNo();
}); });
if (iter != sellers_.end()) if (iter != sellers_.end())
maxArtNoInDb = (*iter)->getMaxArticleNo(); maxArtNoInDb = (*iter)->getMaxArticleNo();
auto iter2 = 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(); return a->getArticleNo() < b->getArticleNo();
}); });
@ -73,13 +73,13 @@ int Marketplace::getNextArticleNo()
int Marketplace::getNumSellersDelete() int Marketplace::getNumSellersDelete()
{ {
int count = std::count_if(sellers_.begin(), sellers_.end(), 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; return count;
} }
int Marketplace::getNumArticlesSold() 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 a + seller->numArticlesSold();
}); });
return sum; return sum;
@ -87,7 +87,7 @@ int Marketplace::getNumArticlesSold()
int Marketplace::getNumArticlesOffered() 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 a + seller->numArticlesOffered();
}); });
return sum; return sum;
@ -95,10 +95,10 @@ int Marketplace::getNumArticlesOffered()
void Marketplace::sortSellers() { std::sort(sellers_.begin(), sellers_.end()); } 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(), 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()) if (iter == sellers_.end())
return nullptr; return nullptr;
return (*iter).get(); return (*iter).get();
@ -129,12 +129,12 @@ void Marketplace::finishCurrentSale(std::unique_ptr<Sale> sale)
storeToDb(); storeToDb();
} }
BasketVec& Marketplace::getBasket() { return basket_; } BasketVec &Marketplace::getBasket() { return basket_; }
int Marketplace::getBasketSumInCent() int Marketplace::getBasketSumInCent()
{ {
int sum = std::accumulate(basket_.begin(), basket_.end(), 0, 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; return sum;
} }
@ -148,23 +148,23 @@ std::string Marketplace::getBasketSumAsString()
void Marketplace::removeSale(boost::uuids::uuid uuid) void Marketplace::removeSale(boost::uuids::uuid uuid)
{ {
sales_.erase(std::remove_if(sales_.begin(), sales_.end(), 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()); sales_.end());
} }
void Marketplace::setSalesToDelete(int cashPointNo) 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) { if (sale->getSourceNo() == cashPointNo) {
sale->setState(Sale::State::DELETE); sale->setState(Sale::State::DELETE);
for (auto& article : sale->getArticles()) { for (auto &article : sale->getArticles()) {
article->setState(Article::State::DELETE); 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); std::ofstream file(filePath);
@ -173,7 +173,7 @@ void Marketplace::exportReportToCSV(const fs::path& filePath, int feeInPercent,
<< "Anz. gemeldet" << delimiter << "Anz. verkauft" << delimiter << "Umsatz" << delimiter << "Anz. gemeldet" << delimiter << "Anz. verkauft" << delimiter << "Umsatz" << delimiter
<< "Auszahlung\n"; << "Auszahlung\n";
for (const auto& seller : sellers_) { for (const auto &seller : sellers_) {
file << seller->getSellerNo() << delimiter file << seller->getSellerNo() << delimiter
<< escapeCsvValue(seller->getLastName(), delimiter) << delimiter << escapeCsvValue(seller->getLastName(), delimiter) << delimiter
<< escapeCsvValue(seller->getFirstName(), delimiter) << delimiter << escapeCsvValue(seller->getFirstName(), delimiter) << delimiter
@ -189,7 +189,7 @@ void Marketplace::exportReportToCSV(const fs::path& filePath, int feeInPercent,
int Marketplace::getOverallSumInCent() int Marketplace::getOverallSumInCent()
{ {
int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, 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; return sum;
} }
@ -202,7 +202,7 @@ std::string Marketplace::getOverallSumAsString()
int Marketplace::getOverallPaymentInCent(int percent, int maxFee) int Marketplace::getOverallPaymentInCent(int percent, int maxFee)
{ {
int sum = std::accumulate( 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 a + b->sumInCents() - marketFee(b->sumInCents(), percent, maxFee);
}); });
return sum; return sum;
@ -240,7 +240,7 @@ std::string paymentAsString(int sumInCent, int percent, int maxFeeInCent)
return formatCentAsEuroString(sumInCent - marketFee(sumInCent, percent, 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; std::stringstream output;
bool containsDelim{false}; bool containsDelim{false};
@ -250,7 +250,7 @@ std::string escapeCsvValue(const std::string& value, const char delimiter)
output << '"'; output << '"';
} }
for (auto& symbol : value) { for (auto &symbol : value) {
if (symbol == '"') { if (symbol == '"') {
output << '"' << symbol; output << '"' << symbol;
} else { } else {

View File

@ -20,26 +20,26 @@ using BasketVec = std::vector<std::unique_ptr<Article>>;
class Marketplace class Marketplace
{ {
public: public:
Marketplace(); Marketplace();
void storeToDb(bool onlyDelete = false); void storeToDb(bool onlyDelete = false);
Database::InitResult loadFromDb(); Database::InitResult loadFromDb();
SellersVec& getSellers(); SellersVec &getSellers();
SalesVec& getSales(); SalesVec &getSales();
int getNextSellerNo(); int getNextSellerNo();
int getNextArticleNo(); int getNextArticleNo();
int getNumSellersDelete(); int getNumSellersDelete();
int getNumArticlesSold(); int getNumArticlesSold();
int getNumArticlesOffered(); int getNumArticlesOffered();
BasketVec& getBasket(); BasketVec &getBasket();
int getBasketSumInCent(); int getBasketSumInCent();
std::string getBasketSumAsString(); std::string getBasketSumAsString();
void sortSellers(); void sortSellers();
Seller* findSellerWithSellerNo(int sellerNo); Seller *findSellerWithSellerNo(int sellerNo);
Seller* findSellerWithUuid(const std::string& uuid); Seller *findSellerWithUuid(const std::string &uuid);
void addArticleToBasket(std::unique_ptr<Article> article); void addArticleToBasket(std::unique_ptr<Article> article);
size_t basketSize(); size_t basketSize();
void finishCurrentSale(std::unique_ptr<Sale> sale); void finishCurrentSale(std::unique_ptr<Sale> sale);
@ -54,12 +54,12 @@ class Marketplace
void clear(); void clear();
void exportReportToCSV(const std::filesystem::path& filePath, int feeInPercent, void exportReportToCSV(const std::filesystem::path &filePath, int feeInPercent,
int maxFeeInEuro); int maxFeeInEuro);
friend class ExcelReader; friend class ExcelReader;
private: private:
SellersVec sellers_; SellersVec sellers_;
SalesVec sales_; SalesVec sales_;
BasketVec basket_; BasketVec basket_;
@ -68,6 +68,6 @@ class Marketplace
double marketFee(int sumInCent, int percent, int maxFeeInCent); double marketFee(int sumInCent, int percent, int maxFeeInCent);
std::string marketFeeAsString(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 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

13
src/core/meson.build Normal file
View File

@ -0,0 +1,13 @@
boost = dependency('boost', modules: ['date_time'], static: true)
xlnt = dependency('xlnt')
sqlite = dependency('sqlite3')
src = ['database.cpp', 'entity.cpp', 'entityint.cpp', 'entityuuid.cpp',
'seller.cpp', 'article.cpp', 'sale.cpp', 'marketplace.cpp',
'excelreader.cpp', 'csvreader.cpp', 'jsonutil.cpp', 'utils.cpp']
core_inc = include_directories('..')
core_lib = static_library('core', src, dependencies: [boost, xlnt, sqlite, nlohmann_lib, csv_dep])
core_dep = declare_dependency(link_with: core_lib, include_directories : core_inc)

View File

@ -3,41 +3,41 @@
#include <numeric> #include <numeric>
void Sale::addArticle(Article* articlePtr) void Sale::addArticle(Article *articlePtr)
{ {
articlePtr->setSale(this); articlePtr->setSale(this);
articles_.push_back(articlePtr); m_articles.push_back(articlePtr);
} }
ArticlesVec& Sale::getArticles() { return articles_; } ArticlesVec &Sale::getArticles() { return m_articles; }
void Sale::removeArticle(const Article* articlePtr) void Sale::removeArticle(const Article *articlePtr)
{ {
auto it = std::find(articles_.begin(), articles_.end(), articlePtr); auto it = std::find(m_articles.begin(), m_articles.end(), articlePtr);
if (it != articles_.end()) { if (it != m_articles.end()) {
(*it)->setSale(nullptr); (*it)->setSale(nullptr);
(*it)->setState( (*it)->setState(
Article::State::DELETE); // since we only have ad-hoc articles, that have all been sold Article::State::DELETE); // since we only have ad-hoc articles, that have all been sold
articles_.erase(it); m_articles.erase(it);
} }
} }
int Sale::sumInCents() int Sale::sumInCents()
{ {
int sum = std::accumulate(articles_.begin(), articles_.end(), 0, int sum = std::accumulate(m_articles.begin(), m_articles.end(), 0,
[](int a, const Article* b) { return a + b->getPrice(); }); [](int a, const Article *b) { return a + b->getPrice(); });
return sum; return sum;
} }
std::string Sale::sumAsString() { return formatCentAsEuroString(sumInCents()); } std::string Sale::sumAsString() { return formatCentAsEuroString(sumInCents()); }
std::string Sale::getTimestamp() const { return timestamp_; } std::string Sale::getTimestamp() const { return m_timestamp; }
void Sale::setTimestamp(const std::string& timestamp) { timestamp_ = timestamp; } void Sale::setTimestamp(const std::string &timestamp) { m_timestamp = timestamp; }
std::string Sale::getTimestampFormatted() const std::string Sale::getTimestampFormatted() const
{ {
boost::posix_time::ptime time = boost::posix_time::from_iso_extended_string(timestamp_); boost::posix_time::ptime time = boost::posix_time::from_iso_extended_string(m_timestamp);
return boost::posix_time::to_simple_string(time); return boost::posix_time::to_simple_string(time);
} }

View File

@ -11,30 +11,30 @@
namespace namespace
{ {
using ArticlesVec = std::vector<Article*>; using ArticlesVec = std::vector<Article *>;
} }
class Sale : public EntityUuid class Sale : public EntityUuid
{ {
public: public:
Sale() = default; Sale() = default;
Sale(const Sale&) = delete; Sale(const Sale &) = delete;
virtual ~Sale() = default; virtual ~Sale() = default;
void addArticle(Article* articlePtr); void addArticle(Article *articlePtr);
void setTimestamp(const std::string& timestamp); void setTimestamp(const std::string &timestamp);
ArticlesVec& getArticles(); ArticlesVec &getArticles();
std::string getTimestamp() const; std::string getTimestamp() const;
std::string getTimestampFormatted() const; std::string getTimestampFormatted() const;
int sumInCents(); int sumInCents();
std::string sumAsString(); std::string sumAsString();
void removeArticle(const Article* articlePtr); void removeArticle(const Article *articlePtr);
private: private:
std::string timestamp_{ std::string m_timestamp{
boost::posix_time::to_iso_extended_string(boost::posix_time::second_clock::local_time())}; boost::posix_time::to_iso_extended_string(boost::posix_time::second_clock::local_time())};
mutable ArticlesVec articles_{}; mutable ArticlesVec m_articles{};
}; };
#endif #endif

View File

@ -5,32 +5,32 @@
#include <numeric> #include <numeric>
#include <sstream> #include <sstream>
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) int numArticlesOffered)
: EntityInt(sellerNo) : EntityInt(sellerNo)
{ {
firstName_ = firstName; m_firstName = firstName;
lastName_ = lastName; m_lastName = lastName;
numArticlesOffered_ = numArticlesOffered; m_numArticlesOffered = numArticlesOffered;
} }
void Seller::setSellerNo(int seller_no) { setId(seller_no); } void Seller::setSellerNo(int seller_no) { setId(seller_no); }
void Seller::setFirstName(const std::string& firstName) { firstName_ = firstName; } void Seller::setFirstName(const std::string &firstName) { m_firstName = firstName; }
void Seller::setLastName(const std::string& lastName) { lastName_ = lastName; } void Seller::setLastName(const std::string &lastName) { m_lastName = lastName; }
void Seller::setNumArticlesOffered(int number) { numArticlesOffered_ = number; } void Seller::setNumArticlesOffered(int number) { m_numArticlesOffered = number; }
void Seller::addArticle(std::unique_ptr<Article> article) void Seller::addArticle(std::unique_ptr<Article> article)
{ {
article->setSeller(this); article->setSeller(this);
articles_.push_back(std::move(article)); m_articles.push_back(std::move(article));
} }
std::string Seller::getFirstName() const { return firstName_; } std::string Seller::getFirstName() const { return m_firstName; }
std::string Seller::getLastName() const { return lastName_; } std::string Seller::getLastName() const { return m_lastName; }
int Seller::getSellerNo() const { return getId(); } int Seller::getSellerNo() const { return getId(); }
@ -38,16 +38,16 @@ std::string Seller::getSellerNoAsString() const
{ {
std::stringstream selNoStr; std::stringstream selNoStr;
selNoStr << std::setfill('0') << std::setw(3) << id_; selNoStr << std::setfill('0') << std::setw(3) << m_id;
return selNoStr.str(); return selNoStr.str();
; ;
} }
std::vector<Article*> Seller::getArticles(bool onlySold) const std::vector<Article *> Seller::getArticles(bool onlySold) const
{ {
std::vector<Article*> articles; std::vector<Article *> articles;
for (const auto& article : articles_) { for (const auto &article : m_articles) {
if (onlySold && article->isSold()) { if (onlySold && article->isSold()) {
articles.push_back(article.get()); articles.push_back(article.get());
} else if (!onlySold) { } else if (!onlySold) {
@ -57,54 +57,54 @@ std::vector<Article*> Seller::getArticles(bool onlySold) const
return articles; return articles;
} }
Article* Seller::getArticleByUuid(const std::string& uuidString) Article *Seller::getArticleByUuid(const std::string &uuidString)
{ {
auto iter = std::find_if(articles_.begin(), articles_.end(), [&uuidString](const auto& art) { auto iter = std::find_if(m_articles.begin(), m_articles.end(), [&uuidString](const auto &art) {
return art->getUuidAsString() == uuidString; return art->getUuidAsString() == uuidString;
}); });
if (iter == articles_.end()) if (iter == m_articles.end())
return nullptr; return nullptr;
return (*iter).get(); return (*iter).get();
} }
int Seller::numArticlesSold() const { return static_cast<int>(getArticles(true).size()); } int Seller::numArticlesSold() const { return static_cast<int>(getArticles(true).size()); }
int Seller::numArticlesOffered() const { return numArticlesOffered_; } int Seller::numArticlesOffered() const { return m_numArticlesOffered; }
int Seller::getMaxArticleNo() const int Seller::getMaxArticleNo() const
{ {
auto iter = std::max_element( auto iter = std::max_element(
articles_.begin(), articles_.end(), m_articles.begin(), m_articles.end(),
[](const auto& a, const auto& b) -> bool { return a->getArticleNo() < b->getArticleNo(); }); [](const auto &a, const auto &b) -> bool { return a->getArticleNo() < b->getArticleNo(); });
if (iter == articles_.end()) if (iter == m_articles.end())
return 0; return 0;
return (*iter)->getArticleNo(); return (*iter)->getArticleNo();
} }
void Seller::cleanupArticles() void Seller::cleanupArticles()
{ {
articles_.erase(std::remove_if(articles_.begin(), articles_.end(), m_articles.erase(std::remove_if(m_articles.begin(), m_articles.end(),
[](const auto& article) { [](const auto &article) {
return article->getState() == Article::State::DELETE; return article->getState() == Article::State::DELETE;
}), }),
articles_.end()); m_articles.end());
for (auto& article : articles_) { for (auto &article : m_articles) {
article->setState(Article::State::OK); article->setState(Article::State::OK);
} }
} }
int Seller::sumInCents() int Seller::sumInCents()
{ {
int sum = std::accumulate(articles_.begin(), articles_.end(), 0, int sum = std::accumulate(m_articles.begin(), m_articles.end(), 0,
[](int a, const auto& b) { return a + b->getPrice(); }); [](int a, const auto &b) { return a + b->getPrice(); });
return sum; return sum;
} }
std::string Seller::sumAsString() { return formatCentAsEuroString(sumInCents()); } std::string Seller::sumAsString() { return formatCentAsEuroString(sumInCents()); }
bool operator<(const Seller& li, const Seller& re) { return li.id_ < re.id_; } bool operator<(const Seller &li, const Seller &re) { return li.m_id < re.m_id; }
bool operator<(const std::unique_ptr<Seller>& li, const std::unique_ptr<Seller>& re) bool operator<(const std::unique_ptr<Seller> &li, const std::unique_ptr<Seller> &re)
{ {
return li->id_ < re->id_; return li->m_id < re->m_id;
} }

View File

@ -12,16 +12,16 @@
class Seller : public EntityInt class Seller : public EntityInt
{ {
public: public:
Seller() = default; Seller() = default;
Seller(const Seller&) = delete; Seller(const Seller &) = delete;
virtual ~Seller() = default; virtual ~Seller() = default;
Seller(const std::string& firstName, const std::string& lastName, int sellerNo = 0, Seller(const std::string &firstName, const std::string &lastName, int sellerNo = 0,
int numArticlesOffered = 0); int numArticlesOffered = 0);
void setSellerNo(int sellerNo); void setSellerNo(int sellerNo);
void setFirstName(const std::string& firstName); void setFirstName(const std::string &firstName);
void setLastName(const std::string& lastName); void setLastName(const std::string &lastName);
void setNumArticlesOffered(int number); void setNumArticlesOffered(int number);
void addArticle(std::unique_ptr<Article> article); void addArticle(std::unique_ptr<Article> article);
void cleanupArticles(); void cleanupArticles();
@ -32,20 +32,20 @@ class Seller : public EntityInt
std::string getSellerNoAsString() const; std::string getSellerNoAsString() const;
int numArticlesOffered() const; int numArticlesOffered() const;
int numArticlesSold() const; int numArticlesSold() const;
std::vector<Article*> getArticles(bool onlySold = true) const; std::vector<Article *> getArticles(bool onlySold = true) const;
Article* getArticleByUuid(const std::string& uuidString); Article *getArticleByUuid(const std::string &uuidString);
int getMaxArticleNo() const; int getMaxArticleNo() const;
int sumInCents(); int sumInCents();
std::string sumAsString(); std::string sumAsString();
friend bool operator<(const Seller& li, const Seller& re); friend bool operator<(const Seller &li, const Seller &re);
friend bool operator<(const std::unique_ptr<Seller>& li, const std::unique_ptr<Seller>& re); friend bool operator<(const std::unique_ptr<Seller> &li, const std::unique_ptr<Seller> &re);
private: private:
int numArticlesOffered_{}; int m_numArticlesOffered{};
std::string firstName_{}; std::string m_firstName{};
std::string lastName_{}; std::string m_lastName{};
std::vector<std::unique_ptr<Article>> articles_{}; std::vector<std::unique_ptr<Article>> m_articles{};
}; };
#endif #endif

View File

@ -1,64 +1,53 @@
#include "utils.h" #include "utils.h"
#include <algorithm> #include <algorithm>
#include <clocale>
#include <fmt/format.h>
#include <iomanip> #include <iomanip>
#include <numeric> #include <numeric>
#include <iostream>
using namespace fmt;
std::string formatCentAsEuroString(const int cent, int width) std::string formatCentAsEuroString(const int cent, int width)
{ {
std::stringstream currStream; /*std::stringstream currStream;
try { try {
std::locale myLocale("de_DE.utf8"); std::locale myLocale("de_DE.utf8");
currStream.imbue(myLocale); currStream.imbue(myLocale);
std::cout << ">>> " << fmt::format(myLocale, "{:6.2Lf}", 1.12345) << '\n';
currStream << std::right << std::setw(width) << std::showbase currStream << std::right << std::setw(width) << std::showbase
<< std::put_money(cent, false); << 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) currStream << std::fixed << std::setw(width >= 4 ? width - 4 : width)
<< std::setprecision(2) << cent / 100.0L << ""; << std::setprecision(2) << cent / 100.0L << "";
} }
return currStream.str(); return currStream.str();*/
#if defined(_WIN64) || defined(_WIN32)
std::locale myLocale;
#else
std::locale myLocale{"de_DE.utf8"};
#endif
return fmt::format(myLocale, "{:{}.2Lf} €", cent / 100.0L, width);
} }
std::optional<PrinterDevice> convertToPosPrinterDevice(const std::string& device, std::string &ltrim(std::string &str, const std::string &chars)
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;
}
std::string& ltrim(std::string& str, const std::string& chars)
{ {
str.erase(0, str.find_first_not_of(chars)); str.erase(0, str.find_first_not_of(chars));
return str; return str;
} }
std::string& rtrim(std::string& str, const std::string& chars) std::string &rtrim(std::string &str, const std::string &chars)
{ {
str.erase(str.find_last_not_of(chars) + 1); str.erase(str.find_last_not_of(chars) + 1);
return str; return str;
} }
std::string& trim(std::string& str, const std::string& chars) std::string &trim(std::string &str, const std::string &chars)
{ {
return ltrim(rtrim(str, chars), chars); return ltrim(rtrim(str, chars), chars);
} }
@ -71,4 +60,11 @@ bool case_insensitive_match(std::string s1, std::string s2)
if (s1.compare(s2) == 0) if (s1.compare(s2) == 0)
return true; // The strings are same return true; // The strings are same
return false; // not matched return false; // not matched
}
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();
} }

View File

@ -1,18 +1,15 @@
#ifndef UTILS_H #ifndef CORE_UTILS_H
#define UTILS_H #define CORE_UTILS_H
#include "posprinter.h"
#include <locale> #include <locale>
#include <optional> #include <optional>
#include <string> #include <string>
std::string formatCentAsEuroString(const int cent, int width = 10); std::string formatCentAsEuroString(const int cent, int width = 6);
std::optional<PrinterDevice> convertToPosPrinterDevice(const std::string& vendor, std::string &ltrim(std::string &str, const std::string &chars = "\t\n\v\f\r ");
const std::string& endpoint); std::string &rtrim(std::string &str, const std::string &chars = "\t\n\v\f\r ");
std::string& ltrim(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 ");
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 case_insensitive_match(std::string s1, std::string s2);
bool isNumber(const std::string &str);
#endif #endif

View File

@ -8,11 +8,12 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON) set(CMAKE_AUTORCC ON)
# Find the QtWidgets library # Find the QtWidgets library
find_package(Qt5Widgets CONFIG REQUIRED) find_package(Qt6 COMPONENTS Widgets Network PrintSupport CONFIG REQUIRED)
find_package(Qt5PrintSupport CONFIG REQUIRED) #find_package(Qt5Widgets CONFIG REQUIRED)
#find_package(Qt5PrintSupport CONFIG REQUIRED)
# For SingleApplication: # For SingleApplication:
find_package(Qt5Network CONFIG REQUIRED) #find_package(Qt5Network CONFIG REQUIRED)
set(QAPPLICATION_CLASS QApplication) set(QAPPLICATION_CLASS QApplication)
add_compile_definitions(QAPPLICATION_CLASS=${QAPPLICATION_CLASS}) add_compile_definitions(QAPPLICATION_CLASS=${QAPPLICATION_CLASS})
@ -33,14 +34,16 @@ set(GUI_SOURCES
settingsdialog.cpp settingsdialog.cpp
settingsdialog.ui settingsdialog.ui
../../kima2.qrc ../../kima2.qrc
${PROJECT_SOURCE_DIR}/3rdparty/singleapplication/singleapplication.cpp ${PROJECT_SOURCE_DIR}/subprojects/singleapplication/singleapplication.git/singleapplication.cpp
${PROJECT_SOURCE_DIR}/3rdparty/singleapplication/singleapplication_p.cpp ${PROJECT_SOURCE_DIR}/subprojects/singleapplication/singleapplication.git/singleapplication_p.cpp
) )
add_executable(kima2 ${GUI_SOURCES} kima2.rc) add_executable(kima2 ${GUI_SOURCES} kima2.rc)
target_include_directories(kima2 PRIVATE ${PROJECT_BINARY_DIR}) target_include_directories(kima2 PRIVATE ${PROJECT_BINARY_DIR})
target_include_directories(kima2 PRIVATE ${PROJECT_SOURCE_DIR}/3rdparty/singleapplication) target_include_directories(kima2 PRIVATE ${PROJECT_SOURCE_DIR}/subprojects/singleapplication/singleapplication.git)
target_link_libraries(kima2 core printer Qt5::Widgets Qt5::PrintSupport Qt5::Network stdc++fs) # target_link_libraries(kima2 core printer Qt5::Widgets Qt5::PrintSupport Qt5::Network stdc++fs)
target_link_libraries(kima2 core printer Qt::Core Qt::PrintSupport Qt::Network)
if(WIN32) if(WIN32)
set_target_properties(kima2 PROPERTIES LINK_FLAGS "-mwindows") set_target_properties(kima2 PROPERTIES LINK_FLAGS "-mwindows")
endif(WIN32) endif(WIN32)

View File

@ -5,13 +5,13 @@
#include <QSettings> #include <QSettings>
BasketModel::BasketModel(Marketplace* market, QObject* parent) BasketModel::BasketModel(Marketplace* market, QObject* parent)
: QAbstractTableModel(parent), marketplace_(market) : QAbstractTableModel(parent), m_marketplace(market)
{ {
} }
int BasketModel::rowCount([[maybe_unused]] const QModelIndex& parent) const int BasketModel::rowCount([[maybe_unused]] const QModelIndex& parent) const
{ {
return static_cast<int>(marketplace_->basketSize()); return static_cast<int>(m_marketplace->basketSize());
} }
int BasketModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 4; } int BasketModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 4; }
@ -46,10 +46,10 @@ QVariant BasketModel::data(const QModelIndex& index, int role) const
if (role != Qt::DisplayRole) if (role != Qt::DisplayRole)
return QVariant(); return QVariant();
if (marketplace_->basketSize() == 0) if (m_marketplace->basketSize() == 0)
return QVariant(); return QVariant();
Article* article = marketplace_->getBasket().at(index.row()).get(); Article* article = m_marketplace->getBasket().at(index.row()).get();
switch (index.column()) { switch (index.column()) {
case 0: 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) void BasketModel::addArticle(Seller* seller, int price, const std::string& desc)
{ {
emit beginInsertRows(QModelIndex(), marketplace_->getBasket().size(), emit beginInsertRows(QModelIndex(), m_marketplace->getBasket().size(),
marketplace_->getBasket().size()); m_marketplace->getBasket().size());
auto article = std::make_unique<Article>(price); auto article = std::make_unique<Article>(price);
article->createUuid(); article->createUuid();
article->setDescription(desc); article->setDescription(desc);
article->setArticleNo(marketplace_->getNextArticleNo()); article->setArticleNo(m_marketplace->getNextArticleNo());
article->setSourceNo(QSettings().value("global/cashPointNo").toInt()); article->setSourceNo(QSettings().value("global/cashPointNo").toInt());
article->setSeller(seller); article->setSeller(seller);
marketplace_->addArticleToBasket(std::move(article)); m_marketplace->addArticleToBasket(std::move(article));
emit endInsertRows(); emit endInsertRows();
} }
void BasketModel::finishSale() void BasketModel::finishSale()
{ {
emit beginRemoveRows(QModelIndex(), 0, marketplace_->getBasket().size() - 1); emit beginRemoveRows(QModelIndex(), 0, m_marketplace->getBasket().size() - 1);
auto sale = std::make_unique<Sale>(); auto sale = std::make_unique<Sale>();
sale->createUuid(); sale->createUuid();
sale->setSourceNo(QSettings().value("global/cashPointNo").toInt()); sale->setSourceNo(QSettings().value("global/cashPointNo").toInt());
marketplace_->finishCurrentSale(std::move(sale)); m_marketplace->finishCurrentSale(std::move(sale));
emit endRemoveRows(); emit endRemoveRows();
emit basketDataChanged(); emit basketDataChanged();
} }
void BasketModel::cancelSale() void BasketModel::cancelSale()
{ {
emit beginRemoveRows(QModelIndex(), 0, marketplace_->getBasket().size() - 1); emit beginRemoveRows(QModelIndex(), 0, m_marketplace->getBasket().size() - 1);
marketplace_->getBasket().clear(); m_marketplace->getBasket().clear();
emit endRemoveRows(); emit endRemoveRows();
} }
bool BasketModel::removeRows(int row, int count, const QModelIndex& parent) bool BasketModel::removeRows(int row, int count, const QModelIndex& parent)
{ {
auto article = marketplace_->getBasket().at(row).get(); auto article = m_marketplace->getBasket().at(row).get();
emit beginRemoveRows(parent, row, row + count - 1); emit beginRemoveRows(parent, row, row + count - 1);
marketplace_->getBasket().erase( m_marketplace->getBasket().erase(
std::remove_if(marketplace_->getBasket().begin(), marketplace_->getBasket().end(), std::remove_if(m_marketplace->getBasket().begin(), m_marketplace->getBasket().end(),
[&article](const auto& a) { return a->getUuid() == article->getUuid(); }), [&article](const auto& a) { return a->getUuid() == article->getUuid(); }),
marketplace_->getBasket().end()); m_marketplace->getBasket().end());
emit endRemoveRows(); emit endRemoveRows();
return true; return true;
} }

View File

@ -1,7 +1,7 @@
#ifndef BASKET_MODEL_H #ifndef BASKET_MODEL_H
#define BASKET_MODEL_H #define BASKET_MODEL_H
#include <marketplace.h> #include <core/marketplace.h>
#include <QAbstractTableModel> #include <QAbstractTableModel>
@ -24,7 +24,7 @@ class BasketModel : public QAbstractTableModel
void basketDataChanged(); void basketDataChanged();
private: private:
Marketplace* marketplace_; Marketplace* m_marketplace;
}; };
#endif #endif

View File

@ -7,11 +7,13 @@
#include <QMessageBox> #include <QMessageBox>
#include <QSettings> #include <QSettings>
#include <QSharedMemory> #include <QSharedMemory>
#include <QStyleFactory>
#include <QTranslator> #include <QTranslator>
#include <singleapplication.h> #include <singleapplication.h>
#include <stdexcept>
int main(int argc, char* argv[]) int main(int argc, char *argv[])
{ {
SingleApplication kimaApp(argc, argv); SingleApplication kimaApp(argc, argv);
@ -19,16 +21,12 @@ int main(int argc, char* argv[])
QCoreApplication::setOrganizationDomain("rustysoft.de"); QCoreApplication::setOrganizationDomain("rustysoft.de");
QCoreApplication::setApplicationName("kima2"); QCoreApplication::setApplicationName("kima2");
QTranslator qTranslator; QTranslator qtTranslator;
QLocale german(QLocale::German);
#ifdef __linux__ if (qtTranslator.load(QLocale::system(), u"qtbase"_qs, u"_"_qs,
qTranslator.load("qt_" + german.name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); QLibraryInfo::path(QLibraryInfo::TranslationsPath))) {
#endif kimaApp.installTranslator(&qtTranslator);
#ifdef _WIN32 }
qTranslator.load("qt_" + german.name(),
QApplication::applicationDirPath() + QDir::separator() + "translations");
#endif
kimaApp.installTranslator(&qTranslator);
QSettings settings{}; QSettings settings{};
while (!settings.contains("global/cashPointNo")) { while (!settings.contains("global/cashPointNo")) {

View File

@ -1,19 +1,18 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "basketmodel.h" #include "basketmodel.h"
#include "config.h"
#include "jsonutil.h"
#include "pricedialog.h" #include "pricedialog.h"
#include "reportdialog.h" #include "reportdialog.h"
#include "salemodel.h" #include "salemodel.h"
#include "sellerdialog.h" #include "sellerdialog.h"
#include "settingsdialog.h" #include "settingsdialog.h"
#include <config.h>
#include <utils.h> #include <core/csvreader.h>
#include <core/jsonutil.h>
#include <csvreader.h> #include <core/utils.h>
#include <excelreader.h> #include <printer/posprinter.h>
#include <posprinter.h> #include <printer/utils.h>
#include <exception> #include <exception>
#include <filesystem> #include <filesystem>
@ -32,10 +31,10 @@ constexpr int STATUSBAR_TIMEOUT = 5000;
MainWindow::MainWindow() MainWindow::MainWindow()
{ {
ui_.setupUi(this); m_ui.setupUi(this);
marketplace_ = std::make_unique<Marketplace>(); m_marketplace = std::make_unique<Marketplace>();
Database::InitResult res = marketplace_->loadFromDb(); Database::InitResult res = m_marketplace->loadFromDb();
if (res == Database::InitResult::OUTDATED_REPLACED) { if (res == Database::InitResult::OUTDATED_REPLACED) {
QMessageBox(QMessageBox::Icon::Information, "Datenbankinformation", QMessageBox(QMessageBox::Icon::Information, "Datenbankinformation",
"Es wurde eine <b>veraltete</b> Datenbankdatei erkannt.<br />Diese wurde " "Es wurde eine <b>veraltete</b> Datenbankdatei erkannt.<br />Diese wurde "
@ -44,19 +43,19 @@ MainWindow::MainWindow()
} }
statusBar()->showMessage("Gespeicherte Daten wurden geladen.", STATUSBAR_TIMEOUT); statusBar()->showMessage("Gespeicherte Daten wurden geladen.", STATUSBAR_TIMEOUT);
BasketModel* model = new BasketModel(getMarketplace(), ui_.basketView); BasketModel *model = new BasketModel(getMarketplace(), m_ui.basketView);
ui_.basketView->setModel(model); m_ui.basketView->setModel(model);
ui_.basketView->setColumnHidden(0, true); // hide the uuid m_ui.basketView->setColumnHidden(0, true); // hide the uuid
setWindowTitle("KIMA2 - Kasse Nr. " + QSettings().value("global/cashPointNo").toString()); setWindowTitle("KIMA2 - Kasse Nr. " + QSettings().value("global/cashPointNo").toString());
ui_.salesView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); m_ui.salesView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
setSaleModel(); setSaleModel();
connect(ui_.actionQuit, &QAction::triggered, qApp, QApplication::closeAllWindows, connect(m_ui.actionQuit, &QAction::triggered, qApp, QApplication::closeAllWindows,
Qt::QueuedConnection); Qt::QueuedConnection);
connect(ui_.newAction, &QAction::triggered, this, [=]() { connect(m_ui.newAction, &QAction::triggered, this, [this]() {
if (marketplace_->getSellers().size() == 0 && marketplace_->getSales().size() == 0) { if (m_marketplace->getSellers().size() == 0 && m_marketplace->getSales().size() == 0) {
return; return;
} }
auto dlgResult = auto dlgResult =
@ -68,46 +67,45 @@ MainWindow::MainWindow()
if (dlgResult == QMessageBox::No) if (dlgResult == QMessageBox::No)
return; return;
delete ui_.salesView->model(); delete m_ui.salesView->model();
dynamic_cast<BasketModel*>(ui_.basketView->model())->cancelSale(); dynamic_cast<BasketModel *>(m_ui.basketView->model())->cancelSale();
marketplace_->clear(); m_marketplace->clear();
setSaleModel(); setSaleModel();
updateStatLabel(); updateStatLabel();
}); });
ui_.sellerNoEdit->installEventFilter(this); m_ui.sellerNoEdit->installEventFilter(this);
ui_.givenSpinBox->installEventFilter(this); m_ui.givenSpinBox->installEventFilter(this);
connect(ui_.actionEditSeller, &QAction::triggered, this, connect(m_ui.actionEditSeller, &QAction::triggered, this,
&MainWindow::onActionEditSellerTriggered); &MainWindow::onActionEditSellerTriggered);
connect(ui_.paidButton, &QPushButton::clicked, this, &MainWindow::onPaidButtonTriggered); connect(m_ui.paidButton, &QPushButton::clicked, this, &MainWindow::onPaidButtonTriggered);
connect(ui_.givenSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, connect(m_ui.givenSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
&MainWindow::onGivenSpinBoxValueChanged); &MainWindow::onGivenSpinBoxValueChanged);
connect(ui_.basketView->selectionModel(), &QItemSelectionModel::selectionChanged, this, connect(m_ui.basketView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
&MainWindow::onBasketViewSelectionChanged); &MainWindow::onBasketViewSelectionChanged);
connect(ui_.cancelArticleButton, &QPushButton::clicked, this, connect(m_ui.cancelArticleButton, &QPushButton::clicked, this,
&MainWindow::onCancelArticleButtonClicked); &MainWindow::onCancelArticleButtonClicked);
connect(ui_.cancelSaleButton, &QPushButton::clicked, this, connect(m_ui.cancelSaleButton, &QPushButton::clicked, this,
&MainWindow::onCancelSaleButtonClicked); &MainWindow::onCancelSaleButtonClicked);
connect(ui_.printSaleReceiptButton, &QPushButton::clicked, this, connect(m_ui.printSaleReceiptButton, &QPushButton::clicked, this,
&MainWindow::onPrintSaleReceiptButtonClicked); &MainWindow::onPrintSaleReceiptButtonClicked);
connect(ui_.cancelAllArticlesButton, &QPushButton::clicked, this, connect(m_ui.cancelAllArticlesButton, &QPushButton::clicked, this,
&MainWindow::onCancelAllArticlesButtonClicked); &MainWindow::onCancelAllArticlesButtonClicked);
connect(ui_.aboutQtAction, &QAction::triggered, this, &MainWindow::onAboutQt); connect(m_ui.aboutQtAction, &QAction::triggered, this, &MainWindow::onAboutQt);
connect(ui_.aboutAction, &QAction::triggered, this, &MainWindow::onAbout); connect(m_ui.aboutAction, &QAction::triggered, this, &MainWindow::onAbout);
connect(ui_.openManualAction, &QAction::triggered, this, []() { connect(m_ui.openManualAction, &QAction::triggered, this, []() {
auto locations = QStandardPaths::standardLocations(QStandardPaths::DataLocation); auto locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation);
for (auto location : locations) { for (auto location : locations) {
if (QFile::exists(location + QString("/Benutzerhandbuch.pdf"))) { if (QFile::exists(location + QString("/Benutzerhandbuch.pdf"))) {
QDesktopServices::openUrl( QDesktopServices::openUrl(
QUrl(QString("file:///") + location + QString("/Benutzerhandbuch.pdf"), QUrl::fromLocalFile(location + QString("/Benutzerhandbuch.pdf")));
QUrl::TolerantMode));
} }
} }
}); });
connect(ui_.licenseAction, &QAction::triggered, this, [=]() { connect(m_ui.licenseAction, &QAction::triggered, this, [this]() {
QString licenseText( QString licenseText(
"Copyright © 2018-2019 Martin Brodbeck\n\n" "Copyright © 2018-2024 Martin Brodbeck\n\n"
"Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der " "Hiermit wird unentgeltlich jeder Person, die eine Kopie der Software und der "
"zugehörigen Dokumentationen (die \"Software\") erhält, die Erlaubnis erteilt, " "zugehörigen Dokumentationen (die \"Software\") erhält, die Erlaubnis erteilt, "
"sie uneingeschränkt zu nutzen, inklusive und ohne Ausnahme mit dem Recht, " "sie uneingeschränkt zu nutzen, inklusive und ohne Ausnahme mit dem Recht, "
@ -126,34 +124,30 @@ MainWindow::MainWindow()
"SOFTWARE ODER SONSTIGER VERWENDUNG DER SOFTWARE ENTSTANDEN."); "SOFTWARE ODER SONSTIGER VERWENDUNG DER SOFTWARE ENTSTANDEN.");
QMessageBox::information(this, "Lizenzinformation", licenseText); QMessageBox::information(this, "Lizenzinformation", licenseText);
}); });
connect(ui_.reportAction, &QAction::triggered, this, [=]() { ReportDialog(this).exec(); }); connect(m_ui.reportAction, &QAction::triggered, this, [this]() { ReportDialog(this).exec(); });
connect(ui_.configAction, &QAction::triggered, this, [=]() { connect(m_ui.configAction, &QAction::triggered, this, [this]() {
int result = SettingsDialog(this).exec(); int result = SettingsDialog(this).exec();
if (result == QDialog::Accepted) { if (result == QDialog::Accepted) {
delete ui_.salesView->model(); delete m_ui.salesView->model();
marketplace_->loadFromDb(); m_marketplace->loadFromDb();
setSaleModel(); setSaleModel();
} }
this->setWindowTitle("KIMA2 - Kasse Nr. " + this->setWindowTitle("KIMA2 - Kasse Nr. " +
QSettings().value("global/cashPointNo").toString()); QSettings().value("global/cashPointNo").toString());
}); });
connect(ui_.importSellerExcelAction, &QAction::triggered, this, connect(m_ui.importSellerAction, &QAction::triggered, this,
&MainWindow::onImportSellerExcelActionTriggered); &MainWindow::onImportSellerActionTriggered);
connect(ui_.importSellerJsonAction, &QAction::triggered, this, connect(m_ui.exportSalesJsonAction, &QAction::triggered, this,
&MainWindow::onImportSellerJsonActionTriggered);
connect(ui_.exportSellerJsonAction, &QAction::triggered, this,
&MainWindow::onExportSellerJsonActionTriggered);
connect(ui_.exportSalesJsonAction, &QAction::triggered, this,
&MainWindow::onExportSalesJsonActionTriggered); &MainWindow::onExportSalesJsonActionTriggered);
connect(ui_.importSalesJsonAction, &QAction::triggered, this, connect(m_ui.importSalesJsonAction, &QAction::triggered, this,
&MainWindow::onImportSalesJsonActionTriggered); &MainWindow::onImportSalesJsonActionTriggered);
readGeometry(); readGeometry();
setWindowIcon(QIcon(":/misc/kima2.ico")); setWindowIcon(QIcon(":/misc/kima2.ico"));
updateStatLabel(); updateStatLabel();
ui_.lastPriceLabel1->setText(formatCentAsEuroString(0).c_str()); m_ui.lastPriceLabel1->setText(formatCentAsEuroString(0).c_str());
ui_.lastPriceLabel2->setText(formatCentAsEuroString(0).c_str()); m_ui.lastPriceLabel2->setText(formatCentAsEuroString(0).c_str());
} }
void MainWindow::onActionEditSellerTriggered() void MainWindow::onActionEditSellerTriggered()
@ -161,11 +155,11 @@ void MainWindow::onActionEditSellerTriggered()
auto dialog = std::make_unique<SellerDialog>(this); auto dialog = std::make_unique<SellerDialog>(this);
int retCode = dialog->exec(); int retCode = dialog->exec();
delete ui_.salesView->model(); delete m_ui.salesView->model();
if (retCode == QDialog::Accepted) { if (retCode == QDialog::Accepted) {
marketplace_->sortSellers(); m_marketplace->sortSellers();
marketplace_->storeToDb(); m_marketplace->storeToDb();
statusBar()->showMessage("Änderungen an den Verkäufer-Stammdaten gespeichert.", statusBar()->showMessage("Änderungen an den Verkäufer-Stammdaten gespeichert.",
STATUSBAR_TIMEOUT); STATUSBAR_TIMEOUT);
} else { } else {
@ -179,42 +173,42 @@ void MainWindow::onActionEditSellerTriggered()
void MainWindow::setSaleModel() void MainWindow::setSaleModel()
{ {
ui_.salesView->setModel(new SaleModel(getMarketplace(), ui_.salesView)); m_ui.salesView->setModel(new SaleModel(getMarketplace(), m_ui.salesView));
ui_.salesView->setColumnHidden(2, true); m_ui.salesView->setColumnHidden(2, true);
ui_.salesView->resizeColumnToContents(0); m_ui.salesView->resizeColumnToContents(0);
ui_.salesView->resizeColumnToContents(1); m_ui.salesView->resizeColumnToContents(1);
ui_.printSaleReceiptButton->setEnabled(false); m_ui.printSaleReceiptButton->setEnabled(false);
ui_.cancelSaleButton->setEnabled(false); m_ui.cancelSaleButton->setEnabled(false);
connect(static_cast<BasketModel*>(ui_.basketView->model()), &BasketModel::basketDataChanged, connect(static_cast<BasketModel *>(m_ui.basketView->model()), &BasketModel::basketDataChanged,
static_cast<SaleModel*>(ui_.salesView->model()), &SaleModel::onBasketDataChanged); static_cast<SaleModel *>(m_ui.salesView->model()), &SaleModel::onBasketDataChanged);
connect(ui_.salesView->selectionModel(), &QItemSelectionModel::selectionChanged, this, connect(m_ui.salesView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
&MainWindow::onSalesViewSelectionChanged); &MainWindow::onSalesViewSelectionChanged);
} }
void MainWindow::onPaidButtonTriggered() void MainWindow::onPaidButtonTriggered()
{ {
if (marketplace_->basketSize() > 0) { if (m_marketplace->basketSize() > 0) {
QString lastPrice{marketplace_->getBasketSumAsString().c_str()}; QString lastPrice{m_marketplace->getBasketSumAsString().c_str()};
dynamic_cast<BasketModel*>(ui_.basketView->model())->finishSale(); dynamic_cast<BasketModel *>(m_ui.basketView->model())->finishSale();
ui_.salesView->resizeColumnToContents(0); m_ui.salesView->resizeColumnToContents(0);
ui_.lastPriceLabel1->setText(lastPrice); m_ui.lastPriceLabel1->setText(lastPrice);
ui_.lastPriceLabel2->setText(lastPrice); m_ui.lastPriceLabel2->setText(lastPrice);
ui_.basketSumLabel->setText(formatCentAsEuroString(0).c_str()); m_ui.basketSumLabel->setText(formatCentAsEuroString(0).c_str());
ui_.drawbackLabel->setText(formatCentAsEuroString(0).c_str()); m_ui.drawbackLabel->setText(formatCentAsEuroString(0).c_str());
ui_.drawbackContainerWidget->setEnabled(false); m_ui.drawbackContainerWidget->setEnabled(false);
ui_.sellerNoEdit->setFocus(); m_ui.sellerNoEdit->setFocus();
statusBar()->showMessage("Verkaufsvorgang erfolgreich durchgeführt.", STATUSBAR_TIMEOUT); statusBar()->showMessage("Verkaufsvorgang erfolgreich durchgeführt.", STATUSBAR_TIMEOUT);
updateStatLabel(); updateStatLabel();
} }
} }
bool MainWindow::eventFilter(QObject* target, QEvent* event) bool MainWindow::eventFilter(QObject *target, QEvent *event)
{ {
if (target == ui_.sellerNoEdit) { if (target == m_ui.sellerNoEdit) {
if (event->type() == QEvent::KeyPress) { if (event->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event); QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key::Key_Enter || keyEvent->key() == Qt::Key::Key_Return) { 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); checkSellerNo(true);
@ -225,18 +219,18 @@ bool MainWindow::eventFilter(QObject* target, QEvent* event)
return true; return true;
} }
} }
} else if (target == ui_.givenSpinBox) { } else if (target == m_ui.givenSpinBox) {
if (event->type() == QEvent::KeyPress) { if (event->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event); QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key::Key_Enter || keyEvent->key() == Qt::Key::Key_Return) { if (keyEvent->key() == Qt::Key::Key_Enter || keyEvent->key() == Qt::Key::Key_Return) {
if (keyEvent->modifiers() & Qt::ControlModifier) { if (keyEvent->modifiers() & Qt::ControlModifier) {
onPaidButtonTriggered(); onPaidButtonTriggered();
return true; return true;
} }
} else if (keyEvent->key() == Qt::Key::Key_Escape) { } else if (keyEvent->key() == Qt::Key::Key_Escape) {
ui_.drawbackLabel->setText(formatCentAsEuroString(0).c_str()); m_ui.drawbackLabel->setText(formatCentAsEuroString(0).c_str());
ui_.drawbackContainerWidget->setEnabled(false); m_ui.drawbackContainerWidget->setEnabled(false);
ui_.sellerNoEdit->setFocus(); m_ui.sellerNoEdit->setFocus();
} }
} }
} }
@ -247,15 +241,15 @@ void MainWindow::checkSellerNo(bool ctrlPressed)
{ {
using std::regex, std::regex_match, std::smatch; using std::regex, std::regex_match, std::smatch;
auto inputText = ui_.sellerNoEdit->text().toStdString(); auto inputText = m_ui.sellerNoEdit->text().toStdString();
if (inputText.empty()) { if (inputText.empty()) {
if (ctrlPressed == false) { if (ctrlPressed == false) {
onPaidButtonTriggered(); onPaidButtonTriggered();
} else if (marketplace_->getBasket().size() > 0) { } else if (m_marketplace->getBasket().size() > 0) {
ui_.drawbackContainerWidget->setEnabled(true); m_ui.drawbackContainerWidget->setEnabled(true);
ui_.givenSpinBox->setFocus(); m_ui.givenSpinBox->setFocus();
ui_.givenSpinBox->selectAll(); m_ui.givenSpinBox->selectAll();
} }
return; return;
} }
@ -264,13 +258,13 @@ void MainWindow::checkSellerNo(bool ctrlPressed)
smatch result; smatch result;
if (!regex_match(inputText, result, pattern)) { if (!regex_match(inputText, result, pattern)) {
ui_.sellerNoEdit->clear(); m_ui.sellerNoEdit->clear();
return; return;
} }
int sellerNo = std::stoi(result[0]); int sellerNo = std::stoi(result[0]);
auto seller = marketplace_->findSellerWithSellerNo(sellerNo); auto seller = m_marketplace->findSellerWithSellerNo(sellerNo);
if (seller) { if (seller) {
PriceDialog priceDialog(this); PriceDialog priceDialog(this);
if (sellerNo == 0) { if (sellerNo == 0) {
@ -280,52 +274,52 @@ void MainWindow::checkSellerNo(bool ctrlPressed)
if (dialogResult == QDialog::Accepted) { if (dialogResult == QDialog::Accepted) {
int price = priceDialog.getPrice(); int price = priceDialog.getPrice();
std::string desc = priceDialog.getDescription(); std::string desc = priceDialog.getDescription();
dynamic_cast<BasketModel*>(ui_.basketView->model())->addArticle(seller, price, desc); dynamic_cast<BasketModel *>(m_ui.basketView->model())->addArticle(seller, price, desc);
ui_.basketView->resizeColumnToContents(1); m_ui.basketView->resizeColumnToContents(1);
ui_.basketSumLabel->setText(marketplace_->getBasketSumAsString().c_str()); m_ui.basketSumLabel->setText(m_marketplace->getBasketSumAsString().c_str());
} }
} }
ui_.sellerNoEdit->clear(); m_ui.sellerNoEdit->clear();
} }
void MainWindow::onGivenSpinBoxValueChanged(double value) void MainWindow::onGivenSpinBoxValueChanged(double value)
{ {
int givenInCent = std::round(value * 100); int givenInCent = std::round(value * 100);
int basketSumInCent = marketplace_->getBasketSumInCent(); int basketSumInCent = m_marketplace->getBasketSumInCent();
int drawback = givenInCent - basketSumInCent; int drawback = givenInCent - basketSumInCent;
ui_.drawbackLabel->setText(formatCentAsEuroString(drawback).c_str()); m_ui.drawbackLabel->setText(formatCentAsEuroString(drawback).c_str());
} }
void MainWindow::onBasketViewSelectionChanged(const QItemSelection& selected, void MainWindow::onBasketViewSelectionChanged(const QItemSelection &selected,
[[maybe_unused]] const QItemSelection& deselected) [[maybe_unused]] const QItemSelection &deselected)
{ {
if (selected.size() > 0) { if (selected.size() > 0) {
ui_.cancelArticleButton->setEnabled(true); m_ui.cancelArticleButton->setEnabled(true);
} else { } else {
ui_.cancelArticleButton->setEnabled(false); m_ui.cancelArticleButton->setEnabled(false);
} }
} }
void MainWindow::onSalesViewSelectionChanged(const QItemSelection& selected, void MainWindow::onSalesViewSelectionChanged(const QItemSelection &selected,
[[maybe_unused]] const QItemSelection& deselected) [[maybe_unused]] const QItemSelection &deselected)
{ {
if (selected.size() > 0) { if (selected.size() > 0) {
ui_.cancelSaleButton->setEnabled(true); m_ui.cancelSaleButton->setEnabled(true);
if (!selected.indexes()[0].parent().isValid()) if (!selected.indexes()[0].parent().isValid())
ui_.printSaleReceiptButton->setEnabled(true); m_ui.printSaleReceiptButton->setEnabled(true);
else else
ui_.printSaleReceiptButton->setEnabled(false); m_ui.printSaleReceiptButton->setEnabled(false);
} else { } else {
ui_.cancelSaleButton->setEnabled(false); m_ui.cancelSaleButton->setEnabled(false);
ui_.printSaleReceiptButton->setEnabled(false); m_ui.printSaleReceiptButton->setEnabled(false);
} }
} }
void MainWindow::onCancelArticleButtonClicked([[maybe_unused]] bool checked) void MainWindow::onCancelArticleButtonClicked([[maybe_unused]] bool checked)
{ {
auto selModel = ui_.basketView->selectionModel(); auto selModel = m_ui.basketView->selectionModel();
if (selModel->hasSelection() == false) if (selModel->hasSelection() == false)
return; return;
@ -342,16 +336,17 @@ void MainWindow::onCancelArticleButtonClicked([[maybe_unused]] bool checked)
// Deleting the rows, beginning with the last one! // Deleting the rows, beginning with the last one!
for (auto iter = indexes.constEnd() - 1; iter >= indexes.constBegin(); --iter) { for (auto iter = indexes.constEnd() - 1; iter >= indexes.constBegin(); --iter) {
ui_.basketView->model()->removeRow(iter->row()); m_ui.basketView->model()->removeRow(iter->row());
} }
ui_.basketSumLabel->setText(marketplace_->getBasketSumAsString().c_str()); // Update basket sum m_ui.basketSumLabel->setText(
ui_.sellerNoEdit->setFocus(); m_marketplace->getBasketSumAsString().c_str()); // Update basket sum
m_ui.sellerNoEdit->setFocus();
} }
void MainWindow::onCancelSaleButtonClicked([[maybe_unused]] bool checked) void MainWindow::onCancelSaleButtonClicked([[maybe_unused]] bool checked)
{ {
auto selModel = ui_.salesView->selectionModel(); auto selModel = m_ui.salesView->selectionModel();
if (selModel->hasSelection() == false) if (selModel->hasSelection() == false)
return; return;
@ -368,25 +363,25 @@ void MainWindow::onCancelSaleButtonClicked([[maybe_unused]] bool checked)
// Deleting the rows, beginning with the last one! // Deleting the rows, beginning with the last one!
for (auto iter = indexes.constEnd() - 1; iter >= indexes.constBegin(); --iter) { for (auto iter = indexes.constEnd() - 1; iter >= indexes.constBegin(); --iter) {
ui_.salesView->model()->removeRow(iter->row(), iter->parent()); m_ui.salesView->model()->removeRow(iter->row(), iter->parent());
} }
ui_.salesView->collapseAll(); m_ui.salesView->collapseAll();
QString lastPriceValue(formatCentAsEuroString(0).c_str()); QString lastPriceValue(formatCentAsEuroString(0).c_str());
if (ui_.salesView->model()->rowCount() > 0) { if (m_ui.salesView->model()->rowCount() > 0) {
lastPriceValue = lastPriceValue =
ui_.salesView->model()->data(ui_.salesView->model()->index(0, 1)).toString(); m_ui.salesView->model()->data(m_ui.salesView->model()->index(0, 1)).toString();
} }
ui_.lastPriceLabel1->setText(lastPriceValue); m_ui.lastPriceLabel1->setText(lastPriceValue);
ui_.lastPriceLabel2->setText(lastPriceValue); m_ui.lastPriceLabel2->setText(lastPriceValue);
updateStatLabel(); updateStatLabel();
} }
void MainWindow::onPrintSaleReceiptButtonClicked([[maybe_unused]] bool checked) void MainWindow::onPrintSaleReceiptButtonClicked([[maybe_unused]] bool checked)
{ {
auto selModel = ui_.salesView->selectionModel(); auto selModel = m_ui.salesView->selectionModel();
if (selModel->hasSelection() == false) if (selModel->hasSelection() == false)
return; return;
@ -395,7 +390,7 @@ void MainWindow::onPrintSaleReceiptButtonClicked([[maybe_unused]] bool checked)
QString posPrinterEndpoint = settings.value("global/posPrinterEndpoint", "").toString(); QString posPrinterEndpoint = settings.value("global/posPrinterEndpoint", "").toString();
auto indexes = selModel->selectedRows(); auto indexes = selModel->selectedRows();
auto& sale = marketplace_->getSales().at(indexes[0].row()); auto &sale = m_marketplace->getSales().at(indexes[0].row());
auto printerDevice = auto printerDevice =
convertToPosPrinterDevice(posPrinterDevice.toStdString(), posPrinterEndpoint.toStdString()); convertToPosPrinterDevice(posPrinterDevice.toStdString(), posPrinterEndpoint.toStdString());
@ -415,7 +410,7 @@ void MainWindow::onPrintSaleReceiptButtonClicked([[maybe_unused]] bool checked)
void MainWindow::onCancelAllArticlesButtonClicked([[maybe_unused]] bool checked) void MainWindow::onCancelAllArticlesButtonClicked([[maybe_unused]] bool checked)
{ {
if (ui_.basketView->model()->rowCount() == 0) if (m_ui.basketView->model()->rowCount() == 0)
return; return;
auto dlgResult = auto dlgResult =
@ -426,10 +421,11 @@ void MainWindow::onCancelAllArticlesButtonClicked([[maybe_unused]] bool checked)
if (dlgResult == QMessageBox::No) if (dlgResult == QMessageBox::No)
return; return;
dynamic_cast<BasketModel*>(ui_.basketView->model())->cancelSale(); dynamic_cast<BasketModel *>(m_ui.basketView->model())->cancelSale();
ui_.basketSumLabel->setText(marketplace_->getBasketSumAsString().c_str()); // Update basket sum m_ui.basketSumLabel->setText(
ui_.sellerNoEdit->setFocus(); m_marketplace->getBasketSumAsString().c_str()); // Update basket sum
m_ui.sellerNoEdit->setFocus();
} }
void MainWindow::onAboutQt() { QMessageBox::aboutQt(this); } void MainWindow::onAboutQt() { QMessageBox::aboutQt(this); }
@ -445,9 +441,9 @@ void MainWindow::onAbout()
">info@rustysoft.de</a>&gt;</p>"); ">info@rustysoft.de</a>&gt;</p>");
} }
void MainWindow::onImportSellerExcelActionTriggered() void MainWindow::onImportSellerActionTriggered()
{ {
if (!marketplace_->getSales().empty()) { if (!m_marketplace->getSales().empty()) {
QMessageBox(QMessageBox::Icon::Information, "Import nicht möglich", QMessageBox(QMessageBox::Icon::Information, "Import nicht möglich",
"Der Import ist nicht möglich, da schon Verkäufe getätigt wurden.", "Der Import ist nicht möglich, da schon Verkäufe getätigt wurden.",
QMessageBox::StandardButton::Ok, this) QMessageBox::StandardButton::Ok, this)
@ -455,9 +451,9 @@ void MainWindow::onImportSellerExcelActionTriggered()
return; return;
} }
auto filename = QFileDialog::getOpenFileName( auto filename =
this, "Verkäufer importieren", QString(), QFileDialog::getOpenFileName(this, "Verkäufer importieren", QString(),
"Alle unterstützte Dateien (*.xlsx *.csv);;Excel Dateien (*.xlsx);;CSV Dateien (*.csv)"); "Alle unterstützte Dateien (*.csv);;CSV Dateien (*.csv)");
if (filename.isEmpty()) if (filename.isEmpty())
return; return;
@ -469,76 +465,19 @@ void MainWindow::onImportSellerExcelActionTriggered()
#endif #endif
std::size_t numImported{}; std::size_t numImported{};
if (case_insensitive_match(filePath.extension().string(), std::string(".xlsx"))) { numImported = CsvReader::readSellersFromFile(filePath, m_marketplace.get());
numImported = ExcelReader::readSellersFromFile(filePath, marketplace_.get());
} else {
numImported = CsvReader::readSellersFromFile(filePath, marketplace_.get());
}
updateStatLabel(); updateStatLabel();
using namespace std::string_literals; using namespace std::string_literals;
std::ostringstream msg; std::ostringstream msg;
msg << "Aus der Excel/CSV-Datei wurden <b>"s << std::to_string(numImported) msg << "Aus der CSV-Datei wurden <b>"s << std::to_string(numImported)
<< "</b> Verkäufer importiert."; << "</b> Verkäufer importiert.";
QMessageBox(QMessageBox::Icon::Information, "Verkäufer erfolgreich importiert", QMessageBox(QMessageBox::Icon::Information, "Verkäufer erfolgreich importiert",
msg.str().c_str(), QMessageBox::StandardButton::Ok, this) msg.str().c_str(), QMessageBox::StandardButton::Ok, this)
.exec(); .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;
#if defined(_WIN64) || defined(_WIN32)
fs::path filePath(filename.toStdWString());
#else
fs::path filePath(filename.toStdString());
#endif
std::size_t numImported{};
numImported = JsonUtil::importSellers(filePath, marketplace_.get());
updateStatLabel();
using namespace std::string_literals;
std::ostringstream msg;
msg << "Aus der JSON-Datei wurden <b>"s << std::to_string(numImported)
<< "</b> Verkäufer importiert.";
QMessageBox(QMessageBox::Icon::Information, "Verkäufer erfolgreich importiert",
msg.str().c_str(), QMessageBox::StandardButton::Ok, this)
.exec();
}
void MainWindow::onExportSellerJsonActionTriggered()
{
auto filename = QFileDialog::getSaveFileName(
this, "Verkäufer exportieren", QString("kima2_verkaeufer.json"), "JSON Dateien (*.json)");
if (filename.isEmpty())
return;
#if defined(_WIN64) || defined(_WIN32)
fs::path filePath(filename.toStdWString());
#else
fs::path filePath(filename.toStdString());
#endif
JsonUtil::exportSellers(filePath, marketplace_.get());
}
void MainWindow::onExportSalesJsonActionTriggered() void MainWindow::onExportSalesJsonActionTriggered()
{ {
QSettings settings; QSettings settings;
@ -557,7 +496,7 @@ void MainWindow::onExportSalesJsonActionTriggered()
fs::path filePath(filename.toStdString()); fs::path filePath(filename.toStdString());
#endif #endif
JsonUtil::exportSales(filePath, marketplace_.get(), JsonUtil::exportSales(filePath, m_marketplace.get(),
settings.value("global/cashPointNo").toInt()); settings.value("global/cashPointNo").toInt());
} }
@ -565,27 +504,30 @@ void MainWindow::onImportSalesJsonActionTriggered()
{ {
QSettings settings; QSettings settings;
auto filename = QFileDialog::getOpenFileName(this, "Umsätze/Transaktionen importieren", auto filenames = QFileDialog::getOpenFileNames(this, "Umsätze/Transaktionen importieren",
QString(), "JSON Dateien (*.json)"); QString(), "JSON Dateien (*.json)");
if (filename.isEmpty()) if (filenames.isEmpty())
return; return;
for(auto filename: filenames) {
#if defined(_WIN64) || defined(_WIN32) #if defined(_WIN64) || defined(_WIN32)
fs::path filePath(filename.toStdWString()); fs::path filePath(filename.toStdWString());
#else #else
fs::path filePath(filename.toStdString()); fs::path filePath(filename.toStdString());
#endif #endif
delete ui_.salesView->model(); delete m_ui.salesView->model();
try { try {
JsonUtil::importSales(filePath, marketplace_.get(), JsonUtil::importSales(filePath, m_marketplace.get(),
settings.value("global/cashPointNo").toInt()); settings.value("global/cashPointNo").toInt());
} catch (std::runtime_error& err) { } catch (std::runtime_error &err) {
QMessageBox(QMessageBox::Icon::Warning, "Import nicht möglich", err.what(), QMessageBox::Ok, QMessageBox(QMessageBox::Icon::Warning, "Import nicht möglich", err.what(), QMessageBox::Ok,
this) this)
.exec(); .exec();
}
} }
setSaleModel(); setSaleModel();
updateStatLabel(); updateStatLabel();
} }
@ -610,7 +552,7 @@ void MainWindow::readGeometry()
settings.endGroup(); settings.endGroup();
} }
void MainWindow::closeEvent(QCloseEvent* event) void MainWindow::closeEvent(QCloseEvent *event)
{ {
writeGeometry(); writeGeometry();
event->accept(); event->accept();
@ -620,9 +562,9 @@ void MainWindow::updateStatLabel()
{ {
std::string statistics("<b>KIMA2 - Version "); std::string statistics("<b>KIMA2 - Version ");
statistics += PROJECT_VERSION; statistics += PROJECT_VERSION;
statistics += "</b><br />Verkäufer: " + std::to_string(marketplace_->getSellers().size() - 1); statistics += "</b><br />Verkäufer: " + std::to_string(m_marketplace->getSellers().size() - 1);
statistics += "<br />Kunden: " + std::to_string(marketplace_->getSales().size()); statistics += "<br />Kunden: " + std::to_string(m_marketplace->getSales().size());
statistics += "<br />Umsatz: " + marketplace_->getOverallSumAsString(); statistics += "<br />Umsatz: " + m_marketplace->getOverallSumAsString();
ui_.statLabel->setText(statistics.c_str()); m_ui.statLabel->setText(statistics.c_str());
} }

View File

@ -3,7 +3,7 @@
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include <marketplace.h> #include <core/marketplace.h>
#include <QMainWindow> #include <QMainWindow>
#include <QtGui/QCloseEvent> #include <QtGui/QCloseEvent>
@ -16,7 +16,7 @@ class MainWindow : public QMainWindow
public: public:
MainWindow(); MainWindow();
Marketplace* getMarketplace() { return marketplace_.get(); } Marketplace* getMarketplace() { return m_marketplace.get(); }
private slots: private slots:
void onBasketViewSelectionChanged(const QItemSelection& selected, void onBasketViewSelectionChanged(const QItemSelection& selected,
@ -39,9 +39,7 @@ class MainWindow : public QMainWindow
void checkSellerNo(bool ctrlPressed = false); void checkSellerNo(bool ctrlPressed = false);
void onPaidButtonTriggered(); void onPaidButtonTriggered();
void onGivenSpinBoxValueChanged(double value); void onGivenSpinBoxValueChanged(double value);
void onImportSellerExcelActionTriggered(); void onImportSellerActionTriggered();
void onImportSellerJsonActionTriggered();
void onExportSellerJsonActionTriggered();
void onExportSalesJsonActionTriggered(); void onExportSalesJsonActionTriggered();
void onImportSalesJsonActionTriggered(); void onImportSalesJsonActionTriggered();
void setSaleModel(); void setSaleModel();
@ -49,8 +47,8 @@ class MainWindow : public QMainWindow
void readGeometry(); void readGeometry();
void updateStatLabel(); void updateStatLabel();
Ui::MainWindow ui_; Ui::MainWindow m_ui;
std::unique_ptr<Marketplace> marketplace_; std::unique_ptr<Marketplace> m_marketplace;
}; };
#endif #endif

View File

@ -423,7 +423,7 @@ drucken</string>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>817</width> <width>817</width>
<height>30</height> <height>24</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menu_Datei"> <widget class="QMenu" name="menu_Datei">
@ -440,16 +440,8 @@ drucken</string>
<property name="title"> <property name="title">
<string>&amp;Verkäufer</string> <string>&amp;Verkäufer</string>
</property> </property>
<widget class="QMenu" name="importSellerMenu">
<property name="title">
<string>Importieren</string>
</property>
<addaction name="importSellerExcelAction"/>
<addaction name="importSellerJsonAction"/>
</widget>
<addaction name="actionEditSeller"/> <addaction name="actionEditSeller"/>
<addaction name="importSellerMenu"/> <addaction name="importSellerAction"/>
<addaction name="exportSellerJsonAction"/>
</widget> </widget>
<widget class="QMenu" name="menuHilfe"> <widget class="QMenu" name="menuHilfe">
<property name="title"> <property name="title">
@ -513,9 +505,9 @@ drucken</string>
<string>Exportieren für andere Kasse (JSON)</string> <string>Exportieren für andere Kasse (JSON)</string>
</property> </property>
</action> </action>
<action name="importSellerExcelAction"> <action name="importSellerActionX">
<property name="text"> <property name="text">
<string>Aus Excel/CSV-Datei (initial)</string> <string>Aus CSV-Datei (initial)</string>
</property> </property>
</action> </action>
<action name="importSellerJsonAction"> <action name="importSellerJsonAction">
@ -548,6 +540,11 @@ drucken</string>
<string>Lizenz</string> <string>Lizenz</string>
</property> </property>
</action> </action>
<action name="importSellerAction">
<property name="text">
<string>Importieren (aus CSV-Datei)</string>
</property>
</action>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>

23
src/gui/meson.build Normal file
View File

@ -0,0 +1,23 @@
qt5 = import('qt5')
qt5_dep = dependency('qt5', modules: ['Core', 'Gui', 'PrintSupport', 'Network'])
thread_dep = dependency('threads')
src = ['kima2.cpp', 'mainwindow.cpp', 'sellerdialog.cpp', 'sellermodel.cpp',
'pricedialog.cpp', 'basketmodel.cpp', 'salemodel.cpp', 'reportdialog.cpp',
'reportmodel.cpp', 'settingsdialog.cpp']
ui = ['mainwindow.ui', 'sellerdialog.ui', 'pricedialog.ui', 'reportdialog.ui', 'settingsdialog.ui']
processed = qt5.preprocess(moc_headers : ['basketmodel.h', 'mainwindow.h', 'pricedialog.h',
'reportdialog.h', 'sellerdialog.h', 'settingsdialog.h',
'sellermodel.h', 'salemodel.h'],
ui_files : ui,
qresources : '../../kima2.qrc',
dependencies: qt5_dep)
kima2 = executable('kima2', sources : [src, processed],
dependencies : [qt5_dep, singleapp_dep, core_dep, printer_dep, thread_dep],
include_directories : [configuration_inc],
install : true)

View File

@ -6,31 +6,31 @@
PriceDialog::PriceDialog(QWidget* parent, bool forceDesc, Qt::WindowFlags f) : QDialog(parent, f) PriceDialog::PriceDialog(QWidget* parent, bool forceDesc, Qt::WindowFlags f) : QDialog(parent, f)
{ {
forceDesc_ = forceDesc; m_forceDesc = forceDesc;
ui_.setupUi(this); m_ui.setupUi(this);
ui_.priceSpinBox->setFocus(); m_ui.priceSpinBox->setFocus();
} }
int PriceDialog::getPrice() const { return static_cast<int>(ui_.priceSpinBox->value() * 100); } int PriceDialog::getPrice() const { return static_cast<int>(m_ui.priceSpinBox->value() * 100); }
std::string PriceDialog::getDescription() const { return ui_.descEdit->text().toStdString(); } std::string PriceDialog::getDescription() const { return m_ui.descEdit->text().toStdString(); }
void PriceDialog::accept() void PriceDialog::accept()
{ {
if (static_cast<int>(std::round(ui_.priceSpinBox->value() * 100.0L)) % 50 != 0) { if (static_cast<int>(std::round(m_ui.priceSpinBox->value() * 100.0L)) % 50 != 0) {
QMessageBox(QMessageBox::Icon::Warning, "Falsche Preiseingabe", QMessageBox(QMessageBox::Icon::Warning, "Falsche Preiseingabe",
"Es sind nur 0,50 Cent-Schritte erlaubt.", QMessageBox::StandardButton::Ok, "Es sind nur 0,50 Cent-Schritte erlaubt.", QMessageBox::StandardButton::Ok,
this) this)
.exec(); .exec();
} else if (forceDesc_ && ui_.descEdit->text().trimmed().isEmpty()) { } else if (m_forceDesc && m_ui.descEdit->text().trimmed().isEmpty()) {
QMessageBox(QMessageBox::Icon::Warning, "Artikelbeschreibung fehlt", QMessageBox(QMessageBox::Icon::Warning, "Artikelbeschreibung fehlt",
"Da Sie auf das Sonderkonto buchen ist eine Artikelbeschreibung erforderlich.", "Da Sie auf das Sonderkonto buchen ist eine Artikelbeschreibung erforderlich.",
QMessageBox::StandardButton::Ok, this) QMessageBox::StandardButton::Ok, this)
.exec(); .exec();
ui_.descEdit->setFocus(); m_ui.descEdit->setFocus();
} else { } else {
QDialog::accept(); QDialog::accept();
} }
} }
void PriceDialog::setForceDesc(bool force) { forceDesc_ = force; } void PriceDialog::setForceDesc(bool force) { m_forceDesc = force; }

View File

@ -19,8 +19,8 @@ class PriceDialog : public QDialog
private: private:
void on_model_duplicateSellerNo(const QString& message); void on_model_duplicateSellerNo(const QString& message);
virtual void accept() override; virtual void accept() override;
Ui::PriceDialog ui_; Ui::PriceDialog m_ui;
bool forceDesc_; bool m_forceDesc;
}; };
#endif #endif

View File

@ -2,8 +2,9 @@
#include "mainwindow.h" #include "mainwindow.h"
#include <posprinter.h> #include <core/utils.h>
#include <utils.h> #include <printer/posprinter.h>
#include <printer/utils.h>
#include <filesystem> #include <filesystem>
@ -16,22 +17,22 @@
namespace fs = std::filesystem; namespace fs = std::filesystem;
ReportDialog::ReportDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f) ReportDialog::ReportDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f)
{ {
ui_.setupUi(this); m_ui.setupUi(this);
market_ = dynamic_cast<MainWindow*>(parent)->getMarketplace(); m_market = dynamic_cast<MainWindow *>(parent)->getMarketplace();
model_ = std::make_unique<ReportModel>(market_, ui_.reportView); m_model = std::make_unique<ReportModel>(m_market, m_ui.reportView);
ui_.reportView->setModel(model_.get()); m_ui.reportView->setModel(m_model.get());
ui_.reportView->hideColumn(0); m_ui.reportView->hideColumn(0);
ui_.reportView->setRowHidden(0, true); // hide the special "Sonderkonto" user m_ui.reportView->setRowHidden(0, true); // hide the special "Sonderkonto" user
connect(ui_.exportCsvButton, &QPushButton::clicked, this, connect(m_ui.exportCsvButton, &QPushButton::clicked, this,
&ReportDialog::onExportCsvButtonClicked); &ReportDialog::onExportCsvButtonClicked);
connect(ui_.printReportButton, &QPushButton::clicked, this, connect(m_ui.printReportButton, &QPushButton::clicked, this,
&ReportDialog::onPrintReportButtonClicked); &ReportDialog::onPrintReportButtonClicked);
connect(ui_.printSellerReceiptButton, &QPushButton::clicked, this, connect(m_ui.printSellerReceiptButton, &QPushButton::clicked, this,
&ReportDialog::onPrintSellerReceiptButtonClicked); &ReportDialog::onPrintSellerReceiptButtonClicked);
connect(ui_.reportView->selectionModel(), &QItemSelectionModel::selectionChanged, this, connect(m_ui.reportView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
&ReportDialog::onReportViewSelectionChanged); &ReportDialog::onReportViewSelectionChanged);
} }
@ -47,9 +48,13 @@ void ReportDialog::onExportCsvButtonClicked()
if (filename.isEmpty()) if (filename.isEmpty())
return; return;
#if defined(_WIN64) || defined(_WIN32)
fs::path filePath(filename.toStdWString()); fs::path filePath(filename.toStdWString());
#else
fs::path filePath(filename.toStdString());
#endif
market_->exportReportToCSV(filePath, feeInPercent, maxFeeInEuro); m_market->exportReportToCSV(filePath, feeInPercent, maxFeeInEuro);
} }
void ReportDialog::onPrintReportButtonClicked() void ReportDialog::onPrintReportButtonClicked()
@ -70,8 +75,8 @@ void ReportDialog::onPrintReportButtonClicked()
QPainter painter; QPainter painter;
int height = printer.height(); int height = printer.height();
int width = printer.width(); int width = printer.width();
const double ENTRIES_PER_PAGE = 51; const double ENTRIES_PER_PAGE = 45;
const auto& sellers = market_->getSellers(); const auto &sellers = m_market->getSellers();
unsigned int numPages = std::ceil(sellers.size() / ENTRIES_PER_PAGE); unsigned int numPages = std::ceil(sellers.size() / ENTRIES_PER_PAGE);
painter.begin(&printer); painter.begin(&printer);
@ -121,7 +126,7 @@ void ReportDialog::onPrintReportButtonClicked()
} }
// pieces booked on the special account "Sonderkonto" // pieces booked on the special account "Sonderkonto"
const auto specialSeller = market_->findSellerWithSellerNo(0); const auto specialSeller = m_market->findSellerWithSellerNo(0);
if (specialSeller && specialSeller->numArticlesSold() > 0) { if (specialSeller && specialSeller->numArticlesSold() > 0) {
printer.newPage(); printer.newPage();
painter.setFont(QFont("Arial", 16, QFont::Bold)); painter.setFont(QFont("Arial", 16, QFont::Bold));
@ -131,7 +136,7 @@ void ReportDialog::onPrintReportButtonClicked()
QString content("Einzelteile ohne Nummer\n=======================\n\n"); QString content("Einzelteile ohne Nummer\n=======================\n\n");
unsigned int lines{0}; unsigned int lines{0};
unsigned int pages{1}; 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:").arg(article->getDescription().substr(0, 45).c_str(), -45);
content += QString("%1\n").arg(article->getPriceAsString().c_str(), 11); content += QString("%1\n").arg(article->getPriceAsString().c_str(), 11);
++lines; ++lines;
@ -158,8 +163,8 @@ void ReportDialog::onPrintReportButtonClicked()
"Auswertung Kindersachenmarkt"); "Auswertung Kindersachenmarkt");
painter.setFont(fixedFont); painter.setFont(fixedFont);
QString content("Gesamtstatistik\n===============\n\n"); QString content("Gesamtstatistik\n===============\n\n");
int numArticlesOffered = market_->getNumArticlesOffered(); int numArticlesOffered = m_market->getNumArticlesOffered();
int numArticlesSold = market_->getNumArticlesSold(); int numArticlesSold = m_market->getNumArticlesSold();
double percentArticlesSold = double percentArticlesSold =
(static_cast<double>(numArticlesSold) / static_cast<double>(numArticlesOffered)) * 100; (static_cast<double>(numArticlesSold) / static_cast<double>(numArticlesOffered)) * 100;
content += QString("Registrierte Verkäufer: %1\n").arg(sellers.size() - 1, 6); content += QString("Registrierte Verkäufer: %1\n").arg(sellers.size() - 1, 6);
@ -167,14 +172,14 @@ void ReportDialog::onPrintReportButtonClicked()
content += QString("Verkaufte Artikel: %1 (%L2 %)\n") content += QString("Verkaufte Artikel: %1 (%L2 %)\n")
.arg(numArticlesSold, 6) .arg(numArticlesSold, 6)
.arg(percentArticlesSold, 0, 'f', 2); .arg(percentArticlesSold, 0, 'f', 2);
content += QString("Anzahl Kunden: %1\n\n").arg(market_->getSales().size(), 6); content += QString("Anzahl Kunden: %1\n\n").arg(m_market->getSales().size(), 6);
content += QString("Gesamtumsatz: %1\n").arg(market_->getOverallSumAsString().c_str(), 10); content += QString("Gesamtumsatz: %1\n").arg(m_market->getOverallSumAsString().c_str(), 10);
content += content +=
QString("Ausgezahlt: %1\n") QString("Ausgezahlt: %1\n")
.arg(market_->getOverallPaymentAsString(feeInPercent, maxFeeInEuro * 100).c_str(), 10); .arg(m_market->getOverallPaymentAsString(feeInPercent, maxFeeInEuro * 100).c_str(), 10);
content += content +=
QString("Verbleibend: %1\n\n") QString("Verbleibend: %1\n\n")
.arg(market_->getOverallRevenueAsString(feeInPercent, maxFeeInEuro * 100).c_str(), 10); .arg(m_market->getOverallRevenueAsString(feeInPercent, maxFeeInEuro * 100).c_str(), 10);
content += QString("(Einbehaltener Prozentsatz: %1 %)\n").arg(feeInPercent, 3); content += QString("(Einbehaltener Prozentsatz: %1 %)\n").arg(feeInPercent, 3);
content += QString("(Maximal einbehaltener Betrag: %1 €)\n").arg(maxFeeInEuro, 3); content += QString("(Maximal einbehaltener Betrag: %1 €)\n").arg(maxFeeInEuro, 3);
@ -191,12 +196,12 @@ void ReportDialog::onPrintSellerReceiptButtonClicked()
QString posPrinterDevice = settings.value("global/posPrinterDevice", "").toString(); QString posPrinterDevice = settings.value("global/posPrinterDevice", "").toString();
QString posPrinterEndpoint = settings.value("global/posPrinterEndpoint", "").toString(); QString posPrinterEndpoint = settings.value("global/posPrinterEndpoint", "").toString();
auto selModel = ui_.reportView->selectionModel(); auto selModel = m_ui.reportView->selectionModel();
if (selModel->hasSelection() == false) if (selModel->hasSelection() == false)
return; return;
auto indexes = selModel->selectedRows(); auto indexes = selModel->selectedRows();
auto& seller = market_->getSellers().at(indexes[0].row()); auto &seller = m_market->getSellers().at(indexes[0].row());
auto printerDevice = auto printerDevice =
convertToPosPrinterDevice(posPrinterDevice.toStdString(), posPrinterEndpoint.toStdString()); convertToPosPrinterDevice(posPrinterDevice.toStdString(), posPrinterEndpoint.toStdString());
@ -215,12 +220,12 @@ void ReportDialog::onPrintSellerReceiptButtonClicked()
settings.value("global/commune", "Dettingen").toString().toStdString()); settings.value("global/commune", "Dettingen").toString().toStdString());
} }
void ReportDialog::onReportViewSelectionChanged(const QItemSelection& selected, void ReportDialog::onReportViewSelectionChanged(const QItemSelection &selected,
[[maybe_unused]] const QItemSelection& deselected) [[maybe_unused]] const QItemSelection &deselected)
{ {
if (selected.size() > 0) { if (selected.size() > 0) {
ui_.printSellerReceiptButton->setEnabled(true); m_ui.printSellerReceiptButton->setEnabled(true);
} else { } else {
ui_.printSellerReceiptButton->setEnabled(false); m_ui.printSellerReceiptButton->setEnabled(false);
} }
} }

View File

@ -5,7 +5,7 @@
#include "reportmodel.h" #include "reportmodel.h"
#include <marketplace.h> #include <core/marketplace.h>
#include <QDialog> #include <QDialog>
@ -25,9 +25,9 @@ class ReportDialog : public QDialog
const QItemSelection& deselected); const QItemSelection& deselected);
private: private:
Ui::ReportDialog ui_; Ui::ReportDialog m_ui;
Marketplace* market_; Marketplace* m_market;
std::unique_ptr<ReportModel> model_; std::unique_ptr<ReportModel> m_model;
}; };
#endif #endif

View File

@ -5,16 +5,16 @@
#include <QSettings> #include <QSettings>
ReportModel::ReportModel(Marketplace* market, QObject* parent) ReportModel::ReportModel(Marketplace* market, QObject* parent)
: QAbstractTableModel(parent), market_(market) : QAbstractTableModel(parent), m_market(market)
{ {
QSettings settings; QSettings settings;
feeInPercent_ = settings.value("global/feeInPercent").toInt(); m_feeInPercent = settings.value("global/feeInPercent").toInt();
maxFeeInCent_ = settings.value("global/maxFeeInEuro").toInt() * 100; m_maxFeeInCent = settings.value("global/maxFeeInEuro").toInt() * 100;
} }
int ReportModel::rowCount([[maybe_unused]] const QModelIndex& parent) const int ReportModel::rowCount([[maybe_unused]] const QModelIndex& parent) const
{ {
return static_cast<int>(market_->getSellers().size()); return static_cast<int>(m_market->getSellers().size());
} }
int ReportModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 7; } int ReportModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 7; }
@ -52,10 +52,10 @@ QVariant ReportModel::data(const QModelIndex& index, int role) const
if (role != Qt::DisplayRole) if (role != Qt::DisplayRole)
return QVariant(); return QVariant();
if (market_->getSellers().size() == 0) if (m_market->getSellers().size() == 0)
return QVariant(); return QVariant();
Seller* seller = market_->getSellers().at(index.row()).get(); Seller* seller = m_market->getSellers().at(index.row()).get();
switch (index.column()) { switch (index.column()) {
case 0: case 0:
@ -71,7 +71,7 @@ QVariant ReportModel::data(const QModelIndex& index, int role) const
case 5: case 5:
return seller->sumAsString().c_str(); return seller->sumAsString().c_str();
case 6: case 6:
return paymentAsString(seller->sumInCents(), feeInPercent_, maxFeeInCent_).c_str(); return paymentAsString(seller->sumInCents(), m_feeInPercent, m_maxFeeInCent).c_str();
default: default:
return "???"; return "???";
} }

View File

@ -1,7 +1,7 @@
#ifndef REPORT_MODEL_H #ifndef REPORT_MODEL_H
#define REPORT_MODEL_H #define REPORT_MODEL_H
#include <marketplace.h> #include <core/marketplace.h>
#include <QAbstractTableModel> #include <QAbstractTableModel>
@ -15,9 +15,9 @@ class ReportModel : public QAbstractTableModel
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
private: private:
Marketplace* market_; Marketplace* m_market;
int feeInPercent_{}; int m_feeInPercent{};
int maxFeeInCent_{}; int m_maxFeeInCent{};
}; };
#endif #endif

View File

@ -1,6 +1,6 @@
#include "salemodel.h" #include "salemodel.h"
#include <article.h> #include <core/article.h>
#include <algorithm> #include <algorithm>
@ -9,7 +9,7 @@
SaleModel::SaleModel(Marketplace* market, QObject* parent) : QAbstractItemModel(parent) SaleModel::SaleModel(Marketplace* market, QObject* parent) : QAbstractItemModel(parent)
{ {
marketplace_ = market; m_marketplace = market;
} }
QModelIndex SaleModel::index(int row, int column, const QModelIndex& parent) const 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(); return QModelIndex();
if (!parent.isValid()) { if (!parent.isValid()) {
Sale* sale = marketplace_->getSales().at(row).get(); Sale* sale = m_marketplace->getSales().at(row).get();
return createIndex(row, column, sale); return createIndex(row, column, sale);
} else if (!parent.parent().isValid()) { } else if (!parent.parent().isValid()) {
Sale* sale = static_cast<Sale*>(parent.internalPointer()); Sale* sale = static_cast<Sale*>(parent.internalPointer());
@ -49,10 +49,10 @@ QModelIndex SaleModel::parent(const QModelIndex& index) const
sale = dynamic_cast<Sale*>(ent); sale = dynamic_cast<Sale*>(ent);
if (sale) { if (sale) {
if (sale == rootItem.get()) if (sale == m_rootItem.get())
return QModelIndex(); return QModelIndex();
else { else {
return createIndex(-1, 0, rootItem.get()); return createIndex(-1, 0, m_rootItem.get());
} }
} else { } else {
article = dynamic_cast<Article*>(ent); article = dynamic_cast<Article*>(ent);
@ -132,7 +132,7 @@ int SaleModel::rowCount(const QModelIndex& parent) const
return 0; return 0;
if (!parent.isValid()) { if (!parent.isValid()) {
return marketplace_->getSales().size(); return m_marketplace->getSales().size();
} else if (!parent.parent().isValid()) { } else if (!parent.parent().isValid()) {
Sale* sale = static_cast<Sale*>(parent.internalPointer()); Sale* sale = static_cast<Sale*>(parent.internalPointer());
return sale->getArticles().size(); return sale->getArticles().size();
@ -167,7 +167,7 @@ QVariant SaleModel::headerData(int section, Qt::Orientation orientation, int rol
void SaleModel::onBasketDataChanged() void SaleModel::onBasketDataChanged()
{ {
emit beginResetModel(); emit beginResetModel();
auto& sales = marketplace_->getSales(); auto& sales = m_marketplace->getSales();
std::sort(sales.begin(), sales.end(), [](const auto& lhs, const auto& rhs) { std::sort(sales.begin(), sales.end(), [](const auto& lhs, const auto& rhs) {
return lhs->getTimestamp() > rhs->getTimestamp(); return lhs->getTimestamp() > rhs->getTimestamp();
}); });
@ -179,11 +179,11 @@ bool SaleModel::removeRows(int row, int count, const QModelIndex& parent)
if (!parent.isValid()) { if (!parent.isValid()) {
// remove complete sale // remove complete sale
emit beginRemoveRows(parent, row, row + count - 1); emit beginRemoveRows(parent, row, row + count - 1);
auto& sale = marketplace_->getSales().at(row); auto& sale = m_marketplace->getSales().at(row);
sale->setState(Sale::State::DELETE); sale->setState(Sale::State::DELETE);
std::for_each(sale->getArticles().begin(), sale->getArticles().end(), std::for_each(sale->getArticles().begin(), sale->getArticles().end(),
[](auto& a) { a->setState(Article::State::DELETE); }); [](auto& a) { a->setState(Article::State::DELETE); });
marketplace_->storeToDb(); m_marketplace->storeToDb();
emit endRemoveRows(); emit endRemoveRows();
} else if (!parent.parent().isValid()) { } else if (!parent.parent().isValid()) {
@ -199,7 +199,7 @@ bool SaleModel::removeRows(int row, int count, const QModelIndex& parent)
sale->setState(Sale::State::DELETE); sale->setState(Sale::State::DELETE);
} }
emit beginRemoveRows(parent.parent(), 0, 0); emit beginRemoveRows(parent.parent(), 0, 0);
marketplace_->storeToDb(); m_marketplace->storeToDb();
emit endRemoveRows(); emit endRemoveRows();
} }

View File

@ -1,7 +1,7 @@
#ifndef SALEMODEL_H #ifndef SALEMODEL_H
#define SALEMODEL_H #define SALEMODEL_H
#include <marketplace.h> #include <core/marketplace.h>
#include <QAbstractItemModel> #include <QAbstractItemModel>
@ -24,8 +24,8 @@ class SaleModel : public QAbstractItemModel
void onBasketDataChanged(); void onBasketDataChanged();
private: private:
Marketplace* marketplace_; Marketplace* m_marketplace;
std::unique_ptr<Sale> rootItem{new Sale()}; std::unique_ptr<Sale> m_rootItem{new Sale()};
}; };
#endif #endif

View File

@ -7,25 +7,25 @@
SellerDialog::SellerDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f) SellerDialog::SellerDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f)
{ {
ui_.setupUi(this); m_ui.setupUi(this);
ui_.editButton->setVisible(false); m_ui.editButton->setVisible(false);
market_ = dynamic_cast<MainWindow*>(parent)->getMarketplace(); m_market = dynamic_cast<MainWindow*>(parent)->getMarketplace();
model_ = std::make_unique<SellerModel>(market_, ui_.tableView); m_model = std::make_unique<SellerModel>(m_market, m_ui.tableView);
ui_.tableView->setModel(model_.get()); m_ui.tableView->setModel(m_model.get());
ui_.tableView->setColumnHidden(0, true); // hide the uuid m_ui.tableView->setColumnHidden(0, true); // hide the uuid
ui_.tableView->setRowHidden(0, true); // hide the special "Sonderkonto" user m_ui.tableView->setRowHidden(0, true); // hide the special "Sonderkonto" user
connect(ui_.newButton, &QPushButton::clicked, this, &SellerDialog::on_newButton_clicked); connect(m_ui.newButton, &QPushButton::clicked, this, &SellerDialog::on_newButton_clicked);
connect(ui_.deleteButton, &QPushButton::clicked, this, &SellerDialog::on_deleteButton_clicked); connect(m_ui.deleteButton, &QPushButton::clicked, this, &SellerDialog::on_deleteButton_clicked);
connect(model_.get(), &SellerModel::duplicateSellerNo, this, connect(m_model.get(), &SellerModel::duplicateSellerNo, this,
&SellerDialog::on_model_duplicateSellerNo); &SellerDialog::on_model_duplicateSellerNo);
connect(ui_.tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this, connect(m_ui.tableView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
&SellerDialog::onSellerViewSelectionChanged); &SellerDialog::onSellerViewSelectionChanged);
} }
void SellerDialog::on_newButton_clicked() void SellerDialog::on_newButton_clicked()
{ {
// Don't allow new seller if market has already started // Don't allow new seller if market has already started
if (market_->getSales().size() > 0) { if (m_market->getSales().size() > 0) {
QMessageBox(QMessageBox::Icon::Warning, "Hinweis", QMessageBox(QMessageBox::Icon::Warning, "Hinweis",
"Da die Verkaufsphase schon begonnen hat (Artikel wurden bereits verkauft) " "Da die Verkaufsphase schon begonnen hat (Artikel wurden bereits verkauft) "
"können Sie keine Verkäufer mehr hinzufügen.", "können Sie keine Verkäufer mehr hinzufügen.",
@ -34,22 +34,22 @@ void SellerDialog::on_newButton_clicked()
return; return;
} }
ui_.tableView->reset(); m_ui.tableView->reset();
ui_.tableView->model()->insertRows(ui_.tableView->model()->rowCount(), 1); m_ui.tableView->model()->insertRows(m_ui.tableView->model()->rowCount(), 1);
ui_.tableView->scrollToBottom(); m_ui.tableView->scrollToBottom();
ui_.tableView->selectRow(ui_.tableView->model()->rowCount() - 1); m_ui.tableView->selectRow(m_ui.tableView->model()->rowCount() - 1);
QModelIndex idx = ui_.tableView->model()->index(ui_.tableView->model()->rowCount() - 1, 2); QModelIndex idx = m_ui.tableView->model()->index(m_ui.tableView->model()->rowCount() - 1, 2);
ui_.tableView->setCurrentIndex(idx); m_ui.tableView->setCurrentIndex(idx);
ui_.tableView->edit(idx); m_ui.tableView->edit(idx);
} }
void SellerDialog::on_deleteButton_clicked() void SellerDialog::on_deleteButton_clicked()
{ {
auto selModel = ui_.tableView->selectionModel(); auto selModel = m_ui.tableView->selectionModel();
if (selModel->hasSelection() == false) if (selModel->hasSelection() == false)
return; return;
if (market_->getSales().size() > 0) { if (m_market->getSales().size() > 0) {
QMessageBox(QMessageBox::Icon::Warning, "Hinweis", QMessageBox(QMessageBox::Icon::Warning, "Hinweis",
"Da die Verkaufsphase schon begonnen hat (Artikel wurden bereits verkauft) " "Da die Verkaufsphase schon begonnen hat (Artikel wurden bereits verkauft) "
"können Sie keine Verkäufer mehr löschen.", "können Sie keine Verkäufer mehr löschen.",
@ -72,7 +72,7 @@ void SellerDialog::on_deleteButton_clicked()
// Deleting the rows, beginning with the last one! // Deleting the rows, beginning with the last one!
for (auto iter = indexes.constEnd() - 1; iter >= indexes.constBegin(); --iter) { for (auto iter = indexes.constEnd() - 1; iter >= indexes.constBegin(); --iter) {
ui_.tableView->model()->removeRow(iter->row()); m_ui.tableView->model()->removeRow(iter->row());
} }
} }
@ -102,8 +102,8 @@ void SellerDialog::onSellerViewSelectionChanged(const QItemSelection& selected,
[[maybe_unused]] const QItemSelection& deselected) [[maybe_unused]] const QItemSelection& deselected)
{ {
if (selected.size() > 0) { if (selected.size() > 0) {
ui_.deleteButton->setEnabled(true); m_ui.deleteButton->setEnabled(true);
} else { } else {
ui_.deleteButton->setEnabled(false); m_ui.deleteButton->setEnabled(false);
} }
} }

View File

@ -26,9 +26,9 @@ class SellerDialog : public QDialog
void on_deleteButton_clicked(); void on_deleteButton_clicked();
void on_model_duplicateSellerNo(const QString& message); void on_model_duplicateSellerNo(const QString& message);
virtual void accept() override; virtual void accept() override;
Ui::SellerDialog ui_; Ui::SellerDialog m_ui;
Marketplace* market_; Marketplace* m_market;
std::unique_ptr<SellerModel> model_; std::unique_ptr<SellerModel> m_model;
}; };
#endif #endif

View File

@ -5,13 +5,13 @@
#include <QMessageBox> #include <QMessageBox>
SellerModel::SellerModel(Marketplace* market, QObject* parent) SellerModel::SellerModel(Marketplace* market, QObject* parent)
: QAbstractTableModel(parent), marketplace_(market) : QAbstractTableModel(parent), m_marketplace(market)
{ {
} }
int SellerModel::rowCount([[maybe_unused]] const QModelIndex& parent) const int SellerModel::rowCount([[maybe_unused]] const QModelIndex& parent) const
{ {
return marketplace_->getSellers().size(); return m_marketplace->getSellers().size();
} }
int SellerModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 5; } int SellerModel::columnCount([[maybe_unused]] const QModelIndex& parent) const { return 5; }
@ -21,10 +21,10 @@ QVariant SellerModel::data(const QModelIndex& index, int role) const
if (role != Qt::DisplayRole) if (role != Qt::DisplayRole)
return QVariant(); return QVariant();
if (marketplace_->getSellers().size() == 0) if (m_marketplace->getSellers().size() == 0)
return QVariant(); return QVariant();
Seller* seller = marketplace_->getSellers().at(index.row()).get(); Seller* seller = m_marketplace->getSellers().at(index.row()).get();
switch (index.column()) { switch (index.column()) {
case 0: case 0:
@ -78,7 +78,7 @@ bool SellerModel::setData(const QModelIndex& index, const QVariant& value, int r
if (role != Qt::EditRole) if (role != Qt::EditRole)
return false; return false;
Seller* seller = marketplace_->getSellers().at(index.row()).get(); Seller* seller = m_marketplace->getSellers().at(index.row()).get();
switch (index.column()) { switch (index.column()) {
case 0: case 0:
@ -88,11 +88,11 @@ bool SellerModel::setData(const QModelIndex& index, const QVariant& value, int r
if (value.toInt() < 0) if (value.toInt() < 0)
return false; return false;
auto iter = auto iter =
std::find_if(marketplace_->getSellers().begin(), marketplace_->getSellers().end(), std::find_if(m_marketplace->getSellers().begin(), m_marketplace->getSellers().end(),
[&value](const std::unique_ptr<Seller>& s) { [&value](const std::unique_ptr<Seller>& s) {
return value.toInt() == s->getSellerNo(); return value.toInt() == s->getSellerNo();
}); });
if (iter != marketplace_->getSellers().end()) { if (iter != m_marketplace->getSellers().end()) {
emit duplicateSellerNo( emit duplicateSellerNo(
"Die Verkäufernummer muss eindeutig sein.\n(Möglicherweise wird die Nummer von " "Die Verkäufernummer muss eindeutig sein.\n(Möglicherweise wird die Nummer von "
"einem (ausgeblendeten) Eintrag, der zum Löschen vorgemerkt ist, verwendet.)"); "einem (ausgeblendeten) Eintrag, der zum Löschen vorgemerkt ist, verwendet.)");
@ -123,8 +123,8 @@ bool SellerModel::insertRows(int row, int count, const QModelIndex& parent)
{ {
emit beginInsertRows(parent, row, row + count - 1); emit beginInsertRows(parent, row, row + count - 1);
auto seller = std::make_unique<Seller>(); auto seller = std::make_unique<Seller>();
seller->setSellerNo(marketplace_->getNextSellerNo()); seller->setSellerNo(m_marketplace->getNextSellerNo());
marketplace_->getSellers().push_back(std::move(seller)); m_marketplace->getSellers().push_back(std::move(seller));
emit endInsertRows(); emit endInsertRows();
return true; return true;
@ -132,21 +132,21 @@ bool SellerModel::insertRows(int row, int count, const QModelIndex& parent)
bool SellerModel::removeRows(int row, int count, const QModelIndex& parent) bool SellerModel::removeRows(int row, int count, const QModelIndex& parent)
{ {
auto seller = marketplace_->getSellers().at(row).get(); auto seller = m_marketplace->getSellers().at(row).get();
if (seller->getState() == Seller::State::NEW) { if (seller->getState() == Seller::State::NEW) {
emit beginRemoveRows(parent, row, row + count - 1); emit beginRemoveRows(parent, row, row + count - 1);
marketplace_->getSellers().erase( m_marketplace->getSellers().erase(
std::remove_if(marketplace_->getSellers().begin(), marketplace_->getSellers().end(), std::remove_if(m_marketplace->getSellers().begin(), m_marketplace->getSellers().end(),
[&seller](const std::unique_ptr<Seller>& a) { [&seller](const std::unique_ptr<Seller>& a) {
return a->getId() == seller->getId(); return a->getId() == seller->getId();
}), }),
marketplace_->getSellers().end()); m_marketplace->getSellers().end());
emit endRemoveRows(); emit endRemoveRows();
return true; return true;
} else { } else {
emit beginRemoveRows(parent, row, row + count - 1); emit beginRemoveRows(parent, row, row + count - 1);
seller->setState(Seller::State::DELETE); seller->setState(Seller::State::DELETE);
marketplace_->storeToDb(true); m_marketplace->storeToDb(true);
emit endRemoveRows(); emit endRemoveRows();
return true; return true;
} }

View File

@ -1,7 +1,7 @@
#ifndef SELLER_MODEL_H #ifndef SELLER_MODEL_H
#define SELLER_MODEL_H #define SELLER_MODEL_H
#include <marketplace.h> #include <core/marketplace.h>
#include <QAbstractTableModel> #include <QAbstractTableModel>
@ -9,23 +9,23 @@ class SellerModel : public QAbstractTableModel
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit SellerModel(Marketplace* market, QObject* parent = nullptr); explicit SellerModel(Marketplace *market, QObject *parent = nullptr);
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
virtual int columnCount(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 data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
virtual Qt::ItemFlags flags(const QModelIndex& index) const override; virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
virtual bool setData(const QModelIndex& index, const QVariant& value, virtual bool setData(const QModelIndex &index, const QVariant &value,
int role = Qt::EditRole) override; int role = Qt::EditRole) override;
virtual bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex()) 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 bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
signals: signals:
void duplicateSellerNo(const QString& message); void duplicateSellerNo(const QString &message);
private: private:
Marketplace* marketplace_; Marketplace *m_marketplace;
}; };
#endif #endif

View File

@ -2,9 +2,10 @@
#include "mainwindow.h" #include "mainwindow.h"
#include <database.h> #include <core/database.h>
#include <posprinter.h> #include <core/utils.h>
#include <utils.h> #include <printer/posprinter.h>
#include <printer/utils.h>
#include <exception> #include <exception>
#include <stdexcept> #include <stdexcept>
@ -12,9 +13,9 @@
#include <QMessageBox> #include <QMessageBox>
#include <QSettings> #include <QSettings>
SettingsDialog::SettingsDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(parent, f) SettingsDialog::SettingsDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f)
{ {
ui_.setupUi(this); m_ui.setupUi(this);
QSettings settings{}; QSettings settings{};
int cashPointNo = settings.value("global/cashPointNo").toInt(); int cashPointNo = settings.value("global/cashPointNo").toInt();
@ -25,25 +26,25 @@ SettingsDialog::SettingsDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(par
int maxFeeInEuro = settings.value("global/maxFeeInEuro").toInt(); int maxFeeInEuro = settings.value("global/maxFeeInEuro").toInt();
if (parent) if (parent)
market_ = dynamic_cast<MainWindow*>(parent)->getMarketplace(); m_market = dynamic_cast<MainWindow *>(parent)->getMarketplace();
ui_.cashPointNoSpinBox->setValue(cashPointNo); m_ui.cashPointNoSpinBox->setValue(cashPointNo);
ui_.communeEdit->setText(commune); m_ui.communeEdit->setText(commune);
ui_.posPrinterDeviceEdit->setText(posPrinterDevice); m_ui.posPrinterDeviceEdit->setText(posPrinterDevice);
ui_.posPrinterEndpointEdit->setText(posPrinterEndpoint); m_ui.posPrinterEndpointEdit->setText(posPrinterEndpoint);
ui_.feePercentSpinBox->setValue(feeInPercent); m_ui.feePercentSpinBox->setValue(feeInPercent);
ui_.maxFeeSpinBox->setValue(maxFeeInEuro); m_ui.maxFeeSpinBox->setValue(maxFeeInEuro);
connect(ui_.testPosPrinterButton, &QPushButton::clicked, this, [=]() { connect(m_ui.testPosPrinterButton, &QPushButton::clicked, this, [this]() {
using namespace std::string_literals; using namespace std::string_literals;
try { try {
if (ui_.posPrinterDeviceEdit->text().isEmpty()) { if (m_ui.posPrinterDeviceEdit->text().isEmpty()) {
PosPrinter printer; PosPrinter printer;
printer.printTest(); printer.printTest();
} else { } else {
std::string posPrinterDeviceString = ui_.posPrinterDeviceEdit->text().toStdString(); std::string posPrinterDeviceString = m_ui.posPrinterDeviceEdit->text().toStdString();
std::string posPrinterEndpointString = std::string posPrinterEndpointString =
ui_.posPrinterEndpointEdit->text().toStdString(); m_ui.posPrinterEndpointEdit->text().toStdString();
try { try {
auto printerDevice = auto printerDevice =
@ -54,7 +55,7 @@ SettingsDialog::SettingsDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(par
printer.printTest(); printer.printTest();
} }
} catch (std::exception&) { } catch (std::exception &) {
QMessageBox(QMessageBox::Icon::Warning, "Falsche Eingabe", QMessageBox(QMessageBox::Icon::Warning, "Falsche Eingabe",
QString("Eingabeformat für Device (hexadezimale IDs): " QString("Eingabeformat für Device (hexadezimale IDs): "
"<VendorID>:<ProductID>\nBeispiel: 0416:5011\n " "<VendorID>:<ProductID>\nBeispiel: 0416:5011\n "
@ -64,7 +65,7 @@ SettingsDialog::SettingsDialog(QWidget* parent, Qt::WindowFlags f) : QDialog(par
return; return;
} }
} }
} catch (std::runtime_error& err) { } catch (std::runtime_error &err) {
QMessageBox(QMessageBox::Icon::Warning, "Bondrucker Fehler", QMessageBox(QMessageBox::Icon::Warning, "Bondrucker Fehler",
QString("Test schlug fehl: ") + err.what(), QMessageBox::StandardButton::Ok, QString("Test schlug fehl: ") + err.what(), QMessageBox::StandardButton::Ok,
this) this)
@ -79,17 +80,17 @@ void SettingsDialog::accept()
QSettings settings; QSettings settings;
int oldCashPointNo = settings.value("global/cashPointNo").toInt(); int oldCashPointNo = settings.value("global/cashPointNo").toInt();
int newCashPointNo = ui_.cashPointNoSpinBox->value(); int newCashPointNo = m_ui.cashPointNoSpinBox->value();
settings.setValue("global/commune", ui_.communeEdit->text().trimmed()); settings.setValue("global/commune", m_ui.communeEdit->text().trimmed());
settings.setValue("global/posPrinterDevice", ui_.posPrinterDeviceEdit->text().trimmed()); settings.setValue("global/posPrinterDevice", m_ui.posPrinterDeviceEdit->text().trimmed());
settings.setValue("global/posPrinterEndpoint", ui_.posPrinterEndpointEdit->text().trimmed()); settings.setValue("global/posPrinterEndpoint", m_ui.posPrinterEndpointEdit->text().trimmed());
settings.setValue("global/feeInPercent", ui_.feePercentSpinBox->value()); settings.setValue("global/feeInPercent", m_ui.feePercentSpinBox->value());
settings.setValue("global/maxFeeInEuro", ui_.maxFeeSpinBox->value()); settings.setValue("global/maxFeeInEuro", m_ui.maxFeeSpinBox->value());
if (oldCashPointNo != newCashPointNo) { if (oldCashPointNo != newCashPointNo) {
int result{0}; int result{0};
if (market_ && market_->getSales().size() > 0) { if (m_market && m_market->getSales().size() > 0) {
result = QMessageBox(QMessageBox::Icon::Question, "Sind Sie sicher?", result = QMessageBox(QMessageBox::Icon::Question, "Sind Sie sicher?",
"Möchten Sie die Kassen-Nr wirklich ändern? Diese muss über alle " "Möchten Sie die Kassen-Nr wirklich ändern? Diese muss über alle "
"Installationen hinweg eindeutig sein.", "Installationen hinweg eindeutig sein.",
@ -102,7 +103,7 @@ void SettingsDialog::accept()
if (result == QMessageBox::Yes) { if (result == QMessageBox::Yes) {
try { try {
Database().updateCashPointNo(oldCashPointNo, newCashPointNo); Database().updateCashPointNo(oldCashPointNo, newCashPointNo);
} catch (std::exception& ex) { } catch (std::exception &ex) {
std::string errMsg("Das Ändern der Kassen-Nr. ist fehlgeschlagen: "); std::string errMsg("Das Ändern der Kassen-Nr. ist fehlgeschlagen: ");
errMsg.append(ex.what()); errMsg.append(ex.what());
QMessageBox(QMessageBox::Icon::Critical, "Fehler", errMsg.c_str(), QMessageBox(QMessageBox::Icon::Critical, "Fehler", errMsg.c_str(),
@ -111,9 +112,9 @@ void SettingsDialog::accept()
QDialog::accept(); QDialog::accept();
return; return;
} }
settings.setValue("global/cashPointNo", ui_.cashPointNoSpinBox->value()); settings.setValue("global/cashPointNo", m_ui.cashPointNoSpinBox->value());
} }
} }
QDialog::accept(); QDialog::accept();
} }

View File

@ -3,12 +3,14 @@
#include "ui_settingsdialog.h" #include "ui_settingsdialog.h"
#include <marketplace.h> #include <core/marketplace.h>
#include <QDialog> #include <QDialog>
class SettingsDialog : public QDialog class SettingsDialog : public QDialog
{ {
Q_OBJECT
public: public:
SettingsDialog(QWidget* parent = nullptr, SettingsDialog(QWidget* parent = nullptr,
Qt::WindowFlags f = Qt::WindowTitleHint | Qt::WindowSystemMenuHint); Qt::WindowFlags f = Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
@ -17,8 +19,8 @@ class SettingsDialog : public QDialog
void accept() override; void accept() override;
private: private:
Ui::SettingsDialog ui_; Ui::SettingsDialog m_ui;
Marketplace* market_{}; Marketplace* m_market{};
}; };
#endif #endif

3
src/meson.build Normal file
View File

@ -0,0 +1,3 @@
subdir('core')
subdir('printer')
subdir('gui')

View File

@ -1,6 +1,6 @@
set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_LIBS ON)
find_package(Boost 1.62 REQUIRED) find_package(Boost 1.78 REQUIRED)
if(WIN32) if(WIN32)
find_package(LIBUSB REQUIRED) find_package(LIBUSB REQUIRED)
@ -11,6 +11,7 @@ endif()
set(PRINTER_SOURCES set(PRINTER_SOURCES
posprinter.cpp posprinter.cpp
utils.cpp
) )
add_library(printer STATIC ${PRINTER_SOURCES}) add_library(printer STATIC ${PRINTER_SOURCES})
@ -19,4 +20,4 @@ if(WIN32)
else() else()
target_link_libraries(printer core ${LibUSB_LIBRARIES}) target_link_libraries(printer core ${LibUSB_LIBRARIES})
endif() endif()
target_include_directories(printer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(printer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/.. ${Boost_INCLUDE_DIRS})

9
src/printer/meson.build Normal file
View File

@ -0,0 +1,9 @@
libusb = dependency('libusb-1.0')
src = ['posprinter.cpp', 'utils.cpp']
printer_inc = include_directories('..')
printer_lib = static_library('printer', src, dependencies: [libusb, core_dep])
printer_dep = declare_dependency(link_with : printer_lib, include_directories : printer_inc)

View File

@ -1,6 +1,6 @@
#include "posprinter.h" #include "posprinter.h"
#include <marketplace.h> #include <core/marketplace.h>
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
@ -213,4 +213,4 @@ bool PosPrinter::isValid()
return true; return true;
else else
return false; return false;
} }

View File

@ -1,8 +1,8 @@
#ifndef POS_PRINTER_H #ifndef POS_PRINTER_H
#define POS_PRINTER_H #define POS_PRINTER_H
#include <sale.h> #include <core/sale.h>
#include <seller.h> #include <core/seller.h>
#include <memory> #include <memory>

26
src/printer/utils.cpp Normal file
View File

@ -0,0 +1,26 @@
#include "utils.h"
std::optional<PrinterDevice> 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;
}

12
src/printer/utils.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef PRINTER_UTILS_H
#define PRINTER_UTILS_H
#include "posprinter.h"
#include <optional>
#include <string>
std::optional<PrinterDevice> convertToPosPrinterDevice(const std::string& vendor,
const std::string& endpoint);
#endif

View File

@ -2,4 +2,4 @@ if(NOT KIMA2_USE_EXTERNAL_JSON)
set(JSON_BuildTests OFF CACHE INTERNAL "") set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(nlohmann_json EXCLUDE_FROM_ALL) add_subdirectory(nlohmann_json EXCLUDE_FROM_ALL)
endif() endif()
add_subdirectory(csv-parser) #add_subdirectory(csv-parser)

@ -0,0 +1 @@
Subproject commit 9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03

View File

@ -0,0 +1,27 @@
project('singleapplication')
qt5 = import('qt5')
dep_qt5 = dependency('qt5', modules: ['Core', 'Widgets', 'Network'])
singleapp_inc = include_directories('singleapplication.git')
singleapp_moc = qt5.preprocess(
moc_headers: ['singleapplication.git/singleapplication.h', 'singleapplication.git/singleapplication_p.h'],
moc_extra_arguments: ['-DQAPPLICATION_CLASS=QApplication'],
dependencies: dep_qt5
)
singleapp_lib = static_library('SingleApplication',
['singleapplication.git/singleapplication.cpp', 'singleapplication.git/singleapplication_p.cpp', singleapp_moc],
include_directories: singleapp_inc,
cpp_args : '-DQAPPLICATION_CLASS=QApplication',
dependencies: dep_qt5
)
singleapp_dep = declare_dependency(
include_directories: singleapp_inc,
link_with: singleapp_lib
)
# On windows, SingleApplication needs to be linked against advapi32. This is
# done by adding 'advapi32' to cpp_winlibs, where it should be by default.

@ -0,0 +1 @@
Subproject commit 8c48163c4d3fbba603cfe8a5b94046c9dad71825