mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-19 13:54:25 +01:00
[ongoing] fixes for invoices pdf files
This commit is contained in:
parent
02a4660a76
commit
86ded2b8d2
@ -72,8 +72,8 @@ Application.Controllers.controller('MembersController', ['$scope', 'Member', 'me
|
||||
/**
|
||||
* Controller used when editing the current user's profile
|
||||
*/
|
||||
Application.Controllers.controller('EditProfileController', ['$scope', '$rootScope', '$state', '$window', 'Member', 'Auth', 'Session', 'activeProviderPromise', 'growl', 'dialogs', 'CSRF', 'memberPromise', 'groups', '_t',
|
||||
function ($scope, $rootScope, $state, $window, Member, Auth, Session, activeProviderPromise, growl, dialogs, CSRF, memberPromise, groups, _t) {
|
||||
Application.Controllers.controller('EditProfileController', ['$scope', '$rootScope', '$state', '$window', '$sce', 'Member', 'Auth', 'Session', 'activeProviderPromise', 'growl', 'dialogs', 'CSRF', 'memberPromise', 'groups', '_t',
|
||||
function ($scope, $rootScope, $state, $window, $sce, Member, Auth, Session, activeProviderPromise, growl, dialogs, CSRF, memberPromise, groups, _t) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// API URL where the form will be posted
|
||||
@ -194,7 +194,13 @@ Application.Controllers.controller('EditProfileController', ['$scope', '$rootSco
|
||||
object () {
|
||||
return {
|
||||
title: _t('confirmation_required'),
|
||||
msg: _t('do_you_really_want_to_delete_your_account') + ' ' + _t('all_data_relative_to_your_projects_will_be_lost')
|
||||
msg: $sce.trustAsHtml(
|
||||
_t('confirm_delete_your_account') + '<br/>' +
|
||||
'<strong>' + _t('all_data_will_be_lost') + '</strong><br/><br/>' +
|
||||
_t('invoicing_data_kept') + '<br/>' +
|
||||
_t('statistic_data_anonymized') + '<br/>' +
|
||||
_t('no_further_access_to_projects')
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,9 @@
|
||||
<td ng-if="!invoice.is_avoir">{{ invoice.date | amDateFormat:'L LTS' }}</td>
|
||||
<td ng-if="invoice.is_avoir">{{ invoice.date | amDateFormat:'L' }}</td>
|
||||
<td>{{ invoice.total | currency}}</td>
|
||||
<td><a href="" ui-sref="app.admin.members_edit({id: invoice.user_id})">{{ invoice.name }} </a>
|
||||
<td>
|
||||
<a href="" ui-sref="app.admin.members_edit({id: invoice.user_id})" ng-show="invoice.user_id">{{ invoice.name }}</a>
|
||||
<span ng-hide="invoice.user_id">{{ invoice.name }}</span>
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<a class="btn btn-default" ng-href="api/invoices/{{invoice.id}}/download" target="_blank" ng-if="!invoice.is_avoir">
|
||||
|
@ -78,7 +78,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="widget-content no-bg text-center auto wrapper">
|
||||
<button class="btn text-white btn-danger btn-sm" ng-click="deleteUser(user)"><i class="fa fa-warning"></i> {{ 'delete_my_account' | translate }}</button>
|
||||
<button class="btn text-white btn-danger btn-sm" ng-click="deleteUser(user)"><i class="fa fa-warning m-r-xs"></i> {{ 'delete_my_account' | translate }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -65,7 +65,7 @@ class API::MembersController < API::ApiController
|
||||
|
||||
def destroy
|
||||
authorize @member
|
||||
@member.soft_destroy
|
||||
@member.destroy
|
||||
sign_out(@member)
|
||||
head :no_content
|
||||
end
|
||||
|
@ -31,9 +31,9 @@ class Invoice < ActiveRecord::Base
|
||||
validates_with ClosedPeriodValidator
|
||||
|
||||
def file
|
||||
dir = "invoices/#{user.id}"
|
||||
dir = "invoices/#{invoicing_profile.id}"
|
||||
|
||||
# create directories if they doesn't exists (invoice & user_id)
|
||||
# create directories if they doesn't exists (invoice & invoicing_profile_id)
|
||||
FileUtils.mkdir_p dir
|
||||
"#{dir}/#{filename}"
|
||||
end
|
||||
@ -142,7 +142,7 @@ class Invoice < ActiveRecord::Base
|
||||
|
||||
# for debug & used by rake task "fablab:maintenance:regenerate_invoices"
|
||||
def regenerate_invoice_pdf
|
||||
pdf = ::PDF::Invoice.new(self, nil).render
|
||||
pdf = ::PDF::Invoice.new(self, subscription&.expiration_date).render
|
||||
File.binwrite(file, pdf)
|
||||
end
|
||||
|
||||
@ -211,9 +211,12 @@ class Invoice < ActiveRecord::Base
|
||||
##
|
||||
# Check if the current invoice is about a training that was previously validated for the concerned user.
|
||||
# In that case refunding the invoice shouldn't be allowed.
|
||||
# Moreover, an invoice cannot be refunded if the users' account was deleted
|
||||
# @return {Boolean}
|
||||
##
|
||||
def prevent_refund?
|
||||
return true if user.nil?
|
||||
|
||||
if invoiced_type == 'Reservation' && invoiced.reservable_type == 'Training'
|
||||
user.trainings.include?(invoiced.reservable_id)
|
||||
else
|
||||
|
@ -227,7 +227,7 @@ class Reservation < ActiveRecord::Base
|
||||
def save_with_payment(operator_id, coupon_code = nil)
|
||||
begin
|
||||
clean_pending_strip_invoice_items
|
||||
build_invoice(invoicing_profile: user.invoicing_profile, operator_id: operator_id)
|
||||
build_invoice(invoicing_profile: user.invoicing_profile, statistic_profile: user.statistic_profile, operator_id: operator_id)
|
||||
invoice_items = generate_invoice_items(false, coupon_code)
|
||||
rescue StandardError => e
|
||||
logger.error e
|
||||
@ -369,7 +369,7 @@ class Reservation < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def save_with_local_payment(operator_id, coupon_code = nil)
|
||||
build_invoice(invoicing_profile: user.invoicing_profile, operator_id: operator_id)
|
||||
build_invoice(invoicing_profile: user.invoicing_profile, statistic_profile: user.statistic_profile, operator_id: operator_id)
|
||||
generate_invoice_items(true, coupon_code)
|
||||
|
||||
return false unless valid?
|
||||
|
@ -165,8 +165,22 @@ class Subscription < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
invoice = Invoice.new(invoiced_id: id, invoiced_type: 'Subscription', invoicing_profile: user.invoicing_profile, total: total, stp_invoice_id: stp_invoice_id, coupon_id: coupon_id, operator_id: operator_id)
|
||||
invoice.invoice_items.push InvoiceItem.new(amount: plan.amount, stp_invoice_item_id: stp_subscription_id, description: plan.name, subscription_id: self.id)
|
||||
invoice = Invoice.new(
|
||||
invoiced_id: id,
|
||||
invoiced_type: 'Subscription',
|
||||
invoicing_profile: user.invoicing_profile,
|
||||
statistic_profile: user.statistic_profile,
|
||||
total: total,
|
||||
stp_invoice_id: stp_invoice_id,
|
||||
coupon_id: coupon_id,
|
||||
operator_id: operator_id
|
||||
)
|
||||
invoice.invoice_items.push InvoiceItem.new(
|
||||
amount: plan.amount,
|
||||
stp_invoice_item_id: stp_subscription_id,
|
||||
description: plan.name,
|
||||
subscription_id: id
|
||||
)
|
||||
invoice
|
||||
end
|
||||
|
||||
@ -208,11 +222,18 @@ class Subscription < ActiveRecord::Base
|
||||
expiration_date
|
||||
end
|
||||
|
||||
def free_extend(expiration)
|
||||
def free_extend(expiration, operator_id)
|
||||
return false if expiration <= expired_at
|
||||
|
||||
od = offer_days.create(start_at: expired_at, end_at: expiration)
|
||||
invoice = Invoice.new(invoiced_id: od.id, invoiced_type: 'OfferDay', invoicing_profile: user.invoicing_profile, total: 0)
|
||||
invoice = Invoice.new(
|
||||
invoiced_id: od.id,
|
||||
invoiced_type: 'OfferDay',
|
||||
invoicing_profile: user.invoicing_profile,
|
||||
statistic_profile: user.statistic_profile,
|
||||
operator_id: operator_id,
|
||||
total: 0
|
||||
)
|
||||
invoice.invoice_items.push InvoiceItem.new(amount: 0, description: plan.name, subscription_id: id)
|
||||
invoice.save
|
||||
|
||||
|
@ -38,8 +38,6 @@ class User < ActiveRecord::Base
|
||||
has_many :training_credits, through: :users_credits, source: :training_credit
|
||||
has_many :machine_credits, through: :users_credits, source: :machine_credit
|
||||
|
||||
has_many :operated_invoices, foreign_key: :operator_id, class_name: 'Invoice', dependent: :nullify
|
||||
|
||||
has_many :user_tags, dependent: :destroy
|
||||
has_many :tags, through: :user_tags
|
||||
accepts_nested_attributes_for :tags, allow_destroy: true
|
||||
@ -139,16 +137,6 @@ class User < ActiveRecord::Base
|
||||
Stripe::Customer.retrieve stp_customer_id
|
||||
end
|
||||
|
||||
def soft_destroy
|
||||
update_attribute(:is_active, false)
|
||||
uninvolve_from_projects
|
||||
end
|
||||
|
||||
def uninvolve_from_projects
|
||||
my_projects.destroy_all
|
||||
project_users.destroy_all
|
||||
end
|
||||
|
||||
def active_for_authentication?
|
||||
super && is_active?
|
||||
end
|
||||
|
@ -131,14 +131,16 @@ class PDF::Invoice < Prawn::Document
|
||||
else
|
||||
subscription_end_at = if subscription_expiration_date.is_a?(Time)
|
||||
subscription_expiration_date
|
||||
else
|
||||
elsif subscription_expiration_date.is_a?(String)
|
||||
DateTime.parse(subscription_expiration_date)
|
||||
else
|
||||
subscription.expiration_date
|
||||
end
|
||||
subscription_start_at = subscription_end_at - subscription.plan.duration
|
||||
details += I18n.t('invoices.subscription_NAME_from_START_to_END',
|
||||
NAME: item.description,
|
||||
START: I18n.l(subscription_start_at.to_date),
|
||||
END: I18n.l(subscription_expiration_date.to_date))
|
||||
END: I18n.l(subscription_end_at.to_date))
|
||||
end
|
||||
|
||||
|
||||
|
@ -30,6 +30,13 @@ class Members::MembersService
|
||||
# if the user is created by an admin and the authentication is made through an SSO, generate a migration token
|
||||
@member.generate_auth_migration_token if current_user.admin? && AuthProvider.active.providable_type != DatabaseProvider.name
|
||||
|
||||
# setup the attached profiles (invoicing & statistics)
|
||||
@member.invoicing_profile.email = params[:email]
|
||||
@member.invoicing_profile.first_name = params[:profile_attributes][:first_name]
|
||||
@member.invoicing_profile.last_name = params[:profile_attributes][:last_name]
|
||||
@member.statistic_profile.group_id = params[:group_id]
|
||||
@member.statistic_profile.role_id = Role.find_by(name: 'member').id
|
||||
|
||||
if @member.save
|
||||
@member.generate_subscription_invoice(current_user.id)
|
||||
@member.send_confirmation_instructions
|
||||
|
@ -21,7 +21,7 @@ class Subscriptions::Subscribe
|
||||
end
|
||||
|
||||
def extend_subscription(subscription, new_expiration_date, free_days)
|
||||
return subscription.free_extend(new_expiration_date) if free_days
|
||||
return subscription.free_extend(new_expiration_date, @operator_id) if free_days
|
||||
|
||||
new_sub = Subscription.create(
|
||||
plan_id: subscription.plan_id,
|
||||
|
@ -48,8 +48,11 @@ en:
|
||||
edit_my_profile: "Edit my profile"
|
||||
your_group_has_been_successfully_changed: "Your group has been successfully changed."
|
||||
an_unexpected_error_prevented_your_group_from_being_changed: "An unexpected error prevented your group from being changed."
|
||||
do_you_really_want_to_delete_your_account: "Do you really want to delete your account?"
|
||||
all_data_relative_to_your_projects_will_be_lost: "All data relative to your projects will be lost."
|
||||
confirm_delete_your_account: "Do you really want to delete your account?"
|
||||
all_data_will_be_lost: "All your data will be destroyed and won't be recoverable."
|
||||
invoicing_data_kept: "According to regulation, all data related to your invoices will be kept separately for 10 years."
|
||||
statistic_data_anonymized: "Some data (sex, date of birth, group) will be anonymized and kept for statistical purposes."
|
||||
no_further_access_to_projects: "Your published projects will be anonymized and you won't get any further ability to edit them."
|
||||
your_user_account_has_been_successfully_deleted_goodbye: "Your user account has been successfully deleted. Goodbye."
|
||||
an_error_occured_preventing_your_account_from_being_deleted: "An error occurred, preventing your account from being deleted."
|
||||
projects:
|
||||
|
@ -48,8 +48,11 @@ es:
|
||||
edit_my_profile: "Editar mi perfil"
|
||||
your_group_has_been_successfully_changed: "Su grupo ha sido cambiado con exito."
|
||||
an_unexpected_error_prevented_your_group_from_being_changed: "Un error inesperado impidió que su grupo fuese cambiado."
|
||||
do_you_really_want_to_delete_your_account: "¿Está seguro de querer eliminar su cuenta?"
|
||||
all_data_relative_to_your_projects_will_be_lost: "Todo dato relacionado con sus proyectos se perderá"
|
||||
confirm_delete_your_account: "¿Está seguro de querer eliminar su cuenta?"
|
||||
all_data_will_be_lost: "All your data will be destroyed and won't be recoverable." # missing translation
|
||||
invoicing_data_kept: "According to regulation, all data related to your invoices will be kept separately for 10 years." # missing translation
|
||||
statistic_data_anonymized: "Some data (sex, date of birth, group) will be anonymized and kept for statistical purposes." # missing translation
|
||||
no_further_access_to_projects: "Your published projects will be anonymized and you won't get any further ability to edit them." # missing translation
|
||||
your_user_account_has_been_successfully_deleted_goodbye: "Su cuenta ha sido eliminada con éxito. Adiós"
|
||||
an_error_occured_preventing_your_account_from_being_deleted: "Un error inesperado impidió que su cuenta fuese eliminada."
|
||||
projects:
|
||||
|
@ -48,8 +48,11 @@ fr:
|
||||
edit_my_profile: "Éditer votre profil"
|
||||
your_group_has_been_successfully_changed: "Votre groupe a bien été changé."
|
||||
an_unexpected_error_prevented_your_group_from_being_changed: "Une erreur inattendue a empêché votre changement de groupe."
|
||||
do_you_really_want_to_delete_your_account: "Êtes-vous sûr de vouloir supprimer votre compte ?"
|
||||
all_data_relative_to_your_projects_will_be_lost: "Toutes les données relatives à vos projets seront détruites."
|
||||
confirm_delete_your_account: "Êtes-vous sûr de vouloir supprimer votre compte ?"
|
||||
all_data_will_be_lost: "Toutes vos données seront détruites et ne pourront pas être récupérées."
|
||||
invoicing_data_kept: "Conformément à la réglementation, les données relatives à vos facturations seront conservées de manière séparée pendant 10 ans."
|
||||
statistic_data_anonymized: "Certaines données (sexe, date de naissance, groupe) seront anonymisées et conservées à des fins statistiques."
|
||||
no_further_access_to_projects: "Vos projets publiés seront anonymisés et vous n'aurez plus de possibilité de les modifier."
|
||||
your_user_account_has_been_successfully_deleted_goodbye: "Votre compte utilisateur a bien été supprimé. Au revoir."
|
||||
an_error_occured_preventing_your_account_from_being_deleted: "Une erreur est survenue qui a empêché la suppression de votre compte."
|
||||
projects:
|
||||
|
@ -48,8 +48,11 @@ pt:
|
||||
edit_my_profile: "Editar meu perfil"
|
||||
your_group_has_been_successfully_changed: "Seu grupo foi modificado com sucesso."
|
||||
an_unexpected_error_prevented_your_group_from_being_changed: "Um erro inesperado impediu o seu grupo de ser alterado."
|
||||
do_you_really_want_to_delete_your_account: "Você realmente deseja deletar sua conta?"
|
||||
all_data_relative_to_your_projects_will_be_lost: "Todos os dados relativos aos seus projectos serão perdidos."
|
||||
confirm_delete_your_account: "Você realmente deseja deletar sua conta?"
|
||||
all_data_will_be_lost: "All your data will be destroyed and won't be recoverable." # missing translation
|
||||
invoicing_data_kept: "According to regulation, all data related to your invoices will be kept separately for 10 years." # missing translation
|
||||
statistic_data_anonymized: "Some data (sex, date of birth, group) will be anonymized and kept for statistical purposes." # missing translation
|
||||
no_further_access_to_projects: "Your published projects will be anonymized and you won't get any further ability to edit them." # missing translation
|
||||
your_user_account_has_been_successfully_deleted_goodbye: "Sua conta de usuário foi excluída com êxito. Até mais."
|
||||
an_error_occured_preventing_your_account_from_being_deleted: "Ocorreu um erro, impedindo que sua conta fosse excluída."
|
||||
projects:
|
||||
@ -98,19 +101,19 @@ pt:
|
||||
machines_reserve:
|
||||
# book a machine
|
||||
machine_planning: "Planejamento de máquinas"
|
||||
i_ve_reserved: "Eu tenho reserva"
|
||||
i_ve_reserved: "Eu tenho reserva"
|
||||
not_available: "Não disponível"
|
||||
i_reserve: "Eu reservo"
|
||||
i_shift: "Eu mudo"
|
||||
i_change: "Eu altero"
|
||||
|
||||
|
||||
trainings_reserve:
|
||||
# book a training
|
||||
trainings_planning: "Planos de treinamento"
|
||||
planning_of: "Planejamento de" # followed by the training name (eg. "Planning of 3d printer training")
|
||||
all_trainings: "Todos treinamentos"
|
||||
cancel_my_selection: "Cancelar minha seleção"
|
||||
i_ve_reserved: "Eu reservei"
|
||||
cancel_my_selection: "Cancelar minha seleção"
|
||||
i_ve_reserved: "Eu reservei"
|
||||
|
||||
space_reserve:
|
||||
# book a space
|
||||
@ -118,7 +121,7 @@ pt:
|
||||
planning_of_space_NAME: "Plano de {{NAME}} espaço" # angular interpolation
|
||||
i_ve_reserved: "Eu reservei"
|
||||
i_shift: "Eu troco"
|
||||
i_change: "Eu altero"
|
||||
i_change: "Eu altero"
|
||||
|
||||
notifications:
|
||||
notifications_center: "Centro de notificações"
|
||||
|
@ -9,8 +9,8 @@ namespace :fablab do
|
||||
month = args.month || Time.now.month
|
||||
start_date = Time.new(year.to_i, month.to_i, 1)
|
||||
end_date = start_date.next_month
|
||||
puts "-> Start regenerate the invoices PDF between #{I18n.l start_date, format: :long} in " \
|
||||
" #{I18n.l end_date - 1.minute, format: :long}"
|
||||
puts "-> Start regenerate the invoices PDF between #{I18n.l start_date, format: :long} and " \
|
||||
"#{I18n.l end_date - 1.minute, format: :long}"
|
||||
invoices = Invoice.only_invoice
|
||||
.where('created_at >= :start_date AND created_at < :end_date', start_date: start_date, end_date: end_date)
|
||||
.order(created_at: :asc)
|
||||
|
@ -79,5 +79,22 @@ namespace :fablab do
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'migrate invoices PDF to folders by invoicing_profile'
|
||||
task migrate_invoices_pdf_folders: :environment do
|
||||
require 'fileutils'
|
||||
Invoice.all.each do |i|
|
||||
invoicing_profile = i.invoicing_profile
|
||||
user_id = invoicing_profile.user_id
|
||||
|
||||
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)
|
||||
end
|
||||
FileUtils.rm_rf 'invoices'
|
||||
FileUtils.mv 'tmp/invoices', 'invoices'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user