1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-18 12:54:27 +01:00

Ability to configure the duration of a reservation slot

Merge branch 'slot-duration' into dev
This commit is contained in:
Sylvain 2019-10-30 15:39:41 +01:00
commit d044a3147a
8 changed files with 36 additions and 12 deletions

View File

@ -1,10 +1,12 @@
# Changelog Fab Manager
- An administrator can delete a member
- Ability to configure the duration of a reservation slot. Previously, only 60 minutes slots were allowed
- Improved user experience in defining slots in the calendar management
- Improved notification email to the member when a rolling subscription is taken
- Handle Ctrl^C in upgrade scripts
- Updated moment-timezone
- [TODO DEPLOY] add the `SLOT_DURATION` environment variable (see [doc/environment.md](doc/environment.md#SLOT_DURATION) for configuration details)
## v4.2.3 2019 October 22

View File

@ -30,7 +30,7 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
const BOOKING_SNAP = '00:30:00';
// We do not allow the creation of slots that are not a multiple of 60 minutes
const SLOT_MULTIPLE = 60;
const SLOT_MULTIPLE = Fablab.slotDuration;
/* PUBLIC SCOPE */
@ -283,12 +283,12 @@ Application.Controllers.controller('AdminCalendarController', ['$scope', '$state
return uiCalendarConfig.calendars.calendar.fullCalendar('unselect');
}
// check that the selected slot is an N-hours multiple (ie. not decimal)
// check that the selected slot is an multiple of SLOT_MULTIPLE (ie. not decimal)
const slots = Math.trunc((end.valueOf() - start.valueOf()) / (60 * 1000)) / SLOT_MULTIPLE;
if (!Number.isInteger(slots)) {
// otherwise, round it to nearest decimal
const nearest = Math.round(slots) * SLOT_MULTIPLE;
end = moment(start).add(nearest, 'minutes');
// otherwise, round it to upper decimal
const upper = Math.ceil(slots) * SLOT_MULTIPLE;
end = moment(start).add(upper, 'minutes');
}
// then we open a modal window to let the admin specify the slot type
@ -507,21 +507,25 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
Tag.query().$promise.then(function (data) { $scope.tags = data; });
// When we configure a machine availability, do not let the user change the end time, as the total
// time must be dividable by 60 minutes (base slot duration). For training availabilities, the user
// When we configure a machine/space availability, do not let the user change the end time, as the total
// time must be dividable by Fablab.slotDuration minutes (base slot duration). For training availabilities, the user
// can configure any duration as it does not matters.
$scope.$watch('availability.available_type', function (newValue, oldValue, scope) {
if ((newValue === 'machines') || (newValue === 'space')) {
$scope.endDateReadOnly = true;
const diff = moment($scope.end).diff($scope.start, 'hours'); // the result is rounded down by moment.js
$scope.end = moment($scope.start).add(diff, 'hours').toDate();
const slots = Math.trunc(($scope.end.valueOf() - $scope.start.valueOf()) / (60 * 1000)) / Fablab.slotDuration;
if (!Number.isInteger(slots)) {
// otherwise, round it to upper decimal
const upper = Math.ceil(slots) * Fablab.slotDuration;
$scope.end = moment($scope.start).add(upper, 'minutes').toDate();
}
return $scope.availability.end_at = $scope.end;
} else {
return $scope.endDateReadOnly = false;
}
});
// When the start date is changed, if we are configuring a machine availability,
// When the start date is changed, if we are configuring a machine/space availability,
// maintain the relative length of the slot (ie. change the end time accordingly)
$scope.$watch('start', function (newValue, oldValue, scope) {
// for machine or space availabilities, adjust the end time
@ -542,7 +546,7 @@ Application.Controllers.controller('CreateEventModalController', ['$scope', '$ui
// Maintain consistency between the end time and the date object in the availability object
return $scope.$watch('end', function (newValue, oldValue, scope) {
// we prevent the admin from setting the end of the availability before its begining
if (moment($scope.start).add(1, 'hour').isAfter(newValue)) {
if (moment($scope.start).add(Fablab.slotDuration, 'minutes').isAfter(newValue)) {
$scope.end = oldValue;
}
// update availability object

View File

@ -7,7 +7,7 @@ module ApplicationHelper
require 'message_format'
## machine/spaces availabilities are divided in multiple slots of 60 minutes
SLOT_DURATION ||= 60
SLOT_DURATION ||= Rails.application.secrets.slot_duration || 60
##
# Verify if the provided attribute is in the provided attributes array, whatever it exists or not

View File

@ -20,6 +20,7 @@
Fablab.withoutSpaces = ('<%= Rails.application.secrets.fablab_without_spaces %>' !== 'false');
Fablab.withoutOnlinePayment = ('<%= Rails.application.secrets.fablab_without_online_payments %>' === 'true');
Fablab.withoutInvoices = ('<%= Rails.application.secrets.fablab_without_invoices %>' === 'true');
Fablab.slotDuration = parseInt("<%= ApplicationHelper::SLOT_DURATION %>", 10);
Fablab.disqusShortname = "<%= Rails.application.secrets.disqus_shortname %>";
Fablab.defaultHost = "<%= Rails.application.secrets.default_host %>";
Fablab.gaId = "<%= Rails.application.secrets.google_analytics_id %>";

View File

@ -21,6 +21,8 @@ FABLAB_WITHOUT_SPACES: 'true'
FABLAB_WITHOUT_ONLINE_PAYMENT: 'false'
FABLAB_WITHOUT_INVOICES: 'false'
SLOT_DURATION: '60'
DEFAULT_MAIL_FROM: Fab Manager Demo <noreply@fab-manager.com>
# Configure carefully!

View File

@ -20,6 +20,7 @@ development:
fablab_without_spaces: <%= ENV["FABLAB_WITHOUT_SPACES"] %>
fablab_without_online_payments: <%= ENV["FABLAB_WITHOUT_ONLINE_PAYMENT"] %>
fablab_without_invoices: <%= ENV["FABLAB_WITHOUT_INVOICES"] %>
slot_duration: <%= ENV["SLOT_DURATION"] %>
default_host: <%= ENV["DEFAULT_HOST"] %>
default_protocol: <%= ENV["DEFAULT_PROTOCOL"] %>
time_zone: <%= ENV["TIME_ZONE"] %>
@ -62,6 +63,7 @@ test:
fablab_without_spaces: false
fablab_without_online_payments: false
fablab_without_invoices: false
slot_duration: <%= ENV["SLOT_DURATION"] %>
default_host: <%= ENV["DEFAULT_HOST"] %>
default_protocol: <%= ENV["DEFAULT_PROTOCOL"] %>
time_zone: Paris
@ -104,6 +106,7 @@ staging:
fablab_without_spaces: <%= ENV["FABLAB_WITHOUT_SPACES"] %>
fablab_without_online_payments: <%= ENV["FABLAB_WITHOUT_ONLINE_PAYMENT"] %>
fablab_without_invoices: <%= ENV["FABLAB_WITHOUT_INVOICES"] %>
slot_duration: <%= ENV["SLOT_DURATION"] %>
default_host: <%= ENV["DEFAULT_HOST"] %>
default_protocol: <%= ENV["DEFAULT_PROTOCOL"] %>
delivery_method: <%= ENV['DELIVERY_METHOD'] %>
@ -157,6 +160,7 @@ production:
fablab_without_spaces: <%= ENV["FABLAB_WITHOUT_SPACES"] %>
fablab_without_online_payments: <%= ENV["FABLAB_WITHOUT_ONLINE_PAYMENT"] %>
fablab_without_invoices: <%= ENV["FABLAB_WITHOUT_INVOICES"] %>
slot_duration: <%= ENV["SLOT_DURATION"] %>
default_host: <%= ENV["DEFAULT_HOST"] %>
default_protocol: <%= ENV["DEFAULT_PROTOCOL"] %>
delivery_method: <%= ENV['DELIVERY_METHOD'] %>

View File

@ -102,6 +102,15 @@ Valid stripe API keys are still required, even if you don't require online payme
If set to 'true', the invoices will be disabled.
This is useful if you have your own invoicing system and you want to prevent Fab-manager from generating and sending invoices to members.
**Very important**: if you disable invoices, you still have to configure VAT in the interface to prevent errors in accounting and prices.
<a name="SLOT_DURATION"></a>
SLOT_DURATION
Machine and space availabilities are divided in multiple slots of the duration set by this variable.
Default value is 60 minutes (1 hour).
⚠ Changing this value during the application life may cause serious issues.
Please ensure there's no machine/space availabilities opened to reservation or already reserved **in the future** when you change this value.
<a name="DEFAULT_MAIL_FROM"></a>
DEFAULT_MAIL_FROM

View File

@ -14,6 +14,8 @@ FABLAB_WITHOUT_SPACES=true
FABLAB_WITHOUT_ONLINE_PAYMENT=true
FABLAB_WITHOUT_INVOICES=false
SLOT_DURATION=60
DEFAULT_MAIL_FROM=Fab Manager Demo <noreply@fab-manager.com>
DEFAULT_HOST=demo.fab-manager.com
DEFAULT_PROTOCOL=http