this repo has no description
1import birl
2import gleam/bool
3import gleam/dict
4import gleam/dynamic
5import gleam/dynamic/decode
6import gleam/http/response
7import gleam/json
8import gleam/list
9import gleam/option
10import gleam/order
11import gleam/string_tree
12import models/count_provider
13import models/payment_request.{type PaymentRequest, PaymentRequest}
14import redis
15import valkyrie/resp
16import web/server
17import wisp
18
19fn decode_payment_body(
20 body: dynamic.Dynamic,
21 cb: fn(PaymentRequest) -> wisp.Response,
22) {
23 let decoder = {
24 use correlation <- decode.field("correlationId", decode.string)
25 use amount <- decode.field("amount", decode.float)
26
27 decode.success(PaymentRequest(
28 correlation_id: correlation,
29 amount: amount,
30 requested_at: birl.now(),
31 provider: option.None,
32 ))
33 }
34 case decode.run(body, decoder) {
35 Ok(body) -> cb(body)
36 Error(_) -> wisp.bad_request()
37 }
38}
39
40pub fn handle_payment_post(
41 req: wisp.Request,
42 ctx: server.Context,
43) -> response.Response(wisp.Body) {
44 use json <- wisp.require_json(req)
45 use body <- decode_payment_body(json)
46
47 let data_to_insert =
48 body
49 |> payment_request.to_json
50 |> json.to_string
51 |> list.wrap
52
53 let assert Ok(_) =
54 ctx.valkye_conn
55 |> redis.enqueue_payments(data_to_insert)
56
57 wisp.no_content()
58}
59
60fn get_all_payments_response(
61 default: count_provider.CountProvider,
62 fallback: count_provider.CountProvider,
63) -> json.Json {
64 [
65 #("default", count_provider.to_json(default)),
66 #("fallback", count_provider.to_json(fallback)),
67 ]
68 |> json.object
69}
70
71fn all_payments_empty_body() {
72 let body =
73 get_all_payments_response(
74 count_provider.new("default"),
75 count_provider.new("fallback"),
76 )
77 |> json.to_string_tree
78
79 wisp.ok()
80 |> wisp.json_body(body)
81}
82
83pub fn get_all_payments(
84 req: wisp.Request,
85 ctx: server.Context,
86) -> response.Response(wisp.Body) {
87 let params =
88 req
89 |> wisp.get_query
90 |> list.map(fn(param) {
91 let #(key, value) = param
92 let assert Ok(v) = value |> birl.parse
93
94 #(key, v)
95 })
96 |> dict.from_list
97
98 use <- bool.lazy_guard(
99 when: !dict.has_key(params, "from"),
100 return: all_payments_empty_body,
101 )
102
103 use <- bool.lazy_guard(
104 when: !dict.has_key(params, "to"),
105 return: all_payments_empty_body,
106 )
107
108 let assert Ok(from) = dict.get(params, "from")
109 let assert Ok(to) = dict.get(params, "to")
110
111 let data_in_redis = case redis.get_all_saved_data(ctx.valkye_conn) {
112 Ok(data) ->
113 data
114 |> dict.values
115 |> list.filter_map(fn(value) {
116 let assert resp.BulkString(v) = value
117 let assert Ok(json_data) = payment_request.from_json_string(v)
118
119 use <- bool.guard(
120 when: birl.compare(json_data.requested_at, from) == order.Lt,
121 return: Error(Nil),
122 )
123 use <- bool.guard(
124 when: birl.compare(json_data.requested_at, to) == order.Gt,
125 return: Error(Nil),
126 )
127
128 Ok(json_data)
129 })
130 Error(_) -> []
131 }
132
133 use <- bool.guard(
134 when: data_in_redis == [],
135 return: wisp.no_content()
136 |> wisp.json_body(string_tree.from_string("[]")),
137 )
138
139 let grouped_by_provider =
140 data_in_redis
141 |> list.group(by: fn(data) {
142 case data {
143 payment_request.PaymentRequest(provider: option.Some("default"), ..) ->
144 "default"
145 _ -> "fallback"
146 }
147 })
148
149 let default_requests =
150 count_provider.new("default")
151 |> count_provider.count_provider(grouped_by_provider)
152 let fallback_requests =
153 count_provider.new("fallback")
154 |> count_provider.count_provider(grouped_by_provider)
155
156 wisp.ok()
157 |> wisp.json_body(
158 get_all_payments_response(default_requests, fallback_requests)
159 |> json.to_string_tree,
160 )
161}
162
163pub fn purge_payments(
164 _req: wisp.Request,
165 ctx: server.Context,
166) -> response.Response(wisp.Body) {
167 case redis.delete_saved_data(ctx.valkye_conn) {
168 _ -> wisp.no_content()
169 }
170}