18constexpr auto kContractBaseName =
"Contract";
24std::vector<std::string> normalizedSorted(std::vector<std::string> values) {
25 std::vector<std::string> out;
26 out.reserve(values.size());
27 for (
const auto& value : values) {
29 if (!normalized.empty()) {
30 out.push_back(normalized);
33 std::sort(out.begin(), out.end());
37bool sameStringSet(
const std::vector<std::string>& lhs,
38 const std::vector<std::string>& rhs) {
39 return normalizedSorted(lhs) == normalizedSorted(rhs);
42std::vector<std::string> normalizedValues(
const std::vector<std::string>& values) {
43 std::vector<std::string> out;
44 out.reserve(values.size());
45 for (
const auto& value : values) {
47 if (!normalized.empty()) {
48 out.push_back(normalized);
54bool containsValue(
const std::vector<std::string>& values,
55 const std::string& value) {
60 const auto normalized = normalizedValues(values);
61 return std::find(normalized.begin(), normalized.end(), target) != normalized.end();
64bool containsAllValues(
const std::vector<std::string>& values,
65 const std::vector<std::string>& required) {
66 const auto normalizedRequired = normalizedValues(required);
67 return std::all_of(normalizedRequired.begin(), normalizedRequired.end(),
68 [&](
const std::string& value) {
69 return containsValue(values, value);
73int trailingContractIndex(
const std::string& value) {
75 const std::string prefix = std::string(kContractBaseName) +
" ";
76 if (trimmed.size() <= prefix.size() ||
81 std::size_t consumed = 0;
82 const int index = std::stoi(trimmed.substr(prefix.size()), &consumed);
83 return consumed == trimmed.size() - prefix.size() ? index : -1;
90 const std::string&
id,
91 const std::string& name) {
100 const std::string&
id) {
102 if (target.empty()) {
106 if (contract && contract->id() == target) {
107 return contract.get();
118 : session_(&session) {
126 return session_->
state();
130 return projector_.project(stateRef(),
currentPath());
138 return projector_.projectStatementDraft(stateRef(), draftId);
142 const auto target = normalizedText(name);
143 if (target.empty()) {
146 for (
const auto& actor : stateRef().catalog.actors()) {
147 if (actor && normalizedText(actor->name()) == target) {
148 return identity(actor->id(), actor->name());
155 const auto target = normalizedText(name);
156 if (target.empty()) {
159 for (
const auto& property : stateRef().catalog.properties()) {
160 if (property && normalizedText(property->name()) == target) {
161 return identity(property->id(), property->name());
168 const std::string& name,
169 const std::string& type,
170 const std::vector<std::string>& actorIds,
171 const std::vector<std::string>& propertyIds)
const {
172 const auto normalizedName = normalizedText(name);
173 const auto normalizedType = normalizedText(type);
174 if (normalizedName.empty() || normalizedType.empty()) {
177 for (
const auto& contract : stateRef().catalog.contracts()) {
179 normalizedText(contract->name()) != normalizedName ||
180 normalizedText(contract->type()) != normalizedType ||
181 !sameStringSet(contract->actorIds(), actorIds) ||
182 !sameStringSet(contract->propertyIds(), propertyIds)) {
186 auto out = identity(contract->id(), contract->name());
187 out.type = contract->type();
188 out.allocatableMode = contract->allocatableMode();
189 out.actorIds = normalizedSorted(contract->actorIds());
190 out.propertyIds = normalizedSorted(contract->propertyIds());
203 if (
const auto* contract = findContractById(stateRef(), out.
contractId)) {
204 const auto actorIds = normalizedValues(contract->actorIds());
205 out.
actorId = actorIds.empty() ? std::string{} : actorIds.front();
206 out.
propertyIds = normalizedValues(contract->propertyIds());
215 const auto* contract = findContractById(stateRef(), out.
contractId);
216 if (contract && !out.
actorId.empty() &&
217 !containsValue(contract->actorIds(), out.
actorId)) {
224 const auto* contract = findContractById(stateRef(), out.
contractId);
225 if (contract && !containsAllValues(contract->propertyIds(), out.
propertyIds)) {
235 for (
const auto& contract : stateRef().catalog.contracts()) {
239 maxIndex = std::max(maxIndex, trailingContractIndex(contract->name()));
241 return std::string(kContractBaseName) +
" " + std::to_string(maxIndex + 1);
Shared alias normalization and ranking helpers for core entities.
Domain model for contracts.
Reads workspace snapshots and draft projections from the application layer.
Declares the mutable workspace session that ties in-memory state to storage.
core::ports::workspace::WorkspaceSnapshot workspaceSnapshot() const
Projects full workspace snapshot for port consumers.
std::optional< core::ports::workspace::StatementDraftSnapshot > statementDraftSnapshot(const std::string &draftId={}) const
Projects one statement draft snapshot.
core::ports::workspace::WorkspaceIdentitySnapshot contractIdentityBySignature(const std::string &name, const std::string &type, const std::vector< std::string > &actorIds, const std::vector< std::string > &propertyIds) const
Finds a contract identity by normalized signature.
core::ports::workspace::TransactionCatalogSelection transactionCatalogSelection(const core::ports::workspace::TransactionCatalogSelectionChange &change) const
Applies catalog consistency rules to a transaction form selection.
WorkspaceQueryService(WorkspaceSession &session)
Creates the query service for one workspace session.
core::ports::workspace::WorkspaceIdentitySnapshot actorIdentityByName(const std::string &name) const
Finds an actor identity by normalized name.
std::string nextContractName() const
Returns the next generated contract name.
core::ports::workspace::WorkspaceIdentitySnapshot propertyIdentityByName(const std::string &name) const
Finds a property identity by normalized name.
const std::string & currentPath() const noexcept
Returns current workspace file path.
Maintains the editable app state for one workspace and persists it through IStorageManager.
const core::application::workspace::WorkspaceSessionState & state() const noexcept
const ContractList & contracts() const noexcept
Returns all contracts in the catalog.
Collects common core includes and aliases for precompiled-header builds.
std::string canonicalAliasValue(std::string value)
Canonicalizes an alias string for comparison.
std::string trimCopy(std::string value)
Trims leading and trailing whitespace from text.
QString normalizedText(const QString &value)
Normalizes text for case-insensitive UI comparisons.
core::domain::catalog::WorkspaceCatalog catalog
Catalog selection change request for transaction forms.
bool propertiesChanged
True when propertyIds contains user-selected properties.
bool contractChanged
True when contractId contains a user-selected contract.
std::string actorId
New actor id when actorChanged is true.
TransactionCatalogSelection current
Current transaction catalog selection.
std::string contractId
New contract id when contractChanged is true.
bool actorChanged
True when actorId contains a user-selected actor.
std::vector< std::string > propertyIds
New property ids when propertiesChanged is true.
Transaction catalog ids selected by a UI form or workspace query.
std::vector< std::string > propertyIds
Selected property ids.
std::string contractId
Selected contract id.
std::string actorId
Selected actor id.