mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-06 01:08:21 +01:00
ability to set invoices as erroneous
This commit is contained in:
parent
5fca8370ff
commit
ecf80b0591
@ -7,6 +7,7 @@
|
|||||||
- 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`
|
- [TODO DEPLOY] `rails fablab:fix_invoices`
|
||||||
|
- [TODO DEPLOY] `rails fablab:maintenance:regenerate_invoices[year,month]` Depending on the status of the above command, you'll need to run that one for the months with erroneous invoices
|
||||||
|
|
||||||
## v4.7.9 2021 May 17
|
## v4.7.9 2021 May 17
|
||||||
|
|
||||||
|
@ -177,6 +177,14 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
spaceLabel: {
|
spaceLabel: {
|
||||||
name: 'accounting_Space_label',
|
name: 'accounting_Space_label',
|
||||||
value: settings.accounting_Space_label
|
value: settings.accounting_Space_label
|
||||||
|
},
|
||||||
|
errorCode: {
|
||||||
|
name: 'accounting_Error_code',
|
||||||
|
value: settings.accounting_Error_code
|
||||||
|
},
|
||||||
|
errorLabel: {
|
||||||
|
name: 'accounting_Error_label',
|
||||||
|
value: settings.accounting_Error_label
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -861,6 +861,7 @@ angular.module('application.router', ['ui.router'])
|
|||||||
"'accounting_VAT_code', 'accounting_VAT_label', 'accounting_subscription_code', 'accounting_subscription_label', " +
|
"'accounting_VAT_code', 'accounting_VAT_label', 'accounting_subscription_code', 'accounting_subscription_label', " +
|
||||||
"'accounting_Machine_code', 'accounting_Machine_label', 'accounting_Training_code', 'accounting_Training_label', " +
|
"'accounting_Machine_code', 'accounting_Machine_label', 'accounting_Training_code', 'accounting_Training_label', " +
|
||||||
"'accounting_Event_code', 'accounting_Event_label', 'accounting_Space_code', 'accounting_Space_label', " +
|
"'accounting_Event_code', 'accounting_Event_label', 'accounting_Space_code', 'accounting_Space_label', " +
|
||||||
|
"'accounting_Error_code', 'accounting_Error_label', " +
|
||||||
"'feature_tour_display', 'online_payment_module', 'stripe_public_key', 'stripe_currency', 'invoice_prefix']"
|
"'feature_tour_display', 'online_payment_module', 'stripe_public_key', 'stripe_currency', 'invoice_prefix']"
|
||||||
}).$promise;
|
}).$promise;
|
||||||
}],
|
}],
|
||||||
|
@ -106,6 +106,16 @@
|
|||||||
<input type="text" id="spaceLabel" ng-model="settings.spaceLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_space_label' | translate }}"/>
|
<input type="text" id="spaceLabel" ng-model="settings.spaceLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_space_label' | translate }}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="spaceCode" translate>{{ 'app.admin.invoices.accounting_Error_code' }}</label>
|
||||||
|
<input type="text" id="errorCode" ng-model="settings.errorCode.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_error_code' | translate }}" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="spaceLabel" translate>{{ 'app.admin.invoices.accounting_Error_label' }}</label>
|
||||||
|
<input type="text" id="errorLabel" ng-model="settings.errorLabel.value" class="form-control" placeholder="{{ 'app.admin.invoices.general_error_label' | translate }}"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<button name="button" class="btn btn-warning m-t-lg" ng-click="save()" translate>{{ 'app.shared.buttons.save' }}</button>
|
<button name="button" class="btn btn-warning m-t-lg" ng-click="save()" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -109,7 +109,9 @@ class Setting < ApplicationRecord
|
|||||||
upcoming_events_shown
|
upcoming_events_shown
|
||||||
payment_schedule_prefix
|
payment_schedule_prefix
|
||||||
trainings_module
|
trainings_module
|
||||||
address_required] }
|
address_required
|
||||||
|
accounting_Error_code
|
||||||
|
accounting_Error_label] }
|
||||||
# WARNING: when adding a new key, you may also want to add it in app/policies/setting_policy.rb#public_whitelist
|
# WARNING: when adding a new key, you may also want to add it in app/policies/setting_policy.rb#public_whitelist
|
||||||
|
|
||||||
def value
|
def value
|
||||||
|
@ -108,6 +108,8 @@ class PDF::Invoice < Prawn::Document
|
|||||||
object = subscription_verbose(invoice.invoiced, name)
|
object = subscription_verbose(invoice.invoiced, name)
|
||||||
when 'OfferDay'
|
when 'OfferDay'
|
||||||
object = offer_day_verbose(invoice.invoiced, name)
|
object = offer_day_verbose(invoice.invoiced, name)
|
||||||
|
when 'Error'
|
||||||
|
object = I18n.t('invoices.error_invoice')
|
||||||
else
|
else
|
||||||
puts "ERROR : specified invoiced type (#{invoice.invoiced_type}) is unknown"
|
puts "ERROR : specified invoiced type (#{invoice.invoiced_type}) is unknown"
|
||||||
end
|
end
|
||||||
@ -174,13 +176,8 @@ class PDF::Invoice < Prawn::Document
|
|||||||
count: t.booked,
|
count: t.booked,
|
||||||
NAME: t.event_price_category.price_category.name)
|
NAME: t.event_price_category.price_category.name)
|
||||||
end
|
end
|
||||||
### wallet credit
|
|
||||||
when nil
|
|
||||||
details = item.description
|
|
||||||
|
|
||||||
### Other cases (not expected)
|
|
||||||
else
|
else
|
||||||
details += I18n.t('invoices.reservation_other')
|
details += item.description
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -70,6 +70,11 @@ class AccountingExportService
|
|||||||
end
|
end
|
||||||
elsif invoice.invoiced_type == 'WalletTransaction'
|
elsif invoice.invoiced_type == 'WalletTransaction'
|
||||||
rows << "#{wallet_row(invoice)}\n"
|
rows << "#{wallet_row(invoice)}\n"
|
||||||
|
elsif invoice.invoiced_type == 'Error'
|
||||||
|
items = invoice.invoice_items.select { |ii| ii.subscription.nil? }
|
||||||
|
items.each do |item|
|
||||||
|
rows << "#{error_row(invoice, item)}\n"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
rows
|
rows
|
||||||
end
|
end
|
||||||
@ -142,6 +147,16 @@ class AccountingExportService
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def error_row(invoice, item)
|
||||||
|
row(
|
||||||
|
invoice,
|
||||||
|
account(invoice, :error),
|
||||||
|
account(invoice, :error, type: :label),
|
||||||
|
item.net_amount / 100.00,
|
||||||
|
line_label: label(invoice)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
# Generate a row of the export, filling the configured columns with the provided values
|
# Generate a row of the export, filling the configured columns with the provided values
|
||||||
def row(invoice, account_code, account_label, amount, line_label: '', debit_method: :debit, credit_method: :credit)
|
def row(invoice, account_code, account_label, amount, line_label: '', debit_method: :debit, credit_method: :credit)
|
||||||
row = ''
|
row = ''
|
||||||
@ -202,6 +217,8 @@ class AccountingExportService
|
|||||||
else
|
else
|
||||||
puts "WARN: Invoice #{invoice.id} is not a wallet credit"
|
puts "WARN: Invoice #{invoice.id} is not a wallet credit"
|
||||||
end
|
end
|
||||||
|
when :error
|
||||||
|
Setting.find_by(name: "accounting_Error_#{type}")&.value
|
||||||
else
|
else
|
||||||
puts "Unsupported account #{account}"
|
puts "Unsupported account #{account}"
|
||||||
end || ''
|
end || ''
|
||||||
|
@ -598,6 +598,10 @@ en:
|
|||||||
general_space_code: "Accounting code for all spaces"
|
general_space_code: "Accounting code for all spaces"
|
||||||
accounting_Space_label: "Spaces label"
|
accounting_Space_label: "Spaces label"
|
||||||
general_space_label: "Account label for all spaces"
|
general_space_label: "Account label for all spaces"
|
||||||
|
accounting_Error_code: "Errors code"
|
||||||
|
general_error_code: "Accounting code for erroneous invoices"
|
||||||
|
accounting_Error_label: "Errors label"
|
||||||
|
general_error_label: "Account label for erroneous invoices"
|
||||||
codes_customization_success: "Customization of the accounting codes successfully saved."
|
codes_customization_success: "Customization of the accounting codes successfully saved."
|
||||||
unexpected_error_occurred: "An unexpected error occurred while saving the codes. Please try again later."
|
unexpected_error_occurred: "An unexpected error occurred while saving the codes. Please try again later."
|
||||||
export_accounting_data: "Export accounting data"
|
export_accounting_data: "Export accounting data"
|
||||||
|
@ -598,6 +598,10 @@ fr:
|
|||||||
general_space_code: "Code comptable pour tous les espaces"
|
general_space_code: "Code comptable pour tous les espaces"
|
||||||
accounting_Space_label: "Libellé espaces"
|
accounting_Space_label: "Libellé espaces"
|
||||||
general_space_label: "Libellé du compte pour tous les espaces"
|
general_space_label: "Libellé du compte pour tous les espaces"
|
||||||
|
accounting_Error_code: "Code erreurs"
|
||||||
|
general_error_code: "Code comptable pour les factures en erreur"
|
||||||
|
accounting_Error_label: "Libellé erreurs"
|
||||||
|
general_error_label: "Libellé du compte pour les factures en erreur"
|
||||||
codes_customization_success: "La personnalisation des codes comptables a bien été enregistrée."
|
codes_customization_success: "La personnalisation des codes comptables a bien été enregistrée."
|
||||||
unexpected_error_occurred: "Une erreur inattendue est survenue lors de l’enregistrement des codes. Veuillez réessayer plus tard."
|
unexpected_error_occurred: "Une erreur inattendue est survenue lors de l’enregistrement des codes. Veuillez réessayer plus tard."
|
||||||
export_accounting_data: "Exporter les données comptables"
|
export_accounting_data: "Exporter les données comptables"
|
||||||
|
@ -88,7 +88,6 @@ en:
|
|||||||
other_rate_ticket:
|
other_rate_ticket:
|
||||||
one: "One %{NAME} ticket"
|
one: "One %{NAME} ticket"
|
||||||
other: "%{count} %{NAME} tickets"
|
other: "%{count} %{NAME} tickets"
|
||||||
reservation_other: "Reservation (other)"
|
|
||||||
coupon_CODE_discount_of_DISCOUNT: "Coupon {CODE}: discount of {DISCOUNT}{TYPE, select, percent_off{%} other{}}" #messageFormat interpolation
|
coupon_CODE_discount_of_DISCOUNT: "Coupon {CODE}: discount of {DISCOUNT}{TYPE, select, percent_off{%} other{}}" #messageFormat interpolation
|
||||||
total_including_all_taxes: "Total incl. all taxes"
|
total_including_all_taxes: "Total incl. all taxes"
|
||||||
including_VAT_RATE: "Including VAT %{RATE}%"
|
including_VAT_RATE: "Including VAT %{RATE}%"
|
||||||
@ -113,6 +112,7 @@ en:
|
|||||||
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Subscription of %{NAME} extended (Free days) starting from %{STARTDATE} until %{ENDDATE}"
|
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Subscription of %{NAME} extended (Free days) starting from %{STARTDATE} until %{ENDDATE}"
|
||||||
and: 'and'
|
and: 'and'
|
||||||
invoice_text_example: "Our association is not subject to VAT"
|
invoice_text_example: "Our association is not subject to VAT"
|
||||||
|
error_invoice: "Erroneous invoice. The items below ware not booked. Please contact the FabLab for a refund."
|
||||||
#PDF payment schedule generation
|
#PDF payment schedule generation
|
||||||
payment_schedules:
|
payment_schedules:
|
||||||
schedule_reference: "Payment schedule reference: %{REF}"
|
schedule_reference: "Payment schedule reference: %{REF}"
|
||||||
|
@ -88,7 +88,6 @@ fr:
|
|||||||
other_rate_ticket:
|
other_rate_ticket:
|
||||||
one: "Une place %{NAME}"
|
one: "Une place %{NAME}"
|
||||||
other: "%{count} places %{NAME}"
|
other: "%{count} places %{NAME}"
|
||||||
reservation_other: "Réservation (autre)"
|
|
||||||
coupon_CODE_discount_of_DISCOUNT: "Code {CODE} : remise de {DISCOUNT} {TYPE, select, percent_off{%} other{}}" #messageFormat interpolation
|
coupon_CODE_discount_of_DISCOUNT: "Code {CODE} : remise de {DISCOUNT} {TYPE, select, percent_off{%} other{}}" #messageFormat interpolation
|
||||||
total_including_all_taxes: "Total TTC"
|
total_including_all_taxes: "Total TTC"
|
||||||
including_VAT_RATE: "Dont TVA %{RATE}%"
|
including_VAT_RATE: "Dont TVA %{RATE}%"
|
||||||
@ -113,6 +112,7 @@ fr:
|
|||||||
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Prolongement Abonnement (Jours gratuits) de %{NAME} à compter du %{STARTDATE} jusqu'au %{ENDDATE}"
|
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Prolongement Abonnement (Jours gratuits) de %{NAME} à compter du %{STARTDATE} jusqu'au %{ENDDATE}"
|
||||||
and: 'et'
|
and: 'et'
|
||||||
invoice_text_example: "Notre association n'est pas assujettie à la TVA"
|
invoice_text_example: "Notre association n'est pas assujettie à la TVA"
|
||||||
|
error_invoice: "Facture en erreur. Les éléments ci-dessous n'ont pas été réservés. Veuillez contacter le Fablab pour un remboursement."
|
||||||
#PDF payment schedule generation
|
#PDF payment schedule generation
|
||||||
payment_schedules:
|
payment_schedules:
|
||||||
schedule_reference: "Référence de l'échéancier : %{REF}"
|
schedule_reference: "Référence de l'échéancier : %{REF}"
|
||||||
|
@ -8,7 +8,7 @@ require 'integrity/archive_helper'
|
|||||||
namespace :fablab do
|
namespace :fablab do
|
||||||
desc 'Remove the invoices w/o reservation or regenerate the reservation'
|
desc 'Remove the invoices w/o reservation or regenerate the reservation'
|
||||||
task fix_invoices: :environment do |_task, _args|
|
task fix_invoices: :environment do |_task, _args|
|
||||||
return unless Invoice.where(invoiced_id: nil).count.positive?
|
next unless Invoice.where(invoiced_id: nil).count.positive?
|
||||||
|
|
||||||
include ActionView::Helpers::NumberHelper
|
include ActionView::Helpers::NumberHelper
|
||||||
|
|
||||||
@ -19,17 +19,6 @@ namespace :fablab do
|
|||||||
|
|
||||||
# fix invoices data
|
# fix invoices data
|
||||||
Invoice.where(invoiced_id: nil).each do |invoice|
|
Invoice.where(invoiced_id: nil).each do |invoice|
|
||||||
if invoice.total.zero?
|
|
||||||
puts "Invoice #{invoice.id} has total = 0, destroying..."
|
|
||||||
invoice.destroy
|
|
||||||
next
|
|
||||||
end
|
|
||||||
if invoice.invoiced_type != 'Reservation'
|
|
||||||
STDERR.puts "WARNING: Invoice #{invoice.id} is about #{invoice.invoiced_type}. Please handle manually."
|
|
||||||
STDERR.puts 'Ignoring...'
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
ii = invoice.invoice_items.where(subscription_id: nil).first
|
ii = invoice.invoice_items.where(subscription_id: nil).first
|
||||||
puts '=============================================='
|
puts '=============================================='
|
||||||
puts "Invoice #{invoice.id} (# #{invoice.reference})"
|
puts "Invoice #{invoice.id} (# #{invoice.reference})"
|
||||||
@ -39,12 +28,18 @@ namespace :fablab do
|
|||||||
puts "Operator: #{invoice.operator_profile&.user&.profile&.full_name} (#{invoice.operator_profile&.user&.email})"
|
puts "Operator: #{invoice.operator_profile&.user&.profile&.full_name} (#{invoice.operator_profile&.user&.email})"
|
||||||
puts "Date: #{invoice.created_at}"
|
puts "Date: #{invoice.created_at}"
|
||||||
|
|
||||||
print 'Delete [d] OR create the missing reservation [c]? > '
|
print 'Delete [d], create the missing reservation [c] OR keep as error[e] ? > '
|
||||||
confirm = STDIN.gets.chomp
|
confirm = STDIN.gets.chomp
|
||||||
if confirm == 'd'
|
if confirm == 'd'
|
||||||
puts "Destroying #{invoice.id}..."
|
puts "Destroying #{invoice.id}..."
|
||||||
invoice.destroy
|
invoice.destroy
|
||||||
elsif confirm == 'c'
|
elsif confirm == 'c'
|
||||||
|
if invoice.invoiced_type != 'Reservation'
|
||||||
|
STDERR.puts "WARNING: Invoice #{invoice.id} is about #{invoice.invoiced_type}. Please handle manually."
|
||||||
|
STDERR.puts 'Ignoring...'
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
reservable = find_reservable(ii)
|
reservable = find_reservable(ii)
|
||||||
if reservable
|
if reservable
|
||||||
if reservable.is_a? Event
|
if reservable.is_a? Event
|
||||||
@ -63,6 +58,8 @@ namespace :fablab do
|
|||||||
STDERR.puts "WARNING: Unable to guess the reservable for invoice #{invoice.id}, please handle manually."
|
STDERR.puts "WARNING: Unable to guess the reservable for invoice #{invoice.id}, please handle manually."
|
||||||
STDERR.puts 'Ignoring...'
|
STDERR.puts 'Ignoring...'
|
||||||
end
|
end
|
||||||
|
elsif confirm == 'e'
|
||||||
|
invoice.update_attributes(invoiced_type: 'Error')
|
||||||
else
|
else
|
||||||
puts "Operation #{confirm} unknown. Ignoring invoice #{invoice.id}..."
|
puts "Operation #{confirm} unknown. Ignoring invoice #{invoice.id}..."
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user