Merge in enterprise confirmation

This commit is contained in:
Rob Harrington
2014-10-16 11:52:10 +11:00
17 changed files with 180 additions and 38 deletions

View File

@@ -4,18 +4,20 @@
%header
%h2 Well done!
%h5
You have successfully completed the profile for
That's all of the details we need for
%span.brick{"ng-show" => "enterprise.is_distributor"}
{{ enterprise.name }}
%span.turquoise{"ng-show" => "!enterprise.is_distributor" }
{{ enterprise.name }}
.content{ style: 'text-align: center'}
%h3 Why not check it out on the Open Food Network?
%a.button.primary{ type: "button", href: "/map" } Go to Map Page >
%br
%br
%h3 There's just one last thing we need you to do:
%h5 We've sent a confirmation email to {{ enterprise.email }}, so please follow the instructions there to finalise the creation of your enterprise.
%h3 Next step - add some products:
%a.button.primary{ type: "button", href: "/admin/products/new" } Add a Product >
-# perhaps a pretty picture here?
%br/
%br/
%a.button.primary{ type: "button", href: "/" } Take me home >

View File

@@ -1,13 +1,12 @@
.container#registration-social
%ng-include{ src: "'registration/steps.html'" }
.row
.small-12.columns
%header
%h2 Last step!
%h2 Almost there!
%h5 How can people find {{ enterprise.name }} online?
%form{ name: 'social', novalidate: true, ng: { controller: "RegistrationFormCtrl", submit: "update('finished',social)" } }
.row.content
.small-12.large-7.columns

View File

@@ -0,0 +1,15 @@
.alert
border: 3px solid #919191
border-radius: 6px
margin-bottom: 20px
color: #919191
padding: 5px 10px
h6
color: #919191
.message
font-weight: bold
&:hover
border-color: #DA5354
color: #DA5354
h6
color: #DA5354

View File

@@ -1,10 +1,18 @@
require 'devise/mailers/helpers'
class EnterpriseMailer < Spree::BaseMailer
include Devise::Mailers::Helpers
def creation_confirmation(enterprise)
find_enterprise(enterprise)
subject = "#{@enterprise.name} is now on #{Spree::Config[:site_name]}"
mail(:to => @enterprise.owner.email, :from => from_address, :subject => subject)
end
def confirmation_instructions(record, token, opts={})
@token = token
devise_mail(record, :confirmation_instructions, opts)
end
private
def find_enterprise(enterprise)
@enterprise = enterprise.is_a?(Enterprise) ? enterprise : Enterprise.find(enterprise)

View File

@@ -1,5 +1,5 @@
Spree::UserMailer.class_eval do
def signup_confirmation(user)
@user = user
mail(:to => user.email, :from => from_address,

View File

@@ -2,10 +2,14 @@ class Enterprise < ActiveRecord::Base
TYPES = %w(full single profile)
ENTERPRISE_SEARCH_RADIUS = 100
devise :confirmable, reconfirmable: true
self.inheritance_column = nil
acts_as_gmappable :process_geocoding => false
before_create :check_email
after_create :send_creation_email
has_and_belongs_to_many :groups, class_name: 'EnterpriseGroup'
@@ -59,6 +63,8 @@ class Enterprise < ActiveRecord::Base
scope :by_name, order('name')
scope :visible, where(:visible => true)
scope :confirmed, where('confirmed_at IS NOT NULL')
scope :unconfirmed, where('confirmed_at IS NULL')
scope :is_primary_producer, where(:is_primary_producer => true)
scope :is_distributor, where(:is_distributor => true)
scope :supplying_variant_in, lambda { |variants| joins(:supplied_products => :variants_including_master).where('spree_variants.id IN (?)', variants).select('DISTINCT enterprises.*') }
@@ -260,8 +266,18 @@ class Enterprise < ActiveRecord::Base
select('DISTINCT spree_taxons.*')
end
protected
def devise_mailer
EnterpriseMailer
end
private
def check_email
skip_confirmation! if owner.enterprises.confirmed.map(&:email).include?(email)
end
def send_creation_email
EnterpriseMailer.creation_confirmation(self).deliver
end

View File

@@ -102,6 +102,10 @@ class Api::CachedEnterpriseSerializer < ActiveModel::Serializer
has_one :address, serializer: Api::AddressSerializer
def visible
object.visible && object.confirmed?
end
def pickup
object.shipping_methods.where(:require_ship_address => false).present?
end

View File

@@ -0,0 +1,5 @@
%p= "Welcome #{@resource.contact}!"
%p= "You can confirm this email address for #{@resource.name} using the link below:"
%p= link_to 'Confirm this email address', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token)

View File

@@ -0,0 +1,4 @@
- @enterprises.unconfirmed.each do |enterprise|
.alert
%h6= "Action Required: Please confirm the email address for #{enterprise.name}."
%span.message= "We've sent a confirmation email to #{enterprise.email}, so please check there for further instructions. Thanks!"

View File

