diff --git a/app/assets/javascripts/ie_lt9.js b/app/assets/javascripts/ie_lt9.js index 4e45b0282..b10b4b2ff 100644 --- a/app/assets/javascripts/ie_lt9.js +++ b/app/assets/javascripts/ie_lt9.js @@ -1,2 +1,3 @@ //= require respond.min -//= require rem.min \ No newline at end of file +//= require rem.min +//= require number-polyfill.min \ No newline at end of file diff --git a/app/controllers/valuation/spending_proposals_controller.rb b/app/controllers/valuation/spending_proposals_controller.rb index f5074ab1e..b0d83d96e 100644 --- a/app/controllers/valuation/spending_proposals_controller.rb +++ b/app/controllers/valuation/spending_proposals_controller.rb @@ -17,8 +17,11 @@ class Valuation::SpendingProposalsController < Valuation::BaseController end def valuate - @spending_proposal.update_attributes(valuation_params) - redirect_to valuation_spending_proposal_path(@spending_proposal), notice: t('valuation.spending_proposals.notice.valuate') + if valid_price_params? && @spending_proposal.update(valuation_params) + redirect_to valuation_spending_proposal_path(@spending_proposal), notice: t('valuation.spending_proposals.notice.valuate') + else + render action: :edit + end end private @@ -35,4 +38,16 @@ class Valuation::SpendingProposalsController < Valuation::BaseController raise ActionController::RoutingError.new('Not Found') unless current_user.administrator? || ValuationAssignment.exists?(spending_proposal_id: params[:id], valuator_id: current_user.valuator.id) end + def valid_price_params? + if /\D/.match params[:spending_proposal][:price] + @spending_proposal.errors.add(:price, I18n.t('spending_proposals.wrong_price_format')) + end + + if /\D/.match params[:spending_proposal][:price_first_year] + @spending_proposal.errors.add(:price_first_year, I18n.t('spending_proposals.wrong_price_format')) + end + + @spending_proposal.errors.empty? + end + end diff --git a/config/locales/en.yml b/config/locales/en.yml index e3f51219c..468889c28 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -423,6 +423,7 @@ en: recommendation_two: Any proposal or comment suggesting illegal action will be deleted. recommendations_title: How to create a spending proposal start_new: Create spending proposal + wrong_price_format: Only integer numbers stats: index: visits: Visits diff --git a/config/locales/es.yml b/config/locales/es.yml index 55177e15a..b9701cbf5 100755 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -423,6 +423,7 @@ es: recommendation_two: Cualquier propuesta o comentario que implique acciones ilegales será eliminada. recommendations_title: Cómo crear una propuesta de gasto start_new: Crear una propuesta de gasto + wrong_price_format: Solo puede incluir caracteres numéricos stats: index: visits: Visitas diff --git a/spec/features/valuation/spending_proposals_spec.rb b/spec/features/valuation/spending_proposals_spec.rb index e5bde98d4..a5b761e65 100644 --- a/spec/features/valuation/spending_proposals_spec.rb +++ b/spec/features/valuation/spending_proposals_spec.rb @@ -284,6 +284,20 @@ feature 'Valuation spending proposals' do click_link @spending_proposal.title expect(page).to have_content('Valuation finished') end + + scenario 'Validates price formats' do + visit valuation_spending_proposals_path + within("#spending_proposal_#{@spending_proposal.id}") do + click_link "Edit" + end + + fill_in 'spending_proposal_price', with: '12345,98' + fill_in 'spending_proposal_price_first_year', with: '9876.6' + click_button 'Save changes' + + expect(page).to have_content('2 errors') + expect(page).to have_content('Only integer numbers', count: 2) + end end end diff --git a/vendor/assets/javascripts/number-polyfill.min.js b/vendor/assets/javascripts/number-polyfill.min.js new file mode 100644 index 000000000..b5cea8b09 --- /dev/null +++ b/vendor/assets/javascripts/number-polyfill.min.js @@ -0,0 +1 @@ +(function(){(function(e){var t,n;return t=document.createElement("input"),t.setAttribute("type","number"),"text"!==t.type?(e.fn.inputNumber=function(){return e(this)},void 0):(e.fn.inputNumber=function(){return e(this).filter(function(){var t;return t=e(this),t.is('input[type="number"]')&&!(t.parent().is("span")&&t.next().is("div.number-spin-btn-container")&&t.next().children().first().is("div.number-spin-btn-up")&&t.next().children().eq(1).is("div.number-spin-btn-down"))}).each(function(){n.polyfills.push(new n(this))}),e(this)},n=function(t){var i,r,o,s,a=this;if(this.elem=e(t),!(this.elem.is(":root *")&&this.elem.height()>0))throw Error("Element must be in DOM and displayed so that its height can be measured.");s=this.elem.outerHeight()/2+"px",this.upBtn=e("
",{"class":"number-spin-btn number-spin-btn-up",style:"height: "+s}),this.downBtn=e("",{"class":"number-spin-btn number-spin-btn-down",style:"height: "+s}),this.btnContainer=e("",{"class":"number-spin-btn-container"}),i=e("",{style:"white-space: nowrap"}),this.upBtn.appendTo(this.btnContainer),this.downBtn.appendTo(this.btnContainer),this.elem.wrap(i),this.btnContainer.insertAfter(this.elem),this.elem.on({focus:function(){a.elem.on({DOMMouseScroll:n.domMouseScrollHandler,mousewheel:n.mouseWheelHandler},{p:a})},blur:function(){a.elem.off({DOMMouseScroll:n.domMouseScrollHandler,mousewheel:n.mouseWheelHandler})}}),this.elem.on({keypress:n.elemKeypressHandler,change:n.elemChangeHandler},{p:this}),this.upBtn.on("mousedown",{p:this,func:"increment"},n.elemBtnMousedownHandler),this.downBtn.on("mousedown",{p:this,func:"decrement"},n.elemBtnMousedownHandler),this.elem.css("textAlign","right"),this.attrMutationHandler("class"),"undefined"!=typeof WebKitMutationObserver&&null!==WebKitMutationObserver||r!==void 0&&null!==r?("undefined"==typeof WebKitMutationObserver||null===WebKitMutationObserver||void 0!==r&&null!==r||(r=WebKitMutationObserver),o=new r(function(e){var t,n,i;for(n=0,i=e.length;i>n;n++)t=e[n],"attributes"===t.type&&a.attrMutationHandler(t.attributeName,t.oldValue,a.elem.attr(t.attributeName))}),o.observe(t,{attributes:!0,attributeOldValue:!0,attributeFilter:["class","style","min","max","step"]})):"undefined"!=typeof MutationEvent&&null!==MutationEvent&&this.elem.on("DOMAttrModified",function(e){a.attrMutationHandler(e.originalEvent.attrName,e.originalEvent.prevValue,e.originalEvent.newValue)})},n.polyfills=[],n.isNumber=function(e){return null!=e&&"function"==typeof e.toString?/^-?\d+(?:\.\d+)?$/.test(""+e):!1},n.isFloat=function(e){return null!=e&&"function"==typeof e.toString?/^-?\d+\.\d+$/.test(""+e):!1},n.isInt=function(e){return null!=e&&"function"==typeof e.toString?/^-?\d+$/.test(""+e):!1},n.isNegative=function(e){return null!=e&&"function"==typeof e.toString?/^-\d+(?:\.\d+)?$/.test(""+e):!1},n.raiseNum=function(e){var t,i,r;if("number"==typeof e||"object"==typeof e&&e instanceof Number)return e%1?{num:""+e,precision:0}:n.raiseNum(""+e);if("string"==typeof e||"object"==typeof e&&e instanceof String){if(n.isFloat(e))return e=e.replace(/(\.\d)0+$/,"$1"),r=n.getPrecision(e),i=e.slice(0,-(r+1))+e.slice(-r),i=i.replace(/^(-?)0+(\d+)/,"$1$2"),t={num:i,precision:r};if(n.isInt(e))return{num:e,precision:0}}},n.raiseNumPrecision=function(e,n){var i,r;if(n>e.precision){for(t=i=r=e.precision;n>=r?n>i:i>n;t=n>=r?++i:--i)e.num+="0";e.precision=n}},n.lowerNum=function(e){if(e.precision>0){for(;e.num.length