Billing and Shipping addresses can be set on new standing orders

This commit is contained in:
Rob Harrington
2016-10-14 16:59:48 +11:00
parent b701ca43f4
commit 4ad6b1a65e
12 changed files with 170 additions and 7 deletions

View File

@@ -0,0 +1,25 @@
angular.module("admin.standingOrders").controller "AddressController", ($scope, $filter, StatusMessage, availableCountries) ->
$scope.submitted = false
$scope.countries = availableCountries
$scope.statesFor = (country_id) ->
return [] unless country_id
$filter('filter')(availableCountries, {id: country_id})[0].states
$scope.billStates = $scope.statesFor($scope.standingOrder.bill_address.country_id)
$scope.shipStates = $scope.statesFor($scope.standingOrder.ship_address.country_id)
$scope.next = ->
$scope.submitted = true
if $scope.standing_order_address_form.$valid
StatusMessage.clear()
$scope.setView('products')
else
StatusMessage.display 'failure', t('admin.standing_orders.details.invalid_error')
$scope.back = -> $scope.setView('details')
$scope.$watch 'standingOrder.bill_address.country_id', (newValue, oldValue) ->
$scope.billStates = $scope.statesFor(newValue) if newValue?
$scope.$watch 'standingOrder.ship_address.country_id', (newValue, oldValue) ->
$scope.shipStates = $scope.statesFor(newValue) if newValue?

View File

