~aleteoryx/muditaos

31b24ed4d3b6fb8e21b870a111eb982d4787dddd — Mateusz Grzegorzek 5 years ago 2de63da
[EGD-5932] Add more queries to Quotes agent

Added queries:
- list quotes from selected category,
- enable/disable category,
- enable/disable single quote,
- list enabled quotes,

Other fixes:
- move `msgHandled` and `msgNotHandled` to `Message.hpp`,
- use `typeid` in `QuotesAgent::registerMessages`,
- change `Quotes::Queries` style,
- make `quotesList` private

Queries to add in next PR:
- add/read/write quote
M image/user/db/quotes_001.sql => image/user/db/quotes_001.sql +2 -2
@@ 10,7 10,7 @@ CREATE TABLE IF NOT EXISTS quote_languages (
CREATE TABLE IF NOT EXISTS category_table (
    category_id INTEGER NOT NULL,
    category_name TEXT NOT NULL UNIQUE,
    enabled BOOLEAN DEFAULT TRUE,
    enabled BOOLEAN NOT NULL DEFAULT TRUE,
    PRIMARY KEY (category_id)
    );



@@ 19,7 19,7 @@ CREATE TABLE IF NOT EXISTS quote_table (
    lang_id INTEGER NOT NULL,
    quote TEXT NOT NULL,
    author TEXT,
    enabled BOOLEAN DEFAULT TRUE,
    enabled BOOLEAN NOT NULL DEFAULT TRUE,
    PRIMARY KEY (quote_id),
    FOREIGN KEY (lang_id) REFERENCES quote_languages(lang_id)
    );

M module-apps/Application.cpp => module-apps/Application.cpp +22 -22
@@ 275,10 275,10 @@ namespace app
        else if (auto msg = dynamic_cast<AudioKeyPressedResponse *>(msgl)) {
            if (!msg->muted) {
                handleVolumePopup();
                return msgHandled();
                return sys::msgHandled();
            }
        }
        return msgNotHandled();
        return sys::msgNotHandled();
    }

    sys::MessagePointer Application::handleSignalStrengthUpdate(sys::Message *msgl)


@@ 286,7 286,7 @@ namespace app
        if ((state == State::ACTIVE_FORGROUND) && getCurrentWindow()->updateSignalStrength()) {
            refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
        }
        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleNetworkAccessTechnologyUpdate(sys::Message *msgl)


@@ 294,7 294,7 @@ namespace app
        if ((state == State::ACTIVE_FORGROUND) && getCurrentWindow()->updateNetworkAccessTechnology()) {
            refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
        }
        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleInputEvent(sys::Message *msgl)


@@ 309,7 309,7 @@ namespace app
        if (not windowsStack.isEmpty() && getCurrentWindow()->onInput(msg->getEvent())) {
            refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
        }
        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleKBDKeyEvent(sys::Message *msgl)


@@ 322,7 322,7 @@ namespace app
        if (iev.keyCode != gui::KeyCode::KEY_UNDEFINED) {
            messageInputEventApplication(this, this->GetName(), iev);
        }
        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleBatteryStatusChange()


@@ 330,7 330,7 @@ namespace app
        if ((state == State::ACTIVE_FORGROUND) && getCurrentWindow()->updateBatteryStatus()) {
            refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
        }
        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleMinuteUpdated(sys::Message *msgl)


@@ 338,7 338,7 @@ namespace app
        if (state == State::ACTIVE_FORGROUND && getCurrentWindow()->updateTime()) {
            refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
        }
        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleAction(sys::Message *msgl)


@@ 398,9 398,9 @@ namespace app
                      stateStr(state));
        }
        if (handled) {
            return msgHandled();
            return sys::msgHandled();
        }
        return msgNotHandled();
        return sys::msgNotHandled();
    }

    sys::MessagePointer Application::handleSwitchWindow(sys::Message *msgl)


@@ 428,7 428,7 @@ namespace app
                if (text != nullptr) {
                    text->addText(ret->getDescription());
                    refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
                    return msgHandled();
                    return sys::msgHandled();
                }
            }
            getCurrentWindow()->onBeforeShow(msg->getCommand(), switchData.get());


