mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-21 15:54:22 +01:00
Merge branch 'acd' into dev
This commit is contained in:
commit
15f858ba9c
@ -1,9 +1,9 @@
|
|||||||
Metrics/LineLength:
|
Metrics/LineLength:
|
||||||
Max: 140
|
Max: 140
|
||||||
Metrics/MethodLength:
|
Metrics/MethodLength:
|
||||||
Max: 30
|
Max: 35
|
||||||
Metrics/CyclomaticComplexity:
|
Metrics/CyclomaticComplexity:
|
||||||
Max: 9
|
Max: 12
|
||||||
Metrics/PerceivedComplexity:
|
Metrics/PerceivedComplexity:
|
||||||
Max: 9
|
Max: 9
|
||||||
Metrics/AbcSize:
|
Metrics/AbcSize:
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
# Changelog Fab Manager
|
# Changelog Fab Manager
|
||||||
|
|
||||||
|
- Ability to configure and export the accounting data to the ACD accounting software
|
||||||
|
- [TODO DEPLOY] `rake db:migrate`
|
||||||
|
|
||||||
## v4.0.3 2019 August 01
|
## v4.0.3 2019 August 01
|
||||||
|
|
||||||
- Fix a bug: no user can be created after the last member was deleted
|
- Fix a bug: no user can be created after the last member was deleted
|
||||||
|
2
Procfile
2
Procfile
@ -1,3 +1,3 @@
|
|||||||
web: bundle exec rails server puma -p $PORT -b0.0.0.0
|
web: bundle exec rails server puma -p $PORT -b0.0.0.0
|
||||||
worker: bundle exec sidekiq -C ./config/sidekiq.yml
|
#worker: bundle exec sidekiq -C ./config/sidekiq.yml
|
||||||
mail: bundle exec mailcatcher --foreground
|
mail: bundle exec mailcatcher --foreground
|
||||||
|
@ -76,6 +76,86 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Accounting codes
|
||||||
|
$scope.settings = {
|
||||||
|
journalCode: {
|
||||||
|
name: 'accounting_journal_code',
|
||||||
|
value: settings['accounting_journal_code']
|
||||||
|
},
|
||||||
|
clientCode: {
|
||||||
|
name: 'accounting_client_code',
|
||||||
|
value: settings['accounting_client_code']
|
||||||
|
},
|
||||||
|
clientLabel: {
|
||||||
|
name: 'accounting_client_label',
|
||||||
|
value: settings['accounting_client_label']
|
||||||
|
},
|
||||||
|
walletCode: {
|
||||||
|
name: 'accounting_wallet_code',
|
||||||
|
value: settings['accounting_wallet_code']
|
||||||
|
},
|
||||||
|
walletLabel: {
|
||||||
|
name: 'accounting_wallet_label',
|
||||||
|
value: settings['accounting_wallet_label']
|
||||||
|
},
|
||||||
|
vatCode: {
|
||||||
|
name: 'accounting_VAT_code',
|
||||||
|
value: settings['accounting_VAT_code']
|
||||||
|
},
|
||||||
|
vatLabel: {
|
||||||
|
name: 'accounting_VAT_label',
|
||||||
|
value: settings['accounting_VAT_label']
|
||||||
|
},
|
||||||
|
subscriptionCode: {
|
||||||
|
name: 'accounting_subscription_code',
|
||||||
|
value: settings['accounting_subscription_code']
|
||||||
|
},
|
||||||
|
subscriptionLabel: {
|
||||||
|
name: 'accounting_subscription_label',
|
||||||
|
value: settings['accounting_subscription_label']
|
||||||
|
},
|
||||||
|
machineCode: {
|
||||||
|
name: 'accounting_Machine_code',
|
||||||
|
value: settings['accounting_Machine_code']
|
||||||
|
},
|
||||||
|
machineLabel: {
|
||||||
|
name: 'accounting_Machine_label',
|
||||||
|
value: settings['accounting_Machine_label']
|
||||||
|
},
|
||||||
|
trainingCode: {
|
||||||
|
name: 'accounting_Training_code',
|
||||||
|
value: settings['accounting_Training_code']
|
||||||
|
},
|
||||||
|
trainingLabel: {
|
||||||
|
name: 'accounting_Training_label',
|
||||||
|
value: settings['accounting_Training_label']
|
||||||
|
},
|
||||||
|
eventCode: {
|
||||||
|
name: 'accounting_Event_code',
|
||||||
|
value: settings['accounting_Event_code']
|
||||||
|
},
|
||||||
|
eventLabel: {
|
||||||
|
name: 'accounting_Event_label',
|
||||||
|
value: settings['accounting_Event_label']
|
||||||
|
},
|
||||||
|
spaceCode: {
|
||||||
|
name: 'accounting_Space_code',
|
||||||
|
value: settings['accounting_Space_code']
|
||||||
|
},
|
||||||
|
spaceLabel: {
|
||||||
|
name: 'accounting_Space_label',
|
||||||
|
value: settings['accounting_Space_label']
|
||||||
|
},
|
||||||
|
couponCode: {
|
||||||
|
name: 'accounting_coupon_code',
|
||||||
|
value: settings['accounting_coupon_code']
|
||||||
|
},
|
||||||
|
couponLabel: {
|
||||||
|
name: 'accounting_coupon_label',
|
||||||
|
value: settings['accounting_coupon_label']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Placeholding date for the invoice creation
|
// Placeholding date for the invoice creation
|
||||||
$scope.today = moment();
|
$scope.today = moment();
|
||||||
|
|
||||||
@ -432,6 +512,14 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.toggleExportModal = function() {
|
||||||
|
$uibModal.open({
|
||||||
|
templateUrl: '<%= asset_path "admin/invoices/accountingExportModal.html" %>',
|
||||||
|
controller: 'AccountingExportModalController',
|
||||||
|
size: 'xl'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if the given date is within a closed accounting period
|
* Test if the given date is within a closed accounting period
|
||||||
* @param date {Date} date to test
|
* @param date {Date} date to test
|
||||||
@ -446,6 +534,19 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to save the setting value to the database
|
||||||
|
* @param setting {{value:*, name:string}} note that the value will be stringified
|
||||||
|
*/
|
||||||
|
$scope.save = function(setting) {
|
||||||
|
Setting.update(
|
||||||
|
{ name: setting.name },
|
||||||
|
{ value: setting.value },
|
||||||
|
function () { growl.success(_t('invoices.customization_of_SETTING_successfully_saved', { SETTING: _t(`invoices.${setting.name}`) })); },
|
||||||
|
function (error) { console.log(error); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/* PRIVATE SCOPE */
|
/* PRIVATE SCOPE */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -791,7 +892,7 @@ Application.Controllers.controller('ClosePeriodModalController', ['$scope', '$ui
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cancel the refund, dismiss the modal window
|
* Just dismiss the modal window
|
||||||
*/
|
*/
|
||||||
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||||
|
|
||||||
@ -803,3 +904,130 @@ Application.Controllers.controller('ClosePeriodModalController', ['$scope', '$ui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
Application.Controllers.controller('AccountingExportModalController', ['$scope', '$uibModalInstance', 'Invoice', 'Export', 'CSRF', 'growl', '_t',
|
||||||
|
function ($scope, $uibModalInstance, Invoice, Export, CSRF, growl, _t) {
|
||||||
|
// Retrieve Anti-CSRF tokens from cookies
|
||||||
|
CSRF.setMetaTags();
|
||||||
|
|
||||||
|
const SETTINGS = {
|
||||||
|
acd: {
|
||||||
|
format: 'csv',
|
||||||
|
encoding: 'ISO-8859-1',
|
||||||
|
separator: ';',
|
||||||
|
dateFormat: '%d/%m/%Y',
|
||||||
|
columns: ['journal_code', 'date', 'account_code', 'account_label', 'piece', 'line_label', 'debit_origin', 'credit_origin', 'debit_euro', 'credit_euro', 'lettering']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* PUBLIC SCOPE */
|
||||||
|
|
||||||
|
// API URL where the form will be posted
|
||||||
|
$scope.actionUrl = '/api/accounting/export';
|
||||||
|
|
||||||
|
// Form action on the above URL
|
||||||
|
$scope.method = 'post';
|
||||||
|
|
||||||
|
// Anti-CSRF token to inject into the download form
|
||||||
|
$scope.csrfToken = angular.element('meta[name="csrf-token"]')[0].content;
|
||||||
|
|
||||||
|
// API request body to generate the export
|
||||||
|
$scope.query = null;
|
||||||
|
|
||||||
|
// binding to radio button "export to"
|
||||||
|
$scope.exportTarget = {
|
||||||
|
software: null,
|
||||||
|
startDate: null,
|
||||||
|
endDate: null,
|
||||||
|
settings: null
|
||||||
|
};
|
||||||
|
|
||||||
|
// AngularUI-Bootstrap datepicker parameters to define export dates range
|
||||||
|
$scope.datePicker = {
|
||||||
|
format: Fablab.uibDateFormat,
|
||||||
|
opened: { // default: datePickers are not shown
|
||||||
|
start: false,
|
||||||
|
end: false
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
startingDay: Fablab.weekStartingDay
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Date of the first invoice
|
||||||
|
$scope.firstInvoice = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the close period creation
|
||||||
|
*/
|
||||||
|
$scope.ok = function () {
|
||||||
|
const statusQry = mkQuery();
|
||||||
|
$scope.query = statusQry;
|
||||||
|
|
||||||
|
Export.status(statusQry).then(function (res) {
|
||||||
|
if (!res.data.exists) {
|
||||||
|
growl.success(_t('invoices.export_is_running'));
|
||||||
|
}
|
||||||
|
$uibModalInstance.close(res);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to open/close one of the datepickers
|
||||||
|
* @param event {Object} see https://docs.angularjs.org/guide/expression#-event-
|
||||||
|
* @param picker {string} start | end
|
||||||
|
*/
|
||||||
|
$scope.toggleDatePicker = function(event, picker) {
|
||||||
|
event.preventDefault();
|
||||||
|
$scope.datePicker.opened[picker] = !$scope.datePicker.opened[picker];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will fill the export settings, according to the selected software
|
||||||
|
*/
|
||||||
|
$scope.fillSettings = function() {
|
||||||
|
$scope.exportTarget.settings = SETTINGS[$scope.exportTarget.software];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just dismiss the modal window
|
||||||
|
*/
|
||||||
|
$scope.cancel = function () { $uibModalInstance.dismiss('cancel'); };
|
||||||
|
|
||||||
|
/* PRIVATE SCOPE */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kind of constructor: these actions will be realized first when the controller is loaded
|
||||||
|
*/
|
||||||
|
const initialize = function () {
|
||||||
|
// if the invoice was payed with stripe, allow to refund through stripe
|
||||||
|
Invoice.first(function (data) {
|
||||||
|
$scope.firstInvoice = data.date;
|
||||||
|
$scope.exportTarget.startDate = data.date;
|
||||||
|
$scope.exportTarget.endDate = moment().toISOString();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the query for the export API
|
||||||
|
* @returns {{extension: *, query: *, category: string, type: string, key: *}}
|
||||||
|
*/
|
||||||
|
const mkQuery = function() {
|
||||||
|
return {
|
||||||
|
category: 'accounting',
|
||||||
|
type: 'accounting-software',
|
||||||
|
extension: $scope.exportTarget.settings.format,
|
||||||
|
key: $scope.exportTarget.settings.separator,
|
||||||
|
query: JSON.stringify({
|
||||||
|
columns: $scope.exportTarget.settings.columns,
|
||||||
|
encoding: $scope.exportTarget.settings.encoding,
|
||||||
|
date_format: $scope.exportTarget.settings.dateFormat,
|
||||||
|
start_date: $scope.exportTarget.startDate,
|
||||||
|
end_date: $scope.exportTarget.endDate
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// !!! MUST BE CALLED AT THE END of the controller
|
||||||
|
return initialize();
|
||||||
|
}]);
|
||||||
|
@ -899,15 +899,12 @@ angular.module('application.router', ['ui.router'])
|
|||||||
resolve: {
|
resolve: {
|
||||||
settings: ['Setting', function (Setting) {
|
settings: ['Setting', function (Setting) {
|
||||||
return Setting.query({
|
return Setting.query({
|
||||||
names: `['invoice_legals', \
|
names: `['invoice_legals', 'invoice_text', 'invoice_VAT-rate', 'invoice_VAT-active', 'invoice_order-nb', 'invoice_code-value', \
|
||||||
'invoice_text', \
|
'invoice_code-active', 'invoice_reference', 'invoice_logo', 'accounting_journal_code', 'accounting_client_code', \
|
||||||
'invoice_VAT-rate', \
|
'accounting_client_label', 'accounting_wallet_code', 'accounting_wallet_label', 'accounting_VAT_code', 'accounting_VAT_label', \
|
||||||
'invoice_VAT-active', \
|
'accounting_subscription_code', 'accounting_subscription_label', 'accounting_Machine_code', 'accounting_Machine_label', \
|
||||||
'invoice_order-nb', \
|
'accounting_Training_code', 'accounting_Training_label', 'accounting_Event_code', 'accounting_Event_label', \
|
||||||
'invoice_code-value', \
|
'accounting_Space_code', 'accounting_Space_label', 'accounting_coupon_code', 'accounting_coupon_label']` }).$promise;
|
||||||
'invoice_code-active', \
|
|
||||||
'invoice_reference', \
|
|
||||||
'invoice_logo']` }).$promise;
|
|
||||||
}],
|
}],
|
||||||
invoices: [ 'Invoice', function (Invoice) {
|
invoices: [ 'Invoice', function (Invoice) {
|
||||||
return Invoice.list({
|
return Invoice.list({
|
||||||
|
@ -10,6 +10,10 @@ Application.Services.factory('Invoice', ['$resource', function ($resource) {
|
|||||||
url: '/api/invoices/list',
|
url: '/api/invoices/list',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
isArray: true
|
isArray: true
|
||||||
|
},
|
||||||
|
first: {
|
||||||
|
url: '/api/invoices/first',
|
||||||
|
method: 'GET'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -65,6 +65,10 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-xl {
|
||||||
|
width: 900px;
|
||||||
|
}
|
||||||
|
|
||||||
// component card
|
// component card
|
||||||
.card {
|
.card {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -276,3 +276,31 @@ table.scrollable-3-cols {
|
|||||||
input.form-control.as-writable {
|
input.form-control.as-writable {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.accounting-codes .row {
|
||||||
|
margin-top: 2rem;
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table.export-table-template {
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
thead td {
|
||||||
|
width: 20px;
|
||||||
|
background-color: #227447;
|
||||||
|
color: white;
|
||||||
|
border-bottom: 2px solid black;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 10px 5px;
|
||||||
|
line-height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody td {
|
||||||
|
border-right: 1px solid #d4d4d4;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
<div class="modal-header">
|
||||||
|
<h3 class="text-center red" translate>{{ 'invoices.export_accounting_data' }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form role="form" name="exportForm">
|
||||||
|
<div class="row">
|
||||||
|
<div class="form-group col-md-6">
|
||||||
|
<label for="start_date" translate>{{ 'invoices.export_form_date' }}</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||||
|
<input type="text"
|
||||||
|
class="form-control"
|
||||||
|
name="start_date"
|
||||||
|
id="start_date"
|
||||||
|
ng-model="exportTarget.startDate"
|
||||||
|
uib-datepicker-popup="{{datePicker.format}}"
|
||||||
|
datepicker-options="datePicker.options"
|
||||||
|
is-open="datePicker.opened.start"
|
||||||
|
min-date="firstInvoice"
|
||||||
|
placeholder="{{datePicker.format}}"
|
||||||
|
ng-click="toggleDatePicker($event, 'start')"
|
||||||
|
required/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group col-md-6">
|
||||||
|
<label for="end_date" translate>{{ 'invoices.export_to_date' }}</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
|
||||||
|
<input type="text"
|
||||||
|
class="form-control"
|
||||||
|
name="end_date"
|
||||||
|
id="end_date"
|
||||||
|
ng-model="exportTarget.endDate"
|
||||||
|
uib-datepicker-popup="{{datePicker.format}}"
|
||||||
|
datepicker-options="datePicker.options"
|
||||||
|
is-open="datePicker.opened.end"
|
||||||
|
min-date="exportTarget.startDate || firstInvoice"
|
||||||
|
placeholder="{{datePicker.format}}"
|
||||||
|
ng-click="toggleDatePicker($event, 'end')"
|
||||||
|
required/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h4 class="control-label m-l" translate>{{ 'invoices.export_to' }}</h4>
|
||||||
|
<div class="form-group m-l-lg">
|
||||||
|
<label for="acd">
|
||||||
|
<input type="radio" name="acd" id="acd" ng-model="exportTarget.software" ng-value="'acd'" ng-click="fillSettings()" required/>
|
||||||
|
{{ 'invoices.acd' | translate }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" ng-show="exportTarget.settings">
|
||||||
|
<div class="col-md-4 font-bold" translate>{{ 'invoices.format' }}</div>
|
||||||
|
<div class="col-md-8">{{ exportTarget.settings.format }}</div>
|
||||||
|
<div class="col-md-4 font-bold" translate>{{ 'invoices.encoding' }}</div>
|
||||||
|
<div class="col-md-8">{{ exportTarget.settings.encoding }}</div>
|
||||||
|
<div class="col-md-4 font-bold" translate>{{ 'invoices.separator' }}</div>
|
||||||
|
<div class="col-md-8">{{ exportTarget.settings.separator }}</div>
|
||||||
|
<div class="col-md-4 font-bold" translate>{{ 'invoices.dateFormat' }}</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<a href="https://apidock.com/ruby/DateTime/strftime" class="help-cursor" target="_blank">{{ exportTarget.settings.dateFormat }}</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 font-bold" translate>{{ 'invoices.columns' }}</div>
|
||||||
|
<table class="col-md-12 export-table-template">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td ng-repeat="column in exportTarget.settings.columns" translate>{{ 'invoices.exportColumns.' + column }}</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td ng-repeat="column in exportTarget.settings.columns"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<form role="form" ng-submit="ok()" name="exportFormParams" method="post" action="{{ actionUrl }}" class="inline">
|
||||||
|
<input name="authenticity_token" type="hidden" ng-value="csrfToken"/>
|
||||||
|
<input name="_method" type="hidden" ng-value="method"/>
|
||||||
|
<input name="extension" type="hidden" ng-value="query.extension"/>
|
||||||
|
<input name="key" type="hidden" ng-value="query.key"/>
|
||||||
|
<input name="query" type="hidden" ng-value="query.query"/>
|
||||||
|
<input type="submit" class="btn btn-warning" value="{{ 'confirm' | translate }}" formtarget="export-frame"/>
|
||||||
|
</form>
|
||||||
|
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'cancel' }}</button>
|
||||||
|
</div>
|
@ -12,6 +12,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
||||||
<section class="heading-actions wrapper">
|
<section class="heading-actions wrapper">
|
||||||
|
<a class="btn btn-default rounded m-t-sm" ng-click="toggleExportModal()"><i class="fa fa-book"></i></a>
|
||||||
|
<iframe name="export-frame" height="0" width="0" class="none" id="accounting-export-frame"></iframe>
|
||||||
<a class="btn btn-lg btn-default rounded m-t-sm text-sm" ng-click="closeAnAccountingPeriod()"><i class="fa fa-calendar-check-o"></i> {{ 'invoices.accounting_periods' | translate }}</a>
|
<a class="btn btn-lg btn-default rounded m-t-sm text-sm" ng-click="closeAnAccountingPeriod()"><i class="fa fa-calendar-check-o"></i> {{ 'invoices.accounting_periods' | translate }}</a>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
@ -116,7 +118,7 @@
|
|||||||
|
|
||||||
<uib-tab heading="{{ 'invoices.invoicing_settings' | translate }}">
|
<uib-tab heading="{{ 'invoices.invoicing_settings' | translate }}">
|
||||||
<form class="invoice-placeholder">
|
<form class="invoice-placeholder">
|
||||||
<div class="invoice-logo" style="background-image: url({{invoice.logo}});">
|
<div class="invoice-logo">
|
||||||
<img src="data:image/png;base64," data-src="holder.js/100%x100%/text:/font:FontAwesome/icon" bs-holder ng-if="!invoice.logo" class="img-responsive">
|
<img src="data:image/png;base64," data-src="holder.js/100%x100%/text:/font:FontAwesome/icon" bs-holder ng-if="!invoice.logo" class="img-responsive">
|
||||||
<img base-sixty-four-image="invoice.logo" ng-if="invoice.logo && invoice.logo.base64">
|
<img base-sixty-four-image="invoice.logo" ng-if="invoice.logo && invoice.logo.base64">
|
||||||
<div class="tools-box">
|
<div class="tools-box">
|
||||||
@ -201,6 +203,131 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</uib-tab>
|
</uib-tab>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<uib-tab heading="{{ 'invoices.accounting_codes' | translate }}">
|
||||||
|
<div class="panel panel-default m-t-md accounting-codes">
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="journalCode" translate>{{ 'invoices.accounting_journal_code' }}</label>
|
||||||
|
<input type="text" id="journalCode" ng-model="settings.journalCode.value" class="form-control" placeholder="{{ 'invoices.general_journal_code' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.journalCode)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="clientCode" translate>{{ 'invoices.accounting_client_code' }}</label>
|
||||||
|
<input type="text" id="clientCode" ng-model="settings.clientCode.value" class="form-control" placeholder="{{ 'invoices.general_client_code' | translate }}" />
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.clientCode)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="clientLabel" translate>{{ 'invoices.accounting_client_label' }}</label>
|
||||||
|
<input type="text" id="clientLabel" ng-model="settings.clientLabel.value" class="form-control" placeholder="{{ 'invoices.general_client_label' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.clientLabel)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="walletCode" translate>{{ 'invoices.accounting_wallet_code' }}</label>
|
||||||
|
<input type="text" id="walletCode" ng-model="settings.walletCode.value" class="form-control" placeholder="{{ 'invoices.general_wallet_code' | translate }}" />
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.walletCode)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="walletLabel" translate>{{ 'invoices.accounting_wallet_label' }}</label>
|
||||||
|
<input type="text" id="walletLabel" ng-model="settings.walletLabel.value" class="form-control" placeholder="{{ 'invoices.general_wallet_label' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.walletLabel)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="vatCode" translate>{{ 'invoices.accounting_vat_code' }}</label>
|
||||||
|
<input type="text" id="vatCode" ng-model="settings.vatCode.value" class="form-control" placeholder="{{ 'invoices.general_vat_code' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.vatCode)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="vatLabel" translate>{{ 'invoices.accounting_vat_label' }}</label>
|
||||||
|
<input type="text" id="vatLabel" ng-model="settings.vatLabel.value" class="form-control" placeholder="{{ 'invoices.general_vat_label' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.vatLabel)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="subscriptionCode" translate>{{ 'invoices.accounting_subscription_code' }}</label>
|
||||||
|
<input type="text" id="subscriptionCode" ng-model="settings.subscriptionCode.value" class="form-control" placeholder="{{ 'invoices.general_subscription_code' | translate }}" />
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.subscriptionCode)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="subscriptionLabel" translate>{{ 'invoices.accounting_subscription_label' }}</label>
|
||||||
|
<input type="text" id="subscriptionLabel" ng-model="settings.subscriptionLabel.value" class="form-control" placeholder="{{ 'invoices.general_subscription_label' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.subscriptionLabel)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="machineCode" translate>{{ 'invoices.accounting_Machine_code' }}</label>
|
||||||
|
<input type="text" id="machineCode" ng-model="settings.machineCode.value" class="form-control" placeholder="{{ 'invoices.general_machine_code' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.machineCode)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="machineLabel" translate>{{ 'invoices.accounting_Machine_label' }}</label>
|
||||||
|
<input type="text" id="machineLabel" ng-model="settings.machineLabel.value" class="form-control" placeholder="{{ 'invoices.general_machine_label' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.machineLabel)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="trainingCode" translate>{{ 'invoices.accounting_Training_code' }}</label>
|
||||||
|
<input type="text" id="trainingCode" ng-model="settings.trainingCode.value" class="form-control" placeholder="{{ 'invoices.general_training_code' | translate }}" />
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.trainingCode)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="trainingLabel" translate>{{ 'invoices.accounting_Training_label' }}</label>
|
||||||
|
<input type="text" id="trainingLabel" ng-model="settings.trainingLabel.value" class="form-control" placeholder="{{ 'invoices.general_training_label' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.trainingLabel)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="eventCode" translate>{{ 'invoices.accounting_Event_code' }}</label>
|
||||||
|
<input type="text" id="eventCode" ng-model="settings.eventCode.value" class="form-control" placeholder="{{ 'invoices.general_event_code' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.eventCode)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="eventLabel" translate>{{ 'invoices.accounting_Event_label' }}</label>
|
||||||
|
<input type="text" id="eventLabel" ng-model="settings.eventLabel.value" class="form-control" placeholder="{{ 'invoices.general_event_label' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.eventLabel)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="spaceCode" translate>{{ 'invoices.accounting_Space_code' }}</label>
|
||||||
|
<input type="text" id="spaceCode" ng-model="settings.spaceCode.value" class="form-control" placeholder="{{ 'invoices.general_space_code' | translate }}" />
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.spaceCode)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="spaceLabel" translate>{{ 'invoices.accounting_Space_label' }}</label>
|
||||||
|
<input type="text" id="spaceLabel" ng-model="settings.spaceLabel.value" class="form-control" placeholder="{{ 'invoices.general_space_label' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.spaceLabel)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="couponCode" translate>{{ 'invoices.accounting_coupon_code' }}</label>
|
||||||
|
<input type="text" id="couponCode" ng-model="settings.couponCode.value" class="form-control" placeholder="{{ 'invoices.general_coupon_code' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.couponCode)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="couponLabel" translate>{{ 'invoices.accounting_coupon_label' }}</label>
|
||||||
|
<input type="text" id="couponLabel" ng-model="settings.couponLabel.value" class="form-control" placeholder="{{ 'invoices.general_coupon_label' | translate }}"/>
|
||||||
|
<button name="button" class="btn btn-warning" ng-click="save(settings.couponLabel)" translate>{{ 'save' }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</uib-tab>
|
||||||
</uib-tabset>
|
</uib-tabset>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
35
app/controllers/api/accounting_exports_controller.rb
Normal file
35
app/controllers/api/accounting_exports_controller.rb
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# 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 :accounting_export
|
||||||
|
|
||||||
|
export = Export.where(category: 'accounting', export_type: 'accounting-software', key: params[:key])
|
||||||
|
.where(extension: params[:extension], query: params[:query])
|
||||||
|
.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[:key]
|
||||||
|
)
|
||||||
|
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
|
def download
|
||||||
authorize @export
|
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)
|
if FileTest.exist?(@export.file)
|
||||||
send_file File.join(Rails.root, @export.file),
|
send_file File.join(Rails.root, @export.file),
|
||||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
type: mime_type,
|
||||||
disposition: 'attachment'
|
disposition: 'attachment'
|
||||||
else
|
else
|
||||||
render text: I18n.t('errors.messages.export_not_found'), status: :not_found
|
render text: I18n.t('errors.messages.export_not_found'), status: :not_found
|
||||||
@ -21,28 +28,14 @@ class API::ExportsController < API::ApiController
|
|||||||
def status
|
def status
|
||||||
authorize Export
|
authorize Export
|
||||||
|
|
||||||
export = Export.where(category: params[:category], export_type: params[:type], query: params[:query], key: params[:key])
|
exports = Export.where(
|
||||||
|
category: params[:category],
|
||||||
if params[:category] == 'users'
|
export_type: params[:type],
|
||||||
case params[:type]
|
query: params[:query],
|
||||||
when 'subscriptions'
|
key: params[:key],
|
||||||
export = export.where('created_at > ?', Subscription.maximum('updated_at'))
|
extension: params[:extension]
|
||||||
when 'reservations'
|
)
|
||||||
export = export.where('created_at > ?', Reservation.maximum('updated_at'))
|
export = retrieve_last_export(exports, params[:category], params[:type])
|
||||||
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
|
|
||||||
|
|
||||||
if export.nil? || !FileTest.exist?(export.file)
|
if export.nil? || !FileTest.exist?(export.file)
|
||||||
render json: { exists: false, id: nil }, status: :ok
|
render json: { exists: false, id: nil }, status: :ok
|
||||||
@ -53,6 +46,39 @@ class API::ExportsController < API::ApiController
|
|||||||
|
|
||||||
private
|
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
|
def set_export
|
||||||
@export = Export.find(params[:id])
|
@export = Export.find(params[:id])
|
||||||
end
|
end
|
||||||
|
@ -51,6 +51,12 @@ class API::InvoicesController < API::ApiController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def first
|
||||||
|
authorize Invoice
|
||||||
|
invoice = Invoice.order(:created_at).first
|
||||||
|
@first = invoice&.created_at
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def avoir_params
|
def avoir_params
|
||||||
|
@ -21,7 +21,7 @@ class Export < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def filename
|
def filename
|
||||||
"#{export_type}-#{id}_#{created_at.strftime('%d%m%Y')}.xlsx"
|
"#{export_type}-#{id}_#{created_at.strftime('%d%m%Y')}.#{extension}"
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -34,6 +34,8 @@ class Export < ActiveRecord::Base
|
|||||||
UsersExportWorker.perform_async(id)
|
UsersExportWorker.perform_async(id)
|
||||||
when 'availabilities'
|
when 'availabilities'
|
||||||
AvailabilitiesExportWorker.perform_async(id)
|
AvailabilitiesExportWorker.perform_async(id)
|
||||||
|
when 'accounting'
|
||||||
|
AccountingExportWorker.perform_async(id)
|
||||||
else
|
else
|
||||||
raise NoMethodError, "Unknown export service for #{category}/#{export_type}"
|
raise NoMethodError, "Unknown export service for #{category}/#{export_type}"
|
||||||
end
|
end
|
||||||
|
@ -188,7 +188,7 @@ class Invoice < ActiveRecord::Base
|
|||||||
|
|
||||||
def subscription_invoice?
|
def subscription_invoice?
|
||||||
invoice_items.each do |ii|
|
invoice_items.each do |ii|
|
||||||
return true if ii.subscription && !ii.subscription.expired?
|
return true if ii.subscription
|
||||||
end
|
end
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
@ -40,7 +40,26 @@ class Setting < ActiveRecord::Base
|
|||||||
visibility_yearly
|
visibility_yearly
|
||||||
visibility_others
|
visibility_others
|
||||||
display_name_enable
|
display_name_enable
|
||||||
machines_sort_by] }
|
machines_sort_by
|
||||||
|
accounting_journal_code
|
||||||
|
accounting_client_code
|
||||||
|
accounting_client_label
|
||||||
|
accounting_wallet_code
|
||||||
|
accounting_wallet_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_Event_code
|
||||||
|
accounting_Event_label
|
||||||
|
accounting_Space_code
|
||||||
|
accounting_Space_label
|
||||||
|
accounting_coupon_code
|
||||||
|
accounting_coupon_label] }
|
||||||
|
|
||||||
after_update :update_stylesheet, :notify_privacy_policy_changed if :value_changed?
|
after_update :update_stylesheet, :notify_privacy_policy_changed if :value_changed?
|
||||||
|
|
||||||
|
8
app/policies/accounting_export_policy.rb
Normal file
8
app/policies/accounting_export_policy.rb
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Check the access policies for API::AccountingExportsController
|
||||||
|
class AccountingExportPolicy < ApplicationPolicy
|
||||||
|
def export?
|
||||||
|
user.admin?
|
||||||
|
end
|
||||||
|
end
|
@ -14,4 +14,8 @@ class InvoicePolicy < ApplicationPolicy
|
|||||||
def list?
|
def list?
|
||||||
user.admin?
|
user.admin?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def first?
|
||||||
|
user.admin?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -0,0 +1,247 @@
|
|||||||
|
# frozen_string_literal: false
|
||||||
|
|
||||||
|
# Provides the routine to export the accounting data to an external accounting software
|
||||||
|
class AccountingExportService
|
||||||
|
attr_reader :encoding, :format, :separator, :journal_code, :date_format, :columns, :vat_service
|
||||||
|
|
||||||
|
def initialize(columns, encoding = 'UTF-8', format = 'CSV', separator = ';', date_format = '%d/%m/%Y')
|
||||||
|
@encoding = encoding
|
||||||
|
@format = format
|
||||||
|
@separator = separator
|
||||||
|
@journal_code = Setting.find_by(name: 'accounting_journal_code')&.value || ''
|
||||||
|
@date_format = date_format
|
||||||
|
@columns = columns
|
||||||
|
@vat_service = VatHistoryService.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def export(start_date, end_date, file)
|
||||||
|
# build CVS content
|
||||||
|
content = header_row
|
||||||
|
invoices = Invoice.where('created_at >= ? AND created_at <= ?', start_date, end_date).order('created_at ASC')
|
||||||
|
invoices.each do |i|
|
||||||
|
content << generate_rows(i)
|
||||||
|
end
|
||||||
|
|
||||||
|
# write content to file
|
||||||
|
File.open(file, "w:#{encoding}") { |f| f.puts content.encode(encoding, invalid: :replace, undef: :replace) }
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def header_row
|
||||||
|
row = ''
|
||||||
|
columns.each do |column|
|
||||||
|
row << I18n.t("accounting_export.#{column}") << separator
|
||||||
|
end
|
||||||
|
"#{row}\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_rows(invoice)
|
||||||
|
"#{client_row(invoice)}\n" \
|
||||||
|
"#{items_rows(invoice)}" \
|
||||||
|
"#{vat_row(invoice)}\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate the "subscription" and "reservation" rows associated with the provided invoice
|
||||||
|
def items_rows(invoice)
|
||||||
|
rows = invoice.subscription_invoice? ? "#{subscription_row(invoice)}\n" : ''
|
||||||
|
if invoice.invoiced_type == 'Reservation'
|
||||||
|
invoice.invoice_items.each do |item|
|
||||||
|
rows << "#{reservation_row(invoice, item)}\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rows
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate the "client" row, which contains the debit to the client account, all taxes included
|
||||||
|
def client_row(invoice)
|
||||||
|
total = invoice.total / 100.0
|
||||||
|
row = ''
|
||||||
|
columns.each do |column|
|
||||||
|
case column
|
||||||
|
when 'journal_code'
|
||||||
|
row << journal_code
|
||||||
|
when 'date'
|
||||||
|
row << invoice.created_at&.strftime(date_format)
|
||||||
|
when 'account_code'
|
||||||
|
row << account(invoice, :client)
|
||||||
|
when 'account_label'
|
||||||
|
row << account(invoice, :client, :label)
|
||||||
|
when 'piece'
|
||||||
|
row << invoice.reference
|
||||||
|
when 'line_label'
|
||||||
|
row << invoice.invoicing_profile.full_name
|
||||||
|
when 'debit_origin'
|
||||||
|
row << debit_client(invoice, total)
|
||||||
|
when 'credit_origin'
|
||||||
|
row << credit_client(invoice, total)
|
||||||
|
when 'debit_euro'
|
||||||
|
row << debit_client(invoice, total)
|
||||||
|
when 'credit_euro'
|
||||||
|
row << credit_client(invoice, total)
|
||||||
|
when 'lettering'
|
||||||
|
row << ''
|
||||||
|
else
|
||||||
|
puts "Unsupported column: #{column}"
|
||||||
|
end
|
||||||
|
row << separator
|
||||||
|
end
|
||||||
|
row
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate the "reservation" row, which contains the credit to the reservation account, all taxes excluded
|
||||||
|
def reservation_row(invoice, item)
|
||||||
|
wo_taxes = (item.amount / (vat_service.invoice_vat(invoice) / 100 + 1)) / 100.0
|
||||||
|
row = ''
|
||||||
|
columns.each do |column|
|
||||||
|
case column
|
||||||
|
when 'journal_code'
|
||||||
|
row << journal_code
|
||||||
|
when 'date'
|
||||||
|
row << invoice.created_at&.strftime(date_format)
|
||||||
|
when 'account_code'
|
||||||
|
row << account(invoice, :reservation)
|
||||||
|
when 'account_label'
|
||||||
|
row << account(invoice, :reservation, :label)
|
||||||
|
when 'piece'
|
||||||
|
row << invoice.reference
|
||||||
|
when 'line_label'
|
||||||
|
row << item.description
|
||||||
|
when 'debit_origin'
|
||||||
|
row << debit(invoice, wo_taxes)
|
||||||
|
when 'credit_origin'
|
||||||
|
row << credit(invoice, wo_taxes)
|
||||||
|
when 'debit_euro'
|
||||||
|
row << debit(invoice, wo_taxes)
|
||||||
|
when 'credit_euro'
|
||||||
|
row << credit(invoice, wo_taxes)
|
||||||
|
when 'lettering'
|
||||||
|
row << ''
|
||||||
|
else
|
||||||
|
puts "Unsupported column: #{column}"
|
||||||
|
end
|
||||||
|
row << separator
|
||||||
|
end
|
||||||
|
row
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate the "subscription" row, which contains the credit to the subscription account, all taxes excluded
|
||||||
|
def subscription_row(invoice)
|
||||||
|
subscription_item = invoice.invoice_items.select(&:subscription).first
|
||||||
|
wo_taxes = (subscription_item.amount / (vat_service.invoice_vat(invoice) / 100 + 1)) / 100.0
|
||||||
|
row = ''
|
||||||
|
columns.each do |column|
|
||||||
|
case column
|
||||||
|
when 'journal_code'
|
||||||
|
row << journal_code
|
||||||
|
when 'date'
|
||||||
|
row << invoice.created_at&.strftime(date_format)
|
||||||
|
when 'account_code'
|
||||||
|
row << account(invoice, :subscription)
|
||||||
|
when 'account_label'
|
||||||
|
row << account(invoice, :subscription, :label)
|
||||||
|
when 'piece'
|
||||||
|
row << invoice.reference
|
||||||
|
when 'line_label'
|
||||||
|
row << subscription_item.description
|
||||||
|
when 'debit_origin'
|
||||||
|
row << debit(invoice, wo_taxes)
|
||||||
|
when 'credit_origin'
|
||||||
|
row << credit(invoice, wo_taxes)
|
||||||
|
when 'debit_euro'
|
||||||
|
row << debit(invoice, wo_taxes)
|
||||||
|
when 'credit_euro'
|
||||||
|
row << credit(invoice, wo_taxes)
|
||||||
|
when 'lettering'
|
||||||
|
row << ''
|
||||||
|
else
|
||||||
|
puts "Unsupported column: #{column}"
|
||||||
|
end
|
||||||
|
row << separator
|
||||||
|
end
|
||||||
|
row
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate the "VAT" row, which contains the credit to the VAT account, with VAT amount only
|
||||||
|
def vat_row(invoice)
|
||||||
|
vat = (invoice.total - (invoice.total / (vat_service.invoice_vat(invoice) / 100 + 1))) / 100.0
|
||||||
|
row = ''
|
||||||
|
columns.each do |column|
|
||||||
|
case column
|
||||||
|
when 'journal_code'
|
||||||
|
row << journal_code
|
||||||
|
when 'date'
|
||||||
|
row << invoice.created_at&.strftime(date_format)
|
||||||
|
when 'account_code'
|
||||||
|
row << account(invoice, :vat)
|
||||||
|
when 'account_label'
|
||||||
|
row << account(invoice, :vat, :label)
|
||||||
|
when 'piece'
|
||||||
|
row << invoice.reference
|
||||||
|
when 'line_label'
|
||||||
|
row << I18n.t('accounting_export.VAT')
|
||||||
|
when 'debit_origin'
|
||||||
|
row << debit(invoice, vat)
|
||||||
|
when 'credit_origin'
|
||||||
|
row << credit(invoice, vat)
|
||||||
|
when 'debit_euro'
|
||||||
|
row << debit(invoice, vat)
|
||||||
|
when 'credit_euro'
|
||||||
|
row << credit(invoice, vat)
|
||||||
|
when 'lettering'
|
||||||
|
row << ''
|
||||||
|
else
|
||||||
|
puts "Unsupported column: #{column}"
|
||||||
|
end
|
||||||
|
row << separator
|
||||||
|
end
|
||||||
|
row
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get the account code (or label) for the given invoice and the specified line type (client, vat, subscription or reservation)
|
||||||
|
def account(invoice, account, type = :code)
|
||||||
|
res = case account
|
||||||
|
when :client
|
||||||
|
Setting.find_by(name: "accounting_client_#{type}")&.value
|
||||||
|
when :vat
|
||||||
|
Setting.find_by(name: "accounting_VAT_#{type}")&.value
|
||||||
|
when :subscription
|
||||||
|
if invoice.subscription_invoice?
|
||||||
|
Setting.find_by(name: "accounting_subscription_#{type}")&.value
|
||||||
|
else
|
||||||
|
puts "WARN: Invoice #{invoice.id} has no subscription"
|
||||||
|
end
|
||||||
|
when :reservation
|
||||||
|
if invoice.invoiced_type == 'Reservation'
|
||||||
|
Setting.find_by(name: "accounting_#{invoice.invoiced.reservable_type}_#{type}")&.value
|
||||||
|
else
|
||||||
|
puts "WARN: Invoice #{invoice.id} has no reservation"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
puts "Unsupported account #{account}"
|
||||||
|
end
|
||||||
|
res || ''
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fill the value of the "debit" column: if the invoice is a refund, returns the given amount, returns 0 otherwise
|
||||||
|
def debit(invoice, amount)
|
||||||
|
avoir = invoice.is_a? Avoir
|
||||||
|
avoir ? amount.to_s : '0'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fill the value of the "credit" column: if the invoice is a refund, returns 0, otherwise, returns the given amount
|
||||||
|
def credit(invoice, amount)
|
||||||
|
avoir = invoice.is_a? Avoir
|
||||||
|
avoir ? '0' : amount.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fill the value of the "debit" column for the client row: if the invoice is a refund, returns 0, otherwise, returns the given amount
|
||||||
|
def debit_client(invoice, amount)
|
||||||
|
credit(invoice, amount)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fill the value of the "credit" column, for the client row: if the invoice is a refund, returns the given amount, returns 0 otherwise
|
||||||
|
def credit_client(invoice, amount)
|
||||||
|
debit(invoice, amount)
|
||||||
|
end
|
||||||
|
end
|
@ -1,3 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'abstract_controller'
|
require 'abstract_controller'
|
||||||
require 'action_controller'
|
require 'action_controller'
|
||||||
require 'action_view'
|
require 'action_view'
|
||||||
@ -13,7 +15,7 @@ class StatisticsExportService
|
|||||||
# query all stats with range arguments
|
# query all stats with range arguments
|
||||||
query = MultiJson.load(export.query)
|
query = MultiJson.load(export.query)
|
||||||
|
|
||||||
@results = Elasticsearch::Model.client.search({index: 'stats', scroll: '30s', body: query})
|
@results = Elasticsearch::Model.client.search(index: 'stats', scroll: '30s', body: query)
|
||||||
scroll_id = @results['_scroll_id']
|
scroll_id = @results['_scroll_id']
|
||||||
while @results['hits']['hits'].size != @results['hits']['total']
|
while @results['hits']['hits'].size != @results['hits']['total']
|
||||||
scroll_res = Elasticsearch::Model.client.scroll(scroll: '30s', scroll_id: scroll_id)
|
scroll_res = Elasticsearch::Model.client.scroll(scroll: '30s', scroll_id: scroll_id)
|
||||||
@ -22,9 +24,9 @@ class StatisticsExportService
|
|||||||
end
|
end
|
||||||
|
|
||||||
ids = @results['hits']['hits'].map { |u| u['_source']['userId'] }
|
ids = @results['hits']['hits'].map { |u| u['_source']['userId'] }
|
||||||
@users = User.includes(:profile).where(:id => ids)
|
@users = User.includes(:profile).where(id: ids)
|
||||||
|
|
||||||
@indices = StatisticIndex.all.includes(:statistic_fields, :statistic_types => [:statistic_sub_types])
|
@indices = StatisticIndex.all.includes(:statistic_fields, statistic_types: [:statistic_sub_types])
|
||||||
|
|
||||||
ActionController::Base.prepend_view_path './app/views/'
|
ActionController::Base.prepend_view_path './app/views/'
|
||||||
# place data in view_assigns
|
# place data in view_assigns
|
||||||
@ -37,10 +39,10 @@ class StatisticsExportService
|
|||||||
|
|
||||||
content = av.render template: 'exports/statistics_global.xlsx.axlsx'
|
content = av.render template: 'exports/statistics_global.xlsx.axlsx'
|
||||||
# write content to file
|
# write content to file
|
||||||
File.open(export.file,"w+b") {|f| f.puts content }
|
File.open(export.file, 'w+b') { |f| f.puts content }
|
||||||
end
|
end
|
||||||
|
|
||||||
%w(account event machine project subscription training space).each do |path|
|
%w[account event machine project subscription training space].each do |path|
|
||||||
class_eval %{
|
class_eval %{
|
||||||
def export_#{path}(export)
|
def export_#{path}(export)
|
||||||
|
|
||||||
@ -76,7 +78,7 @@ class StatisticsExportService
|
|||||||
# write content to file
|
# write content to file
|
||||||
File.open(export.file,"w+b") {|f| f.puts content }
|
File.open(export.file,"w+b") {|f| f.puts content }
|
||||||
end
|
end
|
||||||
}
|
}, __FILE__, __LINE__ - 35
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
1
app/views/api/invoices/first.json.jbuilder
Normal file
1
app/views/api/invoices/first.json.jbuilder
Normal file
@ -0,0 +1 @@
|
|||||||
|
json.date @first
|
@ -5,6 +5,6 @@
|
|||||||
<%= t(".body.#{@attached_object.category}_#{@attached_object.export_type}") %>.
|
<%= t(".body.#{@attached_object.category}_#{@attached_object.export_type}") %>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<%= t('.body.click_to_download') %>
|
<%= t('.body.click_to_download', TYPE: t(".body.file_type.#{@attached_object.extension}")) %>
|
||||||
<%=link_to( t('.body.here'), "#{root_url}api/exports/#{@attached_object.id}/download", target: "_blank" )%>
|
<%=link_to( t('.body.here'), "#{root_url}api/exports/#{@attached_object.id}/download", target: "_blank" )%>
|
||||||
</p>
|
</p>
|
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(data['columns'], data['encoding'], export.extension, export.key, data['date_format'])
|
||||||
|
|
||||||
|
service.export(data['start_date'], data['end_date'], export.file)
|
||||||
|
|
||||||
|
NotificationCenter.call type: :notify_admin_export_complete,
|
||||||
|
receiver: export.user,
|
||||||
|
attached_object: export
|
||||||
|
end
|
||||||
|
end
|
@ -432,6 +432,69 @@ en:
|
|||||||
period_START_END_closed_success: "The accounting period from {{START}} to {{END}} has been successfully closed. Archive generation is running, you'll be notified when it's done."
|
period_START_END_closed_success: "The accounting period from {{START}} to {{END}} has been successfully closed. Archive generation is running, you'll be notified when it's done."
|
||||||
failed_to_close_period: "An error occurred, unable to close the accounting period"
|
failed_to_close_period: "An error occurred, unable to close the accounting period"
|
||||||
no_periods: "No closings for now"
|
no_periods: "No closings for now"
|
||||||
|
accounting_codes: "Accounting codes"
|
||||||
|
accounting_journal_code: "Journal code"
|
||||||
|
general_journal_code: "Journal code"
|
||||||
|
accounting_client_code: "Customers code"
|
||||||
|
general_client_code: "Accounting code for all customers"
|
||||||
|
accounting_client_label: "Customers label"
|
||||||
|
general_client_label: "Account label for all customers"
|
||||||
|
accounting_wallet_code: "Wallet code"
|
||||||
|
general_wallet_code: "Accounting code for wallet credit"
|
||||||
|
accounting_wallet_label: "Wallet label"
|
||||||
|
general_wallet_label: "Account label for wallet credit"
|
||||||
|
accounting_vat_code: "VAT code"
|
||||||
|
general_vat_code: "Accounting code for VAT"
|
||||||
|
accounting_vat_label: "VAT label"
|
||||||
|
general_vat_label: "VAT account label"
|
||||||
|
accounting_subscription_code: "Subscriptions code"
|
||||||
|
general_subscription_code: "Accounting code for all subscriptions"
|
||||||
|
accounting_subscription_label: "Subscriptions label"
|
||||||
|
general_subscription_label: "Account label for all subscriptions"
|
||||||
|
accounting_Machine_code: "Machines code"
|
||||||
|
general_machine_code: "Accounting code for all machines"
|
||||||
|
accounting_Machine_label: "Machine label"
|
||||||
|
general_machine_label: "Account label for all machines"
|
||||||
|
accounting_Training_code: "Trainings code"
|
||||||
|
general_training_code: "Accounting code for all trainings"
|
||||||
|
accounting_Training_label: "Trainings label"
|
||||||
|
general_training_label: "Account label for all trainings"
|
||||||
|
accounting_Event_code: "Events code"
|
||||||
|
general_event_code: "Accounting code for all events"
|
||||||
|
accounting_Event_label: "Events label"
|
||||||
|
general_event_label: "Account label for all events"
|
||||||
|
accounting_Space_code: "Space code"
|
||||||
|
general_space_code: "Accounting code for all spaces"
|
||||||
|
accounting_Space_label: "Spaces label"
|
||||||
|
general_space_label: "Account label for all spaces"
|
||||||
|
accounting_coupon_code: "Coupons code"
|
||||||
|
general_coupon_code: "Accounting code for all coupons"
|
||||||
|
accounting_coupon_label: "Coupons label"
|
||||||
|
general_coupon_label: "Account label for all coupons"
|
||||||
|
customization_of_SETTING_successfully_saved: "Customization of the {{SETTING}} successfully saved." # angular interpolation
|
||||||
|
export_accounting_data: "Export accounting data"
|
||||||
|
export_to: "Export to the accounting software"
|
||||||
|
export_is_running: "Export is running. You'll be notified when it's ready."
|
||||||
|
acd: "ACD"
|
||||||
|
export_form_date: "Export from"
|
||||||
|
export_to_date: "Export until"
|
||||||
|
format: "File format"
|
||||||
|
encoding: "Encoding"
|
||||||
|
separator: "Separator"
|
||||||
|
dateFormat: "Date format"
|
||||||
|
columns: "Columns"
|
||||||
|
exportColumns:
|
||||||
|
journal_code: "Journal code"
|
||||||
|
date: "Entry date"
|
||||||
|
account_code: "Account code"
|
||||||
|
account_label: "Account label"
|
||||||
|
piece: "Document"
|
||||||
|
line_label: "Entry label"
|
||||||
|
debit_origin: "Origin debit"
|
||||||
|
credit_origin: "Origin credit"
|
||||||
|
debit_euro: "Euro debit"
|
||||||
|
credit_euro: "Euro credit"
|
||||||
|
lettering: "Lettering"
|
||||||
|
|
||||||
members:
|
members:
|
||||||
# management of users, labels, groups, and so on
|
# management of users, labels, groups, and so on
|
||||||
|
@ -432,6 +432,69 @@ es:
|
|||||||
period_START_END_closed_success: "The accounting period from {{START}} to {{END}} has been successfully closed. Archive generation is running, you'll be notified when it's done." # translation_missing
|
period_START_END_closed_success: "The accounting period from {{START}} to {{END}} has been successfully closed. Archive generation is running, you'll be notified when it's done." # translation_missing
|
||||||
failed_to_close_period: "An error occurred, unable to close the accounting period" # translation_missing
|
failed_to_close_period: "An error occurred, unable to close the accounting period" # translation_missing
|
||||||
no_periods: "No closings for now" # translation_missing
|
no_periods: "No closings for now" # translation_missing
|
||||||
|
accounting_codes: "Accounting codes" # translation_missing
|
||||||
|
accounting_journal_code: "Journal code" # translation_missing
|
||||||
|
general_journal_code: "Journal code" # translation_missing
|
||||||
|
accounting_client_code: "Customers code" # translation_missing
|
||||||
|
general_client_code: "Accounting code for all customers" # translation_missing
|
||||||
|
accounting_client_label: "Customers label" # translation_missing
|
||||||
|
general_client_label: "Account label for all customers" # translation_missing
|
||||||
|
accounting_wallet_code: "Wallet code" # translation_missing
|
||||||
|
general_wallet_code: "Accounting code for wallet credit" # translation_missing
|
||||||
|
accounting_wallet_label: "Wallet label" # translation_missing
|
||||||
|
general_wallet_label: "Account label for wallet credit" # translation_missing
|
||||||
|
accounting_vat_code: "VAT code" # translation_missing
|
||||||
|
general_vat_code: "Accounting code for VAT" # translation_missing
|
||||||
|
accounting_vat_label: "VAT label" # translation_missing
|
||||||
|
general_vat_label: "VAT account label" # translation_missing
|
||||||
|
accounting_subscription_code: "Subscriptions code" # translation_missing
|
||||||
|
general_subscription_code: "Accounting code for all subscriptions" # translation_missing
|
||||||
|
accounting_subscription_label: "Subscriptions label" # translation_missing
|
||||||
|
general_subscription_label: "Account label for all subscriptions" # translation_missing
|
||||||
|
accounting_Machine_code: "Machines code" # translation_missing
|
||||||
|
general_machine_code: "Accounting code for all machines" # translation_missing
|
||||||
|
accounting_Machine_label: "Machine label" # translation_missing
|
||||||
|
general_machine_label: "Account label for all machines" # translation_missing
|
||||||
|
accounting_Training_code: "Trainings code" # translation_missing
|
||||||
|
general_training_code: "Accounting code for all trainings" # translation_missing
|
||||||
|
accounting_Training_label: "Trainings label" # translation_missing
|
||||||
|
general_training_label: "Account label for all trainings" # translation_missing
|
||||||
|
accounting_Event_code: "Events code" # translation_missing
|
||||||
|
general_event_code: "Accounting code for all events" # translation_missing
|
||||||
|
accounting_Event_label: "Events label" # translation_missing
|
||||||
|
general_event_label: "Account label for all events" # translation_missing
|
||||||
|
accounting_Space_code: "Space code" # translation_missing
|
||||||
|
general_space_code: "Accounting code for all spaces" # translation_missing
|
||||||
|
accounting_Space_label: "Spaces label" # translation_missing
|
||||||
|
general_space_label: "Account label for all spaces" # translation_missing
|
||||||
|
accounting_coupon_code: "Coupons code" # translation_missing
|
||||||
|
general_coupon_code: "Accounting code for all coupons" # translation_missing
|
||||||
|
accounting_coupon_label: "Coupons label" # translation_missing
|
||||||
|
general_coupon_label: "Account label for all coupons" # translation_missing
|
||||||
|
customization_of_SETTING_successfully_saved: "Customization of the {{SETTING}} successfully saved." # angular interpolation # translation_missing
|
||||||
|
export_accounting_data: "Export accounting data" # translation_missing
|
||||||
|
export_to: "Export to the accounting software" # translation_missing
|
||||||
|
export_is_running: "Exportando, será notificado cuando esté listo."
|
||||||
|
acd: "ACD" # translation_missing
|
||||||
|
export_form_date: "Export from" # translation_missing
|
||||||
|
export_to_date: "Export until" # translation_missing
|
||||||
|
format: "File format" # translation_missing
|
||||||
|
encoding: "Encoding" # translation_missing
|
||||||
|
separator: "Separator" # translation_missing
|
||||||
|
dateFormat: "Date format" # translation_missing
|
||||||
|
columns: "Columns" # translation_missing
|
||||||
|
exportColumns: # translation_missing
|
||||||
|
journal_code: "Journal code" # translation_missing
|
||||||
|
date: "Entry date" # translation_missing
|
||||||
|
account_code: "Account code" # translation_missing
|
||||||
|
account_label: "Account label" # translation_missing
|
||||||
|
piece: "Document" # translation_missing
|
||||||
|
line_label: "Entry label" # translation_missing
|
||||||
|
debit_origin: "Origin debit" # translation_missing
|
||||||
|
credit_origin: "Origin credit" # translation_missing
|
||||||
|
debit_euro: "Euro debit" # translation_missing
|
||||||
|
credit_euro: "Euro credit" # translation_missing
|
||||||
|
lettering: "Lettering" # translation_missing
|
||||||
|
|
||||||
members:
|
members:
|
||||||
# management of users, labels, groups, and so on
|
# management of users, labels, groups, and so on
|
||||||
|
@ -432,6 +432,69 @@ fr:
|
|||||||
period_START_END_closed_success: "La période comptable du {{START}} au {{END}} a bien été clôturée. La génération de l'archive est en cours, vous serez prévenu lorsque celle-ci sera terminée."
|
period_START_END_closed_success: "La période comptable du {{START}} au {{END}} a bien été clôturée. La génération de l'archive est en cours, vous serez prévenu lorsque celle-ci sera terminée."
|
||||||
failed_to_close_period: "Une erreur est survenue, impossible de clôturer la période comptable"
|
failed_to_close_period: "Une erreur est survenue, impossible de clôturer la période comptable"
|
||||||
no_periods: "Aucune clôture pour le moment"
|
no_periods: "Aucune clôture pour le moment"
|
||||||
|
accounting_codes: "Codes comptables"
|
||||||
|
accounting_journal_code: "Code journal"
|
||||||
|
general_journal_code: "Code journal"
|
||||||
|
accounting_client_code: "Code clients"
|
||||||
|
general_client_code: "Code comptable pour tous les clients"
|
||||||
|
accounting_client_label: "Libellé client"
|
||||||
|
general_client_label: "Libellé du compte pour tous les clients"
|
||||||
|
accounting_wallet_code: "Code porte-monnaie"
|
||||||
|
general_wallet_code: "Code comptable pour le crédit du porte-monnaie"
|
||||||
|
accounting_wallet_label: "Libellé porte-monnaie"
|
||||||
|
general_wallet_label: "Libellé du compte pour le crédit du porte-monnaie"
|
||||||
|
accounting_vat_code: "Code TVA"
|
||||||
|
general_vat_code: "Code comptable pour la TVA"
|
||||||
|
accounting_vat_label: "Libellé TVA"
|
||||||
|
general_vat_label: "Libellé du compte TVA"
|
||||||
|
accounting_subscription_code: "Code abonnements"
|
||||||
|
general_subscription_code: "Code comptable pour tous les abonnements"
|
||||||
|
accounting_subscription_label: "Libellé abonnements"
|
||||||
|
general_subscription_label: "Libellé du compte pour tous les abonnements"
|
||||||
|
accounting_machine_code: "Code machines"
|
||||||
|
general_machine_code: "Code comptable pour toutes les machines"
|
||||||
|
accounting_Machine_label: "Libellé machine"
|
||||||
|
general_machine_label: "Libellé du compte pour toutes les machines"
|
||||||
|
accounting_Training_code: "Code formations"
|
||||||
|
general_training_code: "Code comptable pour toutes les formations"
|
||||||
|
accounting_Training_label: "Libellé formations"
|
||||||
|
general_training_label: "Libellé du compte pour toutes les formations"
|
||||||
|
accounting_Event_code: "Code évènements"
|
||||||
|
general_event_code: "Code comptable pour tous les évènements"
|
||||||
|
accounting_Event_label: "Libellé évènements"
|
||||||
|
general_event_label: "Libellé du compte pour tous les évènements"
|
||||||
|
accounting_Space_code: "Code espaces"
|
||||||
|
general_space_code: "Code comptable pour tous les espaces"
|
||||||
|
accounting_Space_label: "Libellé espaces"
|
||||||
|
general_space_label: "Libellé du compte pour tous les espaces"
|
||||||
|
accounting_coupon_code: "Code pour codes promo"
|
||||||
|
general_coupon_code: "Code comptable pour tous les codes promo"
|
||||||
|
accounting_coupon_label: "Libellé codes promo"
|
||||||
|
general_coupon_label: "Libellé du compte pour tous les codes promo"
|
||||||
|
customization_of_SETTING_successfully_saved: "La personnalisation de {{SETTING}} a bien été enregistrée." # angular interpolation
|
||||||
|
export_accounting_data: "Exporter les données comptables"
|
||||||
|
export_to: "Exporter vers le logiciel comptable"
|
||||||
|
export_is_running: "L'export est en cours. Vous serez notifié lorsqu'il sera prêt."
|
||||||
|
acd: "ACD"
|
||||||
|
export_form_date: "Exporter depuis le"
|
||||||
|
export_to_date: "Exporter jusqu'au"
|
||||||
|
format: "Format de fichier"
|
||||||
|
encoding: "Encodage"
|
||||||
|
separator: "Séparateur"
|
||||||
|
dateFormat: "Format de date"
|
||||||
|
columns: "Colonnes"
|
||||||
|
exportColumns:
|
||||||
|
journal_code: "Code journal"
|
||||||
|
date: "Date écriture"
|
||||||
|
account_code: "Code compte"
|
||||||
|
account_label: "Intitulé compte"
|
||||||
|
piece: "Pièce"
|
||||||
|
line_label: "Libellé écriture"
|
||||||
|
debit_origin: "Débit origine"
|
||||||
|
credit_origin: "Crédit origine"
|
||||||
|
debit_euro: "Débit euro"
|
||||||
|
credit_euro: "Crédit euro"
|
||||||
|
lettering: "Lettrage"
|
||||||
|
|
||||||
members:
|
members:
|
||||||
# gestion des utilisateurs, des groupes, des étiquettes, etc.
|
# gestion des utilisateurs, des groupes, des étiquettes, etc.
|
||||||
|
@ -432,6 +432,69 @@ pt:
|
|||||||
period_START_END_closed_success: "The accounting period from {{START}} to {{END}} has been successfully closed. Archive generation is running, you'll be notified when it's done." # translation_missing
|
period_START_END_closed_success: "The accounting period from {{START}} to {{END}} has been successfully closed. Archive generation is running, you'll be notified when it's done." # translation_missing
|
||||||
failed_to_close_period: "An error occurred, unable to close the accounting period" # translation_missing
|
failed_to_close_period: "An error occurred, unable to close the accounting period" # translation_missing
|
||||||
no_periods: "No closings for now" # translation_missing
|
no_periods: "No closings for now" # translation_missing
|
||||||
|
accounting_codes: "Accounting codes" # translation_missing
|
||||||
|
accounting_journal_code: "Journal code" # translation_missing
|
||||||
|
general_journal_code: "Journal code" # translation_missing
|
||||||
|
accounting_client_code: "Customers code" # translation_missing
|
||||||
|
general_client_code: "Accounting code for all customers" # translation_missing
|
||||||
|
accounting_client_label: "Customers label" # translation_missing
|
||||||
|
general_client_label: "Account label for all customers" # translation_missing
|
||||||
|
accounting_wallet_code: "Wallet code" # translation_missing
|
||||||
|
general_wallet_code: "Accounting code for wallet credit" # translation_missing
|
||||||
|
accounting_wallet_label: "Wallet label" # translation_missing
|
||||||
|
general_wallet_label: "Account label for wallet credit" # translation_missing
|
||||||
|
accounting_vat_code: "VAT code" # translation_missing
|
||||||
|
general_vat_code: "Accounting code for VAT" # translation_missing
|
||||||
|
accounting_vat_label: "VAT label" # translation_missing
|
||||||
|
general_vat_label: "VAT account label" # translation_missing
|
||||||
|
accounting_subscription_code: "Subscriptions code" # translation_missing
|
||||||
|
general_subscription_code: "Accounting code for all subscriptions" # translation_missing
|
||||||
|
accounting_subscription_label: "Subscriptions label" # translation_missing
|
||||||
|
general_subscription_label: "Account label for all subscriptions" # translation_missing
|
||||||
|
accounting_Machine_code: "Machines code" # translation_missing
|
||||||
|
general_machine_code: "Accounting code for all machines" # translation_missing
|
||||||
|
accounting_Machine_label: "Machine label" # translation_missing
|
||||||
|
general_machine_label: "Account label for all machines" # translation_missing
|
||||||
|
accounting_Training_code: "Trainings code" # translation_missing
|
||||||
|
general_training_code: "Accounting code for all trainings" # translation_missing
|
||||||
|
accounting_Training_label: "Trainings label" # translation_missing
|
||||||
|
general_training_label: "Account label for all trainings" # translation_missing
|
||||||
|
accounting_Event_code: "Events code" # translation_missing
|
||||||
|
general_event_code: "Accounting code for all events" # translation_missing
|
||||||
|
accounting_Event_label: "Events label" # translation_missing
|
||||||
|
general_event_label: "Account label for all events" # translation_missing
|
||||||
|
accounting_Space_code: "Space code" # translation_missing
|
||||||
|
general_space_code: "Accounting code for all spaces" # translation_missing
|
||||||
|
accounting_Space_label: "Spaces label" # translation_missing
|
||||||
|
general_space_label: "Account label for all spaces" # translation_missing
|
||||||
|
accounting_coupon_code: "Coupons code" # translation_missing
|
||||||
|
general_coupon_code: "Accounting code for all coupons" # translation_missing
|
||||||
|
accounting_coupon_label: "Coupons label" # translation_missing
|
||||||
|
general_coupon_label: "Account label for all coupons" # translation_missing
|
||||||
|
customization_of_SETTING_successfully_saved: "Customization of the {{SETTING}} successfully saved." # angular interpolation # translation_missing
|
||||||
|
export_accounting_data: "Export accounting data" # translation_missing
|
||||||
|
export_to: "Export to the accounting software" # translation_missing
|
||||||
|
export_is_running: "A Exportação está em andamento. Você será notificado quando terminar."
|
||||||
|
acd: "ACD" # translation_missing
|
||||||
|
export_form_date: "Export from" # translation_missing
|
||||||
|
export_to_date: "Export until" # translation_missing
|
||||||
|
format: "File format" # translation_missing
|
||||||
|
encoding: "Encoding" # translation_missing
|
||||||
|
separator: "Separator" # translation_missing
|
||||||
|
dateFormat: "Date format" # translation_missing
|
||||||
|
columns: "Columns" # translation_missing
|
||||||
|
exportColumns: # translation_missing
|
||||||
|
journal_code: "Journal code" # translation_missing
|
||||||
|
date: "Entry date" # translation_missing
|
||||||
|
account_code: "Account code" # translation_missing
|
||||||
|
account_label: "Account label" # translation_missing
|
||||||
|
piece: "Document" # translation_missing
|
||||||
|
line_label: "Entry label" # translation_missing
|
||||||
|
debit_origin: "Origin debit" # translation_missing
|
||||||
|
credit_origin: "Origin credit" # translation_missing
|
||||||
|
debit_euro: "Euro debit" # translation_missing
|
||||||
|
credit_euro: "Euro credit" # translation_missing
|
||||||
|
lettering: "Lettering" # translation_missing
|
||||||
|
|
||||||
members:
|
members:
|
||||||
# management of users, labels, groups, and so on
|
# management of users, labels, groups, and so on
|
||||||
|
@ -113,8 +113,8 @@ en:
|
|||||||
by_cheque: "by cheque"
|
by_cheque: "by cheque"
|
||||||
by_transfer: "by transfer"
|
by_transfer: "by transfer"
|
||||||
by_cash: "by cash"
|
by_cash: "by cash"
|
||||||
no_refund: "No refund"
|
|
||||||
by_wallet: "by wallet"
|
by_wallet: "by wallet"
|
||||||
|
no_refund: "No refund"
|
||||||
settlement_by_debit_card: "Settlement by debit card"
|
settlement_by_debit_card: "Settlement by debit card"
|
||||||
settlement_done_at_the_reception: "Settlement done at the reception"
|
settlement_done_at_the_reception: "Settlement done at the reception"
|
||||||
settlement_by_wallet: "Settlement by wallet"
|
settlement_by_wallet: "Settlement by wallet"
|
||||||
@ -126,6 +126,20 @@ 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'
|
||||||
|
|
||||||
|
accounting_export:
|
||||||
|
journal_code: "Journal code"
|
||||||
|
date: "Entry date"
|
||||||
|
account_code: "Account code"
|
||||||
|
account_label: "Account label"
|
||||||
|
piece: "Document"
|
||||||
|
line_label: "Entry label"
|
||||||
|
debit_origin: "Origin debit"
|
||||||
|
credit_origin: "Origin credit"
|
||||||
|
debit_euro: "Euro debit"
|
||||||
|
credit_euro: "Euro credit"
|
||||||
|
lettering: "Lettering"
|
||||||
|
VAT: 'VAT'
|
||||||
|
|
||||||
trainings:
|
trainings:
|
||||||
# training availabilities
|
# training availabilities
|
||||||
i_ve_reserved: "I've reserved"
|
i_ve_reserved: "I've reserved"
|
||||||
@ -307,6 +321,7 @@ en:
|
|||||||
users_subscriptions: "of the subscriptions' list"
|
users_subscriptions: "of the subscriptions' list"
|
||||||
users_reservations: "of the reservations' list"
|
users_reservations: "of the reservations' list"
|
||||||
availabilities_index: "of the reservations availabilities"
|
availabilities_index: "of the reservations availabilities"
|
||||||
|
accounting_accounting-software: "of the accounting data"
|
||||||
is_over: "is over."
|
is_over: "is over."
|
||||||
download_here: "Download here"
|
download_here: "Download here"
|
||||||
notify_member_about_coupon:
|
notify_member_about_coupon:
|
||||||
|
@ -126,6 +126,20 @@ es:
|
|||||||
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Subscripción de %{NAME} extendida (Free days) empezando desde %{STARTDATE} hasta %{ENDDATE}"
|
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Subscripción de %{NAME} extendida (Free days) empezando desde %{STARTDATE} hasta %{ENDDATE}"
|
||||||
and: 'y'
|
and: 'y'
|
||||||
|
|
||||||
|
accounting_export:
|
||||||
|
journal_code: "Journal code" # translation_missing
|
||||||
|
date: "Entry date" # translation_missing
|
||||||
|
account_code: "Account code" # translation_missing
|
||||||
|
account_label: "Account label" # translation_missing
|
||||||
|
piece: "Document" # translation_missing
|
||||||
|
line_label: "Entry label" # translation_missing
|
||||||
|
debit_origin: "Origin debit" # translation_missing
|
||||||
|
credit_origin: "Origin credit" # translation_missing
|
||||||
|
debit_euro: "Euro debit" # translation_missing
|
||||||
|
credit_euro: "Euro credit" # translation_missing
|
||||||
|
lettering: "Lettering" # translation_missing
|
||||||
|
VAT: 'IVA'
|
||||||
|
|
||||||
trainings:
|
trainings:
|
||||||
# training availabilities
|
# training availabilities
|
||||||
i_ve_reserved: "he reservado"
|
i_ve_reserved: "he reservado"
|
||||||
@ -307,6 +321,7 @@ es:
|
|||||||
users_subscriptions: "de la lista de suscripciones"
|
users_subscriptions: "de la lista de suscripciones"
|
||||||
users_reservations: "de la lista de reservas"
|
users_reservations: "de la lista de reservas"
|
||||||
availabilities_index: "de las reservas disponibles"
|
availabilities_index: "de las reservas disponibles"
|
||||||
|
accounting_accounting-software: "de los datos contables"
|
||||||
is_over: "se ha acabado."
|
is_over: "se ha acabado."
|
||||||
download_here: "Descargar aquí"
|
download_here: "Descargar aquí"
|
||||||
notify_member_about_coupon:
|
notify_member_about_coupon:
|
||||||
|
@ -126,6 +126,20 @@ 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'
|
||||||
|
|
||||||
|
accounting_export:
|
||||||
|
journal_code: "Code journal"
|
||||||
|
date: "Date écriture"
|
||||||
|
account_code: "Code compte"
|
||||||
|
account_label: "Intitulé compte"
|
||||||
|
piece: "Pièce"
|
||||||
|
line_label: "Libellé écriture"
|
||||||
|
debit_origin: "Débit origine"
|
||||||
|
credit_origin: "Crédit origine"
|
||||||
|
debit_euro: "Débit euro"
|
||||||
|
credit_euro: "Crédit euro"
|
||||||
|
lettering: "Lettrage"
|
||||||
|
VAT: 'TVA'
|
||||||
|
|
||||||
trainings:
|
trainings:
|
||||||
# disponibilités formations
|
# disponibilités formations
|
||||||
i_ve_reserved: "J'ai réservé"
|
i_ve_reserved: "J'ai réservé"
|
||||||
@ -307,6 +321,7 @@ fr:
|
|||||||
users_subscriptions: "de la liste des abonnements"
|
users_subscriptions: "de la liste des abonnements"
|
||||||
users_reservations: "de la liste des réservations"
|
users_reservations: "de la liste des réservations"
|
||||||
availabilities_index: "des disponibilités de réservations"
|
availabilities_index: "des disponibilités de réservations"
|
||||||
|
accounting_accounting-software: "des données comptables"
|
||||||
is_over: "est terminé."
|
is_over: "est terminé."
|
||||||
download_here: "Téléchargez ici"
|
download_here: "Téléchargez ici"
|
||||||
notify_member_about_coupon:
|
notify_member_about_coupon:
|
||||||
|
@ -267,8 +267,12 @@ en:
|
|||||||
users_subscriptions: "of the subscriptions' list"
|
users_subscriptions: "of the subscriptions' list"
|
||||||
users_reservations: "of the reservations' list"
|
users_reservations: "of the reservations' list"
|
||||||
availabilities_index: "of the reservations availabilities"
|
availabilities_index: "of the reservations availabilities"
|
||||||
|
accounting_accounting-software: "of the accounting data"
|
||||||
click_to_download: "Excel file generated successfully. To download it, click"
|
click_to_download: "Excel file generated successfully. To download it, click"
|
||||||
here: "here"
|
here: "here"
|
||||||
|
file_type:
|
||||||
|
xlsx: "Excel"
|
||||||
|
csv: "CSV"
|
||||||
|
|
||||||
notify_member_about_coupon:
|
notify_member_about_coupon:
|
||||||
subject: "Coupon"
|
subject: "Coupon"
|
||||||
|
@ -266,8 +266,12 @@ es:
|
|||||||
users_subscriptions: "de la lista de suscripciones"
|
users_subscriptions: "de la lista de suscripciones"
|
||||||
users_reservations: "de la lista de reservas"
|
users_reservations: "de la lista de reservas"
|
||||||
availabilities_index: "de las reservas disponibles"
|
availabilities_index: "de las reservas disponibles"
|
||||||
|
accounting_accounting-software: "de los datos contables"
|
||||||
click_to_download: " archivo Excel generado correctamente. Para descargarlo, haga clic "
|
click_to_download: " archivo Excel generado correctamente. Para descargarlo, haga clic "
|
||||||
here: "aquí"
|
here: "aquí"
|
||||||
|
file_type:
|
||||||
|
xlsx: "Excel"
|
||||||
|
csv: "CSV"
|
||||||
|
|
||||||
notify_member_about_coupon:
|
notify_member_about_coupon:
|
||||||
subject: "Cupón"
|
subject: "Cupón"
|
||||||
|
@ -267,8 +267,12 @@ fr:
|
|||||||
users_subscriptions: "de la liste des abonnements"
|
users_subscriptions: "de la liste des abonnements"
|
||||||
users_reservations: "de la liste des réservations"
|
users_reservations: "de la liste des réservations"
|
||||||
availabilities_index: "des disponibilités de réservations"
|
availabilities_index: "des disponibilités de réservations"
|
||||||
click_to_download: "La génération est terminée. Pour télécharger le fichier Excel, cliquez"
|
accounting_accounting-software: "des données comptables"
|
||||||
|
click_to_download: "La génération est terminée. Pour télécharger le fichier %{TYPE}, cliquez"
|
||||||
here: "ici"
|
here: "ici"
|
||||||
|
file_type:
|
||||||
|
xlsx: "Excel"
|
||||||
|
csv: "CSV"
|
||||||
|
|
||||||
notify_member_about_coupon:
|
notify_member_about_coupon:
|
||||||
subject: "Code promo"
|
subject: "Code promo"
|
||||||
|
@ -267,8 +267,12 @@ pt:
|
|||||||
users_subscriptions: "da lista de assinaturas"
|
users_subscriptions: "da lista de assinaturas"
|
||||||
users_reservations: "da lista de reservas"
|
users_reservations: "da lista de reservas"
|
||||||
availabilities_index: "as reservas disponíveis"
|
availabilities_index: "as reservas disponíveis"
|
||||||
|
accounting_accounting-software: "de dados contábeis"
|
||||||
click_to_download: "Arquivo do Excel gerado com êxito. Para fazer o download, clique"
|
click_to_download: "Arquivo do Excel gerado com êxito. Para fazer o download, clique"
|
||||||
here: "aqui"
|
here: "aqui"
|
||||||
|
file_type:
|
||||||
|
xlsx: "Excel"
|
||||||
|
csv: "CSV"
|
||||||
|
|
||||||
notify_member_about_coupon:
|
notify_member_about_coupon:
|
||||||
subject: "Cupom"
|
subject: "Cupom"
|
||||||
|
@ -126,6 +126,20 @@ pt:
|
|||||||
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Assinatura de %{NAME} estendida (dias livres) a partir de% STARTDATE até %{ENDDATE}"
|
subscription_of_NAME_extended_starting_from_STARTDATE_until_ENDDATE: "Assinatura de %{NAME} estendida (dias livres) a partir de% STARTDATE até %{ENDDATE}"
|
||||||
and: 'e'
|
and: 'e'
|
||||||
|
|
||||||
|
accounting_export:
|
||||||
|
journal_code: "Journal code" # translation_missing
|
||||||
|
date: "Entry date" # translation_missing
|
||||||
|
account_code: "Account code" # translation_missing
|
||||||
|
account_label: "Account label" # translation_missing
|
||||||
|
piece: "Document" # translation_missing
|
||||||
|
line_label: "Entry label" # translation_missing
|
||||||
|
debit_origin: "Origin debit" # translation_missing
|
||||||
|
credit_origin: "Origin credit" # translation_missing
|
||||||
|
debit_euro: "Euro debit" # translation_missing
|
||||||
|
credit_euro: "Euro credit" # translation_missing
|
||||||
|
lettering: "Lettering" # translation_missing
|
||||||
|
VAT: 'IVA'
|
||||||
|
|
||||||
trainings:
|
trainings:
|
||||||
# training availabilities
|
# training availabilities
|
||||||
i_ve_reserved: "Eu reservei"
|
i_ve_reserved: "Eu reservei"
|
||||||
@ -307,6 +321,7 @@ pt:
|
|||||||
users_subscriptions: "da lista de assinaturas"
|
users_subscriptions: "da lista de assinaturas"
|
||||||
users_reservations: "da lista de reservas"
|
users_reservations: "da lista de reservas"
|
||||||
availabilities_index: "de reservas disponíveis"
|
availabilities_index: "de reservas disponíveis"
|
||||||
|
accounting_accounting-software: "de dados contábeis"
|
||||||
is_over: "está finalizado."
|
is_over: "está finalizado."
|
||||||
download_here: "Baixe aqui"
|
download_here: "Baixe aqui"
|
||||||
notify_member_about_coupon:
|
notify_member_about_coupon:
|
||||||
|
@ -106,6 +106,7 @@ Rails.application.routes.draw do
|
|||||||
resources :invoices, only: %i[index show create] do
|
resources :invoices, only: %i[index show create] do
|
||||||
get 'download', action: 'download', on: :member
|
get 'download', action: 'download', on: :member
|
||||||
post 'list', action: 'list', on: :collection
|
post 'list', action: 'list', on: :collection
|
||||||
|
get 'first', action: 'first', on: :collection
|
||||||
end
|
end
|
||||||
|
|
||||||
# for admin
|
# for admin
|
||||||
@ -135,6 +136,8 @@ Rails.application.routes.draw do
|
|||||||
get 'last_closing_end', on: :collection
|
get 'last_closing_end', on: :collection
|
||||||
get 'archive', action: 'download_archive', on: :member
|
get 'archive', action: 'download_archive', on: :member
|
||||||
end
|
end
|
||||||
|
# export accounting data to csv or equivalent
|
||||||
|
post 'accounting/export' => 'accounting_exports#export'
|
||||||
|
|
||||||
# i18n
|
# i18n
|
||||||
# regex allows using dots in URL for 'state'
|
# 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
|
187
db/schema.rb
187
db/schema.rb
@ -11,12 +11,12 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# 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
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
enable_extension "unaccent"
|
|
||||||
enable_extension "pg_trgm"
|
enable_extension "pg_trgm"
|
||||||
|
enable_extension "unaccent"
|
||||||
|
|
||||||
create_table "abuses", force: :cascade do |t|
|
create_table "abuses", force: :cascade do |t|
|
||||||
t.integer "signaled_id"
|
t.integer "signaled_id"
|
||||||
@ -44,14 +44,14 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
end
|
end
|
||||||
|
|
||||||
create_table "addresses", force: :cascade do |t|
|
create_table "addresses", force: :cascade do |t|
|
||||||
t.string "address"
|
t.string "address", limit: 255
|
||||||
t.string "street_number"
|
t.string "street_number", limit: 255
|
||||||
t.string "route"
|
t.string "route", limit: 255
|
||||||
t.string "locality"
|
t.string "locality", limit: 255
|
||||||
t.string "country"
|
t.string "country", limit: 255
|
||||||
t.string "postal_code"
|
t.string "postal_code", limit: 255
|
||||||
t.integer "placeable_id"
|
t.integer "placeable_id"
|
||||||
t.string "placeable_type"
|
t.string "placeable_type", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
end
|
end
|
||||||
@ -67,9 +67,9 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
|
|
||||||
create_table "assets", force: :cascade do |t|
|
create_table "assets", force: :cascade do |t|
|
||||||
t.integer "viewable_id"
|
t.integer "viewable_id"
|
||||||
t.string "viewable_type"
|
t.string "viewable_type", limit: 255
|
||||||
t.string "attachment"
|
t.string "attachment", limit: 255
|
||||||
t.string "type"
|
t.string "type", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
end
|
end
|
||||||
@ -86,12 +86,12 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
create_table "availabilities", force: :cascade do |t|
|
create_table "availabilities", force: :cascade do |t|
|
||||||
t.datetime "start_at"
|
t.datetime "start_at"
|
||||||
t.datetime "end_at"
|
t.datetime "end_at"
|
||||||
t.string "available_type"
|
t.string "available_type", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.integer "nb_total_places"
|
t.integer "nb_total_places"
|
||||||
t.boolean "destroying", default: false
|
t.boolean "destroying", default: false
|
||||||
t.boolean "lock", default: false
|
t.boolean "lock", default: false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "availability_tags", force: :cascade do |t|
|
create_table "availability_tags", force: :cascade do |t|
|
||||||
@ -105,7 +105,7 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
add_index "availability_tags", ["tag_id"], name: "index_availability_tags_on_tag_id", using: :btree
|
add_index "availability_tags", ["tag_id"], name: "index_availability_tags_on_tag_id", using: :btree
|
||||||
|
|
||||||
create_table "categories", force: :cascade do |t|
|
create_table "categories", force: :cascade do |t|
|
||||||
t.string "name"
|
t.string "name", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "slug"
|
t.string "slug"
|
||||||
@ -114,7 +114,7 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
add_index "categories", ["slug"], name: "index_categories_on_slug", unique: true, using: :btree
|
add_index "categories", ["slug"], name: "index_categories_on_slug", unique: true, using: :btree
|
||||||
|
|
||||||
create_table "components", force: :cascade do |t|
|
create_table "components", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", limit: 255, null: false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "coupons", force: :cascade do |t|
|
create_table "coupons", force: :cascade do |t|
|
||||||
@ -132,7 +132,7 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
|
|
||||||
create_table "credits", force: :cascade do |t|
|
create_table "credits", force: :cascade do |t|
|
||||||
t.integer "creditable_id"
|
t.integer "creditable_id"
|
||||||
t.string "creditable_type"
|
t.string "creditable_type", limit: 255
|
||||||
t.integer "plan_id"
|
t.integer "plan_id"
|
||||||
t.integer "hours"
|
t.integer "hours"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
@ -173,7 +173,7 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
add_index "event_themes", ["slug"], name: "index_event_themes_on_slug", unique: true, using: :btree
|
add_index "event_themes", ["slug"], name: "index_event_themes_on_slug", unique: true, using: :btree
|
||||||
|
|
||||||
create_table "events", force: :cascade do |t|
|
create_table "events", force: :cascade do |t|
|
||||||
t.string "title"
|
t.string "title", limit: 255
|
||||||
t.text "description"
|
t.text "description"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
@ -202,19 +202,20 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
t.string "category"
|
t.string "category"
|
||||||
t.string "export_type"
|
t.string "export_type"
|
||||||
t.string "query"
|
t.string "query"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
t.string "key"
|
t.string "key"
|
||||||
|
t.string "extension", default: "xlsx"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "exports", ["user_id"], name: "index_exports_on_user_id", using: :btree
|
add_index "exports", ["user_id"], name: "index_exports_on_user_id", using: :btree
|
||||||
|
|
||||||
create_table "friendly_id_slugs", force: :cascade do |t|
|
create_table "friendly_id_slugs", force: :cascade do |t|
|
||||||
t.string "slug", null: false
|
t.string "slug", limit: 255, null: false
|
||||||
t.integer "sluggable_id", null: false
|
t.integer "sluggable_id", null: false
|
||||||
t.string "sluggable_type", limit: 50
|
t.string "sluggable_type", limit: 50
|
||||||
t.string "scope"
|
t.string "scope", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -224,10 +225,10 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type", using: :btree
|
add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type", using: :btree
|
||||||
|
|
||||||
create_table "groups", force: :cascade do |t|
|
create_table "groups", force: :cascade do |t|
|
||||||
t.string "name"
|
t.string "name", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "slug"
|
t.string "slug", limit: 255
|
||||||
t.boolean "disabled"
|
t.boolean "disabled"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -247,7 +248,7 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
|
|
||||||
create_table "invoice_items", force: :cascade do |t|
|
create_table "invoice_items", force: :cascade do |t|
|
||||||
t.integer "invoice_id"
|
t.integer "invoice_id"
|
||||||
t.string "stp_invoice_item_id"
|
t.string "stp_invoice_item_id", limit: 255
|
||||||
t.integer "amount"
|
t.integer "amount"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
@ -261,16 +262,16 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
|
|
||||||
create_table "invoices", force: :cascade do |t|
|
create_table "invoices", force: :cascade do |t|
|
||||||
t.integer "invoiced_id"
|
t.integer "invoiced_id"
|
||||||
t.string "invoiced_type"
|
t.string "invoiced_type", limit: 255
|
||||||
t.string "stp_invoice_id"
|
t.string "stp_invoice_id", limit: 255
|
||||||
t.integer "total"
|
t.integer "total"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "reference"
|
t.string "reference", limit: 255
|
||||||
t.string "avoir_mode"
|
t.string "avoir_mode", limit: 255
|
||||||
t.datetime "avoir_date"
|
t.datetime "avoir_date"
|
||||||
t.integer "invoice_id"
|
t.integer "invoice_id"
|
||||||
t.string "type"
|
t.string "type", limit: 255
|
||||||
t.boolean "subscription_to_expire"
|
t.boolean "subscription_to_expire"
|
||||||
t.text "description"
|
t.text "description"
|
||||||
t.integer "wallet_amount"
|
t.integer "wallet_amount"
|
||||||
@ -301,17 +302,17 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
add_index "invoicing_profiles", ["user_id"], name: "index_invoicing_profiles_on_user_id", using: :btree
|
add_index "invoicing_profiles", ["user_id"], name: "index_invoicing_profiles_on_user_id", using: :btree
|
||||||
|
|
||||||
create_table "licences", force: :cascade do |t|
|
create_table "licences", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", limit: 255, null: false
|
||||||
t.text "description"
|
t.text "description"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "machines", force: :cascade do |t|
|
create_table "machines", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", limit: 255, null: false
|
||||||
t.text "description"
|
t.text "description"
|
||||||
t.text "spec"
|
t.text "spec"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "slug"
|
t.string "slug", limit: 255
|
||||||
t.boolean "disabled"
|
t.boolean "disabled"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -328,14 +329,14 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
create_table "notifications", force: :cascade do |t|
|
create_table "notifications", force: :cascade do |t|
|
||||||
t.integer "receiver_id"
|
t.integer "receiver_id"
|
||||||
t.integer "attached_object_id"
|
t.integer "attached_object_id"
|
||||||
t.string "attached_object_type"
|
t.string "attached_object_type", limit: 255
|
||||||
t.integer "notification_type_id"
|
t.integer "notification_type_id"
|
||||||
t.boolean "is_read", default: false
|
t.boolean "is_read", default: false
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "receiver_type"
|
t.string "receiver_type"
|
||||||
t.boolean "is_send", default: false
|
t.boolean "is_send", default: false
|
||||||
t.jsonb "meta_data", default: {}
|
t.jsonb "meta_data", default: {}
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "notifications", ["notification_type_id"], name: "index_notifications_on_notification_type_id", using: :btree
|
add_index "notifications", ["notification_type_id"], name: "index_notifications_on_notification_type_id", using: :btree
|
||||||
@ -404,20 +405,20 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
add_index "organizations", ["invoicing_profile_id"], name: "index_organizations_on_invoicing_profile_id", using: :btree
|
add_index "organizations", ["invoicing_profile_id"], name: "index_organizations_on_invoicing_profile_id", using: :btree
|
||||||
|
|
||||||
create_table "plans", force: :cascade do |t|
|
create_table "plans", force: :cascade do |t|
|
||||||
t.string "name"
|
t.string "name", limit: 255
|
||||||
t.integer "amount"
|
t.integer "amount"
|
||||||
t.string "interval"
|
t.string "interval", limit: 255
|
||||||
t.integer "group_id"
|
t.integer "group_id"
|
||||||
t.string "stp_plan_id"
|
t.string "stp_plan_id", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.integer "training_credit_nb", default: 0
|
t.integer "training_credit_nb", default: 0
|
||||||
t.boolean "is_rolling", default: true
|
t.boolean "is_rolling", default: true
|
||||||
t.text "description"
|
t.text "description"
|
||||||
t.string "type"
|
t.string "type"
|
||||||
t.string "base_name"
|
t.string "base_name"
|
||||||
t.integer "ui_weight", default: 0
|
t.integer "ui_weight", default: 0
|
||||||
t.integer "interval_count", default: 1
|
t.integer "interval_count", default: 1
|
||||||
t.string "slug"
|
t.string "slug"
|
||||||
t.boolean "disabled"
|
t.boolean "disabled"
|
||||||
end
|
end
|
||||||
@ -447,9 +448,9 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
|
|
||||||
create_table "profiles", force: :cascade do |t|
|
create_table "profiles", force: :cascade do |t|
|
||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
t.string "first_name"
|
t.string "first_name", limit: 255
|
||||||
t.string "last_name"
|
t.string "last_name", limit: 255
|
||||||
t.string "phone"
|
t.string "phone", limit: 255
|
||||||
t.text "interest"
|
t.text "interest"
|
||||||
t.text "software_mastered"
|
t.text "software_mastered"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
@ -479,7 +480,7 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
t.integer "project_id"
|
t.integer "project_id"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "title"
|
t.string "title", limit: 255
|
||||||
t.integer "step_nb"
|
t.integer "step_nb"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -490,27 +491,27 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
t.integer "user_id"
|
t.integer "user_id"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.boolean "is_valid", default: false
|
t.boolean "is_valid", default: false
|
||||||
t.string "valid_token"
|
t.string "valid_token", limit: 255
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "project_users", ["project_id"], name: "index_project_users_on_project_id", using: :btree
|
add_index "project_users", ["project_id"], name: "index_project_users_on_project_id", using: :btree
|
||||||
add_index "project_users", ["user_id"], name: "index_project_users_on_user_id", using: :btree
|
add_index "project_users", ["user_id"], name: "index_project_users_on_user_id", using: :btree
|
||||||
|
|
||||||
create_table "projects", force: :cascade do |t|
|
create_table "projects", force: :cascade do |t|
|
||||||
t.string "name"
|
t.string "name", limit: 255
|
||||||
t.text "description"
|
t.text "description"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.text "tags"
|
t.text "tags"
|
||||||
t.integer "licence_id"
|
t.integer "licence_id"
|
||||||
t.string "state"
|
t.string "state", limit: 255
|
||||||
t.string "slug"
|
t.string "slug", limit: 255
|
||||||
t.datetime "published_at"
|
t.datetime "published_at"
|
||||||
t.integer "author_statistic_profile_id"
|
t.integer "author_statistic_profile_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "projects", ["slug"], name: "index_projects_on_slug", unique: true, using: :btree
|
add_index "projects", ["slug"], name: "index_projects_on_slug", using: :btree
|
||||||
|
|
||||||
create_table "projects_components", force: :cascade do |t|
|
create_table "projects_components", force: :cascade do |t|
|
||||||
t.integer "project_id"
|
t.integer "project_id"
|
||||||
@ -549,20 +550,20 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.integer "reservable_id"
|
t.integer "reservable_id"
|
||||||
t.string "reservable_type"
|
t.string "reservable_type", limit: 255
|
||||||
t.string "stp_invoice_id"
|
t.string "stp_invoice_id", limit: 255
|
||||||
t.integer "nb_reserve_places"
|
t.integer "nb_reserve_places"
|
||||||
t.integer "statistic_profile_id"
|
t.integer "statistic_profile_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "reservations", ["reservable_type", "reservable_id"], name: "index_reservations_on_reservable_type_and_reservable_id", using: :btree
|
add_index "reservations", ["reservable_id", "reservable_type"], name: "index_reservations_on_reservable_id_and_reservable_type", using: :btree
|
||||||
add_index "reservations", ["statistic_profile_id"], name: "index_reservations_on_statistic_profile_id", using: :btree
|
add_index "reservations", ["statistic_profile_id"], name: "index_reservations_on_statistic_profile_id", using: :btree
|
||||||
add_index "reservations", ["stp_invoice_id"], name: "index_reservations_on_stp_invoice_id", using: :btree
|
add_index "reservations", ["stp_invoice_id"], name: "index_reservations_on_stp_invoice_id", using: :btree
|
||||||
|
|
||||||
create_table "roles", force: :cascade do |t|
|
create_table "roles", force: :cascade do |t|
|
||||||
t.string "name"
|
t.string "name", limit: 255
|
||||||
t.integer "resource_id"
|
t.integer "resource_id"
|
||||||
t.string "resource_type"
|
t.string "resource_type", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
end
|
end
|
||||||
@ -636,18 +637,18 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
|
|
||||||
create_table "statistic_fields", force: :cascade do |t|
|
create_table "statistic_fields", force: :cascade do |t|
|
||||||
t.integer "statistic_index_id"
|
t.integer "statistic_index_id"
|
||||||
t.string "key"
|
t.string "key", limit: 255
|
||||||
t.string "label"
|
t.string "label", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "data_type"
|
t.string "data_type", limit: 255
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "statistic_fields", ["statistic_index_id"], name: "index_statistic_fields_on_statistic_index_id", using: :btree
|
add_index "statistic_fields", ["statistic_index_id"], name: "index_statistic_fields_on_statistic_index_id", using: :btree
|
||||||
|
|
||||||
create_table "statistic_graphs", force: :cascade do |t|
|
create_table "statistic_graphs", force: :cascade do |t|
|
||||||
t.integer "statistic_index_id"
|
t.integer "statistic_index_id"
|
||||||
t.string "chart_type"
|
t.string "chart_type", limit: 255
|
||||||
t.integer "limit"
|
t.integer "limit"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
@ -656,12 +657,12 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
add_index "statistic_graphs", ["statistic_index_id"], name: "index_statistic_graphs_on_statistic_index_id", using: :btree
|
add_index "statistic_graphs", ["statistic_index_id"], name: "index_statistic_graphs_on_statistic_index_id", using: :btree
|
||||||
|
|
||||||
create_table "statistic_indices", force: :cascade do |t|
|
create_table "statistic_indices", force: :cascade do |t|
|
||||||
t.string "es_type_key"
|
t.string "es_type_key", limit: 255
|
||||||
t.string "label"
|
t.string "label", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.boolean "table", default: true
|
t.boolean "table", default: true
|
||||||
t.boolean "ca", default: true
|
t.boolean "ca", default: true
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "statistic_profile_trainings", force: :cascade do |t|
|
create_table "statistic_profile_trainings", force: :cascade do |t|
|
||||||
@ -689,8 +690,8 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
add_index "statistic_profiles", ["user_id"], name: "index_statistic_profiles_on_user_id", using: :btree
|
add_index "statistic_profiles", ["user_id"], name: "index_statistic_profiles_on_user_id", using: :btree
|
||||||
|
|
||||||
create_table "statistic_sub_types", force: :cascade do |t|
|
create_table "statistic_sub_types", force: :cascade do |t|
|
||||||
t.string "key"
|
t.string "key", limit: 255
|
||||||
t.string "label"
|
t.string "label", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
end
|
end
|
||||||
@ -707,8 +708,8 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
|
|
||||||
create_table "statistic_types", force: :cascade do |t|
|
create_table "statistic_types", force: :cascade do |t|
|
||||||
t.integer "statistic_index_id"
|
t.integer "statistic_index_id"
|
||||||
t.string "key"
|
t.string "key", limit: 255
|
||||||
t.string "label"
|
t.string "label", limit: 255
|
||||||
t.boolean "graph"
|
t.boolean "graph"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
@ -725,7 +726,7 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
|
|
||||||
create_table "subscriptions", force: :cascade do |t|
|
create_table "subscriptions", force: :cascade do |t|
|
||||||
t.integer "plan_id"
|
t.integer "plan_id"
|
||||||
t.string "stp_subscription_id"
|
t.string "stp_subscription_id", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.datetime "expiration_date"
|
t.datetime "expiration_date"
|
||||||
@ -745,7 +746,7 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree
|
add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree
|
||||||
|
|
||||||
create_table "themes", force: :cascade do |t|
|
create_table "themes", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", limit: 255, null: false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "tickets", force: :cascade do |t|
|
create_table "tickets", force: :cascade do |t|
|
||||||
@ -760,13 +761,13 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
add_index "tickets", ["reservation_id"], name: "index_tickets_on_reservation_id", using: :btree
|
add_index "tickets", ["reservation_id"], name: "index_tickets_on_reservation_id", using: :btree
|
||||||
|
|
||||||
create_table "trainings", force: :cascade do |t|
|
create_table "trainings", force: :cascade do |t|
|
||||||
t.string "name"
|
t.string "name", limit: 255
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.integer "nb_total_places"
|
t.integer "nb_total_places"
|
||||||
t.string "slug"
|
t.string "slug", limit: 255
|
||||||
t.text "description"
|
t.text "description"
|
||||||
t.boolean "public_page", default: true
|
t.boolean "public_page", default: true
|
||||||
t.boolean "disabled"
|
t.boolean "disabled"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -812,31 +813,31 @@ ActiveRecord::Schema.define(version: 20190606074801) do
|
|||||||
add_index "user_tags", ["user_id"], name: "index_user_tags_on_user_id", using: :btree
|
add_index "user_tags", ["user_id"], name: "index_user_tags_on_user_id", using: :btree
|
||||||
|
|
||||||
create_table "users", force: :cascade do |t|
|
create_table "users", force: :cascade do |t|
|
||||||
t.string "email", default: "", null: false
|
t.string "email", limit: 255, default: "", null: false
|
||||||
t.string "encrypted_password", default: "", null: false
|
t.string "encrypted_password", limit: 255, default: "", null: false
|
||||||
t.string "reset_password_token"
|
t.string "reset_password_token", limit: 255
|
||||||
t.datetime "reset_password_sent_at"
|
t.datetime "reset_password_sent_at"
|
||||||
t.datetime "remember_created_at"
|
t.datetime "remember_created_at"
|
||||||
t.integer "sign_in_count", default: 0, null: false
|
t.integer "sign_in_count", default: 0, null: false
|
||||||
t.datetime "current_sign_in_at"
|
t.datetime "current_sign_in_at"
|
||||||
t.datetime "last_sign_in_at"
|
t.datetime "last_sign_in_at"
|
||||||
t.string "current_sign_in_ip"
|
t.string "current_sign_in_ip", limit: 255
|
||||||
t.string "last_sign_in_ip"
|
t.string "last_sign_in_ip", limit: 255
|
||||||
t.string "confirmation_token"
|
t.string "confirmation_token", limit: 255
|
||||||
t.datetime "confirmed_at"
|
t.datetime "confirmed_at"
|
||||||
t.datetime "confirmation_sent_at"
|
t.datetime "confirmation_sent_at"
|
||||||
t.string "unconfirmed_email"
|
t.string "unconfirmed_email", limit: 255
|
||||||
t.integer "failed_attempts", default: 0, null: false
|
t.integer "failed_attempts", default: 0, null: false
|
||||||
t.string "unlock_token"
|
t.string "unlock_token", limit: 255
|
||||||
t.datetime "locked_at"
|
t.datetime "locked_at"
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.boolean "is_allow_contact", default: true
|
t.boolean "is_allow_contact", default: true
|
||||||
t.integer "group_id"
|
t.integer "group_id"
|
||||||
t.string "stp_customer_id"
|
t.string "stp_customer_id", limit: 255
|
||||||
t.string "username"
|
t.string "username", limit: 255
|
||||||
t.string "slug"
|
t.string "slug", limit: 255
|
||||||
t.boolean "is_active", default: true
|
t.boolean "is_active", default: true
|
||||||
t.string "provider"
|
t.string "provider"
|
||||||
t.string "uid"
|
t.string "uid"
|
||||||
t.string "auth_token"
|
t.string "auth_token"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user