feat(events): add booking_occupancy on event JSON for studio grid
CI / test (push) Failing after 6m23s
CI / deploy-ift (push) Has been skipped
CI / e2e-ift (push) Has been skipped
CI / deploy-stage (push) Has been skipped
CI / e2e-stage (push) Has been skipped

Expose free|pending|confirmed so commercial calendar can aggregate
slots by occupancy without N GET /bookings calls.
This commit is contained in:
2026-07-30 15:33:49 +03:00
parent 1fce1aa12d
commit edd396dff8
2 changed files with 30 additions and 3 deletions
+6 -2
View File
@@ -339,10 +339,14 @@ parse_datetime_binary(Str) ->
Dt.
occurrence_to_json(Master, Occurrence) ->
%% Virtual row: occupancy by master event id (materialized instances use event_to_json).
#{
master_id => Master#event.id,
start_time => handler_utils:datetime_to_iso8601(Occurrence),
duration => Master#event.duration,
title => Master#event.title,
is_virtual => true
}.
is_virtual => true,
specialist_id => Master#event.specialist_id,
calendar_id => Master#event.calendar_id,
booking_occupancy => handler_utils:booking_occupancy(Master)
}.
+24 -1
View File
@@ -19,6 +19,7 @@
parse_datetime/1,
datetime_to_iso8601/1,
event_to_json/1,
booking_occupancy/1,
user_to_json/1,
review_to_json/1,
review_to_json/2,
@@ -300,6 +301,8 @@ audit_reason(#{<<"reason">> := R}) when is_binary(R) -> R;
audit_reason(_) -> <<>>.
%% @doc Преобразует #event{} в JSON-карту.
%% Добавляет booking_occupancy: free | pending | confirmed
%% (confirmed > pending > free; cancelled/expired и past-pending → не занятость).
-spec event_to_json(#event{}) -> map().
event_to_json(Event) ->
LocationJson = case Event#event.location of
@@ -337,9 +340,29 @@ event_to_json(Event) ->
attachments => Event#event.attachments,
edit_history => Event#event.edit_history,
created_at => datetime_to_iso8601(Event#event.created_at),
updated_at => datetime_to_iso8601(Event#event.updated_at)
updated_at => datetime_to_iso8601(Event#event.updated_at),
booking_occupancy => booking_occupancy(Event)
}.
%% @doc Активная занятость слота для сетки commercial (Studio aggregate).
-spec booking_occupancy(#event{}) -> free | pending | confirmed.
booking_occupancy(#event{id = EventId, start_time = Start}) ->
{ok, Bookings} = core_booking:list_by_event(EventId),
Now = calendar:universal_time(),
lists:foldl(
fun(#booking{status = confirmed}, _Acc) ->
confirmed;
(#booking{status = pending}, Acc) ->
case Start > Now of
true when Acc =/= confirmed -> pending;
_ -> Acc
end;
(_, Acc) ->
Acc
end,
free,
Bookings).
%% @doc Преобразует #user{} в JSON-карту.
-spec user_to_json(#user{}) -> map().
user_to_json(User) ->