@@ 437,7 437,7 @@ namespace app
        else {
            LOG_ERROR("No such window: %s", msg->getWindowName().c_str());
        }
        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleUpdateWindow(sys::Message *msgl)


@@ 453,14 453,14 @@ namespace app
        else {
            LOG_ERROR("No such window: %s", msg->getWindowName().c_str());
        }
        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleAppClose(sys::Message *msgl)
    {
        setState(State::DEACTIVATING);
        app::manager::Controller::confirmClose(this);
        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleAppRebuild(sys::Message *msgl)


@@ 475,7 475,7 @@ namespace app
            refreshWindow(gui::RefreshModes::GUI_REFRESH_DEEP);
        }
        LOG_INFO("App rebuild done");
        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleAppRefresh(sys::Message *msgl)


@@ 486,29 486,29 @@ namespace app
            LOG_DEBUG("Ignore request for window %s we are on window %s",
                      msg->getWindowName().c_str(),
                      windowsStack.isEmpty() ? "none" : getCurrentWindow()->getName().c_str());
            return msgNotHandled();
            return sys::msgNotHandled();
        }
        render(msg->getMode());
        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleGetDOM(sys::Message *msgl)
    {
        if (windowsStack.isEmpty()) {
            LOG_ERROR("Current window is not defined - can't dump DOM");
            return msgNotHandled();
            return sys::msgNotHandled();
        }
        auto window = getCurrentWindow();
        if (window == nullptr) {
            LOG_ERROR("No window - can't dump DOM");
            return msgNotHandled();
            return sys::msgNotHandled();
        }

        auto request = static_cast<app::manager::DOMRequest *>(msgl);
        LOG_DEBUG("Get DOM for: %s", request->getSenderName().c_str());
        bus.sendUnicast(DOMResponder(GetName(), *window, std::move(request->event)).build(), request->getSenderName());

        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleAppFocusLost(sys::Message *msgl)


@@ 517,7 517,7 @@ namespace app
            setState(State::ACTIVE_BACKGROUND);
            app::manager::Controller::confirmSwitch(this);
        }
        return msgHandled();
        return sys::msgHandled();
    }

    sys::MessagePointer Application::handleSIMMessage(sys::Message *msgl)


@@ 525,7 525,7 @@ namespace app
        if (getCurrentWindow()->updateSim()) {
            refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
        }
        return msgHandled();
        return sys::msgHandled();
    }

    sys::ReturnCodes Application::InitHandler()

M module-apps/Application.hpp => module-apps/Application.hpp +0 -10
@@ 65,16 65,6 @@ namespace app
    class Application;
    class GuiTimer;

    inline auto msgHandled() -> sys::MessagePointer
    {
        return std::make_shared<sys::ResponseMessage>();
    }

    inline auto msgNotHandled() -> sys::MessagePointer
    {
        return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Unresolved);
    }

    class ActionHandledResponse; // Forward declaration
    using ActionResult = std::shared_ptr<ActionHandledResponse>;
    auto actionHandled() -> ActionResult;

M module-apps/application-alarm-clock/ApplicationAlarmClock.cpp => module-apps/application-alarm-clock/ApplicationAlarmClock.cpp +3 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ApplicationAlarmClock.hpp"


@@ 56,9 56,9 @@ namespace app
            }
        }
        if (handled) {
            return msgHandled();
            return sys::msgHandled();
        }
        return msgNotHandled();
        return sys::msgNotHandled();
    }

    sys::ReturnCodes ApplicationAlarmClock::InitHandler()

M module-apps/application-calllog/ApplicationCallLog.cpp => module-apps/application-calllog/ApplicationCallLog.cpp +3 -3
@@ 51,17 51,17 @@ namespace app
            for (auto &[name, window] : windowsStack.windows) {
                window->onDatabaseMessage(msgl);
            }
            return msgHandled();
            return sys::msgHandled();
        }

        if (resp != nullptr) {
            if (auto command = callbackStorage->getCallback(resp); command->execute()) {
                refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
                return msgHandled();
                return sys::msgHandled();
            }
        }

        return msgNotHandled();
        return sys::msgNotHandled();
    }

    // Invoked during initialization

M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +1 -1
@@ 361,7 361,7 @@ namespace app
                    getWindow(app::window::name::desktop_update)->handleSwitchData(data.get());
                }
            }
            return msgHandled();
            return sys::msgHandled();
        });

        auto msgToSend =

