10 changed files with 201 additions and 5 deletions
@ -0,0 +1,33 @@ |
|||||||
|
# Add item sequence |
||||||
|
|
||||||
|
```mermaid |
||||||
|
sequenceDiagram |
||||||
|
participant Controller as StoreController |
||||||
|
participant UseCase as AddItem Use Case |
||||||
|
participant Clock as IClock |
||||||
|
participant Policy as ExpirationPolicy |
||||||
|
participant OrderService as OrderingService |
||||||
|
participant HttpClient as HttpClient |
||||||
|
participant Repo as IItemRepository |
||||||
|
|
||||||
|
Controller->>UseCase: execute(item) |
||||||
|
|
||||||
|
UseCase->>Clock: getCurrentTime() |
||||||
|
Clock-->>UseCase: DateTime |
||||||
|
|
||||||
|
UseCase->>Policy: IsExpired(item, currentTime) |
||||||
|
Policy-->>UseCase: boolean |
||||||
|
|
||||||
|
alt Item is expired |
||||||
|
UseCase->>OrderService: orderItem(item) |
||||||
|
OrderService->>HttpClient: POST to order URL |
||||||
|
HttpClient-->>OrderService: Response |
||||||
|
OrderService-->>UseCase: OrderResult |
||||||
|
end |
||||||
|
|
||||||
|
UseCase->>Repo: save(item) |
||||||
|
Repo->>Repo: Persist to storage |
||||||
|
Repo-->>UseCase: Saved Item ID |
||||||
|
|
||||||
|
UseCase-->>Controller: Result (success/error) |
||||||
|
``` |
||||||
@ -0,0 +1,25 @@ |
|||||||
|
# General request sequence with authentication |
||||||
|
|
||||||
|
```mermaid |
||||||
|
sequenceDiagram |
||||||
|
participant Client as HTTP Client |
||||||
|
participant Router as Request Router |
||||||
|
participant Auth as JwtMiddleware |
||||||
|
participant Controller as Controller |
||||||
|
participant UseCase as Use Case |
||||||
|
|
||||||
|
Client->>Router: POST /api/items (with JWT) |
||||||
|
Router->>Auth: Forward request |
||||||
|
|
||||||
|
alt Authentication successful |
||||||
|
Auth->>Auth: Validate JWT |
||||||
|
Auth->>Controller: Forward authenticated request |
||||||
|
Controller->>Controller: Parse request body to DTO |
||||||
|
Controller->>UseCase: execute() |
||||||
|
UseCase-->>Controller: Result (success/error) |
||||||
|
Controller->>Controller: Convert result to HTTP response |
||||||
|
Controller-->>Client: HTTP Response (2xx) |
||||||
|
else Authentication fails |
||||||
|
Auth-->>Client: 401 Unauthorized |
||||||
|
end |
||||||
|
``` |
||||||
@ -1,15 +1,27 @@ |
|||||||
#include "AddItem.h" |
#include "AddItem.h" |
||||||
#include "domain/polices/ItemExpirationPolicy.h" |
#include <stdexcept> |
||||||
|
|
||||||
namespace nxl::autostore::application { |
namespace nxl::autostore::application { |
||||||
|
|
||||||
AddItem::AddItem(IItemRepository& itemRepository) |
AddItem::AddItem(IItemRepository& itemRepository, IClock& clock, |
||||||
: itemRepository(itemRepository) |
IOrderService& orderService) |
||||||
|
: itemRepository(itemRepository), clock(clock), orderService(orderService) |
||||||
{} |
{} |
||||||
|
|
||||||
void AddItem::execute(domain::Item&& item, const IntPresenter& presenter) |
void AddItem::execute(domain::Item&& item, const IntPresenter& presenter) |
||||||
{ |
{ |
||||||
// TODO
|
try { |
||||||
|
const auto currentTime = clock.getCurrentTime(); |
||||||
|
|
||||||
|
if (expirationPolicy.isExpired(item, currentTime)) { |
||||||
|
orderService.orderItem(item); |
||||||
|
} |
||||||
|
|
||||||
|
itemRepository.save(item); |
||||||
|
presenter(1); // Success
|
||||||
|
} catch (const std::exception& e) { |
||||||
|
presenter(0); // Failure
|
||||||
|
} |
||||||
} |
} |
||||||
|
|
||||||
} // namespace nxl::autostore::application
|
} // namespace nxl::autostore::application
|
||||||
@ -0,0 +1,14 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <chrono> |
||||||
|
|
||||||
|
namespace nxl::autostore::application { |
||||||
|
|
||||||
|
class IClock |
||||||
|
{ |
||||||
|
public: |
||||||
|
virtual ~IClock() = default; |
||||||
|
virtual std::chrono::system_clock::time_point getCurrentTime() const = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace nxl::autostore::application
|
||||||
@ -0,0 +1,14 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "domain/entities/Item.h" |
||||||
|
|
||||||
|
namespace nxl::autostore::application { |
||||||
|
|
||||||
|
class IOrderService |
||||||
|
{ |
||||||
|
public: |
||||||
|
virtual ~IOrderService() = default; |
||||||
|
virtual void orderItem(const domain::Item& item) = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace nxl::autostore::application
|
||||||
@ -0,0 +1,18 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "domain/entities/Item.h" |
||||||
|
#include <chrono> |
||||||
|
|
||||||
|
namespace nxl::autostore::domain { |
||||||
|
|
||||||
|
class ItemExpirationPolicy |
||||||
|
{ |
||||||
|
public: |
||||||
|
bool isExpired(const Item& item, |
||||||
|
const std::chrono::system_clock::time_point& currentTime) const |
||||||
|
{ |
||||||
|
return item.expirationDate <= currentTime; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace nxl::autostore::domain
|
||||||
@ -0,0 +1,36 @@ |
|||||||
|
#include "HttpOrderService.h" |
||||||
|
#include <stdexcept> |
||||||
|
#include <iostream> |
||||||
|
|
||||||
|
namespace nxl::autostore::infrastructure { |
||||||
|
|
||||||
|
HttpOrderService::HttpOrderService(const std::string& baseUrl) |
||||||
|
: baseUrl(baseUrl) |
||||||
|
{} |
||||||
|
|
||||||
|
void HttpOrderService::orderItem(const domain::Item& item) |
||||||
|
{ |
||||||
|
if (item.orderUrl.empty()) { |
||||||
|
throw std::runtime_error("Order URL is empty for item: " + item.name); |
||||||
|
} |
||||||
|
|
||||||
|
std::string payload = |
||||||
|
R"({"itemName": ")" + item.name + R"(", "itemId": ")" + item.id + "\"}"; |
||||||
|
sendPostRequest(item.orderUrl, payload); |
||||||
|
} |
||||||
|
|
||||||
|
void HttpOrderService::sendPostRequest(const std::string& url, |
||||||
|
const std::string& payload) |
||||||
|
{ |
||||||
|
// In a real implementation, this would use an HTTP client library
|
||||||
|
// For now, we'll simulate the HTTP call
|
||||||
|
std::cout << "POST request to: " << url << std::endl; |
||||||
|
std::cout << "Payload: " << payload << std::endl; |
||||||
|
|
||||||
|
// Simulate HTTP error handling
|
||||||
|
if (url.find("error") != std::string::npos) { |
||||||
|
throw std::runtime_error("Failed to send order request to: " + url); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace nxl::autostore::infrastructure
|
||||||
@ -0,0 +1,20 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "application/interfaces/IOrderService.h" |
||||||
|
#include "domain/entities/Item.h" |
||||||
|
#include <string> |
||||||
|
|
||||||
|
namespace nxl::autostore::infrastructure { |
||||||
|
|
||||||
|
class HttpOrderService : public application::IOrderService |
||||||
|
{ |
||||||
|
public: |
||||||
|
explicit HttpOrderService(const std::string& baseUrl = ""); |
||||||
|
void orderItem(const domain::Item& item) override; |
||||||
|
|
||||||
|
private: |
||||||
|
std::string baseUrl; |
||||||
|
void sendPostRequest(const std::string& url, const std::string& payload); |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace nxl::autostore::infrastructure
|
||||||
@ -0,0 +1,17 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include "application/interfaces/IClock.h" |
||||||
|
#include <chrono> |
||||||
|
|
||||||
|
namespace nxl::autostore::infrastructure { |
||||||
|
|
||||||
|
class SystemClock : public application::IClock |
||||||
|
{ |
||||||
|
public: |
||||||
|
std::chrono::system_clock::time_point getCurrentTime() const override |
||||||
|
{ |
||||||
|
return std::chrono::system_clock::now(); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
} // namespace nxl::autostore::infrastructure
|
||||||
Loading…
Reference in new issue