1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-19 13:54:25 +01:00

move invoice->operator to invoicing_profile + minor fixes to handle user deletion

This commit is contained in:
Sylvain 2019-06-12 12:22:38 +02:00
parent 86ded2b8d2
commit a53c6e80e7
32 changed files with 116 additions and 67 deletions

View File

@ -11,6 +11,8 @@
- Improved translations syntax according to YML specifications
- Refactored some Ruby code to match style guide
- [TODO DEPLOY] `rake fablab:fix:users_group_ids`
- [TODO DEPLOY] `rake db:migrate`
- [TODO DEPLOY] `rake fablab:setup:migrate_pdf_invoices_folders`
## v3.1.2 2019 May 27

View File

@ -397,8 +397,11 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
* Full reload the results list
*/
$scope.handleFilterChange = function () {
resetSearchInvoice();
return invoiceSearch();
if (searchTimeout) clearTimeout(searchTimeout);
searchTimeout = setTimeout(function() {
resetSearchInvoice();
invoiceSearch();
}, 300);
};
/**
@ -407,7 +410,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
*/
$scope.showNextInvoices = function () {
$scope.page += 1;
return invoiceSearch(true);
invoiceSearch(true);
};
/**
@ -484,6 +487,11 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
});
};
/**
* Will temporize the search query to prevent overloading the API
*/
var searchTimeout = null;
/**
* Output the given integer with leading zeros. If the given value is longer than the given
* length, it will be truncated.
@ -519,7 +527,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
/**
* Run a search query with the current parameters set concerning invoices, then affect or concat the results
* to $scope.invoices
* @param concat {boolean} if true, the result will be append to $scope.invoices instead of being affected
* @param [concat] {boolean} if true, the result will be append to $scope.invoices instead of being affected
*/
var invoiceSearch = function (concat) {
Invoice.list({

View File

@ -6,8 +6,9 @@
{{ 'you_can_validate_the_training_of_the_following_members' | translate }}</p>
<ul class="list-unstyled" ng-if="availability.reservation_users.length > 0">
<li ng-repeat="user in availability.reservation_users">
{{user.full_name}}
<input type="checkbox" ng-checked="user.is_valid" ng-disabled="user.is_valid" ng-click="toggleSelection(user)" />
<label for="{{user.id}}" ng-show="user.id">{{user.full_name}}</label>
<span class="text-gray text-italic" ng-hide="user.id" translate>{{ 'deleted_user' }}</span>
<input type="checkbox" ng-checked="user.is_valid" ng-disabled="user.is_valid || !user.id" ng-click="toggleSelection(user)" id="{{user.id}}" />
</li>
</ul>
<p ng-if="availability.reservation_users.length == 0" translate>{{ 'no_reservation' }}</p>
@ -15,4 +16,4 @@
<div class="modal-footer">
<button class="btn btn-warning" ng-click="ok()" ng-disabled="usersToValid.length == 0" translate>{{ 'validate_the_trainings' }}</button>
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
</div>
</div>

View File

@ -76,7 +76,12 @@
<div class="thumb-lg m-b-xs">
<fab-user-avatar ng-model="project.author.user_avatar" avatar-class="thumb-50"></fab-user-avatar>
</div>
<div><a class="text-sm font-sbold" ui-sref="app.logged.members_show({id: project.author.slug})"><i> {{ 'by_name' | translate:{NAME:project.author.first_name} }}</i></a></div>
<div>
<a ng-show="project.author_id" class="text-sm font-sbold" ui-sref="app.logged.members_show({id: project.author.slug})">
<i> {{ 'by_name' | translate:{NAME:project.author.first_name} }}</i>
</a>
<span ng-hide="project.author_id" class="text-sm font-sbold text-gray" translate>{{ 'deleted_user' }}</span>
</div>
<small class="text-xs m-b"><i>{{ 'posted_on_' | translate }} {{project.created_at | amDateFormat: 'LL'}}</i></small>

View File

@ -26,7 +26,7 @@ class API::ReservationsController < API::ApiController
user_id = current_user.admin? ? params[:reservation][:user_id] : current_user.id
@reservation = Reservation.new(reservation_params)
is_reserve = Reservations::Reserve.new(user_id, current_user.id)
is_reserve = Reservations::Reserve.new(user_id, current_user.invoicing_profile.id)
.pay_and_save(@reservation, method, coupon_params[:coupon_code])
if is_reserve

View File

@ -19,7 +19,7 @@ class API::SubscriptionsController < API::ApiController
user_id = current_user.admin? ? params[:subscription][:user_id] : current_user.id
@subscription = Subscription.new(subscription_params)
is_subscribe = Subscriptions::Subscribe.new(current_user.id, user_id)
is_subscribe = Subscriptions::Subscribe.new(current_user.invoicing_profile.id, user_id)
.pay_and_save(@subscription, method, coupon_params[:coupon_code], true)
if is_subscribe
@ -35,7 +35,7 @@ class API::SubscriptionsController < API::ApiController
free_days = params[:subscription][:free] || false
res = Subscriptions::Subscribe.new(current_user.id)
res = Subscriptions::Subscribe.new(current_user.invoicing_profile.id)
.extend_subscription(@subscription, subscription_update_params[:expired_at], free_days)
if res.is_a?(Subscription)
@subscription = res

View File

@ -22,7 +22,7 @@ class Invoice < ActiveRecord::Base
belongs_to :offer_day, foreign_type: 'OfferDay', foreign_key: 'invoiced_id'
has_one :avoir, class_name: 'Invoice', foreign_key: :invoice_id, dependent: :destroy
belongs_to :operator, foreign_key: :operator_id, class_name: 'User'
belongs_to :operator_profile, foreign_key: :operator_profile_id, class_name: 'InvoicingProfile'
before_create :add_environment
after_create :update_reference, :chain_record

View File

@ -16,6 +16,8 @@ class InvoicingProfile < ActiveRecord::Base
has_many :history_values, dependent: :nullify
has_many :operated_invoices, foreign_key: :operator_profile_id, class_name: 'Invoice', dependent: :nullify
def full_name
# if first_name or last_name is nil, the empty string will be used as a temporary replacement
(first_name || '').humanize.titleize + ' ' + (last_name || '').humanize.titleize

View File

@ -33,7 +33,7 @@ module Project::OpenlabSync
components: components.map(&:name),
themes: themes.map(&:name),
author: author&.profile&.full_name,
collaborators: users.map { |u| u.profile.full_name },
collaborators: users.map { |u| u&.profile&.full_name },
steps_body: steps_body,
image_path: project_image&.attachment&.medium&.url,
project_path: "/#!/projects/#{slug}",

View File

@ -224,10 +224,10 @@ class Reservation < ActiveRecord::Base
invoice_items
end
def save_with_payment(operator_id, coupon_code = nil)
def save_with_payment(operator_profile_id, coupon_code = nil)
begin
clean_pending_strip_invoice_items
build_invoice(invoicing_profile: user.invoicing_profile, statistic_profile: user.statistic_profile, operator_id: operator_id)
build_invoice(invoicing_profile: user.invoicing_profile, statistic_profile: user.statistic_profile, operator_profile_id: operator_profile_id)
invoice_items = generate_invoice_items(false, coupon_code)
rescue StandardError => e
logger.error e
@ -242,7 +242,7 @@ class Reservation < ActiveRecord::Base
if plan_id
self.subscription = Subscription.find_or_initialize_by(statistic_profile_id: statistic_profile_id)
subscription.attributes = { plan_id: plan_id, statistic_profile_id: statistic_profile_id, card_token: card_token, expiration_date: nil }
if subscription.save_with_payment(operator_id, false)
if subscription.save_with_payment(operator_profile_id, false)
self.stp_invoice_id = invoice_items.first.refresh.invoice
invoice.stp_invoice_id = invoice_items.first.refresh.invoice
invoice.invoice_items.push InvoiceItem.new(
@ -368,8 +368,12 @@ class Reservation < ActiveRecord::Base
pending_invoice_items.each(&:delete)
end
def save_with_local_payment(operator_id, coupon_code = nil)
build_invoice(invoicing_profile: user.invoicing_profile, statistic_profile: user.statistic_profile, operator_id: operator_id)
def save_with_local_payment(operator_profile_id, coupon_code = nil)
build_invoice(
invoicing_profile: user.invoicing_profile,
statistic_profile: user.statistic_profile,
operator_profile_id: operator_profile_id
)
generate_invoice_items(true, coupon_code)
return false unless valid?
@ -377,7 +381,7 @@ class Reservation < ActiveRecord::Base
if plan_id
self.subscription = Subscription.find_or_initialize_by(statistic_profile_id: statistic_profile_id)
subscription.attributes = { plan_id: plan_id, statistic_profile_id: statistic_profile_id, expiration_date: nil }
if subscription.save_with_local_payment(operator_id, false)
if subscription.save_with_local_payment(operator_profile_id, false)
invoice.invoice_items.push InvoiceItem.new(
amount: subscription.plan.amount,
description: subscription.plan.name,

View File

@ -20,7 +20,7 @@ class Subscription < ActiveRecord::Base
# Stripe subscription payment
# @param invoice if true then subscription pay itself, dont pay with reservation
# if false then subscription pay with reservation
def save_with_payment(operator_id, invoice = true, coupon_code = nil)
def save_with_payment(operator_profile_id, invoice = true, coupon_code = nil)
return unless valid?
begin
@ -75,7 +75,7 @@ class Subscription < ActiveRecord::Base
# generate invoice
stp_invoice = Stripe::Invoice.all(customer: user.stp_customer_id, limit: 1).data.first
if invoice
db_invoice = generate_invoice(operator_id, stp_invoice.id, coupon_code)
db_invoice = generate_invoice(operator_profile_id, stp_invoice.id, coupon_code)
# debit wallet
wallet_transaction = debit_user_wallet
if wallet_transaction
@ -129,7 +129,7 @@ class Subscription < ActiveRecord::Base
# @param invoice if true then only the subscription is payed, without reservation
# if false then the subscription is payed with reservation
def save_with_local_payment(operator_id, invoice = true, coupon_code = nil)
def save_with_local_payment(operator_profile_id, invoice = true, coupon_code = nil)
return false unless valid?
set_expiration_date
@ -142,7 +142,7 @@ class Subscription < ActiveRecord::Base
# debit wallet
wallet_transaction = debit_user_wallet
invoc = generate_invoice(operator_id, nil, coupon_code)
invoc = generate_invoice(operator_profile_id, nil, coupon_code)
if wallet_transaction
invoc.wallet_amount = @wallet_amount_debit
invoc.wallet_transaction_id = wallet_transaction.id
@ -152,7 +152,7 @@ class Subscription < ActiveRecord::Base
true
end
def generate_invoice(operator_id, stp_invoice_id = nil, coupon_code = nil)
def generate_invoice(operator_profile_id, stp_invoice_id = nil, coupon_code = nil)
coupon_id = nil
total = plan.amount
@ -173,7 +173,7 @@ class Subscription < ActiveRecord::Base
total: total,
stp_invoice_id: stp_invoice_id,
coupon_id: coupon_id,
operator_id: operator_id
operator_profile_id: operator_profile_id
)
invoice.invoice_items.push InvoiceItem.new(
amount: plan.amount,
@ -184,8 +184,8 @@ class Subscription < ActiveRecord::Base
invoice
end
def generate_and_save_invoice(operator_id, stp_invoice_id = nil)
generate_invoice(operator_id, stp_invoice_id).save
def generate_and_save_invoice(operator_profile_id, stp_invoice_id = nil)
generate_invoice(operator_profile_id, stp_invoice_id).save
end
def cancel
@ -222,7 +222,7 @@ class Subscription < ActiveRecord::Base
expiration_date
end
def free_extend(expiration, operator_id)
def free_extend(expiration, operator_profile_id)
return false if expiration <= expired_at
od = offer_days.create(start_at: expired_at, end_at: expiration)
@ -231,7 +231,7 @@ class Subscription < ActiveRecord::Base
invoiced_type: 'OfferDay',
invoicing_profile: user.invoicing_profile,
statistic_profile: user.statistic_profile,
operator_id: operator_id,
operator_profile_id: operator_profile_id,
total: 0
)
invoice.invoice_items.push InvoiceItem.new(amount: 0, description: plan.name, subscription_id: id)

View File

@ -56,6 +56,7 @@ class User < ActiveRecord::Base
after_update :notify_group_changed, if: :group_id_changed?
after_update :update_invoicing_profile, if: :invoicing_data_was_modified?
after_update :update_statistic_profile, if: :statistic_data_was_modified?
before_destroy :remove_orphan_drafts
attr_accessor :cgu
delegate :first_name, to: :profile
@ -127,10 +128,10 @@ class User < ActiveRecord::Base
my_projects.to_a.concat projects
end
def generate_subscription_invoice(operator_id)
def generate_subscription_invoice(operator_profile_id)
return unless subscription
subscription.generate_and_save_invoice(operator_id)
subscription.generate_and_save_invoice(operator_profile_id)
end
def stripe_customer
@ -276,6 +277,15 @@ class User < ActiveRecord::Base
protected
# remove projets drafts that are not linked to another user
def remove_orphan_drafts
orphans = my_projects
.joins('LEFT JOIN project_users ON projects.id = project_users.project_id')
.where('project_users.project_id IS NULL')
.where(state: 'draft')
orphans.map(&:destroy!)
end
def confirmation_required?
false
end

View File

@ -18,7 +18,7 @@ class Availabilities::StatusService
slot.id = s.id
slot.is_reserved = true
slot.title = "#{slot.machine.name} - #{@show_name ? r.user.profile.full_name : I18n.t('availabilities.not_available')}"
slot.title = "#{slot.machine.name} - #{@show_name ? r.user&.profile&.full_name : I18n.t('availabilities.not_available')}"
slot.can_modify = true if @current_user_role == 'admin'
slot.reservations.push r

View File

@ -2,19 +2,19 @@
# Provides helper methods for Reservation actions
class Reservations::Reserve
attr_accessor :user_id, :operator_id
attr_accessor :user_id, :operator_profile_id
def initialize(user_id, operator_id)
def initialize(user_id, operator_profile_id)
@user_id = user_id
@operator_id = operator_id
@operator_profile_id = operator_profile_id
end
def pay_and_save(reservation, payment_method, coupon)
reservation.statistic_profile_id = StatisticProfile.find_by(user_id: user_id).id
if payment_method == :local
reservation.save_with_local_payment(operator_id, coupon)
reservation.save_with_local_payment(operator_profile_id, coupon)
elsif payment_method == :stripe
reservation.save_with_payment(operator_id, coupon)
reservation.save_with_payment(operator_profile_id, coupon)
end
end
end

View File

@ -2,11 +2,11 @@
# Provides helper methods for Subscription actions
class Subscriptions::Subscribe
attr_accessor :user_id, :operator_id
attr_accessor :user_id, :operator_profile_id
def initialize(operator_id, user_id = nil)
def initialize(operator_profile_id, user_id = nil)
@user_id = user_id
@operator_id = operator_id
@operator_profile_id = operator_profile_id
end
def pay_and_save(subscription, payment_method, coupon, invoice)
@ -14,14 +14,14 @@ class Subscriptions::Subscribe
subscription.statistic_profile_id = StatisticProfile.find_by(user_id: user_id).id
if payment_method == :local
subscription.save_with_local_payment(operator_id, invoice, coupon)
subscription.save_with_local_payment(operator_profile_id, invoice, coupon)
elsif payment_method == :stripe
subscription.save_with_payment(operator_id, invoice, coupon)
subscription.save_with_payment(operator_profile_id, invoice, coupon)
end
end
def extend_subscription(subscription, new_expiration_date, free_days)
return subscription.free_extend(new_expiration_date, @operator_id) if free_days
return subscription.free_extend(new_expiration_date, @operator_profile_id) if free_days
new_sub = Subscription.create(
plan_id: subscription.plan_id,
@ -29,7 +29,7 @@ class Subscriptions::Subscribe
expiration_date: new_expiration_date
)
if new_sub.save
new_sub.user.generate_subscription_invoice(operator_id)
new_sub.user.generate_subscription_invoice(operator_profile_id)
return new_sub
end
false

View File

@ -1,5 +1,5 @@
json.title notification.notification_type
json.description t('.a_RESERVABLE_reservation_was_made_by_USER_html',
RESERVABLE: notification.attached_object.reservable.name,
USER: notification.attached_object.user.profile.full_name)
USER: notification.attached_object.user&.profile&.full_name)
json.url notification_url(notification, format: :json)

View File

@ -1,5 +1,5 @@
json.title notification.notification_type
json.description t('.subscription_PLAN_has_been_subscribed_by_USER_html',
PLAN: notification.attached_object.plan.name,
USER: notification.attached_object.user.profile.full_name)
USER: notification.attached_object.user&.profile&.full_name)
json.url notification_url(notification, format: :json)

View File

@ -85,6 +85,7 @@ en:
training_validation: "Training validation"
training_of_the_ : "Training of the " # context: date. eg. "training of the september 1st 2012"
you_can_validate_the_training_of_the_following_members: "You can validate the training of the following members:"
deleted_user: "Deleted user"
no_reservation: "No reservation"
validate_the_trainings: "Validate the trainings"
edition_of_the_description_tooltip: "Edition of the description tooltip"

View File

@ -85,6 +85,7 @@ es:
training_validation: "Validación de la formación"
training_of_the_ : "Training of the " # context: fecha. p.ej. "entrenamiento del 1 de septiembre 2012"
you_can_validate_the_training_of_the_following_members: "Puede validar la formación de los siguientes miembros:"
deleted_user: "Deleted user" # translation_missing
no_reservation: "Sin reserva"
validate_the_trainings: "Validar los entrenamientos"
edition_of_the_description_tooltip: "Edición de la descripción tooltip"

View File

@ -85,6 +85,7 @@ fr:
training_validation: "Validation formation"
training_of_the_ : "Formation du " # context: date. eg. "training of the september 1st 2012"
you_can_validate_the_training_of_the_following_members: "Vous pouvez valider la formation des membres suivants :"
deleted_user: "Utilisateur supprimé"
no_reservation: "Aucune réservation"
validate_the_trainings: "Valider les formations"
edition_of_the_description_tooltip: "Édition de l'infobulle de description"
@ -768,4 +769,4 @@ fr:
confirmation_required: "Confirmez le traitement du signalement"
report_will_be_destroyed: "Une fois le signalement traité, le rapport sera supprimé. Cette action est irréversible, continuer ?"
report_removed: "Le rapport a bien été supprimé"
failed_to_remove: "Une erreur est survenue, impossible de supprimer le rapport"
failed_to_remove: "Une erreur est survenue, impossible de supprimer le rapport"

View File

@ -85,6 +85,7 @@ pt:
training_validation: "Validação de treinamentos"
training_of_the_ : "Treinamento de " # context: date. eg. "training of the september 1st 2012"
you_can_validate_the_training_of_the_following_members: "Você pode validar um treinamento dos seguintes membros:"
deleted_user: "Deleted user" # translation_missing
no_reservation: "Sem reservas"
validate_the_trainings: "Validação de treinamentos"
edition_of_the_description_tooltip: "Edição da descrição tooltip"

View File

@ -171,6 +171,7 @@ en:
# details of a projet
project_description: "Project description"
by_name: "By {{NAME}}" # angular interpolation
deleted_user: "Deleted user"
posted_on_: "Posted on"
CAD_file_to_download: "{COUNT, plural, =0{No CAD files} =1{CAD file to download} other{CAD files to download}}" # messageFormat interpolation
licence: "Licence"

View File

@ -170,6 +170,7 @@ es:
# details of a projet
project_description: "Descripción de proyecto"
by_name: "Por {{NAME}}" # angular interpolation
deleted_user: "Deleted user" #translation_missing
posted_on_: "Subido el"
CAD_file_to_download: "{COUNT, plural, =0{No CAD files} =1{CAD file to download} other{CAD files to download}}" # messageFormat interpolation
licence: "Licencia"

View File

@ -171,6 +171,7 @@ fr:
# détails d'un projet
project_description: "Description du projet"
by_name: "Par {{NAME}}" # angular interpolation
deleted_user: "Utilisateur supprimé"
posted_on_: "posté le"
CAD_file_to_download: "{COUNT, plural, =0{Aucun fichier CAO} =1{Fichier CAO à télécharger} other{Fichiers CAO à télécharger}}" # messageFormat interpolation
licence: "Licence"

View File

@ -171,6 +171,7 @@ pt:
# details of a projet
project_description: "Descrição do projeto"
by_name: "Por {{NAME}}" # angular interpolation
deleted_user: "Deleted user" #translation_missing
posted_on_: "Criado em"
CAD_file_to_download: "{COUNT, plural, =0{No CAD files} =1{CAD file to download} other{CAD files to download}}" # messageFormat interpolation
licence: "Licença"

View File

@ -3,9 +3,7 @@ class AddUsernameToUser < ActiveRecord::Migration
add_column :users, :username, :string, after: :id
User.includes(:profile).each do |u|
if u.respond_to? :username and !u.username?
u.update_columns(username: u.profile.username)
end
u.update_columns(username: u.profile.username) if u.respond_to?(:username) && !u.username?
end
end

View File

@ -14,5 +14,8 @@ class CreateInvoicingProfiles < ActiveRecord::Migration
add_reference :wallets, :invoicing_profile, index: true, foreign_key: true
add_reference :wallet_transactions, :invoicing_profile, index: true, foreign_key: true
add_reference :history_values, :invoicing_profile, index: true, foreign_key: true
add_column :invoices, :operator_profile_id, :integer
add_foreign_key :invoices, :invoicing_profiles, column: :operator_profile_id, primary_key: :id
end
end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
# migrate the invoices from being attached to a user to invoicing_profiles which are GDPR compliant
class MigrateUserToInvoicingProfile < ActiveRecord::Migration
class MigrateInvoiceToInvoicingProfile < ActiveRecord::Migration
def up
# first, check the footprints
check_footprints
@ -13,9 +13,12 @@ class MigrateUserToInvoicingProfile < ActiveRecord::Migration
puts 'Migrating invoices. This may take a while...'
Invoice.order(:id).all.each do |i|
user = User.find(i.user_id)
operator = User.find_by(id: i.operator_id)
i.update_column('invoicing_profile_id', user.invoicing_profile.id)
i.update_column('statistic_profile_id', user.statistic_profile.id)
i.update_column('operator_profile_id', operator&.invoicing_profile&.id)
i.update_column('user_id', nil)
i.update_column('operator_id', nil)
end
# chain all records
InvoiceItem.order(:id).all.each(&:chain_record)
@ -32,8 +35,10 @@ class MigrateUserToInvoicingProfile < ActiveRecord::Migration
# reset invoices
Invoice.order(:created_at).all.each do |i|
i.update_column('user_id', i.invoicing_profile.user_id)
i.update_column('operator_id', i.operator_profile.user_id)
i.update_column('invoicing_profile_id', nil)
i.update_column('statistic_profile_id', nil)
i.update_column('operator_profile_id', nil)
end
# chain all records
InvoiceItem.order(:id).all.each(&:chain_record)

View File

@ -5,5 +5,6 @@ class RemoveUserIdColumns < ActiveRecord::Migration
remove_reference :wallets, :user, index: true, foreign_key: true
remove_reference :wallet_transactions, :user, index: true, foreign_key: true
remove_reference :history_values, :user, index: true, foreign_key: true
remove_reference :invoices, :operator, index: true, foreign_key: true
end
end

View File

@ -278,8 +278,8 @@ ActiveRecord::Schema.define(version: 20190606074801) do
t.integer "coupon_id"
t.string "footprint"
t.string "environment"
t.integer "operator_id"
t.integer "invoicing_profile_id"
t.integer "operator_profile_id"
t.integer "statistic_profile_id"
end
@ -910,8 +910,8 @@ ActiveRecord::Schema.define(version: 20190606074801) do
add_foreign_key "history_values", "settings"
add_foreign_key "invoices", "coupons"
add_foreign_key "invoices", "invoicing_profiles"
add_foreign_key "invoices", "invoicing_profiles", column: "operator_profile_id"
add_foreign_key "invoices", "statistic_profiles"
add_foreign_key "invoices", "users", column: "operator_id"
add_foreign_key "invoices", "wallet_transactions"
add_foreign_key "invoicing_profiles", "users"
add_foreign_key "o_auth2_mappings", "o_auth2_providers"

View File

@ -80,8 +80,8 @@ namespace :fablab do
end
end
desc 'migrate invoices PDF to folders by invoicing_profile'
task migrate_invoices_pdf_folders: :environment do
desc 'migrate PDF invoices to folders numbered by invoicing_profile'
task migrate_pdf_invoices_folders: :environment do
require 'fileutils'
Invoice.all.each do |i|
invoicing_profile = i.invoicing_profile
@ -90,8 +90,10 @@ namespace :fablab do
src = "invoices/#{user_id}/#{i.filename}"
dest = "tmp/invoices/#{invoicing_profile.id}"
FileUtils.mkdir_p dest
FileUtils.mv src, "dest/#{i.filename}", force: true if FileTest.exist?(src)
if FileTest.exist?(src)
FileUtils.mkdir_p dest
FileUtils.mv src, "#{dest}/#{i.filename}", force: true
end
end
FileUtils.rm_rf 'invoices'
FileUtils.mv 'tmp/invoices', 'invoices'

View File

@ -16,9 +16,9 @@ invoice_1:
type:
subscription_to_expire:
description:
footprint: e7fffd325cacbb76218626ea2a35a7a9f052c208c41aac13f70c31eae9f81bc7
footprint: d5fc7141c282279134320a4b1db74c540a82f105a0b1f4eeff6602730ed3e745
environment: test
operator_id:
operator_profile_id: 3
invoice_2:
id: 2
@ -37,9 +37,9 @@ invoice_2:
type:
subscription_to_expire:
description:
footprint: bd0b739c211b40abed7ddb07bc054281513acab4a0adde6c416dc1715dd9f005
footprint: 1c156831c7cd1fcc1c6be8b83d60fbb9b89f84285638e87131582eb54b8a377d
environment: test
operator_id:
operator_profile_id: 1
invoice_3:
id: 3
@ -58,9 +58,9 @@ invoice_3:
type:
subscription_to_expire:
description:
footprint: ab00a9318314b75d29ec220e00c96e738d608d64423b1c5abb25786551f12f8b
footprint: 5fa3ac2e2684f6df1440c63969b78ac24daa9207682b359f61c655d41d4c4f03
environment: test
operator_id:
operator_profile_id: 1
invoice_4:
@ -80,9 +80,9 @@ invoice_4:
type:
subscription_to_expire:
description:
footprint: 6c70f2bbbb3fd02a1ad7437ccd14456d1281d5a1f8666cce2e9d0b64701a837d
footprint: 6de8d985d82f2146aaa60e79882237b3bc8812521643b14498e4d498aec78613
environment: test
operator_id:
operator_profile_id: 1
invoice_5:
id: 5
@ -101,6 +101,6 @@ invoice_5:
type:
subscription_to_expire:
description:
footprint: cccd4f290d900cb7004baa63896191a6938305e75589d137655cb91a0e7dede2
footprint: a78aa3f991718f023f1c6b85b6f30aeda3f3d6b20f2d64504d29a23141db9edb
environment: test
operator_id:
operator_profile_id: 1