feat(booking): materialize occurrence on POST bookings. Refs EventHub/EventHubBack#67
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
-module(logic_booking).
|
||||
-include("records.hrl").
|
||||
-export([create_booking/2, confirm_booking/2, confirm_booking/3,
|
||||
-export([create_booking/2, create_booking/3, confirm_booking/2, confirm_booking/3,
|
||||
cancel_booking/2, cancel_booking/3, get_booking/2,
|
||||
list_bookings/2, list_user_bookings/1, list_user_booking_requests/1,
|
||||
delete_booking/2,
|
||||
@@ -16,15 +16,30 @@
|
||||
-spec create_booking(UserId :: binary(), EventId :: binary()) ->
|
||||
{ok, #booking{}} |
|
||||
{error, full | already_booked | not_found | personal_calendar |
|
||||
subscription_inactive | own_event | event_not_active | access_denied}.
|
||||
subscription_inactive | own_event | event_not_active | access_denied |
|
||||
occurrence_start_required | invalid_occurrence}.
|
||||
create_booking(UserId, EventId) ->
|
||||
create_booking(UserId, EventId, undefined).
|
||||
|
||||
-spec create_booking(UserId :: binary(), EventId :: binary(),
|
||||
OccurrenceStart :: calendar:datetime() | undefined) ->
|
||||
{ok, #booking{}} |
|
||||
{error, full | already_booked | not_found | personal_calendar |
|
||||
subscription_inactive | own_event | event_not_active | access_denied |
|
||||
occurrence_start_required | invalid_occurrence}.
|
||||
create_booking(UserId, EventId, OccurrenceStart) ->
|
||||
case core_event:get_by_id(EventId) of
|
||||
{ok, #event{status = active} = Event} ->
|
||||
case core_calendar:get_by_id(Event#event.calendar_id) of
|
||||
{ok, Calendar} ->
|
||||
create_on_calendar(UserId, Event, Calendar);
|
||||
{error, not_found} ->
|
||||
{error, not_found}
|
||||
case resolve_bookable_event(Event, OccurrenceStart) of
|
||||
{ok, BookEvent} ->
|
||||
case core_calendar:get_by_id(BookEvent#event.calendar_id) of
|
||||
{ok, Calendar} ->
|
||||
create_on_calendar(UserId, BookEvent, Calendar);
|
||||
{error, not_found} ->
|
||||
{error, not_found}
|
||||
end;
|
||||
{error, _} = Err ->
|
||||
Err
|
||||
end;
|
||||
{ok, _} ->
|
||||
{error, event_not_active};
|
||||
@@ -32,6 +47,19 @@ create_booking(UserId, EventId) ->
|
||||
{error, not_found}
|
||||
end.
|
||||
|
||||
resolve_bookable_event(#event{event_type = recurring}, undefined) ->
|
||||
{error, occurrence_start_required};
|
||||
resolve_bookable_event(#event{event_type = recurring} = Master, OccurrenceStart) ->
|
||||
case logic_event:validate_occurrence(Master, OccurrenceStart) of
|
||||
ok ->
|
||||
logic_event:materialize_for_booking(
|
||||
Master#event.id, OccurrenceStart, Master#event.specialist_id);
|
||||
{error, _} = Err ->
|
||||
Err
|
||||
end;
|
||||
resolve_bookable_event(Event, _OccurrenceStart) ->
|
||||
{ok, Event}.
|
||||
|
||||
create_on_calendar(UserId, _Event, #calendar{owner_id = UserId}) ->
|
||||
{error, own_event};
|
||||
create_on_calendar(_UserId, _Event, #calendar{type = personal}) ->
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
-export([create_event/5, create_event/6, create_recurring_event/6, create_recurring_event/7,
|
||||
get_event/2, list_events/2, update_event/3, delete_event/2]).
|
||||
-export([validate_event_time/1, validate_event_time/2, get_occurrences/3, cancel_occurrence/3]).
|
||||
-export([materialize_for_booking/3]).
|
||||
-export([materialize_for_booking/3, validate_occurrence/2]).
|
||||
-export([list_all_events/1, get_event_admin/1, update_event_admin/2, delete_event_admin/1]).
|
||||
-export([search_events/1]).
|
||||
|
||||
@@ -147,6 +147,28 @@ cancel_occurrence(UserId, MasterId, OccurrenceStart) ->
|
||||
materialize_for_booking(MasterId, OccurrenceStart, SpecialistId) ->
|
||||
core_event:materialize_occurrence(MasterId, OccurrenceStart, SpecialistId).
|
||||
|
||||
%% Проверка, что OccurrenceStart — неотменённое вхождение серии.
|
||||
validate_occurrence(#event{event_type = recurring} = Event, OccurrenceStart) ->
|
||||
try
|
||||
Decoded = jsx:decode(Event#event.recurrence_rule, [return_maps]),
|
||||
RRuleMap = case Decoded of
|
||||
Map when is_map(Map) -> Map;
|
||||
_ -> #{}
|
||||
end,
|
||||
{ok, ParsedRule} = logic_recurrence:parse_rrule(RRuleMap),
|
||||
Occurrences = logic_recurrence:generate_occurrences(
|
||||
Event#event.start_time, ParsedRule, OccurrenceStart),
|
||||
Valid = filter_cancelled(Occurrences, get_exceptions(Event#event.id)),
|
||||
case lists:member(OccurrenceStart, Valid) of
|
||||
true -> ok;
|
||||
false -> {error, invalid_occurrence}
|
||||
end
|
||||
catch
|
||||
_:_ -> {error, invalid_occurrence}
|
||||
end;
|
||||
validate_occurrence(_, _) ->
|
||||
{error, not_recurring}.
|
||||
|
||||
%% Получение события с проверкой доступа
|
||||
get_event(UserId, EventId) ->
|
||||
case core_event:get_by_id(EventId) of
|
||||
|
||||
Reference in New Issue
Block a user