FOSSredder 0.5.0
Loading...
Searching...
No Matches
AnalysisWorkflowSupport.cpp
Go to the documentation of this file.
1
5
7
11
12#include <nlohmann/json.hpp>
13
14#include <algorithm>
15#include <cmath>
16#include <unordered_set>
17
19
20namespace {
21
24
25void eraseAll(std::string& value, char ch) {
26 value.erase(std::remove(value.begin(), value.end(), ch), value.end());
27}
28
29} // namespace
30
33 nlohmann::json config;
34 const std::string normalizedType = lowerAscii(trim(input.type));
35
40 input.taxPercent;
41 return config.dump();
42 }
43
44 const std::string plotType = trim(input.plotType);
47 : plotType;
48
49 const std::string plotMeasure = trim(input.plotMeasure);
51 plotMeasure.empty()
53 : plotMeasure;
54
55 nlohmann::json properties = nlohmann::json::array();
56 for (const auto& propertyId : input.propertyIds) {
57 const std::string value = trim(propertyId);
58 if (!value.empty()) {
59 properties.push_back(value);
60 }
61 }
63 std::move(properties);
64
65 nlohmann::json contractTypes = nlohmann::json::array();
66 for (auto contractType : input.contractTypes) {
67 contractType = lowerAscii(trim(contractType));
68 if (!contractType.empty()) {
69 contractTypes.push_back(contractType);
70 }
71 }
73 std::move(contractTypes);
74
75 return config.dump();
76}
77
79 const std::string& dateField, const std::string& dateMode,
80 const std::string& year, const std::string& dateFrom,
81 const std::string& dateTo, const std::vector<std::string>& propertyIds,
82 const std::vector<std::string>& contractTypes,
83 const std::string& allocatableMode) {
85 selection.dateField = lowerAscii(trim(dateField));
86 selection.dateMode = lowerAscii(trim(dateMode));
87 selection.year = trim(year);
88 selection.dateFrom = trim(dateFrom);
89 selection.dateTo = trim(dateTo);
90 selection.allocatableMode = lowerAscii(trim(allocatableMode));
91 selection.propertyIds = propertyIds;
92 selection.contractTypes = contractTypes;
93 for (auto& contractType : selection.contractTypes) {
94 contractType = lowerAscii(trim(contractType));
95 }
96 selection.propertyIds.erase(
97 std::remove_if(selection.propertyIds.begin(), selection.propertyIds.end(),
98 [](const std::string& value) { return trim(value).empty(); }),
99 selection.propertyIds.end());
100 selection.contractTypes.erase(
101 std::remove_if(selection.contractTypes.begin(),
102 selection.contractTypes.end(),
103 [](const std::string& value) { return trim(value).empty(); }),
104 selection.contractTypes.end());
105 return selection;
106}
107
108std::vector<std::pair<std::string, double>>
109parseAnalysisAdjustmentsJson(const std::string& adjustmentsJson) {
110 std::vector<std::pair<std::string, double>> out;
111 if (adjustmentsJson.empty()) {
112 return out;
113 }
114 try {
115 const auto parsed = nlohmann::json::parse(adjustmentsJson);
116 if (!parsed.is_object()) {
117 return out;
118 }
119 out.reserve(parsed.size());
120 for (const auto& [key, value] : parsed.items()) {
121 if (value.is_number()) {
122 out.emplace_back(key, value.get<double>());
123 }
124 }
125 } catch (const nlohmann::json::exception&) {
126 return {};
127 }
128 return out;
129}
130
131std::optional<double> parseAnalysisPercentText(const std::string& text) {
132 std::string normalized = trim(text);
133 if (normalized.empty()) {
134 return std::nullopt;
135 }
136
137 if (normalized.back() == '%') {
138 normalized.pop_back();
139 normalized = trim(normalized);
140 }
141 eraseAll(normalized, ' ');
142
143 try {
144 size_t consumed = 0;
145 const double direct = std::stod(normalized, &consumed);
146 if (consumed == normalized.size() && std::isfinite(direct)) {
147 return direct;
148 }
149 } catch (...) {
150 }
151
152 const auto lastComma = normalized.find_last_of(',');
153 const auto lastDot = normalized.find_last_of('.');
154 if (lastComma != std::string::npos && lastDot != std::string::npos) {
155 if (lastComma > lastDot) {
156 eraseAll(normalized, '.');
157 std::replace(normalized.begin(), normalized.end(), ',', '.');
158 } else {
159 eraseAll(normalized, ',');
160 }
161 } else if (lastComma != std::string::npos) {
162 std::replace(normalized.begin(), normalized.end(), ',', '.');
163 }
164
165 try {
166 size_t consumed = 0;
167 const double parsed = std::stod(normalized, &consumed);
168 if (consumed == normalized.size() && std::isfinite(parsed)) {
169 return parsed;
170 }
171 } catch (...) {
172 }
173 return std::nullopt;
174}
175
177 const std::vector<AnalysisAdjustmentTransactionInput>& transactions,
178 const std::vector<std::string>& selectedTransactionIds, double taxPercent) {
179 std::unordered_set<std::string> selected;
180 selected.reserve(selectedTransactionIds.size());
181 for (const auto& id : selectedTransactionIds) {
182 const std::string value = trim(id);
183 if (!value.empty()) {
184 selected.insert(value);
185 }
186 }
187 if (selected.empty()) {
188 return std::string("{}");
189 }
190
191 const double factor = 1.0 + (taxPercent / 100.0);
192 nlohmann::json adjustments = nlohmann::json::object();
193 for (const auto& transaction : transactions) {
194 const std::string id = trim(transaction.id);
195 if (id.empty() || !selected.contains(id)) {
196 continue;
197 }
198 adjustments[id] = transaction.amount * factor;
199 }
200 return adjustments.dump();
201}
202
205 const std::string& analysisId, bool includeCalculationAdjustments,
206 const std::vector<std::pair<std::string, double>>& adjustments) {
207 const std::string targetId = trim(analysisId);
208 const auto it = std::find_if(
209 workspace.analyses.begin(), workspace.analyses.end(),
210 [&](const auto& analysis) { return analysis.id == targetId; });
211 if (it == workspace.analyses.end()) {
212 return;
213 }
214
215 it->includeCalculationAdjustments = includeCalculationAdjustments;
216 for (const auto& [key, value] : adjustments) {
217 const auto existing =
218 std::find_if(it->adjustments.begin(), it->adjustments.end(),
219 [&](const auto& item) { return item.first == key; });
220 if (existing == it->adjustments.end()) {
221 it->adjustments.emplace_back(key, value);
222 } else {
223 existing->second = value;
224 }
225 }
226}
227
228std::vector<std::string> contractTypesFromSnapshot(
230 std::unordered_set<std::string> seen;
231 std::vector<std::string> values;
232 for (const auto& contract : workspace.contracts) {
233 if (contract.type.empty() || seen.contains(contract.type)) {
234 continue;
235 }
236 seen.insert(contract.type);
237 values.push_back(contract.type);
238 }
239 std::sort(values.begin(), values.end());
240 return values;
241}
242
243} // namespace core::application::analysis
Defines stable analysis type, configuration, filter, and result keys.
Declares analysis use-case request DTOs and filter-spec helpers.
Shared analysis request/config helpers for UI and application layers.
Declares private string helpers shared across core implementation files.
constexpr std::string_view kTypeCalculation
constexpr std::string_view kPlotTypeKey
constexpr std::string_view kPropertiesKey
constexpr std::string_view kPlotMeasureKey
constexpr std::string_view kContractTypesKey
std::vector< std::string > contractTypesFromSnapshot(const core::ports::workspace::WorkspaceSnapshot &workspace)
core::ports::analysis::AnalysisFilterSelection filterSelectionFromFields(const std::string &dateField, const std::string &dateMode, const std::string &year, const std::string &dateFrom, const std::string &dateTo, const std::vector< std::string > &propertyIds, const std::vector< std::string > &contractTypes, const std::string &allocatableMode)
std::string buildAnalysisAdjustmentsJson(const std::vector< AnalysisAdjustmentTransactionInput > &transactions, const std::vector< std::string > &selectedTransactionIds, double taxPercent)
std::optional< double > parseAnalysisPercentText(const std::string &text)
Parses a user-entered analysis percentage.
void applyAnalysisPreviewOverrides(core::ports::workspace::WorkspaceSnapshot &workspace, const std::string &analysisId, bool includeCalculationAdjustments, const std::vector< std::pair< std::string, double > > &adjustments)
std::string lowerAscii(std::string s)
Converts ASCII letters in a string to lowercase.
std::string trim(std::string s)
Removes leading and trailing ASCII whitespace from a string.
std::vector< std::pair< std::string, double > > parseAnalysisAdjustmentsJson(const std::string &adjustmentsJson)
std::string buildAnalysisConfigJson(const core::ports::analysis::AnalysisConfigInput &input)
std::string lowerAscii(std::string s)
Converts ASCII letters in a string to lowercase.
std::string trim(std::string s)
Removes leading and trailing ASCII whitespace from a string.