mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-28 01:53:25 +00:00
Billing and Shipping addresses can be set on new standing orders
This commit is contained in:
@@ -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?
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
91
app/views/admin/standing_orders/_address.html.haml
Normal file
91
app/views/admin/standing_orders/_address.html.haml
Normal 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
|
||||
|
||||
.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 }}
|
||||
@@ -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")
|
||||
|
||||
@@ -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'" } }
|
||||
|
||||
@@ -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) }}
|
||||
|
||||
@@ -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...
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user