@@ -1,17 +1,18 @@
%h1{ :style => 'margin-bottom: 30px'} Dashboard
- if @enterprises.empty?
- if @enterprises.unconfirmed.any?
= render partial: "spree/admin/overview/enterprises"
= render partial: "spree/admin/overview/unconfirmed"
- else
- if can? :admin, Spree::Product
= render partial: "spree/admin/overview/products"
%hr
%div.two.columns
&nbsp;
- if can? :admin, Spree::Product
= render partial: "spree/admin/overview/products"
- if can? :admin, OrderCycle
= render partial: "spree/admin/overview/order_cycles"
%div.two.columns
&nbsp;
= render partial: "spree/admin/overview/enterprises"
- if can? :admin, OrderCycle
= render partial: "spree/admin/overview/order_cycles"
= render partial: "spree/admin/overview/enterprises"

View File

@@ -35,6 +35,8 @@ Openfoodnetwork::Application.routes.draw do
end
end
devise_for :enterprise
namespace :admin do
resources :order_cycles do
post :bulk_update, on: :collection, as: :bulk_update

View File

@@ -0,0 +1,16 @@
class AddConfirmableToEnterprise < ActiveRecord::Migration
def up
add_column :enterprises, :confirmation_token, :string
add_column :enterprises, :confirmed_at, :datetime
add_column :enterprises, :confirmation_sent_at, :datetime
add_column :enterprises, :unconfirmed_email, :string
add_index :enterprises, :confirmation_token, :unique => true
# Existing enterprises are assumed to be confirmed
Enterprise.update_all(:confirmed_at => Time.now)
end
def down
remove_columns :enterprises, :confirmation_token, :confirmed_at, :confirmation_sent_at, :unconfirmed_email
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20140904003026) do
ActiveRecord::Schema.define(:version => 20141010043405) do
create_table "adjustment_metadata", :force => true do |t|
t.integer "adjustment_id"
@@ -266,9 +266,14 @@ ActiveRecord::Schema.define(:version => 20140904003026) do
t.string "linkedin"
t.string "type", :default => "profile", :null => false
t.integer "owner_id", :null => false
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
end
add_index "enterprises", ["address_id"], :name => "index_enterprises_on_address_id"
add_index "enterprises", ["confirmation_token"], :name => "index_enterprises_on_confirmation_token", :unique => true
add_index "enterprises", ["owner_id"], :name => "index_enterprises_on_owner_id"
create_table "exchange_fees", :force => true do |t|

View File

@@ -77,7 +77,7 @@ feature "Registration", js: true do
click_button 'Continue'
# Filling in social
expect(page).to have_content 'Last step!'
expect(page).to have_content 'Almost there!'
fill_in 'enterprise_website', with: 'www.shop.com'
fill_in 'enterprise_facebook', with: 'FaCeBoOk'
fill_in 'enterprise_linkedin', with: 'LiNkEdIn'
@@ -86,7 +86,7 @@ feature "Registration", js: true do
click_button 'Continue'
# Done
expect(page).to have_content "You have successfully completed the profile for My Awesome Enterprise"
expect(page).to have_content "That's all of the details we need for My Awesome Enterprise"
e.reload
expect(e.website).to eq "www.shop.com"
expect(e.facebook).to eq "FaCeBoOk"

View File

@@ -10,4 +10,9 @@ describe EnterpriseMailer do
EnterpriseMailer.creation_confirmation(@enterprise).deliver
ActionMailer::Base.deliveries.count.should == 1
end
it "should send an email confirmation when given an enterprise" do
EnterpriseMailer.confirmation_instructions(@enterprise, 'token').deliver
ActionMailer::Base.deliveries.count.should == 1
end
end

View File

