diff --git a/README.md b/README.md index 77146fe..a5a30c5 100644 --- a/README.md +++ b/README.md @@ -213,13 +213,7 @@ null "treatment_name": "Bipolar I Scheme Urgent", "instructions": "Схема для быстрого и жесткого купирования психозов. Аминазин пить каждый день.", "medications": [ - { - "uuid": "eda5a5f7-167a-44b9-900d-c5c6acfc249b", - "name": "Aminazin", - "dose": 100, - "unit": "mg", - "is_urgent": true - } + "eda5a5f7-167a-44b9-900d-c5c6acfc249b" ] } ] @@ -298,14 +292,7 @@ null `dream_level`: "5", `anxiety_level`: "9", `comment`: "Сильная тревога. Пришлось выпить аминазин", - `user_treatment_scheme`: { - "uuid": "248313cb-a75e-4331-8379-d3f2fc36b68d" - "treatment_name": "Bipolar I Scheme Urgent", - "instructions": "Схема для быстрого и жесткого купирования психозов. Аминазин пить каждый день.", - "medications": [ - "eda5a5f7-167a-44b9-900d-c5c6acfc249b" - ] - }, + `user_treatment_scheme`: "51351bb1-7563-479d-a8e9-201d0ff934c2" } ``` ##### Errors diff --git a/src/DAO/IUserTreatmentSchemesDAO.h b/src/DAO/IUserTreatmentSchemesDAO.h index 0435ed9..a9664c0 100644 --- a/src/DAO/IUserTreatmentSchemesDAO.h +++ b/src/DAO/IUserTreatmentSchemesDAO.h @@ -10,6 +10,11 @@ class IUserTreatmentSchemeDAO { public: virtual std::vector FindByUserUUID(const std::string& login) = 0; + virtual void CreateUserTreatmentScheme( + const std::string& user_login, + const user_treatment_scheme_dto& dto + ) = 0; + virtual ~IUserTreatmentSchemeDAO() = default; }; } diff --git a/src/DAO/MySQLUserTreatmentSchemesDAO.cpp b/src/DAO/MySQLUserTreatmentSchemesDAO.cpp index 6090cd5..b6fa68e 100644 --- a/src/DAO/MySQLUserTreatmentSchemesDAO.cpp +++ b/src/DAO/MySQLUserTreatmentSchemesDAO.cpp @@ -67,4 +67,46 @@ std::vector MySQLUserTreatmentSchemesDAO::FindByUserU return std::move(schemes); } + +void MySQLUserTreatmentSchemesDAO::CreateUserTreatmentScheme( + const std::string& user_uuid, + const user_treatment_scheme_dto& dto) +{ + session_.startTransaction(); + + try { + session_.sql(R"( + INSERT INTO up_and_down.user_treatment_schemes ( + uuid, + user_uuid, + treatment_name, + instructions + ) VALUES (?, ?, ?, ?) + )") + .bind( + dto.uuid, + user_uuid, + dto.treatment_name, + dto.instructions + ) + .execute(); + + for (const auto& medication_uuid : dto.medication_uuids) { + session_.sql(R"( + INSERT INTO up_and_down.treatment_schemes ( + user_treatment_schemes_uuid, + medication_uuid + ) VALUES (?, ?) + )") + .bind(dto.uuid, medication_uuid) + .execute(); + } + + session_.commit(); + } + catch (...) { + session_.rollback(); + throw; + } +} } // uad diff --git a/src/DAO/MySQLUserTreatmentSchemesDAO.h b/src/DAO/MySQLUserTreatmentSchemesDAO.h index e96ad43..a8802f1 100644 --- a/src/DAO/MySQLUserTreatmentSchemesDAO.h +++ b/src/DAO/MySQLUserTreatmentSchemesDAO.h @@ -12,5 +12,10 @@ public: explicit MySQLUserTreatmentSchemesDAO(mysqlx::Session& session); std::vector FindByUserUUID(const std::string& uuid) override; + + void CreateUserTreatmentScheme( + const std::string& user_login, + const user_treatment_scheme_dto& dto + ) override; }; } // uad diff --git a/src/endpoints_handlers/GetUserTreatmentSchemeExecutor.h b/src/endpoints_handlers/GetUserTreatmentSchemeExecutor.h index 331c826..ecc960a 100644 --- a/src/endpoints_handlers/GetUserTreatmentSchemeExecutor.h +++ b/src/endpoints_handlers/GetUserTreatmentSchemeExecutor.h @@ -41,9 +41,9 @@ public: constexpr std::string_view auth_prefix = "Bearer "sv; static const std::string invalid_token_message = - "GET /api/v1/User/Medications - Response 401: Unauthorized"s; + "GET /api/v1/UserTreatmentSchemes - Response 401: Unauthorized"s; - BOOST_LOG_TRIVIAL(info) << "GET /api/v1/User/Medications - Request"; + BOOST_LOG_TRIVIAL(info) << "GET /api/v1/UserTreatmentSchemes - Request"; if (req[http::field::authorization].size() <= auth_prefix.size()) { diff --git a/src/endpoints_handlers/PostUserMedicationsExecutor.h b/src/endpoints_handlers/PostUserMedicationsExecutor.h index 1fa4f54..37aed21 100644 --- a/src/endpoints_handlers/PostUserMedicationsExecutor.h +++ b/src/endpoints_handlers/PostUserMedicationsExecutor.h @@ -68,7 +68,7 @@ public: } catch (const system::system_error& err) { - BOOST_LOG_TRIVIAL(info) << "POST /api/v1/User/Medications - Response 400: Cannot deserialize json"; + BOOST_LOG_TRIVIAL(error) << "POST /api/v1/User/Medications - Response 400: Cannot deserialize json"; throw session_exception(http::status::bad_request, "Cannot deserialize json"); } diff --git a/src/endpoints_handlers/PostUserTreatmentSchemeExecutor.h b/src/endpoints_handlers/PostUserTreatmentSchemeExecutor.h new file mode 100644 index 0000000..6a7e37a --- /dev/null +++ b/src/endpoints_handlers/PostUserTreatmentSchemeExecutor.h @@ -0,0 +1,144 @@ +#pragma once +#include + +#include +#include +#include +#include + +#include "IExecutor.h" +#include "../DAO/IAuthDAO.h" +#include "../DAO/IUserTreatmentSchemesDAO.h" +#include "../exceptions/session_exception.h" + +namespace uad +{ +template +class PostUserTreatmentSchemeExecutor : public IExecutor +{ + mysqlx::Session& session_; + const std::shared_ptr& auth_dao_; + const std::shared_ptr& user_treatment_scheme_dao_; + +public: + PostUserTreatmentSchemeExecutor( + mysqlx::Session& session, + const std::shared_ptr& auth_dao, + const std::shared_ptr& user_treatment_scheme_dao + ) : session_(session), auth_dao_(auth_dao), user_treatment_scheme_dao_(user_treatment_scheme_dao) + { + } + + boost::beast::http::response operator ()( + boost::beast::http::request>&& req + ) override + { + using namespace boost; + using namespace boost::json; + using namespace boost::beast; + using namespace std::string_literals; + using namespace std::string_view_literals; + + constexpr std::string_view auth_prefix = "Bearer "sv; + static const std::string invalid_token_message = + "POST /api/v1/UserTreatmentSchemes - Response 401: Unauthorized"s; + + BOOST_LOG_TRIVIAL(info) << "POST /api/v1/UserTreatmentSchemes - Request"; + + if (req[http::field::authorization].size() <= auth_prefix.size()) + { + BOOST_LOG_TRIVIAL(error) << invalid_token_message; + throw session_exception(http::status::unauthorized, "Unauthorized"); + } + + const std::string auth_token = { + req[http::field::authorization].begin() + auth_prefix.size(), + req[http::field::authorization].end() + }; + + if (!auth_dao_->HasAuthorized(auth_token)) + { + BOOST_LOG_TRIVIAL(error) << invalid_token_message; + throw session_exception(http::status::unauthorized, "Unauthorized"); + } + + std::string_view user_uuid_ref = auth_dao_->GetUUID(auth_token); + const std::string user_uuid{user_uuid_ref.begin(), user_uuid_ref.end()}; + const auto body = req.body(); + value req_json; + + try + { + req_json = json::parse(body); + } + catch (const system::system_error& err) + { + BOOST_LOG_TRIVIAL(error) << + "POST /api/v1/UserTreatmentSchemes - Response 400: Cannot deserialize json"; + throw session_exception(http::status::bad_request, "Cannot deserialize json"); + } + + user_treatment_scheme_dto utsd = FromJSON(req_json); + utsd.uuid = GenerateUUID(); + + try + { + user_treatment_scheme_dao_->CreateUserTreatmentScheme(user_uuid, utsd); + } + catch (...) + { + BOOST_LOG_TRIVIAL(error) << + "POST /api/v1/UserTreatmentSchemes - Response 400: Cannot write entity"; + throw session_exception(http::status::bad_request, "Cannot write entity"); + } + + http::response res{http::status::ok, req.version()}; + json::value res_json = ToJSON(utsd); + + res.body() = serialize(res_json); + res.set(http::field::content_type, "application/json"); + res.content_length(res.body().size()); + + return res; + } + +private: + user_treatment_scheme_dto FromJSON(const boost::json::value& scheme) + { + user_treatment_scheme_dto dto; + + dto.treatment_name = + scheme.at("treatment_name").as_string().c_str(); + + dto.instructions = + scheme.at("instructions").as_string().c_str(); + + for (const auto& med : scheme.at("medications").as_array()) + { + dto.medication_uuids.push_back( + med.as_string().c_str() + ); + } + + return dto; + } + + boost::json::object ToJSON(const user_treatment_scheme_dto& utsd) + { + boost::json::array medications_json; + medications_json.reserve(utsd.medication_uuids.size()); + + for (const auto& medication_uuid : utsd.medication_uuids) { + medications_json.emplace_back(medication_uuid); + } + + boost::json::object scheme_json; + scheme_json["uuid"] = utsd.uuid; + scheme_json["treatment_name"] = utsd.treatment_name; + scheme_json["instructions"] = utsd.instructions; + scheme_json["medications"] = std::move(medications_json); + + return scheme_json; + } +}; +} diff --git a/src/endpoints_handlers/RootExecutor.h b/src/endpoints_handlers/RootExecutor.h index 9a0d97b..b5db07d 100644 --- a/src/endpoints_handlers/RootExecutor.h +++ b/src/endpoints_handlers/RootExecutor.h @@ -9,6 +9,7 @@ #include "AuthLogoutExecutor.h" #include "GetUserMedicationsExecutor.h" #include "GetUserTreatmentSchemeExecutor.h" +#include "PostUserTreatmentSchemeExecutor.h" #include "PostUserMedicationsExecutor.h" #include "GetDiariesExecutor.h" #include "../DAO/IUserDAO.h" @@ -37,6 +38,8 @@ class RootExecutor Body, Allocator, boost::beast::http::string_body>; using RouteGetUserTreatmentSchemeExecutor = GetUserTreatmentSchemeExecutor< Body, Allocator, boost::beast::http::string_body>; + using RoutePostUserTreatmentSchemeExecutor = PostUserTreatmentSchemeExecutor< + Body, Allocator, boost::beast::http::string_body>; using RouteGetDiariesExecutor = GetDiariesExecutor< Body, Allocator, boost::beast::http::string_body>; using IRouteController = IController; @@ -121,6 +124,11 @@ public: std::make_shared(session_, auth_dao_, user_treatment_scheme_dao_) }, + { + boost::beast::http::verb::post, + std::make_shared(session_, auth_dao_, + user_treatment_scheme_dao_) + } } );