@@ -5,6 +5,6 @@ angular.module("admin.standingOrders").controller "DetailsController", ($scope,
$scope.submitted = true
if $scope.standing_order_details_form.$valid
StatusMessage.clear()
$scope.setView('products')
$scope.setView('address')
else
StatusMessage.display 'failure', t('admin.standing_orders.details.invalid_error')

View File

@@ -6,4 +6,4 @@ angular.module("admin.standingOrders").controller "ProductsController", ($scope,
else
StatusMessage.display 'failure', 'Please add at least one product'
$scope.back = -> $scope.setView('details')
$scope.back = -> $scope.setView('address')

View File

@@ -4,7 +4,7 @@ module Admin
class StandingOrdersController < ResourceController
before_filter :load_shop, only: [:new]
before_filter :load_shops, only: [:index]
before_filter :wrap_sli_attrs, only: [:create]
before_filter :wrap_nested_attrs, only: [:create]
respond_to :json
respond_override create: { json: {
@@ -25,6 +25,8 @@ module Admin
def new
@standing_order.shop = @shop
@standing_order.bill_address = Spree::Address.new
@standing_order.ship_address = Spree::Address.new
@customers = Customer.of(@shop)
@schedules = Schedule.with_coordinator(@shop)
@payment_methods = Spree::PaymentMethod.for_distributor(@shop)
@@ -63,13 +65,19 @@ module Admin
end
# Wrap :standing_line_items_attributes in :standing_order root
def wrap_sli_attrs
def wrap_nested_attrs
if params[:standing_line_items].is_a? Array
attributes = params[:standing_line_items].map do |sli|
sli.slice(*StandingLineItem.attribute_names)
end
params[:standing_order][:standing_line_items_attributes] = attributes
end
if bill_address_attrs = params[:bill_address]
params[:standing_order][:bill_address_attributes] = bill_address_attrs.slice(*Spree::Address.attribute_names)
end
if ship_address_attrs = params[:ship_address]
params[:standing_order][:ship_address_attributes] = ship_address_attrs.slice(*Spree::Address.attribute_names)
end
end
# Overriding Spree method to load data from params here so that

View File

@@ -2,6 +2,8 @@ class Api::Admin::StandingOrderSerializer < ActiveModel::Serializer
attributes :id, :shop_id, :customer_id, :schedule_id, :payment_method_id, :shipping_method_id, :begins_at, :ends_at
has_many :standing_line_items, serializer: Api::Admin::StandingLineItemSerializer
has_one :bill_address, serializer: Api::AddressSerializer
has_one :ship_address, serializer: Api::AddressSerializer
def begins_at
object.begins_at.andand.strftime('%F')

View File

@@ -0,0 +1,91 @@
.row
.seven.columns.alpha
%fieldset.no-border-bottom
%legend{ align: 'center'}= t(:bill_address)
.field
%label{ for: 'bill_address_firstname'}= t(:first_name)
%input.fullwidth#bill_address_firstname{ name: 'bill_address_firstname', type: 'text', required: true, ng: { model: "standingOrder.bill_address.firstname" } }
.error{ ng: { show: 'submitted && standing_order_address_form.bill_address_firstname.$error.required' } }= t(:error_required)
.error{ ng: { repeat: "error in errors['bill_address.firstname']", show: 'standing_order_address_form.bill_address_firstname.$pristine' } } {{ error }}
.field
%label{ for: 'bill_address_lastname'}= t(:last_name)
%input.fullwidth#bill_address_lastname{ name: 'bill_address_lastname', type: 'text', required: true, ng: { model: "standingOrder.bill_address.lastname" } }
.error{ ng: { show: 'submitted && standing_order_address_form.bill_address_lastname.$error.required' } }= t(:error_required)
.error{ ng: { repeat: "error in errors['bill_address.lastname']", show: 'standing_order_address_form.bill_address_lastname.$pristine' } } {{ error }}
.field
%label{ for: 'bill_address_address1'}= t(:address)
%input.fullwidth#bill_address_address1{ name: 'bill_address_address1', type: 'text', required: true, ng: { model: "standingOrder.bill_address.address1" } }
.error{ ng: { show: 'submitted && standing_order_address_form.bill_address_address1.$error.required' } }= t(:error_required)
.error{ ng: { repeat: "error in errors['bill_address.address1']", show: 'standing_order_address_form.bill_address_address1.$pristine' } } {{ error }}
.field
%label{ for: 'bill_address_city'}= t(:suburb)
%input.fullwidth#bill_address_city{ name: 'bill_address_city', type: 'text', required: true, ng: { model: "standingOrder.bill_address.city" } }
.error{ ng: { show: 'submitted && standing_order_address_form.bill_address_city.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.bill_address.city', show: 'standing_order_address_form.bill_address_city.$pristine' } } {{ error }}
.field
%label{ for: "bill_address_zipcode"}= t(:postcode)
%input.fullwidth#bill_address_zipcode{ name: 'bill_address_zipcode', type: 'text', required: true, ng: { model: "standingOrder.bill_address.zipcode" } }
.error{ ng: { show: 'submitted && standing_order_address_form.bill_address_zipcode.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.bill_address.zipcode', show: 'standing_order_address_form.bill_address_zipcode.$pristine' } } {{ error }}
.field
%label{ for: "bill_address_phone"}= t(:phone)
%input.fullwidth#bill_address_phone{ name: 'bill_address_phone', type: 'text', required: true, ng: { model: "standingOrder.bill_address.phone" } }
.error{ ng: { show: 'submitted && standing_order_address_form.bill_address_phone.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.bill_address.phone', show: 'standing_order_address_form.bill_address_phone.$pristine' } } {{ error }}
.field
%label{ for: "bill_address_country_id"}= t(:country)
%input.ofn-select2.fullwidth#bill_address_country_id{ name: 'bill_address_country_id', type: 'number', data: 'countries', required: true, placeholder: t('admin.choose'), ng: { model: 'standingOrder.bill_address.country_id' } }
.error{ ng: { show: 'submitted && standing_order_address_form.bill_address_country_id.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.bill_address.country', show: 'standing_order_address_form.bill_address_country_id.$pristine' } } {{ error }}
.field
%label{ for: "bill_address_state_id"}= t(:state)
%input.ofn-select2.fullwidth#bill_address_state_id{ name: 'bill_address_state_id', type: 'number', data: 'billStates', required: true, placeholder: t('admin.choose'), ng: { model: 'standingOrder.bill_address.state_id' } }
.error{ ng: { show: 'submitted && standing_order_address_form.bill_address_state_id.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.bill_address.state', show: 'standing_order_address_form.bill_address_state_id.$pristine' } } {{ error }}
.two.columns
&nbsp;
.seven.columns.omega
%fieldset.no-border-bottom
%legend{ align: 'center'}= t(:ship_address)
.field
%label{ for: 'ship_address_firstname'}= t(:first_name)
%input.fullwidth#ship_address_firstname{ name: 'ship_address_firstname', type: 'text', required: true, ng: { model: "standingOrder.ship_address.firstname" } }
.error{ ng: { show: 'submitted && standing_order_address_form.ship_address_firstname.$error.required' } }= t(:error_required)
.error{ ng: { repeat: "error in errors['ship_address.firstname']", show: 'standing_order_address_form.ship_address_firstname.$pristine' } } {{ error }}
.field
%label{ for: 'ship_address_lastname'}= t(:last_name)
%input.fullwidth#ship_address_lastname{ name: 'ship_address_lastname', type: 'text', required: true, ng: { model: "standingOrder.ship_address.lastname" } }
.error{ ng: { show: 'submitted && standing_order_address_form.ship_address_lastname.$error.required' } }= t(:error_required)
.error{ ng: { repeat: "error in errors['ship_address.lastname']", show: 'standing_order_address_form.ship_address_lastname.$pristine' } } {{ error }}
.field
%label{ for: 'ship_address_address1'}= t(:address)
%input.fullwidth#ship_address_address1{ name: 'ship_address_address1', type: 'text', required: true, ng: { model: "standingOrder.ship_address.address1" } }
.error{ ng: { show: 'submitted && standing_order_address_form.ship_address_address1.$error.required' } }= t(:error_required)
.error{ ng: { repeat: "error in errors['ship_address.address1']", show: 'standing_order_address_form.ship_address_address1.$pristine' } } {{ error }}
.field
%label{ for: 'ship_address_city'}= t(:suburb)
%input.fullwidth#ship_address_city{ name: 'ship_address_city', type: 'text', required: true, ng: { model: "standingOrder.ship_address.city" } }
.error{ ng: { show: 'submitted && standing_order_address_form.ship_address_city.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.ship_address.city', show: 'standing_order_address_form.ship_address_city.$pristine' } } {{ error }}
.field
%label{ for: "ship_address_zipcode"}= t(:potcode)
%input.fullwidth#ship_address_zipcode{ name: 'ship_address_zipcode', type: 'text', required: true, ng: { model: "standingOrder.ship_address.zipcode" } }
.error{ ng: { show: 'submitted && standing_order_address_form.ship_address_zipcode.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.ship_address.zipcode', show: 'standing_order_address_form.ship_address_zipcode.$pristine' } } {{ error }}
.field
%label{ for: "ship_address_phone"}= t(:phone)
%input.fullwidth#ship_address_phone{ name: 'ship_address_phone', type: 'text', required: true, ng: { model: "standingOrder.ship_address.phone" } }
.error{ ng: { show: 'submitted && standing_order_address_form.ship_address_phone.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.ship_address.phone', show: 'standing_order_address_form.ship_address_phone.$pristine' } } {{ error }}
.field
%label{ for: "ship_address_country_id"}= t(:country)
%input.ofn-select2.fullwidth#ship_address_country_id{ name: 'ship_address_country_id', type: 'number', data: 'countries', required: true, placeholder: t('admin.choose'), ng: { model: 'standingOrder.ship_address.country_id' } }
.error{ ng: { show: 'submitted && standing_order_address_form.ship_address_country_id.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.ship_address.country', show: 'standing_order_address_form.ship_address_country_id.$pristine' } } {{ error }}
.field
%label{ for: "ship_address_state_id"}= t(:state)
%input.ofn-select2.fullwidth#ship_address_state_id{ name: 'ship_address_state_id', type: 'number', data: 'shipStates', required: true, placeholder: t('admin.choose'), ng: { model: 'standingOrder.ship_address.state_id' } }
.error{ ng: { show: 'submitted && standing_order_address_form.ship_address_state_id.$error.required' } }= t(:error_required)
.error{ ng: { repeat: 'error in errors.ship_address.state', show: 'standing_order_address_form.ship_address_state_id.$pristine' } } {{ error }}

View File

@@ -4,3 +4,4 @@
= admin_inject_json_ams_array "admin.standingOrders", "schedules", @schedules, Api::Admin::IdNameSerializer if @schedules
= admin_inject_json_ams_array "admin.standingOrders", "paymentMethods", @payment_methods, Api::Admin::IdNameSerializer if @payment_methods
= admin_inject_json_ams_array "admin.standingOrders", "shippingMethods", @shipping_methods, Api::Admin::IdNameSerializer if @shipping_methods
= admin_inject_available_countries(module: "admin.standingOrders")

View File

@@ -8,6 +8,13 @@
%input.red{ type: "button", value: t(:next), ng: { click: 'next()' } }
= render 'details'
.address{ ng: { show: "['address','review'].indexOf(view) >= 0" } }
%ng-form{ name: 'standing_order_address_form', ng: { controller: 'AddressController' } }
%save-bar{ dirty: "standing_order_address_form.$dirty", persist: 'true', ng: { hide: "view == 'review'" } }
%input{ type: "button", value: t(:back), ng: { click: "back()" } }
%input.red{ type: "button", value: t(:next), ng: { click: 'next()' } }
= render 'address'
.products{ ng: { show: "['products','review'].indexOf(view) >= 0" } }
%ng-form{ name: 'standing_order_products_form', ng: { controller: 'ProductsController' } }
%save-bar{ dirty: "standing_order_products_form.$dirty", persist: 'true', ng: { hide: "view == 'review'" } }

View File

@@ -1,3 +1,3 @@
%ul.wizard-progress
%li{ ng: { repeat: "step in ['details','products','review']", class: '{current: view==step}' } }
%li{ ng: { repeat: "step in ['details','address','products','review']", class: '{current: view==step}' } }
{{ stepTitleFor(step) }}

View File

@@ -129,6 +129,8 @@ en:
say_yes: "Yes"
then: then
ongoing: Ongoing
bill_address: Billing Address
ship_address: Shipping Address
sort_order_cycles_on_shopfront_by: "Sort Order Cycles On Shopfront By"
required_fields: Required fields are denoted with an asterisk
select_continue: Select and Continue
@@ -798,8 +800,9 @@ en:
create: Create Standing Order
steps:
details: 1. Basic Details
products: 2. Add Products
review: 3. Review & Save
address: 2. Address
products: 3. Add Products
review: 4. Review & Save
details:
details: Details
invalid_error: Oops! Please fill in all of the required fields...

View File

@@ -159,6 +159,7 @@ describe Admin::StandingOrdersController, type: :controller do
end
context 'when I submit valid and complete params' do
let!(:address) { create(:address) }
before do
params[:standing_order].merge!({
schedule_id: schedule.id,
@@ -168,6 +169,10 @@ describe Admin::StandingOrdersController, type: :controller do
begins_at: 2.days.ago,
ends_at: 3.months.from_now
})
params.merge!({
bill_address: address.attributes.except('id'),
ship_address: address.attributes.except('id')
})
end
it 'creates a standing order' do
@@ -177,6 +182,8 @@ describe Admin::StandingOrdersController, type: :controller do
expect(standing_order.customer).to eq customer
expect(standing_order.payment_method).to eq payment_method
expect(standing_order.shipping_method).to eq shipping_method
expect(standing_order.bill_address.firstname).to eq address.firstname
expect(standing_order.ship_address.firstname).to eq address.firstname
end
context 'with standing_line_items params' do

View File

@@ -85,6 +85,23 @@ feature 'Standing Orders' do
expect(page).to have_content 'Oops! Please fill in all of the required fields...'
fill_in 'begins_at', with: Date.today.strftime('%F')
click_button('Next')
expect(page).to have_content 'BILLING ADDRESS'
click_button('Next')
expect(page).to have_content 'can\'t be blank', count: 16
# Setting the shipping and billing addresses
[:bill_address, :ship_address].each do |type|
fill_in "#{type}_firstname", with: 'Freda'
fill_in "#{type}_lastname", with: 'Figapple'
fill_in "#{type}_address1", with: '7 Tempany Lane'
fill_in "#{type}_city", with: 'Natte Yallock'
fill_in "#{type}_zipcode", with: '3465'
fill_in "#{type}_phone", with: '0400 123 456'
select2_select "Australia", from: "#{type}_country_id"
select2_select "Victoria", from: "#{type}_state_id"
end
click_button('Next')
expect(page).to have_content 'NAME OR SKU'
click_button('Next')
@@ -122,6 +139,8 @@ feature 'Standing Orders' do
expect(standing_order.schedule).to eq schedule
expect(standing_order.payment_method).to eq payment_method
expect(standing_order.shipping_method).to eq shipping_method
expect(standing_order.bill_address.firstname).to eq 'Freda'
expect(standing_order.ship_address.firstname).to eq 'Freda'
# Standing Line Items are created
expect(standing_order.standing_line_items.count).to eq 1