mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-29 18:52:22 +01:00
invoices tour
This commit is contained in:
parent
9f68375ae9
commit
807a9596a8
@ -17,8 +17,8 @@
|
||||
/**
|
||||
* Controller used in the admin invoices listing page
|
||||
*/
|
||||
Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'Invoice', 'AccountingPeriod', 'invoices', 'closedPeriods', '$uibModal', 'growl', '$filter', 'Setting', 'settings', '_t',
|
||||
function ($scope, $state, Invoice, AccountingPeriod, invoices, closedPeriods, $uibModal, growl, $filter, Setting, settings, _t) {
|
||||
Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'Invoice', 'AccountingPeriod', 'invoices', 'closedPeriods', '$uibModal', 'growl', '$filter', 'Setting', 'settings', '_t', 'Member', 'uiTourService',
|
||||
function ($scope, $state, Invoice, AccountingPeriod, invoices, closedPeriods, $uibModal, growl, $filter, Setting, settings, _t, Member, uiTourService) {
|
||||
/* PRIVATE STATIC CONSTANTS */
|
||||
|
||||
// number of invoices loaded each time we click on 'load more...'
|
||||
@ -31,7 +31,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
active: Fablab.withoutInvoices ? 1 : 0
|
||||
};
|
||||
|
||||
// List of all users invoices
|
||||
// List of all invoices
|
||||
$scope.invoices = invoices;
|
||||
|
||||
// Invoices filters
|
||||
@ -245,7 +245,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate an order nmuber sample from the parametrized model
|
||||
* Generate an order number sample from the parametrized model
|
||||
* @returns {string} invoice reference sample
|
||||
*/
|
||||
$scope.mkNumber = function () {
|
||||
@ -559,6 +559,126 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the admin/invoices page.
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
*/
|
||||
$scope.setupInvoicesTour = function () {
|
||||
// get the tour defined by the ui-tour directive
|
||||
const uitour = uiTourService.getTourByName('invoices');
|
||||
// TODO add the steps
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'welcome',
|
||||
order: 0,
|
||||
title: _t('app.admin.tour.invoices.welcome.title'),
|
||||
content: _t('app.admin.tour.invoices.welcome.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.invoices-management .invoices-list',
|
||||
stepId: 'list',
|
||||
order: 1,
|
||||
title: _t('app.admin.tour.invoices.list.title'),
|
||||
content: _t('app.admin.tour.invoices.list.content'),
|
||||
placement: 'top'
|
||||
});
|
||||
if ($scope.invoices.length > 0) {
|
||||
uitour.createStep({
|
||||
selector: '.invoices-management .invoices-list .chained-indicator',
|
||||
stepId: 'chained',
|
||||
order: 2,
|
||||
title: _t('app.admin.tour.invoices.chained.title'),
|
||||
content: _t('app.admin.tour.invoices.chained.content'),
|
||||
placement: 'right'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.invoices-management .invoices-list .download-button',
|
||||
stepId: 'download',
|
||||
order: 3,
|
||||
title: _t('app.admin.tour.invoices.download.title'),
|
||||
content: _t('app.admin.tour.invoices.download.content'),
|
||||
placement: 'left'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.invoices-management .invoices-list .refund-button',
|
||||
stepId: 'refund',
|
||||
order: 4,
|
||||
title: _t('app.admin.tour.invoices.refund.title'),
|
||||
content: _t('app.admin.tour.invoices.refund.content'),
|
||||
placement: 'left'
|
||||
});
|
||||
}
|
||||
uitour.createStep({
|
||||
selector: '.invoices-management .invoices-settings',
|
||||
stepId: 'settings',
|
||||
order: 5,
|
||||
title: _t('app.admin.tour.invoices.settings.title'),
|
||||
content: _t('app.admin.tour.invoices.settings.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.invoices-management .accounting-codes-tab',
|
||||
stepId: 'codes',
|
||||
order: 6,
|
||||
title: _t('app.admin.tour.invoices.codes.title'),
|
||||
content: _t('app.admin.tour.invoices.codes.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.heading .export-accounting-button',
|
||||
stepId: 'export',
|
||||
order: 7,
|
||||
title: _t('app.admin.tour.invoices.export.title'),
|
||||
content: _t('app.admin.tour.invoices.export.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: '.heading .close-accounting-periods-button',
|
||||
stepId: 'periods',
|
||||
order: 8,
|
||||
title: _t('app.admin.tour.invoices.periods.title'),
|
||||
content: _t('app.admin.tour.invoices.periods.content'),
|
||||
placement: 'bottom'
|
||||
});
|
||||
uitour.createStep({
|
||||
selector: 'body',
|
||||
stepId: 'conclusion',
|
||||
order: 9,
|
||||
title: _t('app.admin.tour.conclusion.title'),
|
||||
content: _t('app.admin.tour.conclusion.content'),
|
||||
placement: 'bottom',
|
||||
orphan: true
|
||||
});
|
||||
// on step change, change the active tab if needed
|
||||
uitour.on('stepChanged', function (nextStep) {
|
||||
if (nextStep.stepId === 'list' || nextStep.stepId === 'settings') {
|
||||
$scope.tabs.active = 0;
|
||||
}
|
||||
if (nextStep.stepId === 'settings') {
|
||||
$scope.tabs.active = 1;
|
||||
}
|
||||
if (nextStep.stepId === 'codes' || nextStep.stepId === 'export') {
|
||||
$scope.tabs.active = 2;
|
||||
}
|
||||
});
|
||||
// on tour end, save the status in database
|
||||
uitour.on('ended', function () {
|
||||
if (uitour.getStatus() === uitour.Status.ON && $scope.currentUser.profile.tours.indexOf('invoices') < 0) {
|
||||
Member.completeTour({ id: $scope.currentUser.id }, { tour: 'invoices' }, function (res) {
|
||||
$scope.currentUser.profile.tours = res.tours;
|
||||
});
|
||||
}
|
||||
});
|
||||
// if the user has never seen the tour, show him now
|
||||
if ($scope.currentUser.profile.tours.indexOf('invoices') < 0) {
|
||||
uitour.start();
|
||||
}
|
||||
// start this tour when an user press F1 - this is contextual help
|
||||
window.addEventListener('keydown', handleF1);
|
||||
}
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
@ -585,7 +705,7 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
};
|
||||
|
||||
// Watch the logo, when a change occurs, save it
|
||||
return $scope.$watch('invoice.logo', function () {
|
||||
$scope.$watch('invoice.logo', function () {
|
||||
if ($scope.invoice.logo && $scope.invoice.logo.filesize) {
|
||||
return Setting.update(
|
||||
{ name: 'invoice_logo' },
|
||||
@ -598,6 +718,11 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// listen the $destroy event of the controller to remove the F1 key binding
|
||||
$scope.$on('$destroy', function () {
|
||||
window.removeEventListener('keydown', handleF1);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -665,6 +790,18 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used to trigger the feature tour when the user press the F1 key.
|
||||
* @param e {KeyboardEvent}
|
||||
*/
|
||||
const handleF1 = function (e) {
|
||||
if (e.key === 'F1') {
|
||||
e.preventDefault();
|
||||
const tour = uiTourService.getTourByName('trainings');
|
||||
if (tour) { tour.start(); }
|
||||
}
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
return initialize();
|
||||
}
|
||||
|
@ -336,7 +336,6 @@ Application.Controllers.controller('TrainingsAdminController', ['$scope', '$stat
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Setup the feature-tour for the admin/trainings page.
|
||||
* This is intended as a contextual help (when pressing F1)
|
||||
|
@ -12,15 +12,20 @@
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
||||
<section class="heading-actions wrapper">
|
||||
<a class="btn btn-default rounded m-t-sm" ng-click="toggleExportModal()"><i class="fa fa-book"></i></a>
|
||||
<a class="btn btn-default rounded m-t-sm export-accounting-button" 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> {{ 'app.admin.invoices.accounting_periods' | translate }}</a>
|
||||
<a class="btn btn-lg btn-default rounded m-t-sm text-sm close-accounting-periods-button" ng-click="closeAnAccountingPeriod()"><i class="fa fa-calendar-check-o"></i> {{ 'app.admin.invoices.accounting_periods' | translate }}</a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="m-lg">
|
||||
<section class="m-lg invoices-management"
|
||||
ui-tour="invoices"
|
||||
ui-tour-backdrop="true"
|
||||
ui-tour-template-url="'<%= asset_path "shared/tour-step-template.html" %>'"
|
||||
ui-tour-use-hotkeys="true"
|
||||
post-render="setupInvoicesTour">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<uib-tabset justified="true" active="tabs.active">
|
||||
@ -60,7 +65,7 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<table class="table" ng-if="invoices.length > 0">
|
||||
<table class="table invoices-list" ng-if="invoices.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:5%"></th>
|
||||
@ -77,7 +82,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="invoice in invoices">
|
||||
<td>
|
||||
<td class="chained-indicator">
|
||||
<i class="fa fa-link chained" ng-show="invoice.chained_footprint"/>
|
||||
<i class="fa fa-chain-broken broken" ng-hide="invoice.chained_footprint"/>
|
||||
</td>
|
||||
@ -90,13 +95,13 @@
|
||||
<span ng-hide="invoice.user_id">{{ invoice.name }}</span>
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<a class="btn btn-default" ng-href="api/invoices/{{invoice.id}}/download" target="_blank" ng-if="!invoice.is_avoir">
|
||||
<a class="btn btn-default download-button" ng-href="api/invoices/{{invoice.id}}/download" target="_blank" ng-if="!invoice.is_avoir">
|
||||
<i class="fa fa-file-pdf-o"></i> {{ 'app.admin.invoices.download_the_invoice' | translate }}
|
||||
</a>
|
||||
<a class="btn btn-default" ng-href="api/invoices/{{invoice.id}}/download" target="_blank" ng-if="invoice.is_avoir">
|
||||
<i class="fa fa-file-pdf-o"></i> {{ 'app.admin.invoices.download_the_credit_note' | translate }}
|
||||
</a>
|
||||
<a class="btn btn-default" ng-click="generateAvoirForInvoice(invoice)" ng-if="(!invoice.has_avoir || invoice.has_avoir == 'partial') && !invoice.is_avoir && !invoice.prevent_refund && !isDateClosed(invoice.created_at)">
|
||||
<a class="btn btn-default refund-button" ng-click="generateAvoirForInvoice(invoice)" ng-if="(!invoice.has_avoir || invoice.has_avoir == 'partial') && !invoice.is_avoir && !invoice.prevent_refund && !isDateClosed(invoice.created_at)">
|
||||
<i class="fa fa-reply"></i> {{ 'app.admin.invoices.credit_note' | translate }}
|
||||
</a>
|
||||
</div>
|
||||
@ -116,7 +121,7 @@
|
||||
|
||||
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.invoices.invoicing_settings' | translate }}" index="1">
|
||||
<uib-tab heading="{{ 'app.admin.invoices.invoicing_settings' | translate }}" index="1" class="invoices-settings">
|
||||
<div class="alert alert-warning p-md m-t" role="alert" ng-show="fablabWithoutInvoices">
|
||||
<i class="fa fa-warning m-r"></i>
|
||||
<span translate>{{ 'app.admin.invoices.warning_invoices_disabled' }}</span>
|
||||
@ -211,7 +216,7 @@
|
||||
|
||||
|
||||
|
||||
<uib-tab heading="{{ 'app.admin.invoices.accounting_codes' | translate }}" index="2">
|
||||
<uib-tab heading="{{ 'app.admin.invoices.accounting_codes' | translate }}" index="2" class="accounting-codes-tab">
|
||||
<div class="panel panel-default m-t-md accounting-codes">
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
|
@ -1123,3 +1123,32 @@ fr:
|
||||
sso:
|
||||
title: "Authentification unique"
|
||||
content: "Ici vous pourrez mettre en place et gérer un système d'authentification unique (ou Single Sign-On - SSO)."
|
||||
invoices:
|
||||
welcome:
|
||||
title: "Gérer les factures"
|
||||
content: "Ici, vous pourrez télécharger des factures émises et gérer tout ce qui a trait à la comptabilité et à la facturation."
|
||||
list:
|
||||
title: "Liste des factures"
|
||||
content: "Par défaut, ce tableau liste l'ensemble des factures émises via Fab-Manager. Vous pouvez trier la liste dans un ordre différent en cliquant sur l'entête de chaque colonne."
|
||||
chained:
|
||||
title: "Indicateur de chaînage"
|
||||
content: "Cette icône assure l'inaltérablité des données comptables liées à la facture sur cette ligne. Si une icône rouge apparaît au lieu de cette-ci, merci de contactez immédiatement le support technique."
|
||||
download:
|
||||
title: "Télécharger"
|
||||
content: "Cliquez ici pour télécharger la facture au format PDF."
|
||||
refund:
|
||||
title: "Avoir"
|
||||
content: "Permet de générer un avoir sur la facture de cette ligne ou certains de ses sous-éléments. <strong>Attention :</strong> Cela générera uniquement le document comptable, le remboursement effectif de l'utilisateur restera toujours à votre charge."
|
||||
settings:
|
||||
title: "Paramètres"
|
||||
content: "Ici vous pourrez modifier les paramètres de génération des factures. Cliquez sur l'élément qui vous intéresse pour commencer l'édition."
|
||||
codes:
|
||||
title: "Codes comptables"
|
||||
content: "Paramétrez ici les codes comptables pour tous les types d'écritures générés par le logiciel. Ce paramétrage n'est requis que si vous utilisez la fonctionnalité d'export comptable."
|
||||
export:
|
||||
title: "Export comptable"
|
||||
content: "Une fois les codes configurés, cliquez ici pour accéder à l'interface vous permettant d'exporter les écritures vers un logiciel comptable tiers."
|
||||
periods:
|
||||
title: "Clôturer les périodes comptables"
|
||||
content: "<p>La réglementation de votre pays peut vous imposer de clôturer régulièrement vos comptes. L'interface accessible depuis ce bouton permet de le faire.</p> <p><strong>En France,</strong> si vous êtes soumis à la certification anti-fraude TVA, cette clôture est obligatoire au moins une fois par an.</p><p>Pour rappel, si vous récupérez la TVA pour le compte de l'état et que certains de vos clients sont des particuliers, vous êtes dans l'obligation légale de fournir une attestation de conformité du logiciel à la certification anti-fraude.</p>"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user