-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreset_participations_job.rb
More file actions
83 lines (74 loc) · 3.29 KB
/
Copy pathreset_participations_job.rb
File metadata and controls
83 lines (74 loc) · 3.29 KB
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
class ResetParticipationsJob < ApplicationJob
queue_as :default
def perform
Game.where(recurring: true).find_each do |game|
nd = game.next_date
next unless nd
if game.should_reset_participations?(Date.current)
if game.prebooking_enabled?
apply_prebookings_for_occurrence!(game, nd)
game.mark_participations_reset!(nd)
Rails.logger.info "Reset participations from prebookings for Game##{game.id} for occurrence #{nd}"
else
close_chat_sessions(game)
game.participations.delete_all
game.mark_participations_reset!(nd)
Rails.logger.info "Reset participations for Game##{game.id} for occurrence #{nd}"
end
end
end
end
private
# delete_all идёт мимо колбэков Participation, поэтому режим чата у выбывших
# гасим здесь — иначе они продолжат писать в состав, из которого их убрали.
def close_chat_sessions(game)
game.participations.includes(:user).find_each do |participation|
Telegram::Chat::Session.stop_for(participation.user, game)
end
rescue StandardError => e
Rails.logger.warn("[ResetParticipationsJob] chat cleanup failed for Game##{game.id}: #{e.class}: #{e.message}")
end
# Promote users from prebookings on nd into participations, shift next prebookings up,
# and append a new empty prebooking date at the end.
def apply_prebookings_for_occurrence!(game, nd)
players_needed = (game.players_count.to_i > 0 ? game.players_count.to_i : 4)
# collect sorted future prebooking dates starting with nd
dates = game.prebookings.where("date >= ?", nd).distinct.pluck(:date).sort
# ensure current nd is present in dates (if no prebookings at nd, still include it)
dates = [ nd ] | dates
ActiveRecord::Base.transaction do
# 1) create participations from prebookings on nd (up to players_needed)
nd_prebooks = game.prebookings.where(date: nd).order(:slot_index)
game.participations.delete_all
nd_prebooks.limit(players_needed).each_with_index do |pb, idx|
next unless pb.user_id
game.participations.create!(user_id: pb.user_id)
# remove user from that prebooking slot (moved to participation)
pb.update!(user_id: nil)
end
# 2) shift users from next dates → current, cascading forward
# iterate dates in order, for each date copy users from next date into current
dates.each_with_index do |cur_date, i|
next_date = dates[i + 1]
(1..players_needed).each do |slot_index|
src_user = nil
if next_date
src_pb = game.prebookings.find_by(date: next_date, slot_index: slot_index)
src_user = src_pb&.user_id
end
dest_pb = game.prebookings.find_or_initialize_by(date: cur_date, slot_index: slot_index)
dest_pb.user_id = src_user
dest_pb.save!
end
end
# 3) append a new empty date after the last known date
last_date = dates.max || nd
new_date = last_date + 1.week
(1..players_needed).each do |slot_index|
game.prebookings.find_or_create_by!(date: new_date, slot_index: slot_index) do |pb|
pb.user_id = nil
end
end
end
end
end