M module-apps/application-notes/ApplicationNotes.cpp => module-apps/application-notes/ApplicationNotes.cpp +3 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ApplicationNotes.hpp"


@@ 59,9 59,9 @@ namespace app
            if (auto command = callbackStorage->getCallback(resp); command->execute()) {
                refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
            }
            return msgHandled();
            return sys::msgHandled();
        }
        return msgNotHandled();
        return sys::msgNotHandled();
    }

    sys::ReturnCodes ApplicationNotes::InitHandler()

M module-apps/application-onboarding/ApplicationOnBoarding.cpp => module-apps/application-onboarding/ApplicationOnBoarding.cpp +3 -3
@@ 51,7 51,7 @@ namespace app
            return retMsg;
        }

        return msgNotHandled();
        return sys::msgNotHandled();
    }

    sys::ReturnCodes ApplicationOnBoarding::InitHandler()


@@ 67,10 67,10 @@ namespace app
        connect(typeid(manager::GetCurrentDisplayLanguageResponse), [&](sys::Message *msg) {
            if (gui::window::name::onBoarding_languages == getCurrentWindow()->getName()) {
                switchWindow(gui::window::name::onBoarding_eula, nullptr);
                return msgHandled();
                return sys::msgHandled();
            }
            else {
                return msgNotHandled();
                return sys::msgNotHandled();
            }
        });


M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +7 -7
@@ 273,27 273,27 @@ namespace app::manager
        connect(typeid(InputLanguageChangeRequest), [this](sys::Message *request) {
            auto msg = static_cast<InputLanguageChangeRequest *>(request);
            handleInputLanguageChange(msg);
            return msgHandled();
            return sys::msgHandled();
        });
        connect(typeid(AutomaticDateAndTimeIsOnChangeRequest), [this](sys::Message *request) {
            auto msg = static_cast<AutomaticDateAndTimeIsOnChangeRequest *>(request);
            handleAutomaticDateAndTimeChange(msg);
            return msgHandled();
            return sys::msgHandled();
        });
        connect(typeid(AutomaticTimeZoneIsOnChangeRequest), [this](sys::Message *request) {
            auto msg = static_cast<AutomaticTimeZoneIsOnChangeRequest *>(request);
            handleAutomaticTimeZoneChange(msg);
            return msgHandled();
            return sys::msgHandled();
        });
        connect(typeid(TimeFormatChangeRequest), [this](sys::Message *request) {
            auto msg = static_cast<TimeFormatChangeRequest *>(request);
            handleTimeFormatChange(msg);
            return msgHandled();
            return sys::msgHandled();
        });
        connect(typeid(DateFormatChangeRequest), [this](sys::Message *request) {
            auto msg = static_cast<DateFormatChangeRequest *>(request);
            handleDateFormatChange(msg);
            return msgHandled();
            return sys::msgHandled();
        });
        connect(typeid(ShutdownRequest), [this](sys::Message *) {
            closeApplications();


@@ 313,12 313,12 @@ namespace app::manager
        });
        connect(typeid(UpdateInProgress), [this](sys::Message *) {
            closeApplicationsOnUpdate();
            return msgHandled();
            return sys::msgHandled();
        });
        connect(typeid(SetOsUpdateVersion), [this](sys::Message *request) {
            auto msg = static_cast<SetOsUpdateVersion *>(request);
            handleSetOsUpdateVersionChange(msg);
            return msgHandled();
            return sys::msgHandled();
        });

        connect(typeid(app::manager::DOMRequest), [&](sys::Message *request) { return handleDOMRequest(request); });

M module-services/service-db/agents/file_indexer/FileIndexerAgent.cpp => module-services/service-db/agents/file_indexer/FileIndexerAgent.cpp +8 -8
@@ 279,7 279,7 @@ auto FileIndexerAgent::handleGetRecord(sys::Message *req) -> sys::MessagePointer
        return std::make_shared<FileIndexer::Messages::GetRecordResponseMessage>(
            std::make_unique<FileIndexer::FileRecord>(msg->dbRecord));
    }
    return app::msgHandled();
    return sys::msgHandled();
}

auto FileIndexerAgent::handleSetRecord(sys::Message *req) -> sys::MessagePointer


