diff --git a/app/assets/javascripts/admin/enterprises/controllers/side_menu_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/side_menu_controller.js.coffee index 7981e498b6..a0105fefa4 100644 --- a/app/assets/javascripts/admin/enterprises/controllers/side_menu_controller.js.coffee +++ b/app/assets/javascripts/admin/enterprises/controllers/side_menu_controller.js.coffee @@ -17,8 +17,9 @@ angular.module("admin.enterprises") { name: t('shipping_methods'), icon_class: "icon-truck", show: "showShippingMethods()" } { name: t('payment_methods'), icon_class: "icon-money", show: "showPaymentMethods()" } { name: t('enterprise_fees'), icon_class: "icon-tasks", show: "showEnterpriseFees()" } - { name: t('inventory_settings'), icon_class: "icon-list-ol", show: "showInventorySettings()" } - { name: t('shop_preferences'), icon_class: "icon-shopping-cart", show: "showShopPreferences()" } + { name: t('inventory_settings'), icon_class: "icon-list-ol", show: "enterpriseIsShop()" } + { name: t('tag_rules'), icon_class: "icon-random", show: "enterpriseIsShop()" } + { name: t('shop_preferences'), icon_class: "icon-shopping-cart", show: "enterpriseIsShop()" } ] $scope.select(0) @@ -42,8 +43,5 @@ angular.module("admin.enterprises") $scope.showEnterpriseFees = -> enterprisePermissions.can_manage_enterprise_fees && ($scope.Enterprise.sells != "none" || $scope.Enterprise.is_primary_producer) - $scope.showInventorySettings = -> - $scope.Enterprise.sells != "none" - - $scope.showShopPreferences = -> + $scope.enterpriseIsShop = -> $scope.Enterprise.sells != "none" diff --git a/app/assets/javascripts/admin/enterprises/controllers/tag_rules_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/tag_rules_controller.js.coffee new file mode 100644 index 0000000000..4b007c7744 --- /dev/null +++ b/app/assets/javascripts/admin/enterprises/controllers/tag_rules_controller.js.coffee @@ -0,0 +1,7 @@ +angular.module("admin.enterprises").controller "TagRulesCtrl", ($scope) -> + $scope.groupedTagRules = $scope.Enterprise.tag_rules.reduce (groupedTagRules, rule) -> + key = rule.preferred_customer_tags + groupedTagRules[key] ||= [] + groupedTagRules[key].push rule + groupedTagRules + , {} diff --git a/app/assets/javascripts/admin/enterprises/directives/tag_rules/discount_order.js.coffee b/app/assets/javascripts/admin/enterprises/directives/tag_rules/discount_order.js.coffee new file mode 100644 index 0000000000..079dd04dba --- /dev/null +++ b/app/assets/javascripts/admin/enterprises/directives/tag_rules/discount_order.js.coffee @@ -0,0 +1,4 @@ +angular.module("admin.enterprises").directive "discountOrder", -> + restrict: "E" + replace: true + templateUrl: "admin/tag_rules/discount_order.html" diff --git a/app/assets/javascripts/templates/admin/tag_rules/discount_order.html.haml b/app/assets/javascripts/templates/admin/tag_rules/discount_order.html.haml new file mode 100644 index 0000000000..19b4af427e --- /dev/null +++ b/app/assets/javascripts/templates/admin/tag_rules/discount_order.html.haml @@ -0,0 +1,26 @@ +%div + %input{ type: "hidden", + id: "enterprise_tag_rules_attributes_{{rule.id}}_id", + name: "enterprise[tag_rules_attributes][{{rule.id}}][id]", + ng: { value: "rule.id" } } + + %input{ type: "hidden", + id: "enterprise_tag_rules_attributes_{{rule.id}}_calculator_attributes_id", + name: "enterprise[tag_rules_attributes][{{rule.id}}][calculator_attributes][id]", + ng: { value: "rule.calculator.id" } } + + %input{ type: "hidden", + id: "enterprise_tag_rules_attributes_{{rule.id}}_calculator_attributes_type", + name: "enterprise[tag_rules_attributes][{{rule.id}}][calculator_attributes][type]", + value: "TagRule::FlatPercentItemTotal" } + + %span.text-big Apply a discount of + %span.input-symbol.after + %span.text-big % + %input.text-big{ type: "number", + id: "enterprise_tag_rules_attributes_{{rule.id}}_calculator_attributes_preferred_flat_percent", + name: "enterprise[tag_rules_attributes][{{rule.id}}][calculator_attributes][preferred_flat_percent]", + min: 0, + max: 100, + ng: { model: "rule.calculator.preferred_flat_percent" } } + %span.text-big to order subtotals diff --git a/app/assets/stylesheets/admin/orders.css.scss b/app/assets/stylesheets/admin/orders.css.scss index 9a2dd4385c..761ccbc014 100644 --- a/app/assets/stylesheets/admin/orders.css.scss +++ b/app/assets/stylesheets/admin/orders.css.scss @@ -69,6 +69,21 @@ div#group_buy_calculation { text-indent:1em; } } + + &.after { + + span { + position: absolute; + transform: translate(0,-55%); + top:50%; + right: 0.5em; + pointer-events:none; + } + + input { + padding-right: 1.2em; + } + } } th.actions { diff --git a/app/assets/stylesheets/admin/tag_rules.css.scss b/app/assets/stylesheets/admin/tag_rules.css.scss new file mode 100644 index 0000000000..eafc5826f7 --- /dev/null +++ b/app/assets/stylesheets/admin/tag_rules.css.scss @@ -0,0 +1,13 @@ +.customer_tag { + border: 1px solid #cee1f4; + + .header { + padding: 8px 10px; + background-color: #eff5fc; + border-bottom: 1px solid #cee1f4; + } + + .tag_rule { + padding: 8px 10px; + } +} diff --git a/app/assets/stylesheets/admin/typography.css.scss b/app/assets/stylesheets/admin/typography.css.scss index 20148df3f1..761058fb1d 100644 --- a/app/assets/stylesheets/admin/typography.css.scss +++ b/app/assets/stylesheets/admin/typography.css.scss @@ -7,3 +7,12 @@ font-size: 1.2rem; font-weight: 300; } + +.text-red { + color: #DA5354; +} + + +input.text-big { + font-size: 1.1rem; +} diff --git a/app/controllers/admin/enterprises_controller.rb b/app/controllers/admin/enterprises_controller.rb index 55eaabd7d8..d692984885 100644 --- a/app/controllers/admin/enterprises_controller.rb +++ b/app/controllers/admin/enterprises_controller.rb @@ -4,7 +4,7 @@ module Admin class EnterprisesController < ResourceController before_filter :load_enterprise_set, :only => :index before_filter :load_countries, :except => [:index, :register, :check_permalink] - before_filter :load_methods_and_fees, :only => [:new, :edit, :update, :create] + before_filter :load_methods_and_fees, :only => [:edit, :update] before_filter :load_groups, :only => [:new, :edit, :update, :create] before_filter :load_taxons, :only => [:new, :edit, :update, :create] before_filter :check_can_change_sells, only: :update diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index 3e1326eff8..62462ac425 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -48,6 +48,7 @@ class Enterprise < ActiveRecord::Base accepts_nested_attributes_for :address accepts_nested_attributes_for :producer_properties, allow_destroy: true, reject_if: lambda { |pp| pp[:property_name].blank? } + accepts_nested_attributes_for :tag_rules, allow_destroy: true has_attached_file :logo, styles: { medium: "300x300>", small: "180x180>", thumb: "100x100>" }, diff --git a/app/serializers/api/admin/calculator/flat_percent_item_total_serializer.rb b/app/serializers/api/admin/calculator/flat_percent_item_total_serializer.rb new file mode 100644 index 0000000000..7662edb3f6 --- /dev/null +++ b/app/serializers/api/admin/calculator/flat_percent_item_total_serializer.rb @@ -0,0 +1,7 @@ +class Api::Admin::Calculator::FlatPercentItemTotalSerializer < ActiveModel::Serializer + attributes :id, :preferred_flat_percent + + def preferred_flat_percent + object.preferred_flat_percent.to_i + end +end diff --git a/app/serializers/api/admin/enterprise_serializer.rb b/app/serializers/api/admin/enterprise_serializer.rb index 37a96b402f..1d9c37595d 100644 --- a/app/serializers/api/admin/enterprise_serializer.rb +++ b/app/serializers/api/admin/enterprise_serializer.rb @@ -7,4 +7,5 @@ class Api::Admin::EnterpriseSerializer < ActiveModel::Serializer has_one :owner, serializer: Api::Admin::UserSerializer has_many :users, serializer: Api::Admin::UserSerializer + has_many :tag_rules, serializer: Api::Admin::TagRuleSerializer end diff --git a/app/serializers/api/admin/tag_rule_serializer.rb b/app/serializers/api/admin/tag_rule_serializer.rb new file mode 100644 index 0000000000..a571b9fe5e --- /dev/null +++ b/app/serializers/api/admin/tag_rule_serializer.rb @@ -0,0 +1,19 @@ +class Api::Admin::TagRuleSerializer < ActiveModel::Serializer + def serializable_hash + rule_specific_serializer.serializable_hash + end + + def rule_specific_serializer + "Api::Admin::#{object.class.to_s}Serializer".constantize.new(object) + end +end + +module Api::Admin::TagRule + class BaseSerializer < ActiveModel::Serializer + attributes :id, :enterprise_id, :type, :preferred_customer_tags + end + + class DiscountOrderSerializer < BaseSerializer + has_one :calculator, serializer: Api::Admin::Calculator::FlatPercentItemTotalSerializer + end +end diff --git a/app/views/admin/enterprises/_form.html.haml b/app/views/admin/enterprises/_form.html.haml index 79faeea229..d602f7418d 100644 --- a/app/views/admin/enterprises/_form.html.haml +++ b/app/views/admin/enterprises/_form.html.haml @@ -54,3 +54,7 @@ %fieldset.alpha.no-border-bottom{ ng: { show: "menu.selected.name=='Shop Preferences'" } } %legend Shop Preferences = render 'admin/enterprises/form/shop_preferences', f: f + +%fieldset.alpha.no-border-bottom{ ng: { show: "menu.selected.name=='Tag Rules'" } } + %legend Tag Rules + = render 'admin/enterprises/form/tag_rules', f: f diff --git a/app/views/admin/enterprises/form/_tag_rules.html.haml b/app/views/admin/enterprises/form/_tag_rules.html.haml new file mode 100644 index 0000000000..44b1148058 --- /dev/null +++ b/app/views/admin/enterprises/form/_tag_rules.html.haml @@ -0,0 +1,10 @@ +.row{ ng: { controller: "TagRulesCtrl" } } + .eleven.columns.alpha.omega + .eleven.columns.alpha.omega + .customer_tag{ ng: { repeat: "(tags, rules) in groupedTagRules" }, bindonce: true } + .header + %h3 + For customers tagged + %span.text-red #{{ tags.split(",").join(", #") }} + .tag_rule{ ng: { repeat: "rule in rules" } } + %discount-order{ bo: { if: "rule.type == 'TagRule::DiscountOrder'" } } diff --git a/config/locales/en.yml b/config/locales/en.yml index fe102dff90..7892ecdce1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1001,6 +1001,7 @@ Please follow the instructions there to make your enterprise visible on the Open payment_methods: "Payment Methods" enterprise_fees: "Enterprise Fees" inventory_settings: "Inventory Settings" + tag_rules: "Tag Rules" shop_preferences: "Shop Preferences" validation_msg_relationship_already_established: "^That relationship is already established." validation_msg_at_least_one_hub: "^At least one hub must be selected" diff --git a/spec/features/admin/enterprises_spec.rb b/spec/features/admin/enterprises_spec.rb index b72258f7f9..3e9008968b 100644 --- a/spec/features/admin/enterprises_spec.rb +++ b/spec/features/admin/enterprises_spec.rb @@ -282,6 +282,31 @@ feature %q{ end end + describe "tag rules", js: true do + let!(:enterprise) { create(:distributor_enterprise) } + + context "updating" do + let!(:tag_rule) { create(:tag_rule, enterprise: enterprise, preferred_customer_tags: "member" ) } + + before do + login_to_admin_section + visit main_app.edit_admin_enterprise_path(enterprise) + end + + it "saves changes to the rule" do + click_link "Tag Rules" + + expect(first('.customer_tag .header')).to have_content "For customers tagged #member" + expect(page).to have_input "enterprise[tag_rules_attributes][#{tag_rule.id}][calculator_attributes][preferred_flat_percent]", with: "0" + fill_in "enterprise[tag_rules_attributes][#{tag_rule.id}][calculator_attributes][preferred_flat_percent]", with: 45 + + click_button 'Update' + + expect(tag_rule.calculator.preferred_flat_percent).to eq 45 + end + end + end + context "as an Enterprise user", js: true do let(:supplier1) { create(:supplier_enterprise, name: 'First Supplier') } diff --git a/spec/javascripts/unit/admin/enterprises/controllers/tag_rules_controller_spec.js.coffee b/spec/javascripts/unit/admin/enterprises/controllers/tag_rules_controller_spec.js.coffee new file mode 100644 index 0000000000..1b4ca0f34e --- /dev/null +++ b/spec/javascripts/unit/admin/enterprises/controllers/tag_rules_controller_spec.js.coffee @@ -0,0 +1,25 @@ +describe "TagRulesCtrl", -> + ctrl = null + scope = null + enterprise = null + + beforeEach -> + module('admin.enterprises') + enterprise = + tag_rules: [ + { id: 1, preferred_customer_tags: "member" }, + { id: 2, preferred_customer_tags: "member" }, + { id: 3, preferred_customer_tags: "local" } + ] + + inject ($rootScope, $controller) -> + scope = $rootScope + scope.Enterprise = enterprise + ctrl = $controller 'TagRulesCtrl', {$scope: scope} + + describe "initialization", -> + it "groups rules by preferred_customer_tags", -> + expect(scope.groupedTagRules).toEqual { + member: [{ id: 1, preferred_customer_tags: "member" }, { id: 2, preferred_customer_tags: "member" }], + local: [{ id: 3, preferred_customer_tags: "local" }] + }