• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sleede / fab-manager / #106

pending completion
#106

push

coveralls-ruby

sylvainbx
Merge branch 'dev' for release 6.0.0

704 of 704 new or added lines in 168 files covered. (100.0%)

7919 of 13474 relevant lines covered (58.77%)

15.29 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

23.33
/lib/tasks/fablab/fix.rake
1
# frozen_string_literal: true
2

3
# Correctives for bugs or upgrades migrations tasks
4
namespace :fablab do
1✔
5
  namespace :fix do
1✔
6
    desc '[release 2.3.0] update reservations referencing reservables not present in database'
1✔
7
    task reservations_not_existing_reservable: :environment do
1✔
8
      ActiveRecord::Base.logger = Logger.new($stdout)
×
9
      ActiveRecord::Base.connection.execute(
×
10
        'UPDATE reservations SET reservable_type = NULL, reservable_id = NULL ' \
11
        'WHERE NOT EXISTS (SELECT 1 FROM events WHERE events.id = reservations.reservable_id) ' \
12
        "AND reservations.reservable_type = 'Event'"
13
      )
14
    end
15

16
    desc '[release 2.4.0] put every non-categorized events into a new category called "No Category", to ease re-categorization'
1✔
17
    task assign_category_to_uncategorized_events: :environment do
1✔
18
      c = Category.find_or_create_by!(name: 'No category')
×
19
      Event.where(category: nil).each do |e|
×
20
        e.category = c
×
21
        e.save!
×
22
      end
23
    end
24

25
    desc '[release 2.4.11] fix is_rolling for edited plans'
1✔
26
    task rolling_plans: :environment do
1✔
27
      Plan.where(is_rolling: nil).each do |p|
×
28
        if p.is_rolling.nil? && p.is_rolling != false
×
29
          p.is_rolling = true
×
30
          p.save!
×
31
        end
32
      end
33
    end
34

35
    desc '[release 2.5.0] create missing plans in statistics'
1✔
36
    task new_plans_statistics: :environment do
1✔
37
      StatisticSubType.where(key: nil).each do |sst|
×
38
        p = Plan.find_by(name: sst.label)
×
39
        if p
×
40
          sst.key = p.slug
×
41
          sst.save!
×
42
        end
43
      end
44
    end
45

46
    desc '[release 2.5.5] create missing space prices'
1✔
47
    task new_group_space_prices: :environment do
1✔
48
      Space.all.each do |space|
×
49
        Group.all.each do |group|
×
50
          Price.find(priceable: space, group: group)
×
51
        rescue ActiveRecord::RecordNotFound
52
          Price.create(priceable: space, group: group, amount: 0)
×
53
        end
54
      end
55
    end
56

57
    desc '[release 2.5.11] put all admins in a special group'
1✔
58
    task migrate_admins_group: :environment do
1✔
59
      admins = Group.find_by(slug: 'admins')
×
60
      User.all.each do |user|
×
61
        if user.admin?
×
62
          user.group = admins
×
63
          user.save!
×
64
        end
65
      end
66
    end
67

68
    desc '[release 2.5.14] fix times of recursive events that crosses DST periods'
1✔
69
    task recursive_events_over_DST: :environment do
1✔
70
      def dst_correction(reference, datetime)
×
71
        res = datetime.in_time_zone(reference.time_zone.tzinfo.name)
×
72
        res -= 1.hour if res.dst? && !reference.dst?
×
73
        res += 1.hour if reference.dst? && !res.dst?
×
74
        res
×
75
      end
76
      failed_ids = []
×
77
      groups = Event.group(:recurrence_id).count
×
78
      groups.each_key do |recurrent_event_id|
×
79
        next unless recurrent_event_id
×
80

81
        begin
82
          initial_event = Event.find(recurrent_event_id)
×
83
          Event.where(recurrence_id: recurrent_event_id).where.not(id: recurrent_event_id).each do |event|
×
84
            availability = event.availability
×
85
            next if initial_event.availability.start_at.hour == availability.start_at.hour
×
86

87
            availability.start_at = dst_correction(initial_event.availability.start_at, availability.start_at)
×
88
            availability.end_at = dst_correction(initial_event.availability.end_at, availability.end_at)
×
89
            availability.save!
×
90
          end
91
        rescue ActiveRecord::RecordNotFound
92
          failed_ids.push recurrent_event_id