@@ 303,7 303,7 @@ auto FileIndexerAgent::handleSetRecord(sys::Message *req) -> sys::MessagePointer
            }
        }
    }
    return app::msgHandled();
    return sys::msgHandled();
}

auto FileIndexerAgent::handleDeleteFile(sys::Message *req) -> sys::MessagePointer


@@ 324,7 324,7 @@ auto FileIndexerAgent::handleDeleteFile(sys::Message *req) -> sys::MessagePointe
            parentService->bus.sendUnicast(std::move(notifyMsg), recipient);
        }
    }
    return app::msgHandled();
    return sys::msgHandled();
}

auto FileIndexerAgent::handleDeleteAllFilesInDir(sys::Message *req) -> sys::MessagePointer


@@ 346,7 346,7 @@ auto FileIndexerAgent::handleDeleteAllFilesInDir(sys::Message *req) -> sys::Mess
            parentService->bus.sendUnicast(std::move(notifyMsg), recipient);
        }
    }
    return app::msgHandled();
    return sys::msgHandled();
}

auto FileIndexerAgent::dbGetProperty(std::unique_ptr<FileIndexer::FileMetadata> metaData) -> FileIndexer::FileMetadata


@@ 474,7 474,7 @@ auto FileIndexerAgent::handleGetProperty(sys::Message *req) -> sys::MessagePoint
        return std::make_shared<FileIndexer::Messages::GetPropertyResponseMessage>(
            std::make_unique<FileIndexer::FileMetadata>(msg->dbMetaData));
    }
    return app::msgHandled();
    return sys::msgHandled();
}

auto FileIndexerAgent::handleGetAllProperties(sys::Message *req) -> sys::MessagePointer


@@ 486,7 486,7 @@ auto FileIndexerAgent::handleGetAllProperties(sys::Message *req) -> sys::Message
        return std::make_shared<FileIndexer::Messages::GetPropertyResponseMessage>(
            std::make_unique<FileIndexer::FileMetadata>(msg->dbMetaData));
    }
    return app::msgHandled();
    return sys::msgHandled();
}

auto FileIndexerAgent::handleSetProperty(sys::Message *req) -> sys::MessagePointer


@@ 509,7 509,7 @@ auto FileIndexerAgent::handleSetProperty(sys::Message *req) -> sys::MessagePoint
            dbSetProperty(std::make_unique<FileIndexer::FileMetadata>(metaData));
        }
    }
    return app::msgHandled();
    return sys::msgHandled();
}

auto FileIndexerAgent::handleSetProperties(sys::Message *req) -> sys::MessagePointer


@@ 529,5 529,5 @@ auto FileIndexerAgent::handleSetProperties(sys::Message *req) -> sys::MessagePoi
            parentService->bus.sendUnicast(std::move(notifyMsg), recipient);
        }
    }
    return app::msgHandled();
    return sys::msgHandled();
}

M module-services/service-db/agents/quotes/QuotesAgent.cpp => module-services/service-db/agents/quotes/QuotesAgent.cpp +51 -4
@@ 18,9 18,18 @@ namespace Quotes
    {
        using std::placeholders::_1;

        parentService->connect(Messages::GetCategoryListRequest(),
        parentService->connect(typeid(Messages::GetCategoryListRequest),
                               std::bind(&QuotesAgent::handleCategoryList, this, _1));
        parentService->connect(Messages::GetQuotesListRequest(), std::bind(&QuotesAgent::handleQuotesList, this, _1));
        parentService->connect(typeid(Messages::GetQuotesListRequest),
                               std::bind(&QuotesAgent::handleQuotesList, this, _1));
        parentService->connect(typeid(Messages::GetQuotesListByCategoryIdRequest),
                               std::bind(&QuotesAgent::handleQuotesListByCategoryId, this, _1));
        parentService->connect(typeid(Messages::EnableCategoryByIdRequest),
                               std::bind(&QuotesAgent::handleEnableCategoryById, this, _1));
        parentService->connect(typeid(Messages::EnableQuoteByIdRequest),
                               std::bind(&QuotesAgent::handleEnableQuoteById, this, _1));
        parentService->connect(typeid(Messages::GetEnabledQuotesListRequest),
                               std::bind(&QuotesAgent::handleEnabledQuotesList, this, _1));
    }

    auto QuotesAgent::getDbFilePath() -> const std::string


@@ 45,7 54,7 @@ namespace Quotes
            auto categoryList = getList<CategoryList, CategoryRecord>(std::move(msg->categoryList), std::move(query));
            return std::make_shared<Messages::GetCategoryListResponse>(std::move(categoryList));
        }
        return app::msgNotHandled();
        return sys::msgNotHandled();
    }

    auto QuotesAgent::handleQuotesList(sys::Message *req) -> sys::MessagePointer


