1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use super::*;
use crate::account::*;
use crate::commands::*;
use actix_web::body::BoxBody;
use actix_web::post;
use actix_web::web;
use actix_web::{HttpRequest, HttpResponse, Responder};
use serde_json::json;
use uuid::Uuid;

impl Responder for Account {
    type Body = BoxBody;
    fn respond_to(self, _req: &HttpRequest) -> HttpResponse<Self::Body> {
        let body = serde_json::to_string(&self).unwrap();

        HttpResponse::Ok()
            .content_type("application/json")
            .body(body)
    }
}

#[post("/accounts")]
pub async fn create_account(account: web::Json<OpenAccountPayload>) -> impl Responder {
    match Router::<DefaultApp>::dispatch::<OpenAccount>(
        account.into_inner().into(),
        CommandMetadatas::default(),
    )
    .await
    {
        Ok(res) => HttpResponse::Ok().json(res.first()),
        Err(e) => HttpResponse::Ok().json(json!({ "error": e.to_string() })),
    }
}

#[post("/gift_cards")]
pub async fn create_gift_card(gift_card: web::Json<CreateGiftCardPayload>) -> impl Responder {
    match Router::<DefaultApp>::dispatch::<CreateGiftCard>(
        gift_card.into_inner().into(),
        CommandMetadatas::default(),
    )
    .await
    {
        Ok(res) => HttpResponse::Ok().json(res.first()),
        Err(e) => HttpResponse::Ok().json(json!({ "error": e.to_string() })),
    }
}

#[post("/accounts/{account_id}/orders")]
pub async fn create_order(params: web::Path<Uuid>) -> impl Responder {
    match Router::<DefaultApp>::dispatch::<CreateOrder>(
        CreateOrder {
            order_id: Uuid::new_v4(),
            account_id: params.into_inner(),
        },
        CommandMetadatas::default(),
    )
    .await
    {
        Ok(res) => HttpResponse::Ok().json(res.first()),
        Err(e) => HttpResponse::Ok().json(json!({ "error": e.to_string() })),
    }
}

#[post("/orders/{order_id}/items")]
pub async fn add_order_item(
    params: web::Path<Uuid>,
    payload: web::Json<AddGiftCardToOrderPayload>,
) -> impl Responder {
    let payload = payload.into_inner();
    match Router::<DefaultApp>::dispatch::<AddGiftCardToOrder>(
        AddGiftCardToOrder {
            order_id: params.into_inner(),
            gift_card_id: payload.gift_card_id,
            amount: payload.amount,
            price: 10,
        },
        CommandMetadatas::default(),
    )
    .await
    {
        Ok(res) => HttpResponse::Ok().json(res.first()),
        Err(e) => HttpResponse::Ok().json(json!({ "error": e.to_string() })),
    }
}

#[derive(serde::Deserialize)]
pub struct OpenAccountPayload {
    name: String,
}

#[derive(serde::Deserialize)]
pub struct CreateGiftCardPayload {
    name: String,
    price: i64,
    count: usize,
}

#[derive(serde::Deserialize)]
pub struct AddGiftCardToOrderPayload {
    gift_card_id: Uuid,
    amount: usize,
}

impl From<OpenAccountPayload> for OpenAccount {
    fn from(payload: OpenAccountPayload) -> Self {
        Self {
            account_id: Uuid::new_v4(),
            name: payload.name,
        }
    }
}

impl From<CreateGiftCardPayload> for CreateGiftCard {
    fn from(payload: CreateGiftCardPayload) -> Self {
        Self {
            gift_card_id: Uuid::new_v4(),
            name: payload.name,
            price: payload.price,
            count: payload.count,
        }
    }
}