×
93
        end
94
      end
95

96
      if failed_ids.size.positive?
×
97
        puts "WARNING: The events with IDs #{failed_ids} were not found.\n These were initial events of a recurrence.\n\n" \
×
98
             "You may have to correct the following events manually (IDs): #{Event.where(recurrence_id: failed_ids).map(&:id)}"
99
      end
100
    end
101

102
    desc '[release 2.6.6] reset slug in events categories'
1✔
103
    task categories_slugs: :environment do
1✔
104
      Category.all.each do |cat|
×
105
        # rubocop:disable Layout/LineLength
106
        `curl -XPOST http://#{ENV.fetch('ELASTICSEARCH_HOST', nil)}:9200/stats/event/_update_by_query?conflicts=proceed\\&refresh\\&wait_for_completion -d '
×
107
        {
108
          "script": {
109
            "source": "ctx._source.subType = params.slug",
110
            "lang": "painless",
111
            "params": {
112
              "slug": "#{cat.slug}"
113
            }
114
          },
115
          "query": {
116
            "term": {
117
              "subType": "#{cat.name}"
118
            }
119
          }
120
        }';`
121
        # rubocop:enable Layout/LineLength
122
      end
123
    end
124

125
    desc '[release 2.4.10] set slugs to plans'
1✔
126
    task set_plans_slugs: :environment do
1✔
127
      # this will maintain compatibility with existing statistics
128
      Plan.all.each do |p|
×
129
        p.slug = p.stp_plan_id
×
130
        p.save
×
131
      end
132
    end
133

134
    desc '[release 3.1.2] fix users with invalid group_id'
1✔
135
    task users_group_ids: :environment do
1✔
136
      User.where.not(group_id: Group.all.map(&:id)).each do |u|
×
137
        u.update_columns(group_id: Group.first.id, updated_at: Time.current) # rubocop:disable Rails/SkipsModelValidations
×
138

139
        meta_data = { ex_group_name: 'invalid group' }
×
140

141
        NotificationCenter.call type: :notify_admin_user_group_changed,
×
142
                                receiver: User.admins,
143
                                attached_object: u,
144
                                meta_data: meta_data
145

146
        NotificationCenter.call type: :notify_user_user_group_changed,
×
147
                                receiver: u,
148
                                attached_object: u
149
      end
150
    end
151

152
    desc '[release 4.3.0] add name to theme stylesheet'
1✔
153
    task name_stylesheet: :environment do
1✔
154
      Stylesheet.order(:created_at).first&.update(
×
155
        name: 'theme'
156
      )
157
    end
158

159
    desc '[release 4.3.3] add statistic_profile_id to refund invoices for WalletTransactions'
1✔
160
    task avoirs_wallet_transaction: :environment do
1✔
161
      Avoir.where(invoiced_type: WalletTransaction.name).each do |a|
×
162
        next unless a.statistic_profile_id.nil?
×
163

164
        begin
165
          a.statistic_profile_id = a.invoiced.wallet.user&.statistic_profile&.id
×
166
          a.save!
×
167
        rescue ActiveRecord::RecordInvalid => e
168
          printf "Unable to modify the refund invoice (id %<id>s): %<error>s\nIgnoring that record...\n", id: a.id, error: e
×
169
        end
170
      end
171
    end
172

173
    desc '[release 4.4.2] add missing role to StatisticProfile'
1✔
174
    task role_in_statistic_profile: :environment do
1✔
175
      puts "Fixing #{StatisticProfile.where(role_id: nil).count} bugged profiles...\n"
×
176
      StatisticProfile.where(role_id: nil).each do |sp|
×
177
        role_id = sp.user&.roles&.first&.id
×
178
        sp.role_id = role_id
×
179
        sp.save!
×
180
      end
181
    end
182

183
    desc '[release 4.4.3] fix duration of recurring availabilities'
1✔
184
    task availabilities_duration: :environment do
1✔
185
      Availability.select('occurrence_id').where(is_recurrent: true).group('occurrence_id').each do |a|
×
186
        occurrences = Availability.where(occurrence_id: a.occurrence_id)
×
187
        next unless occurrences.map(&:slot_duration).uniq.size > 1
×
188

189
        duration = occurrences.map(&:slot_duration).uniq.detect { |e| !e.nil? }
×
190
        occurrences.each do |o|