@@ 55,7 64,45 @@ namespace Quotes
            auto quotesList = getList<QuotesList, QuoteRecord>(std::move(msg->quotesList), std::move(query));
            return std::make_shared<Messages::GetQuotesListResponse>(std::move(quotesList));
        }
        return app::msgNotHandled();
        return sys::msgNotHandled();
    }

    auto QuotesAgent::handleQuotesListByCategoryId(sys::Message *req) -> sys::MessagePointer
    {
        if (auto msg = dynamic_cast<Messages::GetQuotesListByCategoryIdRequest *>(req)) {
            auto query      = database->query(Queries::getQuotesByCategoryId, msg->categoryId);
            auto quotesList = getList<QuotesList, QuoteRecord>(std::move(msg->quotesList), std::move(query));
            return std::make_shared<Messages::GetQuotesListByCategoryIdResponse>(std::move(quotesList));
        }
        return sys::msgNotHandled();
    }

    auto QuotesAgent::handleEnableCategoryById(sys::Message *req) -> sys::MessagePointer
    {
        if (auto msg = dynamic_cast<Messages::EnableCategoryByIdRequest *>(req)) {
            auto result = database->execute(Queries::enableCategory, msg->enable, msg->categoryId);
            return std::make_shared<Messages::EnableCategoryByIdResponse>(result);
        }
        return sys::msgNotHandled();
    }

    auto QuotesAgent::handleEnableQuoteById(sys::Message *req) -> sys::MessagePointer
    {
        if (auto msg = dynamic_cast<Messages::EnableQuoteByIdRequest *>(req)) {
            auto result = database->execute(Queries::enableQuote, msg->enable, msg->quoteId);
            return std::make_shared<Messages::EnableQuoteByIdResponse>(result);
        }
        return sys::msgNotHandled();
    }

    auto QuotesAgent::handleEnabledQuotesList(sys::Message *req) -> sys::MessagePointer
    {
        if (auto msg = dynamic_cast<Messages::GetEnabledQuotesListRequest *>(req)) {
            auto query      = database->query(Queries::getEnabledQuotes);
            auto quotesList = getList<QuotesList, QuoteRecord>(std::move(msg->quotesList), std::move(query));
            return std::make_shared<Messages::GetEnabledQuotesListResponse>(std::move(quotesList));
        }
        return sys::msgNotHandled();
    }

} // namespace Quotes

