mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-29 10:24:20 +01:00
check server-side that periods match length requirements + explain requirements to user before closing
This commit is contained in:
parent
93ff761e64
commit
722d5d36e7
@ -676,8 +676,8 @@ Application.Controllers.controller('AvoirModalController', ['$scope', '$uibModal
|
||||
/**
|
||||
* Controller used in the modal window allowing an admin to close an accounting period
|
||||
*/
|
||||
Application.Controllers.controller('ClosePeriodModalController', ['$scope', '$uibModalInstance', '$window', 'Invoice', 'AccountingPeriod', 'periods', 'lastClosingEnd','dialogs', 'growl', '_t',
|
||||
function ($scope, $uibModalInstance, $window, Invoice, AccountingPeriod, periods, lastClosingEnd, dialogs, growl, _t) {
|
||||
Application.Controllers.controller('ClosePeriodModalController', ['$scope', '$uibModalInstance', '$window', '$sce', 'Invoice', 'AccountingPeriod', 'periods', 'lastClosingEnd','dialogs', 'growl', '_t',
|
||||
function ($scope, $uibModalInstance, $window, $sce, Invoice, AccountingPeriod, periods, lastClosingEnd, dialogs, growl, _t) {
|
||||
const YESTERDAY = moment.utc({ h: 0, m: 0, s: 0, ms: 0 }).subtract(1, 'day').toDate();
|
||||
const LAST_CLOSING = moment.utc(lastClosingEnd.last_end_date).toDate();
|
||||
const MAX_END = moment.utc(lastClosingEnd.last_end_date).add(1, 'year').subtract(1, 'day').toDate();
|
||||
@ -734,9 +734,15 @@ Application.Controllers.controller('ClosePeriodModalController', ['$scope', '$ui
|
||||
object () {
|
||||
return {
|
||||
title: _t('invoices.confirmation_required'),
|
||||
msg: _t(
|
||||
'invoices.confirm_close_START_END',
|
||||
{ START: moment.utc($scope.period.start_at).format('LL'), END: moment.utc($scope.period.end_at).format('LL') }
|
||||
msg: $sce.trustAsHtml(
|
||||
_t(
|
||||
'invoices.confirm_close_START_END',
|
||||
{ START: moment.utc($scope.period.start_at).format('LL'), END: moment.utc($scope.period.end_at).format('LL') }
|
||||
)
|
||||
+ '<br/><br/><strong>'
|
||||
+ _t('invoices.period_must_match_fiscal_year')
|
||||
+ '</strong><br/><br/>'
|
||||
+ _t('invoices.this_may_take_a_while')
|
||||
)
|
||||
};
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ class AccountingPeriod < ActiveRecord::Base
|
||||
|
||||
validates :start_at, :end_at, :closed_at, :closed_by, presence: true
|
||||
validates_with DateRangeValidator
|
||||
validates_with DurationValidator
|
||||
validates_with PeriodOverlapValidator
|
||||
validates_with PeriodIntegrityValidator
|
||||
|
||||
|
13
app/validators/duration_validator.rb
Normal file
13
app/validators/duration_validator.rb
Normal file
@ -0,0 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Validates that the duration between start_at and end_at is between 1 day and 1 year
|
||||
class DurationValidator < ActiveModel::Validator
|
||||
def validate(record)
|
||||
the_end = record.end_at
|
||||
the_start = record.start_at
|
||||
diff = (the_end - the_start).to_i
|
||||
return if diff.days >= 1.day && diff.days <= 1.year
|
||||
|
||||
record.errors[:end_at] << I18n.t('errors.messages.invalid_duration', DAYS: diff)
|
||||
end
|
||||
end
|
@ -421,7 +421,9 @@ en:
|
||||
perpetual_total: "Perpetual total"
|
||||
integrity: "Integrity check"
|
||||
confirmation_required: "Confirmation required"
|
||||
confirm_close_START_END: "Do you really want to close the accounting period between {{START}} and {{END}}? Any subsequent changes will be impossible. This operation will take some time to complete"
|
||||
confirm_close_START_END: "Do you really want to close the accounting period between {{START}} and {{END}}? Any subsequent changes will be impossible."
|
||||
period_must_match_fiscal_year: "A closing must occur at the end of a minimum annual period, or per financial year when it is not calendar-based."
|
||||
this_may_take_a_while: "This operation will take some time to complete."
|
||||
period_START_END_closed_success: "The accounting period from {{START}} to {{END}} has been successfully closed"
|
||||
failed_to_close_period: "An error occurred, unable to close the accounting period"
|
||||
no_periods: "No closings for now"
|
||||
|
@ -421,7 +421,9 @@ es:
|
||||
perpetual_total: "Perpetual total" # translation_missing
|
||||
integrity: "Verificación de integridad"
|
||||
confirmation_required: "Confirmation required" # translation_missing
|
||||
confirm_close_START_END: "Do you really want to close the accounting period between {{START}} and {{END}}? Any subsequent changes will be impossible. This operation will take some time to complete" # translation_missing
|
||||
confirm_close_START_END: "Do you really want to close the accounting period between {{START}} and {{END}}? Any subsequent changes will be impossible." # translation_missing
|
||||
period_must_match_fiscal_year: "A closing must occur at the end of a minimum annual period, or per financial year when it is not calendar-based." # translation_missing
|
||||
this_may_take_a_while: "This operation will take some time to complete." # translation_missing
|
||||
period_START_END_closed_success: "The accounting period from {{START}} to {{END}} has been successfully closed" # 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
|
||||
|
@ -421,7 +421,9 @@ fr:
|
||||
perpetual_total: "Total perpétuel"
|
||||
integrity: "Contrôle d'intégrité"
|
||||
confirmation_required: "Confirmation requise"
|
||||
confirm_close_START_END: "Êtes-vous sur de vouloir clôturer la période comptable du {{START}} au {{END}} ? Toute modification ultérieure sera impossible. Cette opération va prendre un certain temps."
|
||||
confirm_close_START_END: "Êtes-vous sur de vouloir clôturer la période comptable du {{START}} au {{END}} ? Toute modification ultérieure sera impossible."
|
||||
period_must_match_fiscal_year: "Une clôture doit intervenir à l'issue d'une période au minimum annuelle, ou par exercice lorsque celui-ci n'est pas calé sur l'année civile."
|
||||
this_may_take_a_while: "Cette opération va prendre un certain temps."
|
||||
period_START_END_closed_success: "La période comptable du {{START}} au {{END}} a bien été clôturée"
|
||||
failed_to_close_period: "Une erreur est survenue, impossible de clôturer la période comptable"
|
||||
no_periods: "Aucune clôture pour le moment"
|
||||
|
@ -421,7 +421,9 @@ pt:
|
||||
perpetual_total: "Perpetual total" # translation_missing
|
||||
integrity: "Verificação de integridade"
|
||||
confirmation_required: "Confirmation required" # translation_missing
|
||||
confirm_close_START_END: "Do you really want to close the accounting period between {{START}} and {{END}}? Any subsequent changes will be impossible. This operation will take some time to complete." # translation_missing
|
||||
confirm_close_START_END: "Do you really want to close the accounting period between {{START}} and {{END}}? Any subsequent changes will be impossible" # translation_missing
|
||||
period_must_match_fiscal_year: "A closing must occur at the end of a minimum annual period, or per financial year when it is not calendar-based." # translation_missing
|
||||
this_may_take_a_while: "This operation will take some time to complete." # translation_missing
|
||||
period_START_END_closed_success: "The accounting period from {{START}} to {{END}} has been successfully closed" # 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
|
||||
|
@ -41,6 +41,7 @@ en:
|
||||
in_closed_period: "can't be within a closed accounting period"
|
||||
invalid_footprint: "invoice's checksum is invalid"
|
||||
end_before_start: "The end date can't be before the start date. Pick a date after %{START}"
|
||||
invalid_duration: "The allowed duration must be between 1 day and 1 year. Your period is %{DAYS} days long."
|
||||
|
||||
activemodel:
|
||||
errors:
|
||||
|
@ -41,6 +41,7 @@ es:
|
||||
in_closed_period: "can't be within a closed accounting period" # missing translation
|
||||
invalid_footprint: "invoice's checksum is invalid" # missing translation
|
||||
end_before_start: "The end date can't be before the start date. Pick a date after %{START}" # missing translation
|
||||
invalid_duration: "The allowed duration must be between 1 day and 1 year. Your period is %{DAYS} days long." # missing translation
|
||||
|
||||
activemodel:
|
||||
errors:
|
||||
|
@ -41,6 +41,7 @@ fr:
|
||||
in_closed_period: "ne peut pas être dans une période comptable fermée"
|
||||
invalid_footprint: "la somme de contrôle de la facture est invalide"
|
||||
end_before_start: "La date de fin ne peut pas être antérieure à la date de début. Choisissez une date après le %{START}"
|
||||
invalid_duration: "La durée doit être comprise entre 1 jour et 1 an. Votre période dure %{DAYS} jours."
|
||||
|
||||
activemodel:
|
||||
errors:
|
||||
|
@ -41,6 +41,7 @@ pt:
|
||||
in_closed_period: "can't be within a closed accounting period" # missing translation
|
||||
invalid_footprint: "invoice's checksum is invalid" # missing translation
|
||||
end_before_start: "The end date can't be before the start date. Pick a date after %{START}" # missing translation
|
||||
invalid_duration: "The allowed duration must be between 1 day and 1 year. Your period is %{DAYS} days long." # missing translation
|
||||
|
||||
activemodel:
|
||||
errors:
|
||||
|
@ -68,4 +68,44 @@ class AccountingPeriodTest < ActionDispatch::IntegrationTest
|
||||
FileUtils.rm_rf(accounting_period.archive_folder)
|
||||
end
|
||||
|
||||
test 'admin tries to closes a too long period' do
|
||||
start_at = '2012-01-01T00:00:00.000Z'
|
||||
end_at = '2014-12-31T00:00:00.000Z'
|
||||
diff = (end_at.to_date - start_at.to_date).to_i
|
||||
|
||||
post '/api/accounting_periods',
|
||||
{
|
||||
accounting_period: {
|
||||
start_at: start_at,
|
||||
end_at: end_at
|
||||
}
|
||||
}.to_json, default_headers
|
||||
|
||||
# Check response format & status
|
||||
assert_equal 422, response.status, response.body
|
||||
assert_equal Mime::JSON, response.content_type
|
||||
|
||||
# check the error
|
||||
assert_match(/#{I18n.t('errors.messages.invalid_duration', DAYS: diff)}/, response.body)
|
||||
end
|
||||
|
||||
test 'admin tries to closes an overlapping period' do
|
||||
start_at = '2014-12-01T00:00:00.000Z'
|
||||
end_at = '2015-02-27T00:00:00.000Z'
|
||||
|
||||
post '/api/accounting_periods',
|
||||
{
|
||||
accounting_period: {
|
||||
start_at: start_at,
|
||||
end_at: end_at
|
||||
}
|
||||
}.to_json, default_headers
|
||||
|
||||
# Check response format & status
|
||||
assert_equal 422, response.status, response.body
|
||||
assert_equal Mime::JSON, response.content_type
|
||||
|
||||
# check the error
|
||||
assert_match(/#{I18n.t('errors.messages.cannot_overlap')}/, response.body)
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user