×
191
          o.update(slot_duration: duration)
×
192
        end
193
      end
194
    end
195

196
    desc '[release 4.7.9] fix invoicing profiles without names'
1✔
197
    task invoices_without_names: :environment do
1✔
198
      InvoicingProfile.where('(first_name IS NULL OR last_name IS NULL) AND user_id IS NOT NULL').each do |ip|
×
199
        ip.update(first_name: ip.user.profile.first_name)
×
200
        ip.update(last_name: ip.user.profile.last_name)
×
201
      end
202
    end
203

204
    desc '[release 5.3.8] fix invoicing profiles without names and email'
1✔
205
    task invoices_without_names_and_email: :environment do
1✔
206
      InvoicingProfile.where('(first_name IS NULL OR last_name IS NULL OR email IS NULL) AND user_id IS NOT NULL').each do |ip|
×
207
        ip.update(first_name: ip.user.profile.first_name)
×
208
        ip.update(last_name: ip.user.profile.last_name)
×
209
        ip.update(email: ip.user.email)
×
210
      end
211
    end
212

213
    desc '[release 5.4.24] fix prepaid pack hours dont count down after a reservation of machine'
1✔
214
    task :prepaid_pack_count_down, %i[start_date end_date] => :environment do |_task, args|
1✔
215
      # set start date to the date of deployment of v5.4.13 that product the bug
216
      start_date = Time.zone.parse('2022-07-28T10:00:00+02:00')
×
217
      if args.start_date
×
218
        begin
219
          start_date = Time.zone.parse(args.start_date)
×
220
        rescue ArgumentError => e
221
          raise e
×
222
        end
223
      end
224
      # set end date to the date of deployment of v5.4.24 after fix the bug
225
      end_date = Time.zone.parse('2022-10-14T18:40:00+02:00')
×
226
      if args.end_date
×
227
        begin
228
          end_date = Time.zone.parse(args.end_date)
×
229
        rescue ArgumentError => e
230
          raise e
×
231
        end
232
      end
233
      # find all machines that has prepaid pack
234
      machine_ids = PrepaidPack.where(disabled: nil).all.map(&:priceable_id).uniq
×
235
      # find all memders that bought a prepaid pack
236
      statistic_profile_ids = StatisticProfilePrepaidPack.all.map(&:statistic_profile_id).uniq
×
237
      # find the reservations that use prepaid pack by machine_ids, members and preriod
238
      reservations = Reservation.where(reservable_type: 'Machine', reservable_id: machine_ids, statistic_profile_id: statistic_profile_ids,
×
239
                                       created_at: start_date..end_date).order(statistic_profile_id: :asc, created_at: :asc)
240
      infos = []
×
241
      reservations.each do |reservation|
×
242
        # find pack by pack's created_at before reservation's create_at and pack's expries_at before start_date
243
        packs = StatisticProfilePrepaidPack
×
244
                .includes(:prepaid_pack)
245
                .references(:prepaid_packs)
246
                .where(prepaid_packs: { priceable_id: reservation.reservable.id })
247
                .where(prepaid_packs: { priceable_type: reservation.reservable.class.name })
248
                .where(statistic_profile_id: reservation.statistic_profile_id)
249
                .where('statistic_profile_prepaid_packs.created_at <= ?', reservation.created_at)
250
                .where('expires_at is NULL or expires_at > ?', start_date)
251
                .order(created_at: :asc)
252

253
        # passe reservation if cannot find any pack
254
        next if packs.empty?
×
255

256
        user = reservation.statistic_profile.user
×
257
        pack = packs.last
×
258

259
        slots_minutes = reservation.slots.map do |slot|
×
260
          (slot.end_at.to_time - slot.start_at.to_time) / 60.0
×
261
        end
262
        # get reservation total minutes
263
        reservation_minutes = slots_minutes.reduce(:+) || 0
×
264

265
        info = {
266
          user: "#{user.profile.full_name} - #{user.email}",
×
267
          reservation: "Reservation #{reservation.original_invoice.reference} for the machine #{reservation.reservable.name} " \
268
                       "by #{reservation_minutes / 60.0} hours at #{I18n.l(reservation.created_at.to_date)}",
269
          pack_before: "Prepaid pack of hours has used #{pack.minutes_used / 60.0} hours / #{pack.prepaid_pack.minutes / 60.0} hours"
270
        }
271