M module-services/service-db/agents/quotes/QuotesAgent.hpp => module-services/service-db/agents/quotes/QuotesAgent.hpp +5 -1
@@ 11,7 11,7 @@ namespace Quotes
    class QuotesAgent : public DatabaseAgent
    {
      public:
        QuotesAgent(sys::Service *parentService);
        explicit QuotesAgent(sys::Service *parentService);
        ~QuotesAgent() = default;

        void initDb() override


@@ 24,6 24,10 @@ namespace Quotes
      protected:
        auto handleCategoryList(sys::Message *req) -> sys::MessagePointer;
        auto handleQuotesList(sys::Message *req) -> sys::MessagePointer;
        auto handleQuotesListByCategoryId(sys::Message *req) -> sys::MessagePointer;
        auto handleEnableCategoryById(sys::Message *req) -> sys::MessagePointer;
        auto handleEnableQuoteById(sys::Message *req) -> sys::MessagePointer;
        auto handleEnabledQuotesList(sys::Message *req) -> sys::MessagePointer;

      private:
        auto getDbInitString() -> const std::string override;

M module-services/service-db/agents/quotes/QuotesQueries.hpp => module-services/service-db/agents/quotes/QuotesQueries.hpp +44 -0
@@ 14,4 14,48 @@ namespace Quotes::Queries
                        SELECT quote_id, lang_id, quote, author, enabled
                        FROM quote_table;
                        )sql";

    constexpr auto getQuotesByCategoryId = R"sql(
                        SELECT QT.quote_id, QT.lang_id, QT.quote, QT.author, QT.enabled
                        FROM 
                            quote_table as QT,
                            quote_category_map as QCM,
                            category_table as CT
                        WHERE
                            QCM.quote_id = QT.quote_id
                            and 
                            QCM.category_id = CT.category_id
                            and
                            QCM.category_id = '%lu'
                            and
                            QT.enabled = TRUE
                            and
                            CT.enabled = TRUE
                        )sql";

    constexpr auto enableCategory = R"sql(
                        UPDATE category_table SET enabled = '%d'
                        WHERE category_id = '%lu';
                        )sql";

    constexpr auto enableQuote = R"sql(
                        UPDATE quote_table SET enabled = '%d'
                        WHERE quote_id = '%lu';
                        )sql";

    constexpr auto getEnabledQuotes = R"sql(
                        SELECT QT.quote_id, QT.lang_id, QT.quote, QT.author, QT.enabled
                        FROM
                            quote_table as QT,
                            quote_category_map as QCM,
                            category_table as CT
                        WHERE
                            QCM.quote_id = QT.quote_id
                            and
                            QCM.category_id = CT.category_id
                            and
                            QT.enabled = TRUE
                            and
                            CT.enabled = TRUE
                        )sql";
} // namespace Quotes::Queries

M module-services/service-db/service-db/QuotesMessages.hpp => module-services/service-db/service-db/QuotesMessages.hpp +104 -10
@@ 45,11 45,6 @@ namespace Quotes
        std::string author;
        bool enabled;

        [[nodiscard]] auto RecordEqual(QuoteRecord qr) const noexcept -> bool
        {
            return qr.lang_id == lang_id && qr.quote == quote;
        }

        QuoteRecord() = default;

        explicit QuoteRecord(QueryResult *query)


@@ 77,7 72,6 @@ namespace Quotes
        class GetCategoryListRequest : public QuotesMessage
        {
          public:
            GetCategoryListRequest() = default;
            explicit GetCategoryListRequest(std::unique_ptr<CategoryList> categoryList)
                : QuotesMessage(), categoryList(std::move(categoryList))
            {}


@@ 91,7 85,6 @@ namespace Quotes
                                             sys::ReturnCodes code = sys::ReturnCodes::Success)
                : sys::ResponseMessage(code), categoryList(std::move(categoryList))
            {}
            std::unique_ptr<CategoryList> categoryList;

            [[nodiscard]] unsigned int getCount() const noexcept
            {


@@ 102,14 95,15 @@ namespace Quotes
            {
                return categoryList->data;
            }

          private:
            std::unique_ptr<CategoryList> categoryList;
        };

        class GetQuotesListRequest : public QuotesMessage
        {
          public:
            GetQuotesListRequest() = default;
            explicit GetQuotesListRequest(std::unique_ptr<QuotesList> quotesList)
                : QuotesMessage(), quotesList(std::move(quotesList))
            explicit GetQuotesListRequest(std::unique_ptr<QuotesList> quotesList) : quotesList(std::move(quotesList))
            {}
            std::unique_ptr<QuotesList> quotesList;
        };


