FOSSredder 0.5.0
Loading...
Searching...
No Matches
AnalysisAdapter.cpp
Go to the documentation of this file.
1
5
7
8#include "ui/i18n/Text.h"
11
12#include <utility>
13
14namespace ui::adapters {
15namespace {
16
17QVariantMap toMetricsMap(const core::ports::analysis::AnalysisResult& result) {
18 QVariantMap metrics;
19 for (const auto& [key, value] : result.metrics) {
20 metrics.insert(QString::fromStdString(key), value);
21 }
22 return metrics;
23}
24
25QVariantList toTableList(const core::ports::analysis::AnalysisResult& result) {
26 QVariantList table;
27 for (const auto& row : result.table) {
28 QVariantList columns;
29 for (const auto& column : row) {
30 columns.push_back(QString::fromStdString(column));
31 }
32 table.push_back(columns);
33 }
34 return table;
35}
36
37QVariantList
38toArtifactList(const core::ports::analysis::AnalysisResult& result) {
39 QVariantList artifacts;
40 for (const auto& artifact : result.artifacts) {
41 artifacts.push_back(QString::fromStdString(artifact));
42 }
43 return artifacts;
44}
45
46QStringList toStringList(const std::vector<std::string>& values) {
47 QStringList out;
48 out.reserve(static_cast<int>(values.size()));
49 for (const auto& value : values) {
50 if (!value.empty()) {
51 out.push_back(QString::fromStdString(value));
52 }
53 }
54 return out;
55}
56
57QVariantList
58toTransactionRows(const core::ports::analysis::AnalysisResult& result) {
59 QVariantList transactions;
60 for (const auto& transaction : result.transactions) {
61 QVariantMap item;
63 QString::fromStdString(transaction.id);
65 QString::fromStdString(transaction.name);
67 QString::fromStdString(transaction.bookingDate);
68 item[ui::payload::keys::common::kAmount] = transaction.amount;
70 QString::fromStdString(transaction.contractId);
72 transaction.contractType.empty()
74 : QString::fromStdString(transaction.contractType);
75
76 QStringList propertyIds;
77 propertyIds.reserve(static_cast<int>(transaction.propertyIds.size()));
78 for (const auto& propertyId : transaction.propertyIds) {
79 if (!propertyId.empty()) {
80 propertyIds.push_back(QString::fromStdString(propertyId));
81 }
82 }
84
85 QStringList propertyNames;
86 propertyNames.reserve(static_cast<int>(transaction.propertyNames.size()));
87 for (const auto& propertyName : transaction.propertyNames) {
88 if (!propertyName.empty()) {
89 propertyNames.push_back(QString::fromStdString(propertyName));
90 }
91 }
92 item[QStringLiteral("propertyNames")] = propertyNames;
93
94 transactions.push_back(item);
95 }
96 return transactions;
97}
98
99std::vector<std::string> toStdStringList(const QStringList& values) {
100 std::vector<std::string> out;
101 out.reserve(values.size());
102 for (const auto& value : values) {
103 const QString trimmed = value.trimmed();
104 if (!trimmed.isEmpty()) {
105 out.push_back(trimmed.toStdString());
106 }
107 }
108 return out;
109}
110
111std::vector<core::ports::analysis::AnalysisAdjustmentTransactionInput>
112toAdjustmentTransactions(const QVariantList& transactions) {
113 std::vector<core::ports::analysis::AnalysisAdjustmentTransactionInput> out;
114 out.reserve(static_cast<std::size_t>(transactions.size()));
115 for (const auto& value : transactions) {
116 const QVariantMap row = value.toMap();
117 core::ports::analysis::AnalysisAdjustmentTransactionInput item;
118 item.id =
119 row.value(QStringLiteral("id")).toString().trimmed().toStdString();
120 item.amount = row.value(QStringLiteral("amount")).toDouble();
121 if (!item.id.empty()) {
122 out.push_back(std::move(item));
123 }
124 }
125 return out;
126}
127
128} // namespace
129
131 std::shared_ptr<core::ports::analysis::IAnalysisRunner> runner)
132 : runner_(std::move(runner)) {}
133
136 const core::ports::analysis::AnalysisRequest& request) const {
137 observability::traceAdapter("AnalysisAdapter::runAnalysis",
138 "Analysis runner invoked",
139 {{"analysisId", request.analysisId}});
140 return runner_ ? runner_->runAnalysis(workspace, request)
142}
143
147 const std::string& filterSpec) const {
148 return runner_ ? runner_->previewTransactions(workspace,
149 parseFilterSpec(filterSpec))
151}
152
155 const QString& filterSpec) const {
157 request.analysisId = analysisId.trimmed().toStdString();
158 request.filter = parseFilterSpec(filterSpec.trimmed().toStdString());
159 return request;
160}
161
163AnalysisAdapter::parseFilterSpec(const std::string& filterSpec) const {
164 return runner_ ? runner_->parseFilterSpec(filterSpec)
166}
167
169AnalysisAdapter::filterSelectionFromFields(
170 const std::string& dateField, const std::string& dateMode,
171 const std::string& year, const std::string& dateFrom,
172 const std::string& dateTo, const std::vector<std::string>& propertyIds,
173 const std::vector<std::string>& contractTypes,
174 const std::string& allocatableMode) const {
175 return runner_ ? runner_->filterSelectionFromFields(
176 dateField, dateMode, year, dateFrom, dateTo, propertyIds,
177 contractTypes, allocatableMode)
179}
180
182 const QString& dateField, const QString& dateMode, const QString& year,
183 const QString& dateFrom, const QString& dateTo,
184 const QStringList& propertyIds, const QStringList& contractTypes,
185 const QString& allocatableMode) const {
186 if (!runner_) {
187 return {};
188 }
189 const auto selection = filterSelectionFromFields(
190 dateField.trimmed().toLower().toStdString(),
191 dateMode.trimmed().toLower().toStdString(), year.trimmed().toStdString(),
192 dateFrom.trimmed().toStdString(), dateTo.trimmed().toStdString(),
193 toStdStringList(propertyIds), toStdStringList(contractTypes),
194 allocatableMode.trimmed().toLower().toStdString());
195 return QString::fromStdString(runner_->buildFilterSpec(selection));
196}
197
199AnalysisAdapter::buildAnalysisAdjustments(
200 const std::vector<
202 transactions,
203 const std::vector<std::string>& selectedTransactionIds,
204 double taxPercent) const {
205 return runner_ ? runner_->buildAnalysisAdjustments(
206 transactions, selectedTransactionIds, taxPercent)
208}
209
211AnalysisAdapter::buildAnalysisAdjustments(
212 const QVariantList& transactions, const QStringList& selectedTransactionIds,
213 double taxPercent) const {
214 return buildAnalysisAdjustments(toAdjustmentTransactions(transactions),
215 toStdStringList(selectedTransactionIds),
216 taxPercent);
217}
218
220 const QVariantList& transactions, const QStringList& selectedTransactionIds,
221 double taxPercent) const {
222 QVariantMap out;
223 for (const auto& [id, amount] : buildAnalysisAdjustments(
224 transactions, selectedTransactionIds, taxPercent)) {
225 out.insert(QString::fromStdString(id), amount);
226 }
227 return out;
228}
229
232 const QVariantMap& amountsById) const {
234 out.reserve(static_cast<std::size_t>(amountsById.size()));
235 for (auto it = amountsById.constBegin(); it != amountsById.constEnd(); ++it) {
236 const QString id = it.key().trimmed();
237 if (!id.isEmpty()) {
238 out.emplace_back(id.toStdString(), it.value().toDouble());
239 }
240 }
241 return out;
242}
243
245 double defaultValue) const {
246 if (!runner_) {
247 return defaultValue;
248 }
249 return runner_->parseAnalysisPercentText(text.toStdString())
250 .value_or(defaultValue);
251}
252
255 const std::string& analysisId, bool includeCalculationAdjustments,
256 const core::ports::analysis::AnalysisAdjustmentAmounts& adjustments) const {
257 if (runner_) {
258 runner_->applyAnalysisPreviewOverrides(
259 workspace, analysisId, includeCalculationAdjustments, adjustments);
260 }
261}
262
266 bool includeCalculationAdjustments,
267 const std::string& unassignedLabel) const {
268 return runner_ ? runner_->projectTableState(result, adjustments,
269 includeCalculationAdjustments,
270 unassignedLabel)
272}
273
274std::vector<std::string> AnalysisAdapter::contractTypes(
275 const core::ports::workspace::WorkspaceSnapshot& workspace) const {
276 return runner_ ? runner_->contractTypes(workspace)
277 : std::vector<std::string>{};
278}
279
281 const core::ports::analysis::AnalysisResult& result) const {
282 QVariantMap payload;
283 payload[ui::payload::keys::analysis::kMetrics] = toMetricsMap(result);
284 payload[ui::payload::keys::analysis::kTable] = toTableList(result);
286 QString::fromStdString(result.type);
288 {QStringLiteral("type"), QString::fromStdString(result.config.type)},
289 {QStringLiteral("plotType"),
290 QString::fromStdString(result.config.plotType)},
291 {QStringLiteral("plotMeasure"),
292 QString::fromStdString(result.config.plotMeasure)},
293 {QStringLiteral("propertyIds"), toStringList(result.config.propertyIds)},
294 {QStringLiteral("contractTypes"),
295 toStringList(result.config.contractTypes)},
296 {QStringLiteral("taxPercent"), result.config.taxPercent},
297 };
299 toTransactionRows(result);
300 payload[ui::payload::keys::analysis::kArtifacts] = toArtifactList(result);
302 QString::fromStdString(result.generatedAt);
303 return payload;
304}
305
308 QVariantList contractTypes;
309 contractTypes.reserve(static_cast<int>(state.contractTypes.size()));
310 for (const auto& contractType : state.contractTypes) {
311 contractTypes.push_back(QString::fromStdString(contractType));
312 }
313
314 QVariantList propertyRows;
315 propertyRows.reserve(static_cast<int>(state.propertyRows.size()));
316 for (const auto& row : state.propertyRows) {
317 QVariantList amounts;
318 amounts.reserve(static_cast<int>(row.amounts.size()));
319 for (double amount : row.amounts) {
320 amounts.push_back(amount);
321 }
322 propertyRows.push_back(
323 QVariantMap{{QStringLiteral("propertyName"),
324 QString::fromStdString(row.propertyName)},
325 {QStringLiteral("amounts"), amounts},
326 {QStringLiteral("total"), row.total}});
327 }
328
329 return QVariantMap{{QStringLiteral("contractTypes"), contractTypes},
330 {QStringLiteral("propertyRows"), propertyRows},
331 {QStringLiteral("grandTotal"), state.grandTotal}};
332}
333
336 QVariantMap out;
337 QVariantList transactions;
338 transactions.reserve(static_cast<int>(preview.transactions.size()));
339
340 for (const auto& transaction : preview.transactions) {
341 QVariantMap row;
342 const QString txId = QString::fromStdString(transaction.id);
343 const QString statementId = QString::fromStdString(transaction.statementId);
344 const QString contractId = QString::fromStdString(transaction.contractId);
345
346 QStringList propertyIds;
347 propertyIds.reserve(static_cast<int>(transaction.propertyIds.size()));
348 for (const auto& propertyId : transaction.propertyIds) {
349 const QString id = QString::fromStdString(propertyId);
350 if (!id.isEmpty() && !propertyIds.contains(id)) {
351 propertyIds.push_back(id);
352 }
353 }
354
355 QStringList propertyNames;
356 propertyNames.reserve(static_cast<int>(transaction.propertyNames.size()));
357 for (const auto& name : transaction.propertyNames) {
358 if (!name.empty()) {
359 propertyNames.push_back(QString::fromStdString(name));
360 }
361 }
362
363 row[QStringLiteral("id")] = txId;
364 row[QStringLiteral("name")] = QString::fromStdString(transaction.name);
365 row[QStringLiteral("transactionName")] =
366 QString::fromStdString(transaction.name);
367 row[QStringLiteral("date")] =
368 QString::fromStdString(transaction.bookingDate);
369 row[QStringLiteral("valuta")] = QString::fromStdString(transaction.valuta);
370 row[QStringLiteral("amount")] = transaction.amount;
371 row[QStringLiteral("statementId")] = statementId;
372 row[QStringLiteral("statementName")] =
373 QString::fromStdString(transaction.statementName);
374 row[QStringLiteral("actorName")] =
375 QString::fromStdString(transaction.actorName);
376 row[QStringLiteral("contractId")] = contractId;
377 row[QStringLiteral("contractName")] =
378 QString::fromStdString(transaction.contractName);
379 row[QStringLiteral("contractType")] =
380 QString::fromStdString(transaction.contractType);
381 row[QStringLiteral("propertyIds")] = propertyIds;
382 row[QStringLiteral("propertyNames")] = propertyNames;
383 row[QStringLiteral("propertiesLabel")] =
384 propertyNames.join(QStringLiteral(", "));
385 row[QStringLiteral("allocatable")] = transaction.allocatable;
386
387 transactions.push_back(row);
388 }
389
390 QVariantMap metrics;
391 metrics[QStringLiteral("statementCount")] = preview.metrics.statementCount;
392 metrics[QStringLiteral("transactionCount")] =
394 metrics[QStringLiteral("amountSum")] = preview.metrics.amountSum;
395
396 out[QStringLiteral("transactions")] = transactions;
397 out[QStringLiteral("metrics")] = metrics;
398 return out;
399}
400
402 const std::vector<std::string>& contractTypes) const {
403 QStringList values;
404 values.reserve(static_cast<int>(contractTypes.size()));
405 for (const auto& type : contractTypes) {
406 values.push_back(QString::fromStdString(type));
407 }
408 return values;
409}
410
411} // namespace ui::adapters
Declares the analysis adapter used by UI workflows.
Declarations for the UI PayloadKeys component.
Provides translated C++ UI strings for shell, workflow, adapter and view model code.
Declarations for the UI Trace component.
QStringList mapContractTypes(const std::vector< std::string > &contractTypes) const
Maps contract types to a QML string list.
QVariantMap buildAnalysisAdjustmentAmounts(const QVariantList &transactions, const QStringList &selectedTransactionIds, double taxPercent) const
Builds analysis adjustment amounts from preview rows.
core::ports::analysis::AnalysisTableState projectTableState(const core::ports::analysis::AnalysisResult &result, const core::ports::analysis::AnalysisAdjustmentAmounts &adjustments, bool includeCalculationAdjustments, const std::string &unassignedLabel) const
Projects table state for QML presentation.
core::ports::analysis::AnalysisAdjustmentAmounts adjustmentAmountsFromMap(const QVariantMap &amountsById) const
Converts a QML adjustment amount map to core adjustment pairs.
AnalysisAdapter(std::shared_ptr< core::ports::analysis::IAnalysisRunner > runner)
Creates an analysis adapter backed by a core runner.
core::ports::analysis::AnalysisFilterSelection parseFilterSpec(const std::string &filterSpec) const
Parses a serialized analysis filter specification through the core runner.
core::ports::analysis::AnalysisResult runAnalysis(const core::ports::workspace::WorkspaceSnapshot &workspace, const core::ports::analysis::AnalysisRequest &request) const
Runs an analysis through the core runner.
QVariantMap mapAnalysisResult(const core::ports::analysis::AnalysisResult &result) const
Maps an analysis result to a QML payload.
QVariantMap mapAnalysisTableState(const core::ports::analysis::AnalysisTableState &state) const
Maps table state to a QML payload.
std::vector< std::string > contractTypes(const core::ports::workspace::WorkspaceSnapshot &workspace) const
Returns available contract types from the core runner.
void applyAnalysisPreviewOverrides(core::ports::workspace::WorkspaceSnapshot &workspace, const std::string &analysisId, bool includeCalculationAdjustments, const core::ports::analysis::AnalysisAdjustmentAmounts &adjustments) const
Applies preview-only overrides to a workspace snapshot.
double parseAnalysisPercentText(const QString &text, double defaultValue=0.0) const
Parses user-entered percent text through the core runner.
core::ports::analysis::AnalysisRequest buildAnalysisRequest(const QString &analysisId, const QString &filterSpec) const
Builds an analysis request from UI-facing ids and filter specs.
QVariantMap mapPreviewResult(const core::ports::analysis::AnalysisPreviewResult &preview) const
Maps preview result to a QML payload.
core::ports::analysis::AnalysisPreviewResult previewTransactions(const core::ports::workspace::WorkspaceSnapshot &workspace, const std::string &filterSpec) const
Builds preview transactions through the core runner.
QString buildFilterSpec(const QString &dateField, const QString &dateMode, const QString &year, const QString &dateFrom, const QString &dateTo, const QStringList &propertyIds, const QStringList &contractTypes, const QString &allocatableMode) const
Builds a serialized analysis filter specification from UI fields.
std::vector< std::pair< std::string, double > > AnalysisAdjustmentAmounts
Adjustment amount pairs keyed by transaction id.
void traceAdapter(const char *origin, std::string message, core::errors::ErrorContext context={})
Emits an adapter trace event.
Definition Trace.h:75
QString unassignedContractType()
Label for transactions without an assigned contract type.
Definition Text.h:432
std::vector< AnalysisPreviewTransaction > transactions
std::vector< std::string > artifacts
std::vector< AnalysisTransaction > transactions
std::vector< std::vector< std::string > > table
std::map< std::string, double > metrics
std::vector< std::string > contractTypes
std::vector< AnalysisTablePropertyRow > propertyRows