diff --git a/app/assets/javascripts/admin/customers/controllers/customers_controller.js.coffee b/app/assets/javascripts/admin/customers/controllers/customers_controller.js.coffee index 23bfb37738..7c70a8baa5 100644 --- a/app/assets/javascripts/admin/customers/controllers/customers_controller.js.coffee +++ b/app/assets/javascripts/admin/customers/controllers/customers_controller.js.coffee @@ -13,6 +13,20 @@ angular.module("admin.customers").controller "customersCtrl", ($scope, $q, Custo Customers.index({enterprise_id: $scope.CurrentShop.shop.id}).then (data) -> $scope.customers = data + $scope.checkForDuplicateCodes = -> + delete this.customer.code unless this.customer.code + this.duplicate = $scope.isDuplicateCode(this.customer.code) + + $scope.isDuplicateCode = (code) -> + return false unless code + customers = $scope.findByCode(code) + customers.length > 1 + + $scope.findByCode = (code) -> + if $scope.customers + $scope.customers.filter (customer) -> + customer.code == code + $scope.findTags = (query) -> defer = $q.defer() params = diff --git a/app/models/customer.rb b/app/models/customer.rb index 34f62a6aa6..b2141df9ec 100644 --- a/app/models/customer.rb +++ b/app/models/customer.rb @@ -5,8 +5,9 @@ class Customer < ActiveRecord::Base belongs_to :user, class_name: Spree.user_class before_validation :downcase_email + before_validation :empty_code - validates :code, uniqueness: { scope: :enterprise_id, allow_blank: true, allow_nil: true } + validates :code, uniqueness: { scope: :enterprise_id, allow_nil: true } validates :email, presence: true, uniqueness: { scope: :enterprise_id, message: I18n.t('validation_msg_is_associated_with_an_exising_customer') } validates :enterprise_id, presence: true @@ -20,6 +21,10 @@ class Customer < ActiveRecord::Base email.andand.downcase! end + def empty_code + self.code = nil if code.blank? + end + def associate_user self.user = user || Spree::User.find_by_email(email) end diff --git a/app/views/admin/customers/index.html.haml b/app/views/admin/customers/index.html.haml index c570632c64..02248923d1 100644 --- a/app/views/admin/customers/index.html.haml +++ b/app/views/admin/customers/index.html.haml @@ -64,7 +64,9 @@ -# %input{ :type => "checkbox", :name => 'bulk', 'ng-model' => 'customer.checked' } %td.email{ 'ng-show' => 'columns.email.visible', "ng-bind" => '::customer.email' } %td.code{ 'ng-show' => 'columns.code.visible' } - %input{ :type => 'text', :name => 'code', :id => 'code', 'ng-model' => 'customer.code', 'obj-for-update' => "customer", "attr-for-update" => "code" } + %input{ type: 'text', name: 'code', ng: {model: 'customer.code', change: 'checkForDuplicateCodes()'}, "obj-for-update" => "customer", "attr-for-update" => "code" } + %i.icon-warning-sign{ ng: {if: 'duplicate'} } + = t('.duplicate_code') %td.tags{ 'ng-show' => 'columns.tags.visible' } .tag_watcher{ 'obj-for-update' => "customer", "attr-for-update" => "tag_list"} %tags_with_translation{ object: 'customer', 'find-tags' => 'findTags(query)' } diff --git a/app/views/spree/admin/overview/_order_cycles.html.haml b/app/views/spree/admin/overview/_order_cycles.html.haml index 8628837a47..1a00bd5102 100644 --- a/app/views/spree/admin/overview/_order_cycles.html.haml +++ b/app/views/spree/admin/overview/_order_cycles.html.haml @@ -6,9 +6,8 @@ %a.three.columns.omega.icon-plus.button.blue{ href: "#{main_app.new_admin_order_cycle_path}" } = t "spree_admin_enterprises_create_new" - else - %a.with-tip{ title: t(:spree_admin_order_cycles_tip) } + %a{ "ofn-with-tip" => t(:spree_admin_order_cycles_tip) } = t "admin.whats_this" - %a{ "ofn-with-tip" => "Order cycles determine when and where your products are available to customers." } What's this? %div.seven.columns.alpha.list - if @order_cycle_count > 0 %div.seven.columns.alpha.list-item diff --git a/config/locales/en.yml b/config/locales/en.yml index 7fd49fc2fe..e103001337 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -113,6 +113,7 @@ en: valid_email_error: Please enter a valid email address add_a_new_customer_for: Add a new customer for %{shop_name} code: Code + duplicate_code: "This code is used already." products: bulk_edit: diff --git a/spec/features/admin/customers_spec.rb b/spec/features/admin/customers_spec.rb index 964608510d..d2f3b9b8bf 100644 --- a/spec/features/admin/customers_spec.rb +++ b/spec/features/admin/customers_spec.rb @@ -50,7 +50,7 @@ feature 'Customers' do within "tr#c_#{customer1.id}" do fill_in "code", with: "new-customer-code" - expect(page).to have_css "input#code.update-pending" + expect(page).to have_css "input[name=code].update-pending" end within "tr#c_#{customer1.id}" do find(:css, "tags-input .tags input").set "awesome\n" @@ -59,7 +59,7 @@ feature 'Customers' do click_button "Save Changes" # Every says it updated - expect(page).to have_css "input#code.update-success" + expect(page).to have_css "input[name=code].update-success" expect(page).to have_css ".tag_watcher.update-success" # And it actually did diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb index 1e69e97b1c..7dc9f474da 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -251,6 +251,8 @@ feature "As a consumer I want to shop with a distributor", js: true do describe "when a product goes out of stock just before it's added to the cart" do it "stops the attempt, shows an error message and refreshes the products asynchronously" do + expect(page).to have_content "Product" + variant.update_attributes! on_hand: 0 # -- Messaging diff --git a/spec/features/consumer/shopping/variant_overrides_spec.rb b/spec/features/consumer/shopping/variant_overrides_spec.rb index 92945a60be..b59cb6a613 100644 --- a/spec/features/consumer/shopping/variant_overrides_spec.rb +++ b/spec/features/consumer/shopping/variant_overrides_spec.rb @@ -193,7 +193,7 @@ feature "shopping with variant overrides defined", js: true do end place_order - page.should have_content "Your order has been processed successfully" + expect(page).to have_content "Your order has been processed successfully" end def click_checkout diff --git a/spec/javascripts/unit/admin/customers/controllers/customers_controller_spec.js.coffee b/spec/javascripts/unit/admin/customers/controllers/customers_controller_spec.js.coffee index 7854700dfd..ec884a284b 100644 --- a/spec/javascripts/unit/admin/customers/controllers/customers_controller_spec.js.coffee +++ b/spec/javascripts/unit/admin/customers/controllers/customers_controller_spec.js.coffee @@ -21,7 +21,7 @@ describe "CustomersCtrl", -> expect(scope.CurrentShop.shop).toEqual {} describe "setting the shop on scope", -> - customer = { id: 5, email: 'someone@email.com'} + customer = { id: 5, email: 'someone@email.com', code: 'a'} customers = [customer] beforeEach -> @@ -33,6 +33,12 @@ describe "CustomersCtrl", -> it "retrievs the list of customers", -> expect(scope.customers).toDeepEqual customers + it "finds customers by code", -> + as = scope.findByCode('a') + expect(as).toDeepEqual customers + as = scope.findByCode('b') + expect(as).toDeepEqual [] + describe "scope.add", -> it "creates a new customer", -> email = "customer@example.org" diff --git a/spec/models/customer_spec.rb b/spec/models/customer_spec.rb index f2ac14e9b2..32e380f4d3 100644 --- a/spec/models/customer_spec.rb +++ b/spec/models/customer_spec.rb @@ -1,6 +1,23 @@ require 'spec_helper' describe Customer, type: :model do + describe 'an existing customer' do + let(:customer) { create(:customer) } + + it "saves its code" do + code = "code one" + customer.code = code + customer.save + expect(customer.code).to eq code + end + + it "can remove its code" do + customer.code = "" + customer.save + expect(customer.code).to be nil + end + end + describe 'creation callbacks' do let!(:user1) { create(:user) } let!(:user2) { create(:user) } diff --git a/spec/support/request/checkout_workflow.rb b/spec/support/request/checkout_workflow.rb index e08fb031da..4a0f37c0ea 100644 --- a/spec/support/request/checkout_workflow.rb +++ b/spec/support/request/checkout_workflow.rb @@ -8,7 +8,7 @@ module CheckoutWorkflow end def place_order - click_button "Place order now" + find("button", text: "Place order now").trigger "click" end def toggle_accordion(id)