@@ 121,7 115,38 @@ namespace Quotes
                                           sys::ReturnCodes code = sys::ReturnCodes::Success)
                : sys::ResponseMessage(code), quotesList(std::move(quotesList))
            {}

            [[nodiscard]] unsigned int getCount() const noexcept
            {
                return quotesList->count;
            }

            [[nodiscard]] auto getResults() const -> std::vector<QuoteRecord>
            {
                return quotesList->data;
            }

          private:
            std::unique_ptr<QuotesList> quotesList;
        };

        class GetQuotesListByCategoryIdRequest : public QuotesMessage
        {
          public:
            explicit GetQuotesListByCategoryIdRequest(std::unique_ptr<QuotesList> quotesList, unsigned int categoryId)
                : quotesList(std::move(quotesList)), categoryId(categoryId)
            {}
            std::unique_ptr<QuotesList> quotesList;
            const unsigned int categoryId;
        };

        class GetQuotesListByCategoryIdResponse : public sys::ResponseMessage
        {
          public:
            explicit GetQuotesListByCategoryIdResponse(std::unique_ptr<QuotesList> quotesList,
                                                       sys::ReturnCodes code = sys::ReturnCodes::Success)
                : sys::ResponseMessage(code), quotesList(std::move(quotesList))
            {}

            [[nodiscard]] unsigned int getCount() const noexcept
            {


@@ 132,6 157,75 @@ namespace Quotes
            {
                return quotesList->data;
            }

          private:
            std::unique_ptr<QuotesList> quotesList;
        };

        class EnableCategoryByIdRequest : public QuotesMessage
        {
          public:
            explicit EnableCategoryByIdRequest(unsigned int categoryId, bool enable)
                : categoryId(categoryId), enable(enable)
            {}
            const unsigned int categoryId;
            const bool enable;
        };

        class EnableCategoryByIdResponse : public QuotesMessage
        {
          public:
            explicit EnableCategoryByIdResponse(bool success) : success(success)
            {}
            const bool success;
        };

        class EnableQuoteByIdRequest : public QuotesMessage
        {
          public:
            explicit EnableQuoteByIdRequest(unsigned int quoteId, bool enable) : quoteId(quoteId), enable(enable)
            {}
            const unsigned int quoteId;
            const bool enable;
        };

        class EnableQuoteByIdResponse : public QuotesMessage
        {
          public:
            explicit EnableQuoteByIdResponse(bool success) : success(success)
            {}
            const bool success;
        };

        class GetEnabledQuotesListRequest : public QuotesMessage
        {
          public:
            explicit GetEnabledQuotesListRequest(std::unique_ptr<QuotesList> quotesList)
                : quotesList(std::move(quotesList))
            {}
            std::unique_ptr<QuotesList> quotesList;
        };

        class GetEnabledQuotesListResponse : public sys::ResponseMessage
        {
          public:
            explicit GetEnabledQuotesListResponse(std::unique_ptr<QuotesList> quotesList,
                                                  sys::ReturnCodes code = sys::ReturnCodes::Success)
                : sys::ResponseMessage(code), quotesList(std::move(quotesList))
            {}

            [[nodiscard]] unsigned int getCount() const noexcept
            {
                return quotesList->count;
            }

            [[nodiscard]] auto getResults() const -> std::vector<QuoteRecord>
            {
                return quotesList->data;
            }

          private:
            std::unique_ptr<QuotesList> quotesList;
        };
    } // namespace Messages
} // namespace Quotes

M module-services/service-db/test/test-service-db-quotes.cpp => module-services/service-db/test/test-service-db-quotes.cpp +52 -0
@@ 9,6 9,7 @@ using namespace Quotes;

constexpr auto totalNumOfCategoriesInDb = 6;
constexpr auto totalNumOfQuotesInDb     = 48;
constexpr auto numOfQuotesWithCategoryIdEqualToOne = 9;

TEST_CASE("Quotes")
{


@@ 74,5 75,56 @@ TEST_CASE("Quotes")
        REQUIRE(response->getResults().size() == totalNumOfQuotesInDb);
    }

    SECTION("Get quotes by category id")
    {
        const unsigned int categoryId = 1;
        auto quotes                   = tester->getQuotesByCategoryId(categoryId);
        REQUIRE(quotes.size() == numOfQuotesWithCategoryIdEqualToOne);
    }

    SECTION("Enable category by id")
    {
        bool enable                   = false;
        const unsigned int categoryId = 1;

        auto response = tester->enableCategory(categoryId, enable);
        REQUIRE(response->success);

        // Quotes in category one should be disabled
        auto quotes = tester->getQuotesByCategoryId(categoryId);
        REQUIRE(quotes.size() == 0);

        enable = true;

        response = tester->enableCategory(categoryId, enable);
        REQUIRE(response->success);

        // Quotes in category one should be enabled
        quotes = tester->getQuotesByCategoryId(categoryId);
        REQUIRE(quotes.size() == numOfQuotesWithCategoryIdEqualToOne);
    }

    SECTION("Enable quote by id")
    {
        bool enable                = false;
        const unsigned int quoteId = 1;

        auto response = tester->enableQuote(quoteId, enable);
        REQUIRE(response->success);

        // All quotes except quote with id=1 should be enabled
        auto quotes = tester->getEnabledQuotes();
        REQUIRE(quotes.size() == totalNumOfQuotesInDb - 1);

        enable = true;

        response = tester->enableQuote(quoteId, enable);
        REQUIRE(response->success);

        // All quotes should be enabled
        quotes = tester->getEnabledQuotes();
        REQUIRE(quotes.size() == totalNumOfQuotesInDb);
    }

    Database::deinitialize();
}

