FOSSredder 0.5.0
Loading...
Searching...
No Matches
WorkspaceCommands.cpp
Go to the documentation of this file.
1
5
7
8#include <QDateTime>
9#include <QUuid>
10#include <algorithm>
11#include <cstddef>
12#include <exception>
13#include <utility>
14
21
22namespace ui {
23
24namespace {
25
26std::vector<std::string> stdStrings(const QStringList& values) {
27 return strings::toStdList(values);
28}
29
30std::vector<core::ports::workspace::AliasSnapshot>
31aliasSnapshots(const QStringList& aliases) {
32 std::vector<core::ports::workspace::AliasSnapshot> out;
33 out.reserve(aliases.size());
34 for (const auto& alias : aliases) {
35 const auto text = strings::toStdString(alias);
36 out.push_back({text, {}, text, 0, {}, {}, {}});
37 }
38 return out;
39}
40
41core::ports::workspace::ActorCommand
42makeActorCommand(const QString& id, const QString& name,
43 const QStringList& aliases, const QStringList& contractIds) {
44 core::ports::workspace::ActorCommand command;
45 command.id = strings::toStdString(id);
46 command.name = strings::toStdString(name);
47 command.aliases = aliasSnapshots(aliases);
48 command.contractIds = stdStrings(contractIds);
49 return command;
50}
51
52core::ports::workspace::PropertyCommand
53makePropertyCommand(const QString& id, const QString& name,
54 const QStringList& aliases,
55 const QStringList& contractIds) {
56 core::ports::workspace::PropertyCommand command;
57 command.id = strings::toStdString(id);
58 command.name = strings::toStdString(name);
59 command.aliases = aliasSnapshots(aliases);
60 command.contractIds = stdStrings(contractIds);
61 return command;
62}
63
64core::ports::workspace::ContractCommand
65makeContractCommand(const QString& id, const QString& name, const QString& type,
66 const QString& allocatableMode, const QStringList& actorIds,
67 const QStringList& propertyIds,
68 const QStringList& aliases) {
69 core::ports::workspace::ContractCommand command;
70 command.id = strings::toStdString(id);
71 command.name = strings::toStdString(name);
72 command.type = strings::toStdString(type);
73 command.allocatableMode = strings::toStdString(allocatableMode);
74 command.actorIds = stdStrings(actorIds);
75 command.propertyIds = stdStrings(propertyIds);
76 command.aliases = aliasSnapshots(aliases);
77 return command;
78}
79
80core::ports::workspace::TransactionCommand
81makeTransactionCommand(const QString& id, const QString& name,
82 const QString& bookingDate, const QString& valuta,
83 const QVariant& amount, const QString& statementId,
84 const QString& insertAfterTransactionId, int status,
85 const QString& actorId, const QString& contractId,
86 bool allocatable, const QStringList& propertyIds) {
87 core::ports::workspace::TransactionCommand command;
88 command.id = strings::toStdString(id);
89 command.name = strings::toStdString(name);
90 command.bookingDate = strings::toStdString(bookingDate);
91 command.valuta = strings::toStdString(valuta);
92 command.amountText = strings::toStdString(amount.toString());
93 command.statementId = strings::toStdString(statementId);
95 strings::toStdString(insertAfterTransactionId);
96 command.status = status;
97 command.actorId = strings::toStdString(actorId);
98 command.contractId = strings::toStdString(contractId);
99 command.allocatable = allocatable;
100 command.propertyIds = stdStrings(propertyIds);
101 return command;
102}
103
104core::ports::workspace::TransactionCommand
105makeTransactionCommand(const QVariantMap& state,
106 const QString& statementId = {}) {
107 return makeTransactionCommand(
108 state.value(QStringLiteral("id")).toString(),
109 state.value(QStringLiteral("name")).toString(),
110 state.value(QStringLiteral("bookingDate")).toString(),
111 state.value(QStringLiteral("valuta")).toString(),
112 state.value(QStringLiteral("amount")), statementId, {},
113 state.value(payload::keys::common::kStatus).toInt(),
114 state.value(payload::keys::transaction::kActorId).toString(),
115 state.value(payload::keys::transaction::kContractId).toString(),
116 state.value(QStringLiteral("allocatable")).toBool(),
118 state.value(payload::keys::transaction::kPropertyIds).toList()));
119}
120
121core::ports::analysis::AnalysisConfigInput
122analysisConfigInput(const QString& type, const QVariantMap& config) {
123 core::ports::analysis::AnalysisConfigInput input;
124 input.type = strings::toStdString(type);
125 input.plotType =
126 strings::toStdString(config.value(QStringLiteral("plotType")).toString());
128 config.value(QStringLiteral("plotMeasure")).toString());
130 config.value(QStringLiteral("propertyIds")).toList()));
132 config.value(QStringLiteral("contractTypes")).toList()));
133 input.taxPercent = config.value(QStringLiteral("taxPercent")).toDouble();
134 return input;
135}
136
137core::ports::analysis::AnalysisFilterSelection
138analysisFilterSelection(const QVariantMap& filter) {
139 core::ports::analysis::AnalysisFilterSelection selection;
141 filter.value(QStringLiteral("dateField")).toString());
142 selection.dateMode =
143 strings::toStdString(filter.value(QStringLiteral("dateMode")).toString());
144 selection.year =
145 strings::toStdString(filter.value(QStringLiteral("year")).toString());
146 selection.dateFrom =
147 strings::toStdString(filter.value(QStringLiteral("dateFrom")).toString());
148 selection.dateTo =
149 strings::toStdString(filter.value(QStringLiteral("dateTo")).toString());
150 selection.propertyIds = stdStrings(payload::mapper::toQStringList(
151 filter.value(QStringLiteral("propertyIds")).toList()));
152 selection.propertyIdsUnassigned =
153 filter.value(QStringLiteral("propertyIdsNone")).toBool();
154 selection.contractTypes = stdStrings(payload::mapper::toQStringList(
155 filter.value(QStringLiteral("contractTypes")).toList()));
156 selection.contractTypesUnassigned =
157 filter.value(QStringLiteral("contractTypesNone")).toBool();
159 filter.value(QStringLiteral("allocatableMode")).toString());
160 return selection;
161}
162
163core::ports::workspace::AnalysisCommand
164makeAnalysisCommand(const QString& id, const QString& name, const QString& type,
165 const QVariantMap& config, const QVariantMap& filter,
166 const QString& exportFormat, bool includeCalcAdjustments,
167 const QVariantList& snapshotTransactions) {
168 core::ports::workspace::AnalysisCommand command;
169 command.id = strings::toStdString(id);
170 command.name = strings::toStdString(name);
171 command.type = strings::toStdString(type);
172 command.config = analysisConfigInput(type, config);
173 command.filter = analysisFilterSelection(filter);
174 command.exportFormat = strings::toStdString(exportFormat);
175 command.includeCalculationAdjustments = includeCalcAdjustments;
176 command.snapshotTransactions.reserve(
177 static_cast<std::size_t>(snapshotTransactions.size()));
178 for (const auto& value : snapshotTransactions) {
179 const QVariantMap row = value.toMap();
180 core::ports::workspace::TransactionSnapshot tx;
182 row.value(QStringLiteral("id"),
183 row.value(QStringLiteral("transactionId")))
184 .toString());
186 row.value(QStringLiteral("name"),
187 row.value(QStringLiteral("transactionName")))
188 .toString());
189 tx.bookingDate =
190 strings::toStdString(row.value(QStringLiteral("bookingDate"),
191 row.value(QStringLiteral("date")))
192 .toString());
193 tx.valuta =
194 strings::toStdString(row.value(QStringLiteral("valuta")).toString());
195 tx.amount = row.value(QStringLiteral("amount")).toDouble();
196 tx.status = row.value(QStringLiteral("status")).toInt();
198 row.value(QStringLiteral("contractId")).toString());
200 row.value(QStringLiteral("contractType")).toString());
201 tx.actorId =
202 strings::toStdString(row.value(QStringLiteral("actorId")).toString());
204 row.value(QStringLiteral("statementId")).toString());
205 tx.allocatable = row.value(QStringLiteral("allocatable")).toBool();
207 row.value(QStringLiteral("propertyIds")).toList()));
209 row.value(QStringLiteral("propertyNames")).toList()));
210 command.snapshotTransactions.push_back(std::move(tx));
211 }
212 return command;
213}
214
215std::vector<std::pair<std::string, double>>
216analysisAdjustmentPairs(const QVariantMap& adjustments) {
217 std::vector<std::pair<std::string, double>> out;
218 out.reserve(static_cast<std::size_t>(adjustments.size()));
219 for (auto it = adjustments.constBegin(); it != adjustments.constEnd(); ++it) {
220 const QString id = it.key().trimmed();
221 if (!id.isEmpty()) {
222 out.emplace_back(strings::toStdString(id), it.value().toDouble());
223 }
224 }
225 return out;
226}
227
228core::ports::workspace::AnnualCommand
229makeAnnualCommand(const QString& id, const QString& name, int year,
230 const QStringList& analysisIds) {
231 core::ports::workspace::AnnualCommand command;
232 command.id = strings::toStdString(id);
233 command.name = strings::toStdString(name);
234 command.year = year;
235 command.assignedAnalysisIds = stdStrings(analysisIds);
236 return command;
237}
238
239} // namespace
240
242 : QObject(parent), store_(store) {}
243
244void WorkspaceCommands::refreshStoreFromReader() {
245 if (store_.reader()) {
246 store_.loadFromState(store_.reader()->workspaceSnapshot());
247 }
248}
249
250bool WorkspaceCommands::rejectInvalidCommand(
251 const char* origin,
252 const core::ports::workspace::ValidationResult& result) const {
253 if (result.valid()) {
254 return false;
255 }
257 {"issueCount", std::to_string(result.issues.size())}};
258 if (!result.issues.empty()) {
259 context.emplace_back(observability::context::kError,
260 result.issues.front().message);
261 context.emplace_back("field", result.issues.front().field);
262 context.emplace_back("code", result.issues.front().code);
263 }
264 observability::traceWorkspace(origin, "Workspace command rejected",
265 std::move(context));
266 return true;
267}
268
269void WorkspaceCommands::runStorageOperation(
270 const QString& operation, const std::function<void()>& action) {
271 if (!store_.writer()) {
273 "WorkspaceCommands::runStorageOperation",
274 "Storage operation ignored because no workspace writer is bound",
275 {{observability::context::kOperation, operation.toStdString()}});
276 return;
277 }
278 try {
279 action();
280 emit operationSucceeded(operation);
281 } catch (const std::exception& ex) {
282 emit operationFailed(operation, QString::fromUtf8(ex.what()));
283 }
284}
285
286std::optional<core::ports::workspace::StatementDraftSnapshot>
287WorkspaceCommands::statementDraftSnapshot(const QString& draftId) const {
288 return store_.reader() ? store_.reader()->statementDraftSnapshot(
289 strings::toStdString(draftId))
290 : std::nullopt;
291}
292
295 if (!store_.writer()) {
296 return {};
297 }
299 command.draft = draft;
300 const QString id =
301 QString::fromStdString(store_.writer()->finalizeStatementDraft(command));
302 refreshStoreFromReader();
303 return id;
304}
305
308 if (!store_.writer()) {
309 return;
310 }
312 command.draft = draft;
313 store_.writer()->saveStatementDraft(command);
314 refreshStoreFromReader();
315}
316
317void WorkspaceCommands::clearStatementDraft(const QString& draftId) {
318 if (!store_.writer()) {
319 return;
320 }
321 store_.writer()->clearStatementDraft(strings::toStdString(draftId));
322 refreshStoreFromReader();
323}
324
325void WorkspaceCommands::saveImportLog(
327 if (!store_.writer()) {
328 return;
329 }
331 command.log = log;
332 store_.writer()->saveImportLog(command);
333 refreshStoreFromReader();
334}
335
337 const QString& logId, const QString& status, const QString& message,
338 bool draftAttached, const QString& draftId, const QString& statementId,
339 const QString& importFile) {
340 if (!store_.writer()) {
341 return;
342 }
344 const QString resolvedLogId =
345 logId.isEmpty() ? QUuid::createUuid().toString(QUuid::WithoutBraces)
346 : logId;
347 for (const auto& existing : store_.snapshot().importLogs) {
348 if (QString::fromStdString(existing.id) == resolvedLogId) {
349 log = existing;
350 break;
351 }
352 }
353
354 log.id = resolvedLogId.toStdString();
355 log.time = QDateTime::currentDateTime()
356 .toString(QStringLiteral("dd.MM.yyyy HH:mm:ss"))
357 .toStdString();
358 log.status = status.toStdString();
359 log.message = message.toStdString();
360 log.draftAttached = draftAttached;
361 log.statementId = statementId.toStdString();
362 if (log.type.empty()) {
363 log.type = "statement";
364 }
365 if (!importFile.isEmpty()) {
366 log.file = importFile.toStdString();
367 }
368 const QString resolvedDraftId =
369 draftAttached ? (draftId.isEmpty() ? resolvedLogId : draftId) : QString();
370 log.draftId = resolvedDraftId.toStdString();
371 log.statementDraftIds.clear();
372 if (draftAttached && !resolvedDraftId.isEmpty()) {
373 log.statementDraftIds.push_back(resolvedDraftId.toStdString());
374 }
375 saveImportLog(log);
376}
377
378void WorkspaceCommands::deleteImportLog(const QString& id) {
379 if (store_.writer()) {
380 store_.writer()->deleteImportLog(strings::toStdString(id));
381 refreshStoreFromReader();
382 }
383}
384
387 if (!store_.writer()) {
388 return;
389 }
391 command.log = log;
392 store_.writer()->saveExportLog(command);
393 refreshStoreFromReader();
394}
395
396void WorkspaceCommands::deleteExportLog(const QString& id) {
397 if (store_.writer()) {
398 store_.writer()->deleteExportLog(strings::toStdString(id));
399 refreshStoreFromReader();
400 }
401}
402
403void WorkspaceCommands::newFile(const QString& path) {
404 runStorageOperation(QStringLiteral("newFile"), [&]() {
405 store_.writer()->newFile(strings::toEncodedPath(path));
406 });
407}
408
409void WorkspaceCommands::openFile(const QString& path) {
410 runStorageOperation(QStringLiteral("openFile"), [&]() {
411 store_.writer()->openFile(strings::toEncodedPath(path));
412 });
413}
414
416 runStorageOperation(QStringLiteral("saveFile"), [&]() {
417 if (beforeStorageSave_) {
418 beforeStorageSave_();
419 }
420 store_.writer()->saveFile();
421 });
422}
423
424void WorkspaceCommands::saveFileAs(const QString& path) {
425 runStorageOperation(QStringLiteral("saveFileAs"), [&]() {
426 if (beforeStorageSave_) {
427 beforeStorageSave_();
428 }
429 store_.writer()->saveFileAs(strings::toEncodedPath(path));
430 });
431}
432
434 std::function<void()> callback) {
435 beforeStorageSave_ = std::move(callback);
436}
437
438QVariantMap
439WorkspaceCommands::validateActor(const QString& id, const QString& name,
440 const QStringList& aliases,
441 const QStringList& contractIds) const {
442 return store_.writer() ? workspace_payloads::validationResult(
443 store_.writer()->validateActor(makeActorCommand(
444 id, name, aliases, contractIds)))
445 : workspace_payloads::validationResult({});
446}
447
448QString WorkspaceCommands::saveActor(const QString& id, const QString& name,
449 const QStringList& aliases,
450 const QStringList& contractIds) {
451 if (!store_.writer()) {
452 return {};
453 }
454 const auto command = makeActorCommand(id, name, aliases, contractIds);
455 if (rejectInvalidCommand("WorkspaceCommands::saveActor",
456 store_.writer()->validateActor(command))) {
457 return {};
458 }
459 const QString savedId =
460 id.isEmpty() ? QString::fromStdString(store_.writer()->addActor(command))
461 : (store_.writer()->updateActor(command), id);
462 refreshStoreFromReader();
463 return savedId;
464}
465
466void WorkspaceCommands::deleteActor(const QString& id) {
467 if (store_.writer()) {
468 store_.writer()->deleteActor(strings::toStdString(id));
469 refreshStoreFromReader();
470 }
471}
472
473QVariantMap
474WorkspaceCommands::validateProperty(const QString& id, const QString& name,
475 const QStringList& aliases,
476 const QStringList& contractIds) const {
477 return store_.writer()
479 store_.writer()->validateProperty(
480 makePropertyCommand(id, name, aliases, contractIds)))
481 : workspace_payloads::validationResult({});
482}
483
484QString WorkspaceCommands::saveProperty(const QString& id, const QString& name,
485 const QStringList& aliases,
486 const QStringList& contractIds) {
487 if (!store_.writer()) {
488 return {};
489 }
490 const auto command = makePropertyCommand(id, name, aliases, contractIds);
491 if (rejectInvalidCommand("WorkspaceCommands::saveProperty",
492 store_.writer()->validateProperty(command))) {
493 return {};
494 }
495 const QString savedId =
496 id.isEmpty()
497 ? QString::fromStdString(store_.writer()->addProperty(command))
498 : (store_.writer()->updateProperty(command), id);
499 refreshStoreFromReader();
500 return savedId;
501}
502
503void WorkspaceCommands::deleteProperty(const QString& id) {
504 if (store_.writer()) {
505 store_.writer()->deleteProperty(strings::toStdString(id));
506 refreshStoreFromReader();
507 }
508}
509
510QVariantMap WorkspaceCommands::validateContract(
511 const QString& id, const QString& name, const QString& type,
512 const QStringList& actorIds, const QStringList& propertyIds,
513 const QStringList& aliases, const QString& allocatableMode) const {
514 return store_.writer()
516 store_.writer()->validateContract(
517 makeContractCommand(id, name, type, allocatableMode,
518 actorIds, propertyIds, aliases)))
519 : workspace_payloads::validationResult({});
520}
521
522QString WorkspaceCommands::saveContract(const QString& id, const QString& name,
523 const QString& type,
524 const QStringList& actorIds,
525 const QStringList& propertyIds,
526 const QStringList& aliases,
527 const QString& allocatableMode) {
528 if (!store_.writer()) {
529 return {};
530 }
531 const auto command = makeContractCommand(id, name, type, allocatableMode,
532 actorIds, propertyIds, aliases);
533 if (rejectInvalidCommand("WorkspaceCommands::saveContract",
534 store_.writer()->validateContract(command))) {
535 return {};
536 }
537 const QString savedId =
538 id.isEmpty()
539 ? QString::fromStdString(store_.writer()->addContract(command))
540 : (store_.writer()->updateContract(command), id);
541 refreshStoreFromReader();
542 return savedId;
543}
544
545void WorkspaceCommands::deleteContract(const QString& id) {
546 if (store_.writer()) {
547 store_.writer()->deleteContract(strings::toStdString(id));
548 refreshStoreFromReader();
549 }
550}
551
552QVariantMap WorkspaceCommands::validateStatement(const QString& id,
553 const QString& name) const {
555 command.id = strings::toStdString(id);
556 command.name = strings::toStdString(name);
557 return store_.writer() ? workspace_payloads::validationResult(
558 store_.writer()->validateStatement(command))
559 : workspace_payloads::validationResult({});
560}
561
562QString WorkspaceCommands::addStatement(const QString& name) {
563 if (!store_.writer()) {
564 return {};
565 }
567 command.name = strings::toStdString(name);
568 if (rejectInvalidCommand("WorkspaceCommands::addStatement",
569 store_.writer()->validateStatement(command))) {
570 return {};
571 }
572 const QString savedId =
573 QString::fromStdString(store_.writer()->addStatement(command));
574 refreshStoreFromReader();
575 return savedId;
576}
577
579 const QString& name, const QVariantList& transactionStates) {
580 if (!store_.writer()) {
581 return {};
582 }
584 command.statement.name = strings::toStdString(name);
585 command.transactions.reserve(
586 static_cast<std::size_t>(transactionStates.size()));
587 for (const auto& stateValue : transactionStates) {
588 command.transactions.push_back(makeTransactionCommand(stateValue.toMap()));
589 }
590 if (rejectInvalidCommand(
591 "WorkspaceCommands::addStatementWithTransactions",
592 store_.writer()->validateStatementWithTransactions(command))) {
593 return {};
594 }
595 const QString savedId = QString::fromStdString(
596 store_.writer()->addStatementWithTransactions(command));
597 refreshStoreFromReader();
598 return savedId;
599}
600
602 const QString& name) {
603 if (!store_.writer()) {
604 return;
605 }
607 command.id = strings::toStdString(id);
608 command.name = strings::toStdString(name);
609 if (!rejectInvalidCommand("WorkspaceCommands::updateStatement",
610 store_.writer()->validateStatement(command))) {
611 store_.writer()->updateStatement(command);
612 refreshStoreFromReader();
613 }
614}
615
616void WorkspaceCommands::deleteStatement(const QString& id) {
617 if (store_.writer()) {
618 store_.writer()->deleteStatement(strings::toStdString(id));
619 refreshStoreFromReader();
620 }
621}
622
623QVariantMap WorkspaceCommands::validateTransaction(
624 const QString& id, const QString& name, const QString& bookingDate,
625 const QString& valuta, const QVariant& amount, const QString& statementId,
626 int status, const QString& actorId, const QString& contractId,
627 bool allocatable, const QStringList& propertyIds) const {
628 return store_.writer()
630 store_.writer()->validateTransaction(makeTransactionCommand(
631 id, name, bookingDate, valuta, amount, statementId, {},
632 status, actorId, contractId, allocatable, propertyIds)))
633 : workspace_payloads::validationResult({});
634}
635
637 const QString& name, const QString& bookingDate, const QString& valuta,
638 const QVariant& amount, const QString& statementId, int status,
639 const QString& actorId, const QString& contractId, bool allocatable,
640 const QStringList& propertyIds) {
641 if (!store_.writer()) {
642 return {};
643 }
644 const auto command = makeTransactionCommand(
645 {}, name, bookingDate, valuta, amount, statementId, {}, status, actorId,
646 contractId, allocatable, propertyIds);
647 if (rejectInvalidCommand("WorkspaceCommands::addTransaction",
648 store_.writer()->validateTransaction(command))) {
649 return {};
650 }
651 const QString savedId =
652 QString::fromStdString(store_.writer()->addTransaction(command));
653 refreshStoreFromReader();
654 return savedId;
655}
656
658 const QString& afterTransactionId, const QString& name,
659 const QString& bookingDate, const QString& valuta, const QVariant& amount,
660 const QString& statementId, int status, const QString& actorId,
661 const QString& contractId, bool allocatable,
662 const QStringList& propertyIds) {
663 if (!store_.writer()) {
664 return {};
665 }
666 const auto command = makeTransactionCommand(
667 {}, name, bookingDate, valuta, amount, statementId, afterTransactionId,
668 status, actorId, contractId, allocatable, propertyIds);
669 if (rejectInvalidCommand("WorkspaceCommands::insertTransactionAfter",
670 store_.writer()->validateTransaction(command))) {
671 return {};
672 }
673 const QString savedId =
674 QString::fromStdString(store_.writer()->addTransaction(command));
675 refreshStoreFromReader();
676 return savedId;
677}
678
680 const QString& id, const QString& name, const QString& bookingDate,
681 const QString& valuta, const QVariant& amount, const QString& statementId,
682 int status, const QString& actorId, const QString& contractId,
683 bool allocatable, const QStringList& propertyIds) {
684 if (!store_.writer()) {
685 return;
686 }
687 const auto command = makeTransactionCommand(
688 id, name, bookingDate, valuta, amount, statementId, {}, status, actorId,
689 contractId, allocatable, propertyIds);
690 if (!rejectInvalidCommand("WorkspaceCommands::updateTransaction",
691 store_.writer()->validateTransaction(command))) {
692 store_.writer()->updateTransaction(command);
693 refreshStoreFromReader();
694 }
695}
696
698 if (store_.writer()) {
699 store_.writer()->deleteTransaction(strings::toStdString(id));
700 refreshStoreFromReader();
701 }
702}
703
704QString WorkspaceCommands::addAnalysis(const QString& name, const QString& type,
705 const QVariantMap& config,
706 const QVariantMap& filter,
707 const QString& exportFormat,
708 bool includeCalcAdjustments,
709 const QVariantList& snapshotTransactions,
710 const QVariantMap& adjustments) {
711 if (!store_.writer()) {
712 return {};
713 }
714 auto command =
715 makeAnalysisCommand({}, name, type, config, filter, exportFormat,
716 includeCalcAdjustments, snapshotTransactions);
717 command.adjustments = analysisAdjustmentPairs(adjustments);
718 if (rejectInvalidCommand("WorkspaceCommands::addAnalysis",
719 store_.writer()->validateAnalysis(command))) {
720 return {};
721 }
722 const QString savedId =
723 QString::fromStdString(store_.writer()->addAnalysis(command));
724 refreshStoreFromReader();
725 return savedId;
726}
727
729 const QString& id, const QString& name, const QString& type,
730 const QVariantMap& config, const QVariantMap& filter,
731 const QString& exportFormat, bool includeCalcAdjustments,
732 const QVariantList& snapshotTransactions, const QVariantMap& adjustments) {
733 if (!store_.writer()) {
734 return;
735 }
736 auto command =
737 makeAnalysisCommand(id, name, type, config, filter, exportFormat,
738 includeCalcAdjustments, snapshotTransactions);
739 command.adjustments = analysisAdjustmentPairs(adjustments);
740 if (!rejectInvalidCommand("WorkspaceCommands::updateAnalysis",
741 store_.writer()->validateAnalysis(command))) {
742 store_.writer()->updateAnalysis(command);
743 refreshStoreFromReader();
744 }
745}
746
747void WorkspaceCommands::deleteAnalysis(const QString& id) {
748 if (store_.writer()) {
749 store_.writer()->deleteAnalysis(strings::toStdString(id));
750 refreshStoreFromReader();
751 }
752}
753
755 const QString& analysisId, const QString& exportFormat) {
756 const std::string target = strings::toStdString(analysisId.trimmed());
757 const auto& analyses = store_.snapshot().analyses;
758 const auto it =
759 std::find_if(analyses.begin(), analyses.end(), [&](const auto& analysis) {
760 return analysis.id == target;
761 });
762 if (it == analyses.end()) {
763 return;
764 }
765 if (!store_.writer()) {
766 return;
767 }
768 core::ports::workspace::AnalysisCommand command = makeAnalysisCommand(
769 analysisId, QString::fromStdString(it->name),
770 QString::fromStdString(it->type),
772 workspace_payloads::analysisFilterRow(it->filter), exportFormat,
773 it->includeCalculationAdjustments,
774 workspace_payloads::transactionRows(it->snapshotTransactions));
775 command.adjustments = it->adjustments;
776 if (!rejectInvalidCommand("WorkspaceCommands::updateAnalysisExportFormat",
777 store_.writer()->validateAnalysis(command))) {
778 store_.writer()->updateAnalysis(command);
779 refreshStoreFromReader();
780 }
781}
782
783QVariantMap
784WorkspaceCommands::validateAnnual(const QString& id, const QString& name,
785 int year,
786 const QStringList& analysisIds) const {
787 return store_.writer()
789 store_.writer()->validateAnnual(
790 makeAnnualCommand(id, name, year, analysisIds)))
791 : workspace_payloads::validationResult({});
792}
793
794QString WorkspaceCommands::addAnnual(const QString& name, int year,
795 const QStringList& analysisIds) {
796 if (!store_.writer()) {
797 return {};
798 }
799 const auto command = makeAnnualCommand({}, name, year, analysisIds);
800 if (rejectInvalidCommand("WorkspaceCommands::addAnnual",
801 store_.writer()->validateAnnual(command))) {
802 return {};
803 }
804 const QString savedId =
805 QString::fromStdString(store_.writer()->addAnnual(command));
806 refreshStoreFromReader();
807 return savedId;
808}
809
810void WorkspaceCommands::updateAnnual(const QString& id, const QString& name,
811 int year, const QStringList& analysisIds) {
812 if (!store_.writer()) {
813 return;
814 }
815 const auto command = makeAnnualCommand(id, name, year, analysisIds);
816 if (!rejectInvalidCommand("WorkspaceCommands::updateAnnual",
817 store_.writer()->validateAnnual(command))) {
818 store_.writer()->updateAnnual(command);
819 refreshStoreFromReader();
820 }
821}
822
823void WorkspaceCommands::deleteAnnual(const QString& id) {
824 if (store_.writer()) {
825 store_.writer()->deleteAnnual(strings::toStdString(id));
826 refreshStoreFromReader();
827 }
828}
829
830} // namespace ui
Declarations for the UI PayloadKeys component.
Declarations for the UI payload mapper helpers.
Declares lightweight conversions between common Qt string types and standard strings.
Declarations for the UI Trace component.
Declares workspace-specific QML payload builders.
virtual WorkspaceSnapshot workspaceSnapshot() const =0
Returns the full immutable workspace snapshot.
virtual ValidationResult validateTransaction(const TransactionCommand &command) const =0
Validates a transaction command without mutating workspace state.
virtual void saveImportLog(const ImportLogCommand &command)=0
Saves or updates one import log.
virtual ValidationResult validateContract(const ContractCommand &command) const =0
Validates a contract command without mutating workspace state.
virtual ValidationResult validateActor(const ActorCommand &command) const =0
Validates an actor command without mutating workspace state.
void deleteAnalysis(const QString &id)
Deletes an analysis.
void deleteStatement(const QString &id)
Deletes a statement.
void operationSucceeded(const QString &operation)
Emitted when a storage command completed.
void deleteImportLog(const QString &id)
Deletes an import log.
void updateTransaction(const QString &id, const QString &name, const QString &bookingDate, const QString &valuta, const QVariant &amount, const QString &statementId, int status, const QString &actorId, const QString &contractId, bool allocatable, const QStringList &propertyIds)
Updates a transaction.
WorkspaceCommands(WorkspaceStore &store, QObject *parent=nullptr)
Creates workspace commands for a store.
QString addAnalysis(const QString &name, const QString &type, const QVariantMap &config, const QVariantMap &filter, const QString &exportFormat, bool includeCalcAdjustments, const QVariantList &snapshotTransactions, const QVariantMap &adjustments={})
Creates an analysis.
QString saveProperty(const QString &id, const QString &name, const QStringList &aliases={}, const QStringList &contractIds={})
Creates or updates a property.
void openFile(const QString &path)
Opens an existing workspace file.
void operationFailed(const QString &operation, const QString &error)
Emitted when a storage command failed.
void upsertImportLog(const QString &logId, const QString &status, const QString &message, bool draftAttached, const QString &draftId={}, const QString &statementId={}, const QString &importFile={})
Creates or updates an import log row.
void deleteTransaction(const QString &id)
Deletes a transaction.
void saveFileAs(const QString &path)
Saves the current workspace file to a new path.
void deleteProperty(const QString &id)
Deletes a property.
void updateAnalysisExportFormat(const QString &analysisId, const QString &exportFormat)
Updates only the stored export format of an analysis.
void deleteActor(const QString &id)
Deletes an actor.
QString addTransaction(const QString &name, const QString &bookingDate, const QString &valuta, const QVariant &amount, const QString &statementId, int status=0, const QString &actorId=QString(), const QString &contractId=QString(), bool allocatable=false, const QStringList &propertyIds={})
Creates a transaction.
QString addAnnual(const QString &name, int year, const QStringList &analysisIds={})
Creates an annual.
QString saveActor(const QString &id, const QString &name, const QStringList &aliases={}, const QStringList &contractIds={})
Creates or updates an actor.
void updateStatement(const QString &id, const QString &name)
Updates a statement.
void setBeforeStorageSaveCallback(std::function< void()> callback)
Registers an optional hook executed immediately before storage save.
QString finalizeStatementDraft(const core::ports::workspace::StatementDraftSnapshot &draft)
Finalizes a statement draft through the workspace writer.
QString addStatementWithTransactions(const QString &name, const QVariantList &transactionStates)
Creates a statement and its transactions in one workspace mutation.
void newFile(const QString &path)
Creates a new workspace file.
void clearStatementDraft(const QString &draftId={})
Removes a statement draft from workspace state.
void deleteContract(const QString &id)
Deletes a contract.
void updateAnnual(const QString &id, const QString &name, int year, const QStringList &analysisIds={})
Updates an annual.
void deleteAnnual(const QString &id)
Deletes an annual.
void deleteExportLog(const QString &id)
Deletes an export log.
QString saveContract(const QString &id, const QString &name, const QString &type, const QStringList &actorIds={}, const QStringList &propertyIds={}, const QStringList &aliases={}, const QString &allocatableMode=QStringLiteral("mixed"))
Creates or updates a contract.
void saveStatementDraft(const core::ports::workspace::StatementDraftSnapshot &draft)
Saves a statement draft in workspace state.
void saveExportLog(const core::ports::workspace::ExportLogSnapshot &log)
Saves an export log in workspace state.
void saveFile()
Saves the current workspace file.
void updateAnalysis(const QString &id, const QString &name, const QString &type, const QVariantMap &config, const QVariantMap &filter, const QString &exportFormat, bool includeCalcAdjustments, const QVariantList &snapshotTransactions, const QVariantMap &adjustments={})
Updates an analysis.
QString addStatement(const QString &name)
Creates a statement.
QString insertTransactionAfter(const QString &afterTransactionId, const QString &name, const QString &bookingDate, const QString &valuta, const QVariant &amount, const QString &statementId, int status=0, const QString &actorId=QString(), const QString &contractId=QString(), bool allocatable=false, const QStringList &propertyIds={})
Creates a transaction after another transaction.
std::optional< core::ports::workspace::StatementDraftSnapshot > statementDraftSnapshot(const QString &draftId={}) const
Reads a statement draft snapshot from workspace state.
Owns the current UI-side workspace snapshot and revision lifecycle.
void loadFromState(const core::ports::workspace::WorkspaceSnapshot &snapshot)
Loads a fresh workspace snapshot.
Write-side boundary command models for workspace operations.
std::vector< std::pair< std::string, std::string > > ErrorContext
Key/value context attached to an error event.
Definition ErrorEvent.h:27
constexpr auto kOperation
Definition Trace.h:34
constexpr auto kError
Definition Trace.h:24
void traceWorkspace(const char *origin, std::string message, core::errors::ErrorContext context={})
Emits a workspace trace event.
Definition Trace.h:119
QStringList toQStringList(const std::vector< std::string > &values)
Converts standard strings to a Qt string list.
std::vector< std::string > toStdList(const QStringList &values)
Converts a Qt string list into a standard string vector.
std::string toStdString(const QString &value)
Converts a QString to a UTF-8 encoded std::string.
std::string toEncodedPath(const QString &path)
Converts a filesystem path to the platform-encoded byte representation.
QVariantList transactionRows(const std::vector< core::ports::workspace::TransactionSnapshot > &transactions)
Builds transaction rows.
QVariantMap analysisConfigRow(const core::ports::analysis::AnalysisConfigInput &config)
Builds an analysis config row.
QVariantMap analysisFilterRow(const core::ports::analysis::AnalysisFilterSelection &filter)
Builds an analysis filter row.
QVariantMap validationResult(const core::ports::workspace::ValidationResult &result)
Maps validation results to a QML-friendly payload.
std::vector< TransactionCommand > transactions
Transaction creation data; statement ids are assigned by core.
bool valid() const noexcept
Reports whether the validation result has no errors.
Declares UI-side workspace command submission.