mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-17 11:54:22 +01:00
api endpoint and worker to export accounting data
This commit is contained in:
parent
82ad69d386
commit
f772bc3509
@ -1,5 +1,6 @@
|
||||
# Changelog Fab Manager
|
||||
|
||||
- Ability to configure and export the accounting data to the ACD accounting software
|
||||
- Fix a bug: no user can be created after the last member was deleted
|
||||
- Fix a bug: unable to generate a refund (Avoir)
|
||||
- Fix a bug: a newly generated refund is displayed as broken (unchained record) even if it is correctly chained
|
||||
@ -9,6 +10,7 @@
|
||||
- Fix some security issues: updated sidekiq to 5.2.7 to fix XSS and CRSF issues
|
||||
- Removed dependency to jQuery UI
|
||||
- Updated angular-xeditable, to remove dependency to jquery 1.11.1
|
||||
- [TODO DEPLOY] `rake db:migrate`
|
||||
|
||||
## v4.0.2 2019 July 10
|
||||
|
||||
|
34
app/controllers/api/accounting_exports_controller.rb
Normal file
34
app/controllers/api/accounting_exports_controller.rb
Normal file
@ -0,0 +1,34 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# API Controller for exporting accounting data to external accounting softwares
|
||||
class API::AccountingExportsController < API::ApiController
|
||||
|
||||
before_action :authenticate_user!
|
||||
|
||||
def export
|
||||
authorize :export
|
||||
|
||||
export = Export.where(category: 'accounting', export_type: 'accounting-software')
|
||||
.where('created_at > ?', Invoice.maximum('updated_at'))
|
||||
.last
|
||||
if export.nil? || !FileTest.exist?(export.file)
|
||||
@export = Export.new(
|
||||
category: 'accounting',
|
||||
export_type: 'accounting-software',
|
||||
user: current_user,
|
||||
extension: params[:extension],
|
||||
query: params[:query],
|
||||
key: params[:separator]
|
||||
)
|
||||
if @export.save
|
||||
render json: { export_id: @export.id }, status: :ok
|
||||
else
|
||||
render json: @export.errors, status: :unprocessable_entity
|
||||
end
|
||||
else
|
||||
send_file File.join(Rails.root, export.file),
|
||||
type: 'text/csv',
|
||||
disposition: 'attachment'
|
||||
end
|
||||
end
|
||||
end
|
@ -8,10 +8,17 @@ class API::ExportsController < API::ApiController
|
||||
|
||||
def download
|
||||
authorize @export
|
||||
mime_type = if @export.extension == 'xlsx'
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
elsif @export.extension == 'csv'
|
||||
'text/csv'
|
||||
else
|
||||
'application/octet-stream'
|
||||
end
|
||||
|
||||
if FileTest.exist?(@export.file)
|
||||
send_file File.join(Rails.root, @export.file),
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
type: mime_type,
|
||||
disposition: 'attachment'
|
||||
else
|
||||
render text: I18n.t('errors.messages.export_not_found'), status: :not_found
|
||||
@ -21,28 +28,8 @@ class API::ExportsController < API::ApiController
|
||||
def status
|
||||
authorize Export
|
||||
|
||||
export = Export.where(category: params[:category], export_type: params[:type], query: params[:query], key: params[:key])
|
||||
|
||||
if params[:category] == 'users'
|
||||
case params[:type]
|
||||
when 'subscriptions'
|
||||
export = export.where('created_at > ?', Subscription.maximum('updated_at'))
|
||||
when 'reservations'
|
||||
export = export.where('created_at > ?', Reservation.maximum('updated_at'))
|
||||
when 'members'
|
||||
export = export.where('created_at > ?', User.with_role(:member).maximum('updated_at'))
|
||||
else
|
||||
raise ArgumentError, "Unknown export users/#{params[:type]}"
|
||||
end
|
||||
elsif params[:category] == 'availabilities'
|
||||
case params[:type]
|
||||
when 'index'
|
||||
export = export.where('created_at > ?', [Availability.maximum('updated_at'), Reservation.maximum('updated_at')].max)
|
||||
else
|
||||
raise ArgumentError, "Unknown type availabilities/#{params[:type]}"
|
||||
end
|
||||
end
|
||||
export = export.last
|
||||
exports = Export.where(category: params[:category], export_type: params[:type], query: params[:query], key: params[:key])
|
||||
export = retrieve_last_export(exports, params[:category], params[:type])
|
||||
|
||||
if export.nil? || !FileTest.exist?(export.file)
|
||||
render json: { exists: false, id: nil }, status: :ok
|
||||
@ -53,6 +40,39 @@ class API::ExportsController < API::ApiController
|
||||
|
||||
private
|
||||
|
||||
def retrieve_last_export(export, category, type)
|
||||
case category
|
||||
when 'users'
|
||||
case type
|
||||
when 'subscriptions'
|
||||
export = export.where('created_at > ?', Subscription.maximum('updated_at'))
|
||||
when 'reservations'
|
||||
export = export.where('created_at > ?', Reservation.maximum('updated_at'))
|
||||
when 'members'
|
||||
export = export.where('created_at > ?', User.with_role(:member).maximum('updated_at'))
|
||||
else
|
||||
raise ArgumentError, "Unknown export users/#{type}"
|
||||
end
|
||||
when 'availabilities'
|
||||
case type
|
||||
when 'index'
|
||||
export = export.where('created_at > ?', [Availability.maximum('updated_at'), Reservation.maximum('updated_at')].max)
|
||||
else
|
||||
raise ArgumentError, "Unknown type availabilities/#{type}"
|
||||
end
|
||||
when 'accounting'
|
||||
case type
|
||||
when 'accounting-software'
|
||||
export = export.where('created_at > ?', Invoice.maximum('updated_at'))
|
||||
else
|
||||
raise ArgumentError, "Unknown type accounting/#{type}"
|
||||
end
|
||||
else
|
||||
raise ArgumentError, "Unknown category #{category}"
|
||||
end
|
||||
export.last
|
||||
end
|
||||
|
||||
def set_export
|
||||
@export = Export.find(params[:id])
|
||||
end
|
||||
|
@ -21,7 +21,7 @@ class Export < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def filename
|
||||
"#{export_type}-#{id}_#{created_at.strftime('%d%m%Y')}.xlsx"
|
||||
"#{export_type}-#{id}_#{created_at.strftime('%d%m%Y')}.#{extension}"
|
||||
end
|
||||
|
||||
private
|
||||
@ -34,6 +34,8 @@ class Export < ActiveRecord::Base
|
||||
UsersExportWorker.perform_async(id)
|
||||
when 'availabilities'
|
||||
AvailabilitiesExportWorker.perform_async(id)
|
||||
when 'accounting'
|
||||
AccountingExportWorker.perform_async(id)
|
||||
else
|
||||
raise NoMethodError, "Unknown export service for #{category}/#{export_type}"
|
||||
end
|
||||
|
8
app/policies/accounting_exports_policy.rb
Normal file
8
app/policies/accounting_exports_policy.rb
Normal file
@ -0,0 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Check the access policies for API::AccountingExportsController
|
||||
class AccountingExportsPolicy < ApplicationPolicy
|
||||
def export?
|
||||
user.admin?
|
||||
end
|
||||
end
|
21
app/workers/accounting_export_worker.rb
Normal file
21
app/workers/accounting_export_worker.rb
Normal file
@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Asynchronously export the accounting data (Invoices & Avoirs) to an external accounting software
|
||||
class AccountingExportWorker
|
||||
include Sidekiq::Worker
|
||||
|
||||
def perform(export_id)
|
||||
export = Export.find(export_id)
|
||||
|
||||
raise SecurityError, 'Not allowed to export' unless export.user.admin?
|
||||
|
||||
data = JSON.parse(export.query)
|
||||
service = AccountingExportService.new(export.file, data['columns'], data['encoding'], export.extension, export.key)
|
||||
|
||||
service.export(data['start_date'], data['end_date'])
|
||||
|
||||
NotificationCenter.call type: :notify_admin_export_complete,
|
||||
receiver: export.user,
|
||||
attached_object: export
|
||||
end
|
||||
end
|
@ -135,6 +135,8 @@ Rails.application.routes.draw do
|
||||
get 'last_closing_end', on: :collection
|
||||
get 'archive', action: 'download_archive', on: :member
|
||||
end
|
||||
# export accounting data to csv or equivalent
|
||||
post 'accounting/export' => 'accounting_exports#export'
|
||||
|
||||
# i18n
|
||||
# regex allows using dots in URL for 'state'
|
||||
|
5
db/migrate/20190730085826_add_extension_to_export.rb
Normal file
5
db/migrate/20190730085826_add_extension_to_export.rb
Normal file
@ -0,0 +1,5 @@
|
||||
class AddExtensionToExport < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :exports, :extension, :string, default: 'xlsx'
|
||||
end
|
||||
end
|
@ -11,12 +11,12 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20190606074801) do
|
||||
ActiveRecord::Schema.define(version: 20190730085826) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
enable_extension "unaccent"
|
||||
enable_extension "pg_trgm"
|
||||
enable_extension "unaccent"
|
||||
|
||||
create_table "abuses", force: :cascade do |t|
|
||||
t.integer "signaled_id"
|
||||
@ -202,10 +202,11 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
||||
t.string "category"
|
||||
t.string "export_type"
|
||||
t.string "query"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "user_id"
|
||||
t.string "key"
|
||||
t.string "extension", default: "xlsx"
|
||||
end
|
||||
|
||||
add_index "exports", ["user_id"], name: "index_exports_on_user_id", using: :btree
|
||||
|
Loading…
x
Reference in New Issue
Block a user