mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-28 09:24:24 +01:00
(feat) generate invoices for missing references
This commit is contained in:
parent
227c6d1844
commit
3cff0d4c28
@ -13,7 +13,7 @@ class PaymentDocument < Footprintable
|
||||
end
|
||||
|
||||
def update_reference
|
||||
generate_reference
|
||||
generate_reference if reference.blank?
|
||||
save
|
||||
end
|
||||
|
||||
|
@ -33,15 +33,10 @@ class Pdf::Invoice < Prawn::Document
|
||||
Rails.logger.error "Unable to decode invoice logo from base64: #{e}"
|
||||
end
|
||||
move_down 20
|
||||
# the following line is a special comment to workaround RubyMine inspection problem
|
||||
# noinspection RubyScope
|
||||
font('Open-Sans', size: 10) do
|
||||
# general information
|
||||
if invoice.is_a?(Avoir)
|
||||
text I18n.t('invoices.refund_invoice_reference', **{ REF: invoice.reference }), leading: 3
|
||||
else
|
||||
text I18n.t('invoices.invoice_reference', **{ REF: invoice.reference }), leading: 3
|
||||
end
|
||||
text I18n.t(invoice.is_a?(Avoir) ? 'invoices.refund_invoice_reference' : 'invoices.invoice_reference',
|
||||
**{ REF: invoice.reference }), leading: 3
|
||||
text I18n.t('invoices.code', **{ CODE: Setting.get('invoice_code-value') }), leading: 3 if Setting.get('invoice_code-active')
|
||||
if invoice.main_item&.object_type != WalletTransaction.name
|
||||
text I18n.t('invoices.order_number', **{ NUMBER: invoice.order_number }), leading: 3
|
||||
|
@ -21,7 +21,7 @@ class Invoices::LabelService
|
||||
when 'OfferDay'
|
||||
offer_day_label(invoice.main_item.object, username)
|
||||
when 'Error'
|
||||
I18n.t('invoices.error_invoice')
|
||||
invoice.main_item&.object_id&.zero? ? I18n.t('invoices.error_invoice') : invoice.main_item&.description
|
||||
when 'StatisticProfilePrepaidPack'
|
||||
I18n.t('invoices.prepaid_pack')
|
||||
when 'OrderItem'
|
||||
|
@ -22,20 +22,32 @@ class Invoices::NumberService
|
||||
saved_number[indices[0]..indices[1]]&.to_i
|
||||
end
|
||||
|
||||
# Replace the number of the reference of the given document and return the new reference
|
||||
# @param document [PaymentDocument,NilClass]
|
||||
# Search for any document matching the provided period and number
|
||||
# @param number [Integer] the number to search
|
||||
# @param date [Time] the date to search around, when using periodicity != 'global'
|
||||
# @param setting [String] 'invoice_reference' | 'invoice_order-nb'
|
||||
# @return [String,NilClass]
|
||||
def change_number(document, new_number, setting = 'invoice_reference')
|
||||
# @param klass [Class] Invoice | Order | PaymentSchedule
|
||||
# @return [PaymentDocument,NilClass]
|
||||
def find_by_number(number, date: Time.current, setting: 'invoice_reference', klass: Invoice)
|
||||
raise TypeError, "invalid setting #{setting}" unless %w[invoice_order-nb invoice_reference].include?(setting)
|
||||
return nil if document.nil?
|
||||
return nil if number.nil?
|
||||
|
||||
saved_number = setting == 'invoice_reference' ? document.reference : document.order_number
|
||||
return nil if saved_number.nil?
|
||||
pattern = pattern(date, setting)
|
||||
pattern = pattern.gsub(/([SXR]\[[^\]]+\])+/, '%')
|
||||
if pattern.match?(/n+/)
|
||||
pattern = pattern.gsub(/n+(?![^\[]*\])/) do |match|
|
||||
pad_and_truncate(number, match.to_s.length)
|
||||
end
|
||||
else
|
||||
start_idx = pattern.index(/y+|m+|d+/)
|
||||
end_idx = pattern.rindex(/y+|m+|d+/)
|
||||
pattern[start_idx..end_idx] = pad_and_truncate(number, end_idx - start_idx + 1)
|
||||
end
|
||||
pattern = PaymentDocumentService.send(:replace_date_pattern, pattern, date)
|
||||
|
||||
indices = number_indices(document, setting)
|
||||
saved_number[indices[0]..indices[1]] = pad_and_truncate(new_number, indices[1] - indices[0])
|
||||
saved_number
|
||||
field = setting == 'invoice_reference' ? 'reference' : 'order_number'
|
||||
field = 'reference' if klass == Order
|
||||
klass.where("#{field} LIKE '#{pattern}'").first
|
||||
end
|
||||
|
||||
# @param document [PaymentDocument,NilClass]
|
||||
@ -45,7 +57,7 @@ class Invoices::NumberService
|
||||
raise TypeError, "invalid setting #{setting}" unless %w[invoice_order-nb invoice_reference].include?(setting)
|
||||
return nil if document.nil?
|
||||
|
||||
pattern = pattern(document, setting)
|
||||
pattern = pattern(document.created_at, setting)
|
||||
pattern = PaymentDocumentService.send(:replace_document_type_pattern, document, pattern)
|
||||
|
||||
return 'global' if pattern.match?(/n+/)
|
||||
@ -56,15 +68,15 @@ class Invoices::NumberService
|
||||
nil
|
||||
end
|
||||
|
||||
# Get the pattern applicable to generate the number of the given invoice.
|
||||
# @param document [PaymentDocument]
|
||||
# Get the pattern applicable to generate the given number at the given date.
|
||||
# @param date [Time]
|
||||
# @param setting [String] 'invoice_reference' | 'invoice_order-nb'
|
||||
# @return [String]
|
||||
def pattern(document, setting = 'invoice_reference')
|
||||
def pattern(date, setting = 'invoice_reference')
|
||||
raise TypeError, "invalid setting #{setting}" unless %w[invoice_order-nb invoice_reference].include?(setting)
|
||||
|
||||
value = Setting.find_by(name: setting).value_at(document.created_at)
|
||||
value || if document.created_at < Setting.find_by(name: setting).first_update
|
||||
value = Setting.find_by(name: setting).value_at(date)
|
||||
value || if date < Setting.find_by(name: setting).first_update
|
||||
Setting.find_by(name: setting).first_value
|
||||
else
|
||||
Setting.get(setting)
|
||||
@ -89,7 +101,7 @@ class Invoices::NumberService
|
||||
raise TypeError, "invalid setting #{setting}" unless %w[invoice_order-nb invoice_reference].include?(setting)
|
||||
return nil if document.nil?
|
||||
|
||||
pattern = pattern(document, setting)
|
||||
pattern = pattern(document.created_at, setting)
|
||||
pattern = PaymentDocumentService.send(:replace_document_type_pattern, document, pattern)
|
||||
start_idx = pattern.index(/n+|y+|m+|d+/)
|
||||
end_idx = pattern.rindex(/n+|y+|m+|d+/)
|
||||
|
@ -16,27 +16,17 @@ class Invoices::PaymentDetailsService
|
||||
build_avoir_details(invoice, total)
|
||||
else
|
||||
# subtract the wallet amount for this invoice from the total
|
||||
if invoice.wallet_amount
|
||||
wallet_amount = invoice.wallet_amount / 100.00
|
||||
total -= wallet_amount
|
||||
else
|
||||
wallet_amount = nil
|
||||
end
|
||||
wallet_amount = wallet_amount(invoice)
|
||||
total -= wallet_amount unless wallet_amount.nil?
|
||||
return '' if wallet_amount.nil? && total.zero?
|
||||
|
||||
# payment method
|
||||
payment_verbose = if invoice.paid_by_card?
|
||||
I18n.t('invoices.settlement_by_debit_card')
|
||||
else
|
||||
I18n.t('invoices.settlement_done_at_the_reception')
|
||||
end
|
||||
|
||||
# if the invoice was 100% payed with the wallet ...
|
||||
payment_verbose = I18n.t('invoices.settlement_by_wallet') if total.zero? && wallet_amount
|
||||
payment_verbose = payment_mean(invoice, total, wallet_amount)
|
||||
|
||||
payment_verbose += " #{I18n.t('invoices.on_DATE_at_TIME',
|
||||
**{ DATE: I18n.l(invoice.created_at.to_date),
|
||||
TIME: I18n.l(invoice.created_at, format: :hour_minute) })}"
|
||||
if total.positive? || !invoice.wallet_amount
|
||||
if total.positive? || wallet_amount.nil?
|
||||
payment_verbose += " #{I18n.t('invoices.for_an_amount_of_AMOUNT', **{ AMOUNT: number_to_currency(total) })}"
|
||||
end
|
||||
if invoice.wallet_amount
|
||||
@ -53,6 +43,30 @@ class Invoices::PaymentDetailsService
|
||||
|
||||
private
|
||||
|
||||
# @param invoice [Invoice]
|
||||
# @return [Float,NilClass]
|
||||
def wallet_amount(invoice)
|
||||
return invoice.wallet_amount / 100.00 if invoice.wallet_amount
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
# @param invoice [Invoice]
|
||||
# @param total [Float]
|
||||
# @param wallet_amount [Float,NilClass]
|
||||
# @return [String]
|
||||
def payment_mean(invoice, total, wallet_amount)
|
||||
# if the invoice was 100% payed with the wallet ...
|
||||
return I18n.t('invoices.settlement_by_wallet') if total.zero? && !wallet_amount.nil?
|
||||
|
||||
# else
|
||||
if invoice.paid_by_card?
|
||||
I18n.t('invoices.settlement_by_debit_card')
|
||||
else
|
||||
I18n.t('invoices.settlement_done_at_the_reception')
|
||||
end
|
||||
end
|
||||
|
||||
# @param invoice [Invoice]
|
||||
# @param total [Float]
|
||||
# @return [String]
|
||||
|
@ -7,7 +7,7 @@ class PaymentDocumentService
|
||||
# @param document [PaymentDocument]
|
||||
# @param date [Time]
|
||||
def generate_reference(document, date: Time.current)
|
||||
pattern = Invoices::NumberService.pattern(document, 'invoice_reference')
|
||||
pattern = Invoices::NumberService.pattern(document.created_at, 'invoice_reference')
|
||||
|
||||
reference = replace_document_number_pattern(pattern, document)
|
||||
reference = replace_date_pattern(reference, date)
|
||||
@ -16,7 +16,7 @@ class PaymentDocumentService
|
||||
|
||||
# @param document [PaymentDocument]
|
||||
def generate_order_number(document)
|
||||
pattern = Invoices::NumberService.pattern(document, 'invoice_order-nb')
|
||||
pattern = Invoices::NumberService.pattern(document.created_at, 'invoice_order-nb')
|
||||
|
||||
# global document number (nn..nn)
|
||||
reference = pattern.gsub(/n+(?![^\[]*\])/) do |match|
|
||||
@ -27,6 +27,19 @@ class PaymentDocumentService
|
||||
replace_date_pattern(reference, document.created_at)
|
||||
end
|
||||
|
||||
# Generate a reference for the given document using the given document number
|
||||
# @param number [Integer]
|
||||
# @param document [PaymentDocument]
|
||||
def generate_numbered_reference(number, document)
|
||||
pattern = Invoices::NumberService.pattern(document.created_at, 'invoice_reference')
|
||||
|
||||
reference = pattern.gsub(/n+|y+|m+|d+(?![^\[]*\])/) do |match|
|
||||
pad_and_truncate(number, match.to_s.length)
|
||||
end
|
||||
reference = replace_date_pattern(reference, document.created_at)
|
||||
replace_document_type_pattern(document, reference)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Output the given integer with leading zeros. If the given value is longer than the given
|
||||
|
@ -102,6 +102,7 @@ en:
|
||||
training_reservation_DESCRIPTION: "Training reservation - %{DESCRIPTION}"
|
||||
event_reservation_DESCRIPTION: "Event reservation - %{DESCRIPTION}"
|
||||
from_payment_schedule: "Due %{NUMBER} out of %{TOTAL}, from %{DATE}. Repayment schedule %{SCHEDULE}"
|
||||
null_invoice: "Invoice at nil, billing jump following a malfunction of the Fab Manager software"
|
||||
full_price_ticket:
|
||||
one: "One full price ticket"
|
||||
other: "%{count} full price tickets"
|
||||
|
@ -102,6 +102,7 @@ fr:
|
||||
training_reservation_DESCRIPTION: "Réservation Formation - %{DESCRIPTION}"
|
||||
event_reservation_DESCRIPTION: "Réservation Événement - %{DESCRIPTION}"
|
||||
from_payment_schedule: "Échéance %{NUMBER} sur %{TOTAL}, du %{DATE}. Échéancier de paiement %{SCHEDULE}"
|
||||
null_invoice: 'Facture à néant, saut de facturation suite à un dysfonctionnement du logiciel Fab Manager'
|
||||
full_price_ticket:
|
||||
one: "Une place plein tarif"
|
||||
other: "%{count} places plein tarif"
|
||||
|
@ -85,11 +85,11 @@ CREATE FUNCTION public.fill_search_vector_for_project() RETURNS trigger
|
||||
select string_agg(description, ' ') as content into step_description from project_steps where project_id = new.id;
|
||||
|
||||
new.search_vector :=
|
||||
setweight(to_tsvector('pg_catalog.norwegian', unaccent(coalesce(new.name, ''))), 'A') ||
|
||||
setweight(to_tsvector('pg_catalog.norwegian', unaccent(coalesce(new.tags, ''))), 'B') ||
|
||||
setweight(to_tsvector('pg_catalog.norwegian', unaccent(coalesce(new.description, ''))), 'D') ||
|
||||
setweight(to_tsvector('pg_catalog.norwegian', unaccent(coalesce(step_title.title, ''))), 'C') ||
|
||||
setweight(to_tsvector('pg_catalog.norwegian', unaccent(coalesce(step_description.content, ''))), 'D');
|
||||
setweight(to_tsvector('pg_catalog.french', unaccent(coalesce(new.name, ''))), 'A') ||
|
||||
setweight(to_tsvector('pg_catalog.french', unaccent(coalesce(new.tags, ''))), 'B') ||
|
||||
setweight(to_tsvector('pg_catalog.french', unaccent(coalesce(new.description, ''))), 'D') ||
|
||||
setweight(to_tsvector('pg_catalog.french', unaccent(coalesce(step_title.title, ''))), 'C') ||
|
||||
setweight(to_tsvector('pg_catalog.french', unaccent(coalesce(step_description.content, ''))), 'D');
|
||||
|
||||
return new;
|
||||
end
|
||||
@ -115,8 +115,8 @@ SET default_tablespace = '';
|
||||
|
||||
CREATE TABLE public.abuses (
|
||||
id integer NOT NULL,
|
||||
signaled_type character varying,
|
||||
signaled_id integer,
|
||||
signaled_type character varying,
|
||||
first_name character varying,
|
||||
last_name character varying,
|
||||
email character varying,
|
||||
@ -236,8 +236,8 @@ CREATE TABLE public.addresses (
|
||||
locality character varying,
|
||||
country character varying,
|
||||
postal_code character varying,
|
||||
placeable_type character varying,
|
||||
placeable_id integer,
|
||||
placeable_type character varying,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone
|
||||
);
|
||||
@ -346,8 +346,8 @@ CREATE TABLE public.ar_internal_metadata (
|
||||
|
||||
CREATE TABLE public.assets (
|
||||
id integer NOT NULL,
|
||||
viewable_type character varying,
|
||||
viewable_id integer,
|
||||
viewable_type character varying,
|
||||
attachment character varying,
|
||||
type character varying,
|
||||
created_at timestamp without time zone,
|
||||
@ -965,8 +965,8 @@ ALTER SEQUENCE public.coupons_id_seq OWNED BY public.coupons.id;
|
||||
|
||||
CREATE TABLE public.credits (
|
||||
id integer NOT NULL,
|
||||
creditable_type character varying,
|
||||
creditable_id integer,
|
||||
creditable_type character varying,
|
||||
plan_id integer,
|
||||
hours integer,
|
||||
created_at timestamp without time zone,
|
||||
@ -1762,15 +1762,15 @@ ALTER SEQUENCE public.notification_types_id_seq OWNED BY public.notification_typ
|
||||
CREATE TABLE public.notifications (
|
||||
id integer NOT NULL,
|
||||
receiver_id integer,
|
||||
attached_object_type character varying,
|
||||
attached_object_id integer,
|
||||
attached_object_type character varying,
|
||||
notification_type_id integer,
|
||||
is_read boolean DEFAULT false,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone,
|
||||
receiver_type character varying,
|
||||
is_send boolean DEFAULT false,
|
||||
meta_data jsonb DEFAULT '"{}"'::jsonb
|
||||
meta_data jsonb DEFAULT '{}'::jsonb
|
||||
);
|
||||
|
||||
|
||||
@ -2498,8 +2498,8 @@ CREATE TABLE public.prices (
|
||||
id integer NOT NULL,
|
||||
group_id integer,
|
||||
plan_id integer,
|
||||
priceable_type character varying,
|
||||
priceable_id integer,
|
||||
priceable_type character varying,
|
||||
amount integer,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
@ -2962,8 +2962,8 @@ CREATE TABLE public.reservations (
|
||||
message text,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone,
|
||||
reservable_type character varying,
|
||||
reservable_id integer,
|
||||
reservable_type character varying,
|
||||
nb_reserve_places integer,
|
||||
statistic_profile_id integer
|
||||
);
|
||||
@ -2995,8 +2995,8 @@ ALTER SEQUENCE public.reservations_id_seq OWNED BY public.reservations.id;
|
||||
CREATE TABLE public.roles (
|
||||
id integer NOT NULL,
|
||||
name character varying,
|
||||
resource_type character varying,
|
||||
resource_id integer,
|
||||
resource_type character varying,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone
|
||||
);
|
||||
@ -5718,14 +5718,6 @@ ALTER TABLE ONLY public.roles
|
||||
ADD CONSTRAINT roles_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.schema_migrations
|
||||
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
|
||||
|
||||
|
||||
--
|
||||
-- Name: settings settings_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@ -7385,6 +7377,21 @@ CREATE INDEX proof_of_identity_type_id_and_proof_of_identity_refusal_id ON publi
|
||||
CREATE UNIQUE INDEX unique_not_null_external_id ON public.invoicing_profiles USING btree (external_id) WHERE (external_id IS NOT NULL);
|
||||
|
||||
|
||||
--
|
||||
-- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING btree (version);
|
||||
|
||||
|
||||
--
|
||||
-- Name: accounting_periods accounting_periods_del_protect; Type: RULE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE RULE accounting_periods_del_protect AS
|
||||
ON DELETE TO public.accounting_periods DO INSTEAD NOTHING;
|
||||
|
||||
|
||||
--
|
||||
-- Name: accounting_periods accounting_periods_upd_protect; Type: RULE; Schema: public; Owner: -
|
||||
--
|
||||
@ -8361,6 +8368,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20140605125131'),
|
||||
('20140605142133'),
|
||||
('20140605151442'),
|
||||
('20140606133116'),
|
||||
('20140609092700'),
|
||||
('20140609092827'),
|
||||
('20140610153123'),
|
||||
@ -8429,12 +8437,14 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20150507075620'),
|
||||
('20150512123546'),
|
||||
('20150520132030'),
|
||||
('20150520133409'),
|
||||
('20150526130729'),
|
||||
('20150527153312'),
|
||||
('20150529113555'),
|
||||
('20150601125944'),
|
||||
('20150603104502'),
|
||||
('20150603104658'),
|
||||
('20150603133050'),
|
||||
('20150604081757'),
|
||||
('20150604131525'),
|
||||
('20150608142234'),
|
||||
@ -8516,6 +8526,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20160905142700'),
|
||||
('20160906094739'),
|
||||
('20160906094847'),
|
||||
('20160906145713'),
|
||||
('20160915105234'),
|
||||
('20161123104604'),
|
||||
('20170109085345'),
|
||||
|
@ -4,6 +4,7 @@ namespace :fablab do
|
||||
desc 'Fill the holes in the logical sequence of invoices references'
|
||||
task fix_references: :environment do |_task, _args|
|
||||
include ActionView::Helpers::NumberHelper
|
||||
include DbHelper
|
||||
|
||||
user = User.adminsys || User.admins.first
|
||||
|
||||
@ -11,37 +12,53 @@ namespace :fablab do
|
||||
missing_references = {}
|
||||
|
||||
# browse invoices to list missing reference
|
||||
puts 'Computing missing references...'
|
||||
not_closed(Invoice).order(created_at: :desc).each do |invoice|
|
||||
number = Invoices::NumberService.number(invoice)
|
||||
next if number == 1
|
||||
|
||||
previous = Invoices::NumberService.change_number(invoice, number - 1)
|
||||
next unless Invoice.find_by(reference: previous).nil?
|
||||
previous = Invoice.where('created_at < :date', date: db_time(invoice.created_at))
|
||||
.order(created_at: :desc)
|
||||
.limit(1)
|
||||
.first
|
||||
previous_number = Invoices::NumberService.number(previous)
|
||||
next if previous_number.nil? || previous_number == number - 1
|
||||
|
||||
missing_references[invoice.created_at] ||= []
|
||||
missing_references[invoice.created_at].push(previous)
|
||||
|
||||
# ignore numbers of already existing invoices
|
||||
(previous_number + 1...number).to_a.each do |num|
|
||||
next unless Invoices::NumberService.find_by_number(num, date: invoice.created_at).nil?
|
||||
|
||||
missing_references[invoice.created_at].push(num)
|
||||
end
|
||||
end
|
||||
|
||||
# create placeholder invoices for found missing references
|
||||
missing_references.each_pair do |date, references|
|
||||
references.reverse_each.with_index do |reference, index|
|
||||
Invoice.create!(
|
||||
puts 'Creating missing invoices...'
|
||||
total = missing_references.values.filter(&:present?).flatten.count
|
||||
counter = 1
|
||||
missing_references.each_pair do |date, numbers|
|
||||
numbers.reverse_each.with_index do |number, index|
|
||||
puts "#{counter} / #{total}"
|
||||
invoice = Invoice.new(
|
||||
total: 0,
|
||||
invoicing_profile: user.invoicing_profile,
|
||||
statistic_profile: user.statistic_profile,
|
||||
operator_profile: user.invoicing_profile,
|
||||
payment_method: '',
|
||||
reference: reference,
|
||||
created_at: date - (index + 1).seconds,
|
||||
description: 'Facture à néant, saut de facturation suite à un dysfonctionnement du logiciel Fab Manager',
|
||||
invoice_items_attributes: [{
|
||||
amount: 0,
|
||||
description: 'facture à zéro',
|
||||
description: I18n.t('invoices.null_invoice'),
|
||||
object_type: 'Error',
|
||||
object_id: 1,
|
||||
main: true
|
||||
}]
|
||||
)
|
||||
invoice.reference = PaymentDocumentService.generate_numbered_reference(number, invoice)
|
||||
invoice.save!
|
||||
counter += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -8,7 +8,9 @@ namespace :fablab do
|
||||
I18n.t('invoices.order_number', locale: 'en', **{ NUMBER: 'REPLACE' }).gsub('REPLACE', ''),
|
||||
I18n.t('invoices.order_number', locale: 'fr', **{ NUMBER: 'REPLACE' }).gsub('REPLACE', '')
|
||||
]
|
||||
max_id = ActiveRecord::Base.connection.execute('SELECT max(id) as max_id FROM invoices').first['max_id']
|
||||
Invoice.order(id: :asc).find_each do |invoice|
|
||||
puts "Processing: #{invoice.id} / #{max_id}"
|
||||
next unless File.exist?(invoice.file)
|
||||
|
||||
found = false
|
||||
@ -21,7 +23,7 @@ namespace :fablab do
|
||||
order_text.each do |label|
|
||||
next unless line.include? label
|
||||
|
||||
number = line.gsub(label, '').strip
|
||||
number = line.gsub(label, '').gsub(/\s{5,}.+$/, '').strip
|
||||
invoice.update(order_number: number)
|
||||
found = true
|
||||
end
|
||||
@ -46,5 +48,12 @@ namespace :fablab do
|
||||
item.invoice&.update(order_number: schedule.order_number)
|
||||
end
|
||||
end
|
||||
Avoir.where(order_number: nil).order(id: :asc).find_each do |refund|
|
||||
next if refund.invoice.nil?
|
||||
|
||||
# refunds are validated against their avoir_date for inclusion in closed periods, so we must bypass the validation
|
||||
# (Invoices are validated on Time.current, so this was not necesseary above)
|
||||
refund.update_attribute('order_number', refund.invoice.order_number) # rubocop:disable Rails/SkipsModelValidations
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -140,4 +140,9 @@ class Invoices::NumberServiceTest < ActiveSupport::TestCase
|
||||
periodicity = Invoices::NumberService.number_periodicity(invoice, 'invoice_order-nb')
|
||||
assert_equal 'month', periodicity
|
||||
end
|
||||
|
||||
test 'find document by number' do
|
||||
invoice = Invoices::NumberService.find_by_number(1, date: Time.zone.parse('2012-03-01'))
|
||||
assert_equal Invoice.first, invoice
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user