M module-services/service-db/test/test-service-db-quotes.hpp => module-services/service-db/test/test-service-db-quotes.hpp +60 -0
@@ 23,5 23,65 @@ namespace Quotes
        {
            return QuotesAgent::handleQuotesList(req);
        }

        auto handleQuotesListByCategoryId(Messages::GetQuotesListByCategoryIdRequest *req) -> sys::MessagePointer
        {
            return QuotesAgent::handleQuotesListByCategoryId(req);
        }

        auto handleEnableCategoryById(Messages::EnableCategoryByIdRequest *req) -> sys::MessagePointer
        {
            return QuotesAgent::handleEnableCategoryById(req);
        }

        auto handleEnableQuoteById(Messages::EnableQuoteByIdRequest *req) -> sys::MessagePointer
        {
            return QuotesAgent::handleEnableQuoteById(req);
        }

        auto handleEnabledQuotesList(Messages::GetEnabledQuotesListRequest *req) -> sys::MessagePointer
        {
            return QuotesAgent::handleEnabledQuotesList(req);
        }

        auto getQuotesByCategoryId(unsigned int categoryId) -> std::vector<QuoteRecord>
        {
            QuotesList quotesList;
            quotesList.limit = 0;

            auto record   = std::make_unique<QuotesList>(quotesList);
            auto request  = std::make_shared<Messages::GetQuotesListByCategoryIdRequest>(std::move(record), categoryId);
            auto response = std::dynamic_pointer_cast<Messages::GetQuotesListByCategoryIdResponse>(
                handleQuotesListByCategoryId(request.get()));

            return response->getResults();
        }

        auto getEnabledQuotes() -> std::vector<QuoteRecord>
        {
            QuotesList quotesList;
            quotesList.limit = 0;

            auto record   = std::make_unique<QuotesList>(quotesList);
            auto request  = std::make_shared<Messages::GetEnabledQuotesListRequest>(std::move(record));
            auto response = std::dynamic_pointer_cast<Messages::GetEnabledQuotesListResponse>(
                handleEnabledQuotesList(request.get()));

            return response->getResults();
        }

        auto enableCategory(unsigned int categoryId, bool enable)
            -> std::shared_ptr<Messages::EnableCategoryByIdResponse>
        {
            auto request = std::make_shared<Messages::EnableCategoryByIdRequest>(categoryId, enable);
            return std::dynamic_pointer_cast<Messages::EnableCategoryByIdResponse>(
                handleEnableCategoryById(request.get()));
        }

        auto enableQuote(unsigned int quoteId, bool enable) -> std::shared_ptr<Messages::EnableQuoteByIdResponse>
        {
            auto request = std::make_shared<Messages::EnableQuoteByIdRequest>(quoteId, enable);
            return std::dynamic_pointer_cast<Messages::EnableQuoteByIdResponse>(handleEnableQuoteById(request.get()));
        }
    };
} // namespace Quotes

M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +1 -1
@@ 269,7 269,7 @@ sys::ReturnCodes EventManager::InitHandler()
        bsp::rtc_SetDateTimeFromTimestamp(msg->getTime());
        bsp::rtc_SetMinuteAlarm(msg->getTime());
        handleMinuteUpdate(msg->getTime());
        return app::msgHandled();
        return sys::msgHandled();
    });

    connect(sevm::BatteryStatusChangeMessage(), [&](sys::Message *msgl) {

M module-sys/Service/Message.hpp => module-sys/Service/Message.hpp +10 -0
@@ 108,4 108,14 @@ namespace sys
        ReturnCodes retCode;
        MessageType responseTo;
    };

    inline auto msgHandled() -> MessagePointer
    {
        return std::make_shared<ResponseMessage>();
    }

    inline auto msgNotHandled() -> MessagePointer
    {
        return std::make_shared<ResponseMessage>(ReturnCodes::Unresolved);
    }
} // namespace sys