mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-21 15:54:22 +01:00
script to fix existing invoices w/o invoiced_id
This commit is contained in:
parent
b151802923
commit
3a910b1182
@ -6,6 +6,7 @@
|
|||||||
- Fix a bug: unable to use run.fab.mn
|
- Fix a bug: unable to use run.fab.mn
|
||||||
- Fix a security issue: updated puma to 4.3.8 to fix [CVE-2019-16770](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-16770)
|
- Fix a security issue: updated puma to 4.3.8 to fix [CVE-2019-16770](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-16770)
|
||||||
- Fix a security issue: updated nokogiri to 1.11.4 to fix [GHSA-7rrm-v45f-jp64](https://github.com/advisories/GHSA-7rrm-v45f-jp64)
|
- Fix a security issue: updated nokogiri to 1.11.4 to fix [GHSA-7rrm-v45f-jp64](https://github.com/advisories/GHSA-7rrm-v45f-jp64)
|
||||||
|
- [TODO DEPLOY] `rails fablab:fix_invoices`
|
||||||
|
|
||||||
## v4.7.9 2021 May 17
|
## v4.7.9 2021 May 17
|
||||||
|
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# This migration will ensure data integrity for invoices.
|
# This take will ensure data integrity for invoices.
|
||||||
# A bug introduced with v4.7.0 has made invoices without invoiced_id for Reservations.
|
# A bug introduced with v4.3.0 has made invoices without saving the associated Reservation (Invoice.invoiced_id is null).
|
||||||
# This issue is concerning slots restricted to subscribers, when the restriction was manually overridden by an admin.
|
# This issue is concerning slots restricted to subscribers, when the restriction is manually overridden by an admin.
|
||||||
class FixInvoicesWithoutInvoicedId < ActiveRecord::Migration[5.2]
|
namespace :fablab do
|
||||||
def up
|
desc 'Remove the invoices w/o reservation or regenerate the reservation'
|
||||||
|
task fix_invoices: :environment do |_task, _args|
|
||||||
return unless Invoice.where(invoiced_id: nil).count.positive?
|
return unless Invoice.where(invoiced_id: nil).count.positive?
|
||||||
|
|
||||||
|
include ActionView::Helpers::NumberHelper
|
||||||
|
|
||||||
# check the footprints and save the archives
|
# check the footprints and save the archives
|
||||||
check_footprints
|
check_footprints
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
periods = backup_and_remove_periods
|
periods = backup_and_remove_periods
|
||||||
|
|
||||||
# fix invoices data
|
# fix invoices data
|
||||||
@ -19,15 +23,31 @@ class FixInvoicesWithoutInvoicedId < ActiveRecord::Migration[5.2]
|
|||||||
next
|
next
|
||||||
end
|
end
|
||||||
if invoice.invoiced_type != 'Reservation'
|
if invoice.invoiced_type != 'Reservation'
|
||||||
STDERR.puts "WARNING: Invoice #{invoice.id} is not about a reservation, ignoring..."
|
STDERR.puts "WARNING: Invoice #{invoice.id} is about #{invoice.invoiced_type}. Please handle manually."
|
||||||
|
STDERR.puts 'Ignoring...'
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
ii = invoice.invoice_items.where(subscription_id: nil).first
|
ii = invoice.invoice_items.where(subscription_id: nil).first
|
||||||
|
puts '=============================================='
|
||||||
|
puts "Invoice #{invoice.id} (# #{invoice.reference})"
|
||||||
|
puts "Total: #{number_to_currency(invoice.total / 100.0)}"
|
||||||
|
puts "Subject: #{ii.description}."
|
||||||
|
puts "Customer: #{invoice.invoicing_profile.full_name} (#{invoice.invoicing_profile.email})"
|
||||||
|
puts "Operator: #{invoice.operator_profile&.user&.profile&.full_name} (#{invoice.operator_profile&.user&.email})"
|
||||||
|
puts "Date: #{invoice.created_at}"
|
||||||
|
|
||||||
|
print 'Delete [d] OR create the missing reservation [c]? > '
|
||||||
|
confirm = STDIN.gets.chomp
|
||||||
|
if confirm == 'd'
|
||||||
|
puts "Destroying #{invoice.id}..."
|
||||||
|
invoice.destroy
|
||||||
|
elsif confirm == 'c'
|
||||||
reservable = find_reservable(ii)
|
reservable = find_reservable(ii)
|
||||||
if reservable
|
if reservable
|
||||||
if reservable.is_a? Event
|
if reservable.is_a? Event
|
||||||
STDERR.puts "WARNING: invoice #{invoice.id} may be linked to the Event #{reservable.id}. This is unsupported, ignoring..."
|
STDERR.puts "WARNING: invoice #{invoice.id} is linked to Event #{reservable.id}. This is unsupported, please handle manually."
|
||||||
|
STDERR.puts 'Ignoring...'
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
reservation = ::Reservation.create!(
|
reservation = ::Reservation.create!(
|
||||||
@ -38,7 +58,11 @@ class FixInvoicesWithoutInvoicedId < ActiveRecord::Migration[5.2]
|
|||||||
)
|
)
|
||||||
invoice.update_attributes(invoiced: reservation)
|
invoice.update_attributes(invoiced: reservation)
|
||||||
else
|
else
|
||||||
STDERR.puts "WARNING: Unable to guess the reservable for invoice #{invoice.id}, ignoring..."
|
STDERR.puts "WARNING: Unable to guess the reservable for invoice #{invoice.id}, please handle manually."
|
||||||
|
STDERR.puts 'Ignoring...'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
puts "Operation #{confirm} unknown. Ignoring invoice #{invoice.id}..."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -50,8 +74,7 @@ class FixInvoicesWithoutInvoicedId < ActiveRecord::Migration[5.2]
|
|||||||
# re-create all archives from the memory dump
|
# re-create all archives from the memory dump
|
||||||
restore_periods(periods)
|
restore_periods(periods)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
def down; end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
@ -111,7 +134,6 @@ class FixInvoicesWithoutInvoicedId < ActiveRecord::Migration[5.2]
|
|||||||
execute("CREATE RULE accounting_periods_del_protect AS ON DELETE TO #{AccountingPeriod.arel_table.name} DO INSTEAD NOTHING;")
|
execute("CREATE RULE accounting_periods_del_protect AS ON DELETE TO #{AccountingPeriod.arel_table.name} DO INSTEAD NOTHING;")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def find_reservable(invoice_item)
|
def find_reservable(invoice_item)
|
||||||
descr = /^([a-zA-Z\u00C0-\u017F]+\s+)+/.match(invoice_item.description)[0].strip[/(.*)\s/, 1]
|
descr = /^([a-zA-Z\u00C0-\u017F]+\s+)+/.match(invoice_item.description)[0].strip[/(.*)\s/, 1]
|
||||||
reservable = InvoiceItem.where('description LIKE ?', "#{descr}%")
|
reservable = InvoiceItem.where('description LIKE ?', "#{descr}%")
|
||||||
@ -130,10 +152,14 @@ class FixInvoicesWithoutInvoicedId < ActiveRecord::Migration[5.2]
|
|||||||
|
|
||||||
def find_slots(invoice)
|
def find_slots(invoice)
|
||||||
invoice.invoice_items.map do |ii|
|
invoice.invoice_items.map do |ii|
|
||||||
# FIXME, datetime parsing is KO
|
description = ii.description
|
||||||
start = DateTime.parse(ii.description)
|
# DateTime.parse only works with english dates, so translate the month name
|
||||||
end_time = DateTime.parse(/- (.+)$/.match(ii.description)[1])
|
month_idx = I18n.t('date.month_names').find_index { |month| month && description.include?(month) }
|
||||||
[start, DateTime.new(start.year, start.month, start.day, end_time.hour, end_time.min, end_time.sec, end_time.zone)]
|
description.gsub!(/#{I18n.t('date.month_names')[month_idx]}/, I18n.t('date.month_names', locale: :en)[month_idx])
|
||||||
|
|
||||||
|
start = DateTime.parse(description)
|
||||||
|
end_time = DateTime.parse(/- (.+)$/.match(description)[1])
|
||||||
|
[start, DateTime.new(start.year, start.month, start.day, end_time.hour, end_time.min, end_time.sec, DateTime.current.zone)]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user