@@ -3,6 +3,25 @@ require 'spec_helper'
describe Enterprise do
include AuthenticationWorkflow
describe "sending emails" do
describe "on creation" do
let!(:user) { create_enterprise_user( enterprise_limit: 2 ) }
let!(:enterprise) { create(:enterprise, owner: user, confirmed_at: Time.now) }
it "when the email address has not already been confirmed" do
mail_message = double "Mail::Message"
EnterpriseMailer.should_receive(:confirmation_instructions).and_return mail_message
mail_message.should_receive :deliver
create(:enterprise, owner: user, email: "unknown@email.com" )
end
it "when the email address has already been confirmed" do
EnterpriseMailer.should_not_receive(:confirmation_instructions)
e = create(:enterprise, owner: user, email: enterprise.email)
end
end
end
describe "associations" do
it { should belong_to(:owner) }
it { should have_many(:supplied_products) }
@@ -102,6 +121,7 @@ describe Enterprise do
it { should delegate(:city).to(:address) }
it { should delegate(:state_name).to(:address) }
end
describe "scopes" do
describe 'active' do
it 'find active enterprises' do
@@ -111,6 +131,28 @@ describe Enterprise do
end
end
describe "confirmed" do
it "find enterprises with a confirmed date" do
s1 = create(:supplier_enterprise, confirmed_at: Time.now)
d1 = create(:distributor_enterprise, confirmed_at: Time.now)
s2 = create(:supplier_enterprise, confirmed_at: nil)
d2 = create(:distributor_enterprise, confirmed_at: nil)
expect(Enterprise.confirmed).to include s1, d1
expect(Enterprise.confirmed).to_not include s2, d2
end
end
describe "unconfirmed" do
it "find enterprises without a confirmed date" do
s1 = create(:supplier_enterprise, confirmed_at: Time.now)
d1 = create(:distributor_enterprise, confirmed_at: Time.now)
s2 = create(:supplier_enterprise, confirmed_at: nil)
d2 = create(:distributor_enterprise, confirmed_at: nil)
expect(Enterprise.unconfirmed).to_not include s1, d1
expect(Enterprise.unconfirmed).to include s2, d2
end
end
describe "distributors_with_active_order_cycles" do
it "finds active distributors by order cycles" do
s = create(:supplier_enterprise)
@@ -507,40 +549,40 @@ describe Enterprise do
# Swap type values full > sell_all, single > sell_own profile > sell_none
# swap is_distributor for new can_supply flag.
let(:producer_sell_all_can_supply) {
let(:producer_sell_all_can_supply) {
create(:enterprise, is_primary_producer: true, type: "full", is_distributor: true)
}
let(:producer_sell_all_cant_supply) {
let(:producer_sell_all_cant_supply) {
create(:enterprise, is_primary_producer: true, type: "full", is_distributor: false)
}
let(:producer_sell_own_can_supply) {
let(:producer_sell_own_can_supply) {
create(:enterprise, is_primary_producer: true, type: "single", is_distributor: true)
}
let(:producer_sell_own_cant_supply) {
let(:producer_sell_own_cant_supply) {
create(:enterprise, is_primary_producer: true, type: "single", is_distributor: false)
}
let(:producer_sell_none_can_supply) {
let(:producer_sell_none_can_supply) {
create(:enterprise, is_primary_producer: true, type: "profile", is_distributor: true)
}
let(:producer_sell_none_cant_supply) {
let(:producer_sell_none_cant_supply) {
create(:enterprise, is_primary_producer: true, type: "profile", is_distributor: false)
}
let(:non_producer_sell_all_can_supply) {
create(:enterprise, is_primary_producer: true, type: "full", is_distributor: true)
}
let(:non_producer_sell_all_cant_supply) {
let(:non_producer_sell_all_cant_supply) {
create(:enterprise, is_primary_producer: true, type: "full", is_distributor: false)
}
let(:non_producer_sell_own_can_supply) {
let(:non_producer_sell_own_can_supply) {
create(:enterprise, is_primary_producer: true, type: "single", is_distributor: true)
}
let(:non_producer_sell_own_cant_supply) {
let(:non_producer_sell_own_cant_supply) {
create(:enterprise, is_primary_producer: true, type: "single", is_distributor: false)
}
let(:non_producer_sell_none_can_supply) {
let(:non_producer_sell_none_can_supply) {
create(:enterprise, is_primary_producer: false, type: "profile", is_distributor: true)
}
let(:non_producer_sell_none_cant_supply) {
let(:non_producer_sell_none_cant_supply) {
create(:enterprise, is_primary_producer: false, type: "profile", is_distributor: false)
}
@@ -555,8 +597,8 @@ describe Enterprise do
producer_sell_own_cant_supply.enterprise_category.should == "producer_shop"
producer_sell_none_can_supply.enterprise_category.should == "producer"
producer_sell_none_cant_supply.enterprise_category.should == "producer_profile"
non_producer_sell_all_can_supply.enterprise_category.should == "hub"
non_producer_sell_all_cant_supply.enterprise_category.should == "hub"
non_producer_sell_all_can_supply.enterprise_category.should == "hub"
non_producer_sell_all_cant_supply.enterprise_category.should == "hub"
non_producer_sell_own_can_supply.enterprise_category.should == "hub"
non_producer_sell_own_cant_supply.enterprise_category.should == "hub"
non_producer_sell_none_can_supply.enterprise_category.should == "hub_profile"

View File

@@ -13,9 +13,27 @@ describe Api::EnterpriseSerializer do
serializer = Api::EnterpriseSerializer.new enterprise
serializer.to_json.should match taxon.id.to_s
end
it "will render urls" do
serializer = Api::EnterpriseSerializer.new enterprise
serializer.to_json.should match "map_005-hub.svg"
end
describe "visibility" do
before do
enterprise.stub(:visible).and_return true
end
it "is visible when confirmed" do
enterprise.stub(:confirmed?).and_return true
serializer = Api::EnterpriseSerializer.new enterprise
expect(serializer.to_json).to match "\"visible\":true"
end
it "is not visible when unconfirmed" do
enterprise.stub(:confirmed?).and_return false
serializer = Api::EnterpriseSerializer.new enterprise
expect(serializer.to_json).to match "\"visible\":false"
end
end
end