FOSSredder 0.5.0
Loading...
Searching...
No Matches
WorkspaceSnapshotProjector.cpp
Go to the documentation of this file.
1
5
7
10
11#include <nlohmann/json.hpp>
12
13#include <algorithm>
14#include <string_view>
15
16namespace {
17
19 return {alias.value(), alias.kind(), alias.source(), alias.hitCount(), alias.lastUsedAt(), alias.createdAt(), alias.updatedAt()};
20}
21
24 snapshot.id = draft.id;
25 snapshot.statementDraftId = draft.statementDraftId;
26 snapshot.name = draft.name;
27 snapshot.bookingDate = draft.bookingDate;
28 snapshot.valuta = draft.valuta;
29 snapshot.amount = draft.amount;
30 snapshot.actorId = draft.actorId;
31 snapshot.contractId = draft.contractId;
32 snapshot.propertyIds = draft.propertyIds;
33 snapshot.status = static_cast<int>(draft.status);
34 snapshot.allocatable = draft.allocatable;
35 snapshot.position = draft.position;
36 snapshot.metadata = draft.metadata;
37 snapshot.proofImageData = draft.proofImageData;
38 return snapshot;
39}
40
41std::string jsonString(const nlohmann::json& object, std::string_view key) {
42 const auto it = object.find(std::string(key));
43 return it != object.end() && it->is_string() ? it->get<std::string>() : std::string{};
44}
45
46double jsonDouble(const nlohmann::json& object, std::string_view key) {
47 const auto it = object.find(std::string(key));
48 return it != object.end() && it->is_number() ? it->get<double>() : 0.0;
49}
50
51bool jsonBool(const nlohmann::json& object, std::string_view key) {
52 const auto it = object.find(std::string(key));
53 return it != object.end() && it->is_boolean() ? it->get<bool>() : false;
54}
55
56std::vector<std::string> jsonStringList(const nlohmann::json& object,
57 std::string_view key) {
58 std::vector<std::string> out;
59 const auto it = object.find(std::string(key));
60 if (it == object.end() || !it->is_array()) {
61 return out;
62 }
63 for (const auto& item : *it) {
64 if (item.is_string()) {
65 out.push_back(item.get<std::string>());
66 }
67 }
68 return out;
69}
70
72analysisConfigFromJson(const std::string& raw, const std::string& type) {
74 out.type = type;
75 if (raw.empty()) {
76 return out;
77 }
78 nlohmann::json config;
79 try {
80 config = nlohmann::json::parse(raw);
81 } catch (...) {
82 return out;
83 }
84 if (!config.is_object()) {
85 return out;
86 }
92 return out;
93}
94
95std::vector<core::ports::workspace::TransactionSnapshot>
96snapshotTransactionsFromJson(const std::string& raw) {
97 std::vector<core::ports::workspace::TransactionSnapshot> out;
98 if (raw.empty()) {
99 return out;
100 }
101 nlohmann::json rows;
102 try {
103 rows = nlohmann::json::parse(raw);
104 } catch (...) {
105 return out;
106 }
107 if (rows.is_object()) {
108 const auto transactions = rows.find("transactions");
109 rows = transactions != rows.end() ? *transactions : nlohmann::json{};
110 }
111 if (!rows.is_array()) {
112 return out;
113 }
114 out.reserve(rows.size());
115 for (const auto& row : rows) {
116 if (!row.is_object()) {
117 continue;
118 }
120 tx.id = jsonString(row, "id");
121 if (tx.id.empty()) {
122 tx.id = jsonString(row, "transactionId");
123 }
124 tx.name = jsonString(row, "name");
125 if (tx.name.empty()) {
126 tx.name = jsonString(row, "transactionName");
127 }
128 tx.bookingDate = jsonString(row, "bookingDate");
129 if (tx.bookingDate.empty()) {
130 tx.bookingDate = jsonString(row, "date");
131 }
132 tx.valuta = jsonString(row, "valuta");
133 tx.amount = jsonDouble(row, "amount");
134 tx.status = static_cast<int>(jsonDouble(row, "status"));
135 tx.contractId = jsonString(row, "contractId");
136 tx.contractType = jsonString(row, "contractType");
137 tx.actorId = jsonString(row, "actorId");
138 tx.statementId = jsonString(row, "statementId");
139 tx.allocatable = jsonBool(row, "allocatable");
140 tx.propertyIds = jsonStringList(row, "propertyIds");
141 tx.propertyNames = jsonStringList(row, "propertyNames");
142 out.push_back(std::move(tx));
143 }
144 return out;
145}
146
147} // namespace
148
149namespace core::application {
150
153 const std::string& currentPath) const {
155 snapshot.currentPath = currentPath;
156 snapshot.hasCurrentPath = !currentPath.empty();
157
158 snapshot.actors.reserve(state.catalog.actors().size());
159 for (const auto& item : state.catalog.actors()) {
160 if (!item) {
161 continue;
162 }
163
165 row.id = item->id();
166 row.name = item->name();
167 row.createdAt = item->createdAt();
168 row.updatedAt = item->updatedAt();
169 row.contractIds = item->contractIds();
170 row.aliases.reserve(item->aliases().size());
171 for (const auto& alias : item->aliases()) {
172 row.aliases.push_back(projectAlias(alias));
173 }
174 snapshot.actors.push_back(std::move(row));
175 }
176
177 snapshot.properties.reserve(state.catalog.properties().size());
178 for (const auto& item : state.catalog.properties()) {
179 if (!item) {
180 continue;
181 }
182
184 row.id = item->id();
185 row.name = item->name();
186 row.createdAt = item->createdAt();
187 row.updatedAt = item->updatedAt();
188 row.contractIds = item->contractIds();
189 row.aliases.reserve(item->aliases().size());
190 for (const auto& alias : item->aliases()) {
191 row.aliases.push_back(projectAlias(alias));
192 }
193 snapshot.properties.push_back(std::move(row));
194 }
195
196 snapshot.contracts.reserve(state.catalog.contracts().size());
197 for (const auto& item : state.catalog.contracts()) {
198 if (!item) {
199 continue;
200 }
201
203 row.id = item->id();
204 row.name = item->name();
205 row.type = item->type();
206 row.allocatableMode = item->allocatableMode();
207 row.actorIds = item->actorIds();
208 row.propertyIds = item->propertyIds();
209 row.createdAt = item->createdAt();
210 row.updatedAt = item->updatedAt();
211 row.aliases.reserve(item->aliases().size());
212 for (const auto& alias : item->aliases()) {
213 row.aliases.push_back(projectAlias(alias));
214 }
215 snapshot.contracts.push_back(std::move(row));
216 }
217
218 snapshot.statements.reserve(state.catalog.statements().size());
219 for (const auto& item : state.catalog.statements()) {
220 if (!item) {
221 continue;
222 }
223
225 row.id = item->id();
226 row.name = item->name();
227 row.transactionIds = item->transactionIds();
228 row.createdAt = item->createdAt();
229 row.updatedAt = item->updatedAt();
230 snapshot.statements.push_back(std::move(row));
231 }
232
233 snapshot.transactions.reserve(state.catalog.transactions().size());
234 for (const auto& item : state.catalog.transactions()) {
235 if (!item) {
236 continue;
237 }
238
240 row.id = item->id();
241 row.name = item->name();
242 row.bookingDate = item->bookingDate();
243 row.valuta = item->valuta();
244 row.amount = item->amount();
245 row.status = static_cast<int>(item->status());
246 row.contractId = item->contractId();
247 row.actorId = item->actorId();
248 row.statementId = item->statementId();
249 row.allocatable = item->isAllocatable();
250 row.propertyIds = item->propertyIds();
251 row.createdAt = item->createdAt();
252 row.updatedAt = item->updatedAt();
253 snapshot.transactions.push_back(std::move(row));
254 }
255
256 snapshot.analyses.reserve(state.catalog.analyses().size());
257 for (const auto& item : state.catalog.analyses()) {
258 if (!item) {
259 continue;
260 }
261
263 row.id = item->id();
264 row.name = item->name();
265 row.type = item->type();
266 row.config = analysisConfigFromJson(item->configJson(), item->type());
268 row.exportFormat = item->exportFormat();
269 row.includeCalculationAdjustments = item->includeCalculationAdjustments();
270 row.snapshotTransactions = snapshotTransactionsFromJson(item->snapshotTransactionsJson());
271 row.createdAt = item->createdAt();
272 row.updatedAt = item->updatedAt();
273 row.adjustments.reserve(item->adjustments().size());
274 for (const auto& [key, value] : item->adjustments()) {
275 row.adjustments.emplace_back(key, value);
276 }
277 snapshot.analyses.push_back(std::move(row));
278 }
279
280 snapshot.annuals.reserve(state.catalog.annuals().size());
281 for (const auto& item : state.catalog.annuals()) {
282 if (!item) {
283 continue;
284 }
285
287 row.id = item->id();
288 row.name = item->name();
289 row.year = item->year();
290 row.analysisIds = item->analysisIds();
291 row.createdAt = item->createdAt();
292 row.updatedAt = item->updatedAt();
293 snapshot.annuals.push_back(std::move(row));
294 }
295
296 snapshot.statementDrafts.reserve(state.workflow.statementDrafts.size());
297 for (const auto& item : state.workflow.statementDrafts) {
298 if (!item) {
299 continue;
300 }
301
303 row.id = item->id;
304 row.name = item->name;
305 row.transactionIds = item->transactionIds;
306 row.createdAt = item->createdAt;
307 row.updatedAt = item->updatedAt;
308
309 std::vector<const core::application::importing::draft::TransactionDraft*> txDrafts;
310 txDrafts.reserve(state.workflow.transactionDrafts.size());
311 for (const auto& tx : state.workflow.transactionDrafts) {
312 if (!tx || tx->statementDraftId != item->id) {
313 continue;
314 }
315 txDrafts.push_back(tx.get());
316 }
317 std::sort(txDrafts.begin(), txDrafts.end(), [](const auto* lhs, const auto* rhs) {
318 return lhs->position < rhs->position;
319 });
320
321 row.transactions.reserve(txDrafts.size());
322 for (const auto* tx : txDrafts) {
323 row.transactions.push_back(projectTransactionDraft(*tx));
324 }
325
326 snapshot.statementDrafts.push_back(std::move(row));
327 }
328
329 snapshot.importLogs.reserve(state.workflow.importLogs.size());
330 for (const auto& item : state.workflow.importLogs) {
331 if (!item) {
332 continue;
333 }
334
335 snapshot.importLogs.push_back({
336 item->id,
337 item->time,
338 item->type,
339 item->file,
340 item->status,
341 item->message,
342 item->draftAttached,
343 item->draftId,
344 item->statementDraftIds,
345 item->statementId
346 });
347 }
348
349 snapshot.exportLogs.reserve(state.workflow.exportLogs.size());
350 for (const auto& item : state.workflow.exportLogs) {
351 if (!item) {
352 continue;
353 }
354
355 snapshot.exportLogs.push_back({
356 item->id,
357 item->time,
358 item->targetPath,
359 item->status,
360 item->message,
361 item->annualIds,
362 item->analysisIds
363 });
364 }
365
366 return snapshot;
367}
368
369std::optional<core::ports::workspace::StatementDraftSnapshot> WorkspaceSnapshotProjector::projectStatementDraft(
371 const std::string& draftId) const {
372 const auto snapshot = project(state, {});
373 if (snapshot.statementDrafts.empty()) {
374 return std::nullopt;
375 }
376
377 if (draftId.empty()) {
378 return snapshot.statementDrafts.front();
379 }
380
381 const auto it = std::find_if(snapshot.statementDrafts.begin(), snapshot.statementDrafts.end(),
382 [&draftId](const auto& item) {
383 return item.id == draftId;
384 });
385 if (it == snapshot.statementDrafts.end()) {
386 return std::nullopt;
387 }
388
389 return *it;
390}
391
392} // namespace core::application
Defines stable analysis type, configuration, filter, and result keys.
Declares analysis use-case request DTOs and filter-spec helpers.
Projects internal workspace session state into immutable port snapshots.
core::ports::workspace::WorkspaceSnapshot project(const core::application::workspace::WorkspaceSessionState &state, const std::string &currentPath) const
Builds an immutable workspace snapshot from session state.
std::optional< core::ports::workspace::StatementDraftSnapshot > projectStatementDraft(const core::application::workspace::WorkspaceSessionState &state, const std::string &draftId={}) const
Resolves a single draft snapshot from session state.
const std::string & lastUsedAt() const noexcept
Definition Alias.cpp:38
const std::string & createdAt() const noexcept
Definition Alias.cpp:34
int hitCount() const noexcept
Definition Alias.cpp:37
const std::string & updatedAt() const noexcept
Definition Alias.cpp:36
const std::string & kind() const noexcept
Definition Alias.cpp:30
const std::string & value() const noexcept
Definition Alias.cpp:27
const std::string & source() const noexcept
Definition Alias.cpp:32
const PropertyList & properties() const noexcept
Returns all properties in the catalog.
const AnnualList & annuals() const noexcept
Returns all annuals in the catalog.
const StatementList & statements() const noexcept
Returns all statements in the catalog.
const TransactionList & transactions() const noexcept
Returns all transactions in the catalog.
const ActorList & actors() const noexcept
Returns all actors in the catalog.
const ContractList & contracts() const noexcept
Returns all contracts in the catalog.
const AnalysisList & analyses() const noexcept
Returns all analyses in the catalog.
constexpr std::string_view kPlotTypeKey
constexpr std::string_view kPropertiesKey
constexpr std::string_view kPlotMeasureKey
constexpr std::string_view kContractTypesKey
AnalysisFilterSelection parseAnalysisFilterSelection(const std::string &filterSpec)
Parses a serialized analysis filter specification.
core::domain::catalog::WorkspaceCatalog catalog
std::vector< AliasSnapshot > aliases
std::vector< std::string > contractIds
core::ports::analysis::AnalysisFilterSelection filter
core::ports::analysis::AnalysisConfigInput config
std::vector< TransactionSnapshot > snapshotTransactions
std::vector< std::pair< std::string, double > > adjustments
std::vector< TransactionDraftSnapshot > transactions
std::vector< AnalysisSnapshot > analyses
std::vector< PropertySnapshot > properties
std::vector< ContractSnapshot > contracts
std::vector< StatementDraftSnapshot > statementDrafts
std::vector< StatementSnapshot > statements
std::vector< ImportLogSnapshot > importLogs
std::vector< ExportLogSnapshot > exportLogs
std::vector< TransactionSnapshot > transactions