cover/Elixir.DaProductAppWeb.SettlementsLive.html

1
:-(
defmodule DaProductAppWeb.SettlementsLive do
2 use DaProductAppWeb, :live_view
3
4 alias DaProductApp.Monitoring
5 alias DaProductApp.Accounts
6
7
:-(
def mount(_params, session, socket) do
8
:-(
case get_current_user(session) do
9
:-(
nil ->
10 {:ok, redirect(socket, to: ~p"/login")}
11
12 user ->
13
:-(
if has_access?(user) do
14
:-(
if connected?(socket) do
15 # Subscribe to settlement events for real-time updates
16
:-(
Phoenix.PubSub.subscribe(DaProductApp.PubSub, "settlements")
17 end
18
19 # Initialize state
20
:-(
socket =
21 socket
22 |> assign(:current_user, user)
23 |> assign(:page_title, "Settlements Management")
24 |> assign(:current_page, :settlements)
25 |> assign(
26 settlements: [],
27 settlement_stats: %{},
28 search_term: "",
29 status_filter: :all,
30 type_filter: :all,
31 partner_filter: :all,
32 date_from: nil,
33 date_to: nil,
34 page: 1,
35 per_page: 20,
36 show_details_modal: false,
37 selected_settlement: nil,
38 loading: true
39 )
40 |> load_settlements()
41 |> load_settlement_stats()
42 |> assign(loading: false)
43
44 {:ok, socket}
45 else
46 {:ok,
47 socket
48 |> put_flash(:error, "Access denied")
49 |> redirect(to: ~p"/login")}
50 end
51 end
52 end
53
54
:-(
def handle_params(%{"id" => settlement_id}, _uri, socket) do
55
:-(
settlement = Monitoring.get_settlement_by_id(settlement_id)
56
57
:-(
socket =
58 socket
59 |> assign(
60 show_details_modal: true,
61 selected_settlement: settlement
62 )
63
64 {:noreply, socket}
65 end
66
67
:-(
def handle_params(_params, _uri, socket) do
68
:-(
socket =
69 socket
70 |> assign(
71 show_details_modal: false,
72 selected_settlement: nil
73 )
74
75 {:noreply, socket}
76 end
77
78
:-(
def handle_event("search", %{"search_term" => search_term}, socket) do
79
:-(
socket =
80 socket
81 |> assign(search_term: search_term, page: 1)
82 |> load_settlements()
83
84 {:noreply, socket}
85 end
86
87
:-(
def handle_event("filter_status", %{"status" => status}, socket) do
88
:-(
status_filter = case status do
89
:-(
"all" -> :all
90
:-(
other -> other
91 end
92
93
:-(
socket =
94 socket
95 |> assign(status_filter: status_filter, page: 1)
96 |> load_settlements()
97
98 {:noreply, socket}
99 end
100
101
:-(
def handle_event("filter_type", %{"type" => type}, socket) do
102
:-(
type_filter = case type do
103
:-(
"all" -> :all
104
:-(
other -> other
105 end
106
107
:-(
socket =
108 socket
109 |> assign(type_filter: type_filter, page: 1)
110 |> load_settlements()
111
112 {:noreply, socket}
113 end
114
115
:-(
def handle_event("filter_partner", %{"partner" => partner}, socket) do
116
:-(
partner_filter = case partner do
117
:-(
"all" -> :all
118
:-(
other -> String.to_integer(partner)
119 end
120
121
:-(
socket =
122 socket
123 |> assign(partner_filter: partner_filter, page: 1)
124 |> load_settlements()
125
126 {:noreply, socket}
127 end
128
129
:-(
def handle_event("filter_date_range", params, socket) do
130
:-(
date_from = case params["date_from"] do
131
:-(
"" -> nil
132
:-(
date_str -> Date.from_iso8601!(date_str)
133 end
134
135
:-(
date_to = case params["date_to"] do
136
:-(
"" -> nil
137
:-(
date_str -> Date.from_iso8601!(date_str)
138 end
139
140
:-(
socket =
141 socket
142 |> assign(date_from: date_from, date_to: date_to, page: 1)
143 |> load_settlements()
144
145 {:noreply, socket}
146 end
147
148
:-(
def handle_event("refresh", _params, socket) do
149
:-(
socket =
150 socket
151 |> assign(loading: true)
152 |> load_settlements()
153 |> load_settlement_stats()
154 |> assign(loading: false)
155
156 {:noreply, socket}
157 end
158
159
:-(
def handle_event("close_details", _params, socket) do
160 {:noreply, push_patch(socket, to: ~p"/settlements")}
161 end
162
163
:-(
def handle_info({:settlement_updated, _settlement}, socket) do
164
:-(
socket =
165 socket
166 |> load_settlements()
167 |> load_settlement_stats()
168
169 {:noreply, socket}
170 end
171
172
:-(
def handle_info({:new_settlement, _settlement}, socket) do
173
:-(
socket =
174 socket
175 |> load_settlements()
176 |> load_settlement_stats()
177
178 {:noreply, socket}
179 end
180
181 defp load_settlements(socket) do
182
:-(
filters = %{
183
:-(
search: socket.assigns.search_term,
184
:-(
status: socket.assigns.status_filter,
185
:-(
type: socket.assigns.type_filter,
186
:-(
partner_id: socket.assigns.partner_filter,
187
:-(
date_from: socket.assigns.date_from,
188
:-(
date_to: socket.assigns.date_to,
189
:-(
page: socket.assigns.page,
190
:-(
per_page: socket.assigns.per_page
191 }
192
193
:-(
settlements = Monitoring.list_settlements_with_filters(filters)
194
:-(
assign(socket, settlements: settlements)
195 end
196
197 defp load_settlement_stats(socket) do
198
:-(
filters = %{
199
:-(
search: socket.assigns.search_term,
200
:-(
status: socket.assigns.status_filter,
201
:-(
type: socket.assigns.type_filter,
202
:-(
partner_id: socket.assigns.partner_filter,
203
:-(
date_from: socket.assigns.date_from,
204
:-(
date_to: socket.assigns.date_to
205 }
206
207
:-(
stats = Monitoring.get_settlement_stats(filters)
208
:-(
assign(socket, settlement_stats: stats)
209 end
210
211 # Helper functions for select options
212
:-(
def status_options do
213 [
214 {"All Statuses", "all"},
215 {"Pending", "pending"},
216 {"Processing", "processing"},
217 {"Completed", "completed"},
218 {"Failed", "failed"},
219 {"Cancelled", "cancelled"}
220 ]
221 end
222
223
:-(
def type_options do
224 [
225 {"All Types", "all"},
226 {"Net Settlement", "net"},
227 {"Gross Settlement", "gross"},
228 {"Merchant Settlement", "merchant"},
229 {"Partner Settlement", "partner"},
230 {"International Settlement", "international"}
231 ]
232 end
233
234 def partner_options do
235
:-(
partners = Monitoring.list_active_settlement_partners()
236
:-(
[{"All Partners", "all"}] ++ Enum.map(partners, &{&1.name, to_string(&1.id)})
237 end
238
239 # Formatting helpers
240 def format_amount(amount) when is_number(amount) do
241 amount
242 |> Decimal.from_float()
243 |> Decimal.round(2)
244 |> Decimal.to_string(:normal)
245
:-(
|> (&Regex.replace(~r/\B(?=(\d{3})+(?!\d))/, &1, ",")).()
246 end
247
248
:-(
def format_amount(amount), do: "0.00"
249
250 def format_currency(amount, currency) when is_number(amount) do
251
:-(
formatted_amount = format_amount(amount)
252
:-(
"#{currency} #{formatted_amount}"
253 end
254
255
:-(
def format_currency(_, currency), do: "#{currency} 0.00"
256
257 def status_badge_class(status) do
258
:-(
case status do
259
:-(
"completed" -> "badge-success"
260
:-(
"processing" -> "badge-info"
261
:-(
"pending" -> "badge-warning"
262
:-(
"failed" -> "badge-error"
263
:-(
"cancelled" -> "badge-ghost"
264
:-(
_ -> "badge-neutral"
265 end
266 end
267
268 def type_badge_class(type) do
269
:-(
case type do
270
:-(
"net" -> "badge-primary"
271
:-(
"gross" -> "badge-secondary"
272
:-(
"merchant" -> "badge-accent"
273
:-(
"partner" -> "badge-info"
274
:-(
"international" -> "badge-warning"
275
:-(
_ -> "badge-neutral"
276 end
277 end
278
279 def priority_badge_class(priority) do
280
:-(
case priority do
281
:-(
"high" -> "badge-error"
282
:-(
"medium" -> "badge-warning"
283
:-(
"low" -> "badge-success"
284
:-(
"normal" -> "badge-info"
285
:-(
_ -> "badge-neutral"
286 end
287 end
288
289 def format_settlement_frequency(frequency) do
290
:-(
case frequency do
291
:-(
"daily" -> "Daily"
292
:-(
"weekly" -> "Weekly"
293
:-(
"monthly" -> "Monthly"
294
:-(
"on_demand" -> "On-Demand"
295
:-(
"real_time" -> "Real-Time"
296
:-(
_ -> String.capitalize(frequency || "unknown")
297 end
298 end
299
300 def calculate_settlement_progress(settlement) do
301
:-(
case settlement.status do
302
:-(
"pending" -> 0
303
:-(
"processing" -> 50
304
:-(
"completed" -> 100
305
:-(
"failed" -> 0
306
:-(
"cancelled" -> 0
307
:-(
_ -> 0
308 end
309 end
310
311 def format_duration(start_time, end_time) when not is_nil(start_time) and not is_nil(end_time) do
312
:-(
diff = NaiveDateTime.diff(end_time, start_time, :second)
313
314
:-(
cond do
315
:-(
diff < 60 -> "#{diff}s"
316
:-(
diff < 3600 -> "#{div(diff, 60)}m #{rem(diff, 60)}s"
317
:-(
diff < 86400 -> "#{div(diff, 3600)}h #{div(rem(diff, 3600), 60)}m"
318
:-(
true -> "#{div(diff, 86400)}d #{div(rem(diff, 86400), 3600)}h"
319 end
320 end
321
322
:-(
def format_duration(_, _), do: "N/A"
323
324 def get_settlement_instructions(settlement) do
325
:-(
case settlement.type do
326
:-(
"net" -> "Net settlement combines all transactions for a specific period and settles the net amount."
327
:-(
"gross" -> "Gross settlement processes each transaction individually in real-time."
328
:-(
"merchant" -> "Merchant settlement transfers funds to merchant accounts after deducting fees."
329
:-(
"partner" -> "Partner settlement handles fund transfers between partner institutions."
330
:-(
"international" -> "International settlement manages cross-border fund transfers with FX conversion."
331
:-(
_ -> "Standard settlement processing with automated reconciliation."
332 end
333 end
334
335 def get_next_expected_settlement(type, frequency) do
336
:-(
now = NaiveDateTime.utc_now()
337
338
:-(
case frequency do
339 "daily" ->
340
:-(
tomorrow = Date.add(Date.utc_today(), 1)
341
:-(
NaiveDateTime.new!(tomorrow, ~T[09:00:00])
342 "weekly" ->
343
:-(
days_until_monday = 7 - Date.day_of_week(Date.utc_today()) + 1
344
:-(
next_monday = Date.add(Date.utc_today(), days_until_monday)
345
:-(
NaiveDateTime.new!(next_monday, ~T[09:00:00])
346 "monthly" ->
347
:-(
next_month = Date.beginning_of_month(Date.add(Date.utc_today(), 32))
348
:-(
NaiveDateTime.new!(next_month, ~T[09:00:00])
349
:-(
_ -> now
350 end
351 end
352
353 # Helper functions for authentication and access control
354
:-(
defp get_current_user(session) do
355
:-(
case session do
356 %{"user_id" => user_id} when is_binary(user_id) or is_integer(user_id) ->
357
:-(
Accounts.get_user!(user_id)
358
:-(
_ ->
359 nil
360 end
361 rescue
362
:-(
_ -> nil
363 end
364
365
:-(
defp has_access?(_user), do: true
366 end
Line Hits Source