272
        if pack.minutes_used == pack.prepaid_pack.minutes && pack.updated_at > start_date
×
273
          info[:pack_after] = 'Reservation minutes is exceed prepaid pack of hours'
×
274
          infos.push(info)
×
275
        elsif pack.minutes_used < pack.prepaid_pack.minutes
×
276
          PrepaidPackService.update_user_minutes(user, reservation)
×
277
          pack.reload
×
278
          info[:pack_after] = "Prepaid pack of hours used #{pack.minutes_used / 60.0} hours after paid this reservation"
×
279
          infos.push(info)
×
280
        end
281
      end
282

283
      infos.each do |i|
×
284
        puts i
×
285
      end
286
    end
287

288
    desc '[release 5.6.6] fix invoice items in error'
1✔
289
    task invoice_items_in_error: :environment do
1✔
290
      next if InvoiceItem.where(object_type: 'Error').count.zero?
×
291

292
      InvoiceItem.where(object_type: 'Error').update_all(object_id: 0) # rubocop:disable Rails/SkipsModelValidations
×
293

294
      FabManager::Application.load_tasks if Rake::Task.tasks.empty?
×
295
      Rake::Task['fablab:chain:invoices_items'].invoke
×
296
    end
297

298
    desc '[release 5.8.2] fix operator of self-bought carts'
1✔
299
    task cart_operator: :environment do |_task, _args|
1✔
300
      Order.where.not(statistic_profile_id: nil).find_each do |order|
×
301
        order.update(operator_profile_id: order.user&.invoicing_profile&.id)
×
302
      end
303
      Order.where.not(operator_profile_id: nil).find_each do |order|
×
304
        order.update(statistic_profile_id: order.operator_profile&.user&.statistic_profile&.id)
×
305
      end
306
    end
307

308
    desc '[release 5.8.2] fix prepaid packs minutes_used'
1✔
309
    task pack_minutes_used: :environment do |_task, _args|
1✔
310
      StatisticProfilePrepaidPack.find_each do |sppp|
×
311
        previous_packs = sppp.statistic_profile.statistic_profile_prepaid_packs
×
312
                             .includes(:prepaid_pack)
313
                             .where(prepaid_packs: { priceable: sppp.prepaid_pack.priceable })
314
                             .where("statistic_profile_prepaid_packs.created_at <= '#{sppp.created_at.utc.strftime('%Y-%m-%d %H:%M:%S.%6N')}'")
315
                             .order('statistic_profile_prepaid_packs.created_at')
316
        remaining = {}
×
317
        previous_packs.each do |pack|
×
318
          available_minutes = pack.prepaid_pack.minutes
×
319
          reservations = Reservation.where(reservable: sppp.prepaid_pack.priceable)
×
320
                                    .where(statistic_profile_id: sppp.statistic_profile_id)
321
                                    .where("created_at > '#{pack.created_at.utc.strftime('%Y-%m-%d %H:%M:%S.%6N')}'")
322
          reservations.each do |reservation|
×
323
            next if available_minutes.zero?
×
324

325
            # if the previous pack has not covered all the duration of this reservation, we substract the remaining minutes from the current pack
326
            if remaining[reservation.id]
×
327
              if remaining[reservation.id] > available_minutes
×
328
                consumed = available_minutes
×
329
                remaining[reservation.id] = remaining[reservation.id] - available_minutes
×
330
              else
331
                consumed = remaining[reservation.id]
×
332
                remaining.except!(reservation.id)
×
333
              end
334
            else
335
              # if there was no remaining from the previous pack, we substract the reservation duration from the current pack
336
              reservation_minutes = reservation.slots.map { |slot| (slot.end_at.to_time - slot.start_at.to_time) / 60.0 }.reduce(:+) || 0
×
337
              if reservation_minutes > available_minutes
×
338
                consumed = available_minutes
×
339
                remaining[reservation.id] = reservation_minutes - consumed
×
340
              else
341
                consumed = reservation_minutes
×
342
              end
343
            end
344
            available_minutes -= consumed
×
345
            PrepaidPackReservation.find_or_create_by!(statistic_profile_prepaid_pack: pack, reservation: reservation, consumed_minutes: consumed)
×
346
          end
347
          pack.update(minutes_used: pack.prepaid_pack.minutes - available_minutes)
×
348
        end
349
      end
350
    end
351
  end
352
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc