Commit d663bb672ef8861404f5d2b1d9b025aeaf7dc3cd

Authored by Braulio Bhavamitra
1 parent 0f263193

Update delivery, orders, orders_cycle, suppliers and shopping_cart to rails4

Showing 113 changed files with 1592 additions and 560 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 113 files displayed.

plugins/delivery/controllers/myprofile/delivery_plugin/admin_method_controller.rb
@@ -14,7 +14,7 @@ class DeliveryPlugin::AdminMethodController < MyProfileController @@ -14,7 +14,7 @@ class DeliveryPlugin::AdminMethodController < MyProfileController
14 14
15 def edit 15 def edit
16 @delivery_method ||= profile.delivery_methods.find_by_id params[:id] 16 @delivery_method ||= profile.delivery_methods.find_by_id params[:id]
17 - if params[:delivery_method].present? and @delivery_method.update_attributes params[:delivery_method] 17 + if params[:delivery_method].present? and @delivery_method.update params[:delivery_method]
18 render partial: 'list' 18 render partial: 'list'
19 else 19 else
20 render partial: 'edit', locals: {delivery_method: @delivery_method} 20 render partial: 'edit', locals: {delivery_method: @delivery_method}
plugins/delivery/controllers/myprofile/delivery_plugin/admin_options_controller.rb
@@ -8,7 +8,13 @@ class DeliveryPlugin::AdminOptionsController < DeliveryPlugin::AdminMethodContro @@ -8,7 +8,13 @@ class DeliveryPlugin::AdminOptionsController < DeliveryPlugin::AdminMethodContro
8 before_filter :load_owner 8 before_filter :load_owner
9 9
10 def select 10 def select
  11 + end
11 12
  13 + def select_all
  14 + missing_methods = profile.delivery_methods - @owner.delivery_methods
  15 + missing_methods.each do |dm|
  16 + DeliveryPlugin::Option.create! owner_id: @owner.id, owner_type: @owner.class.name, delivery_method: dm
  17 + end
12 end 18 end
13 19
14 def new 20 def new
plugins/delivery/db/migrate/20150623125525_add_distribution_margin_to_delivery_plugin_method.rb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +class AddDistributionMarginToDeliveryPluginMethod < ActiveRecord::Migration
  2 +
  3 + def change
  4 + add_column :delivery_plugin_methods, :distribution_margin_fixed, :decimal
  5 + add_column :delivery_plugin_methods, :distribution_margin_percentage, :decimal
  6 + end
  7 +
  8 +end
plugins/delivery/lib/delivery_plugin/display_helper.rb
@@ -9,15 +9,24 @@ module DeliveryPlugin::DisplayHelper @@ -9,15 +9,24 @@ module DeliveryPlugin::DisplayHelper
9 methods = options[:methods] || profile.delivery_methods 9 methods = options[:methods] || profile.delivery_methods
10 10
11 options = methods.map do |method| 11 options = methods.map do |method|
12 - cost = if method.fixed_cost.present? and method.fixed_cost > 0 then float_to_currency_cart(method.fixed_cost, environment) else nil end 12 + cost = if method.fixed_cost.present? and method.fixed_cost > 0 then method.fixed_cost_as_currency else nil end
13 text = if cost.present? then "#{method.name} (#{cost})" else method.name end 13 text = if cost.present? then "#{method.name} (#{cost})" else method.name end
14 14
15 content_tag :option, text, value: method.id, 15 content_tag :option, text, value: method.id,
16 - data: {label: method.name, type: method.delivery_type, instructions: method.description.to_s},  
17 - selected: if method == selected then 'selected' else nil end 16 + data: {label: method.name, type: method.delivery_type, instructions: CGI::escapeHTML(method.description.to_s)},
  17 + selected: if method.id == selected then 'selected' else nil end
18 end.join 18 end.join
19 end 19 end
20 20
  21 + def consumer_delivery_field_value order, field
  22 + # BLACK OR WHITE: do not mix existing delivery data with user's location
  23 + if order.consumer_delivery_data.present?
  24 + order.consumer_delivery_data[field]
  25 + elsif user
  26 + user.send field
  27 + end
  28 + end
  29 +
21 def delivery_context 30 def delivery_context
22 @delivery_context || 'delivery_plugin/admin_method' 31 @delivery_context || 'delivery_plugin/admin_method'
23 end 32 end
plugins/delivery/lib/ext/profile.rb
1 require_dependency 'profile' 1 require_dependency 'profile'
2 2
3 -class Profile 3 +([Profile] + Profile.descendants).each do |subclass|
  4 +subclass.class_eval do
4 5
5 - has_many :delivery_methods, class_name: 'DeliveryPlugin::Method', foreign_key: :profile_id, dependent: :destroy, order: 'id ASC' 6 + has_many :delivery_methods, -> { order 'id ASC' }, class_name: 'DeliveryPlugin::Method', foreign_key: :profile_id, dependent: :destroy
6 7
7 end 8 end
  9 +end
plugins/delivery/locales/en-US.yml
@@ -12,16 +12,23 @@ @@ -12,16 +12,23 @@
12 delivery_type: 'Type' 12 delivery_type: 'Type'
13 delivery_type_help: 'Pickup: the products will be delivered in the consumption place.<br>Delivery: the products will be delivered in the address asked by the consumer.' 13 delivery_type_help: 'Pickup: the products will be delivered in the consumption place.<br>Delivery: the products will be delivered in the address asked by the consumer.'
14 name: Name 14 name: Name
15 - name_help: Write the name of the Consumption Place or the  
16 - fixed_cost: Fixed cost  
17 - free_over_price: Order's minimum price for free delivery 15 + name_help: Write the name of the Consumption Place or the
  16 +
  17 + costs_legend: Delivery's costs
  18 + fixed_cost: Fixed cost of delivery
  19 + free_over_price: Order's minimum value for free delivery
  20 +
  21 + distribution_legend: Distribution's costs
  22 + distribution_margin_percentage: Distribution's margin
  23 + distribution_margin_fixed: Distribution's margin (fixed)
  24 +
18 instructions: Description 25 instructions: Description
19 instructions_help: "Write the address and other important informations about the place of this consumption place.<br> This text will be available" 26 instructions_help: "Write the address and other important informations about the place of this consumption place.<br> This text will be available"
20 views: 27 views:
21 - delivery_option:  
22 - select: 28 + delivery_option:
  29 + select:
23 add: Add selected 30 add: Add selected
24 - _select_content: 31 + _select_content:
25 add: Add option 32 add: Add option
26 add_new: "add new" 33 add_new: "add new"
27 are_you_sure_you_want: "Are you sure you want to remove?" 34 are_you_sure_you_want: "Are you sure you want to remove?"
@@ -29,14 +36,14 @@ @@ -29,14 +36,14 @@
29 choose_a_delivery_met: "Choose a delivery method from the list" 36 choose_a_delivery_met: "Choose a delivery method from the list"
30 edit_this: "Edit" 37 edit_this: "Edit"
31 remove_method: "Remove" 38 remove_method: "Remove"
32 - _show: 39 + _show:
33 x: X 40 x: X
34 - select: 41 + select:
35 add_a_delivery_method: "Add a delivery method to the Orders' Cycle" 42 add_a_delivery_method: "Add a delivery method to the Orders' Cycle"
36 method: 43 method:
37 index: 44 index:
38 new: "New delivery or pickup" 45 new: "New delivery or pickup"
39 - edit: 46 + edit:
40 add: Add 47 add: Add
41 back: back 48 back: back
42 save: Save 49 save: Save
plugins/delivery/locales/pt-BR.yml
@@ -13,15 +13,21 @@ @@ -13,15 +13,21 @@
13 delivery_type_help: "Retirada: os produtos serão buscados pela(o) consumidor(a), por exemplo, no empreendimento, numa feira ou num Núcleo de Consumo.<br>Entrega: os produtos serão entregues no endereço solicitado pelo(a) consumidor(a)." 13 delivery_type_help: "Retirada: os produtos serão buscados pela(o) consumidor(a), por exemplo, no empreendimento, numa feira ou num Núcleo de Consumo.<br>Entrega: os produtos serão entregues no endereço solicitado pelo(a) consumidor(a)."
14 name: Nome 14 name: Nome
15 name_help: "Para opção Retirada: escreva o nome do local onde os produtos deverão ser retirados pela(o) consumidor(a), por exemplo o nome do Núcleo de Consumo, da feira ou do próprio empreendimento.<br>Para a opção Entrega: escreva o nome do local, (uma cidade ou região) ou a forma de entrega (Correios, transportadora)" 15 name_help: "Para opção Retirada: escreva o nome do local onde os produtos deverão ser retirados pela(o) consumidor(a), por exemplo o nome do Núcleo de Consumo, da feira ou do próprio empreendimento.<br>Para a opção Entrega: escreva o nome do local, (uma cidade ou região) ou a forma de entrega (Correios, transportadora)"
16 - fixed_cost: Custo  
17 - free_over_price: "Preço mínimo do pedido para Entrega Grátis" 16 +
  17 + costs_legend: Custos de entrega
  18 + fixed_cost: Custo de entrega
  19 + free_over_price: "Valor mínimo do pedido para Entrega Grátis"
  20 + distribution_legend: Custos de distribuição
  21 + distribution_margin_percentage: Margem de distribuição
  22 + distribution_margin_fixed: Margem de distribuição (valor fixo)
  23 +
18 instructions: Descrição 24 instructions: Descrição
19 instructions_help: "Escreva informações importantes sobre esta opção de Retirada ou Entrega.<br>Por exemplo, o endereço completo do Núcleo de Consumo, a abrangência da região de entrega.<br> Este texto estará disponível no \"Finalizar pedido\" e, ao confirmar a compra, o(a) consumidor(a) receberá um email com o pedido realizado e as informações deste campo." 25 instructions_help: "Escreva informações importantes sobre esta opção de Retirada ou Entrega.<br>Por exemplo, o endereço completo do Núcleo de Consumo, a abrangência da região de entrega.<br> Este texto estará disponível no \"Finalizar pedido\" e, ao confirmar a compra, o(a) consumidor(a) receberá um email com o pedido realizado e as informações deste campo."
20 views: 26 views:
21 - delivery_option:  
22 - select: 27 + delivery_option:
  28 + select:
23 add: "Adicionar selecionados" 29 add: "Adicionar selecionados"
24 - _select_content: 30 + _select_content:
25 add: Adicionar opção 31 add: Adicionar opção
26 add_new: "adicionar novo" 32 add_new: "adicionar novo"
27 are_you_sure_you_want: "Tem certeza de que quer remover?" 33 are_you_sure_you_want: "Tem certeza de que quer remover?"
@@ -29,14 +35,14 @@ @@ -29,14 +35,14 @@
29 choose_a_delivery_met: "Escolha um método de entrega da lista" 35 choose_a_delivery_met: "Escolha um método de entrega da lista"
30 edit_this: Editar 36 edit_this: Editar
31 remove_method: "Remover" 37 remove_method: "Remover"
32 - _show: 38 + _show:
33 x: X 39 x: X
34 - select: 40 + select:
35 add_a_delivery_method: "Adicionar um método de entrega ao ciclo de pedidos" 41 add_a_delivery_method: "Adicionar um método de entrega ao ciclo de pedidos"
36 method: 42 method:
37 index: 43 index:
38 new: "Nova forma de entrega ou retirada" 44 new: "Nova forma de entrega ou retirada"
39 - edit: 45 + edit:
40 add: Adicionar 46 add: Adicionar
41 back: voltar 47 back: voltar
42 save: Salvar 48 save: Salvar
plugins/delivery/models/delivery_plugin/method.rb
1 class DeliveryPlugin::Method < ActiveRecord::Base 1 class DeliveryPlugin::Method < ActiveRecord::Base
2 2
3 - extend CurrencyHelper::ClassMethods  
4 -  
5 Types = ['pickup', 'deliver'] 3 Types = ['pickup', 'deliver']
6 4
7 # see also: Profile::LOCATION_FIELDS 5 # see also: Profile::LOCATION_FIELDS
@@ -10,7 +8,7 @@ class DeliveryPlugin::Method &lt; ActiveRecord::Base @@ -10,7 +8,7 @@ class DeliveryPlugin::Method &lt; ActiveRecord::Base
10 ].map(&:to_sym) 8 ].map(&:to_sym)
11 9
12 attr_accessible :profile, :delivery_type, :name, :description, 10 attr_accessible :profile, :delivery_type, :name, :description,
13 - :fixed_cost, :free_over_price 11 + :fixed_cost, :free_over_price, :distribution_margin_percentage, :distribution_margin_fixed
14 12
15 belongs_to :profile 13 belongs_to :profile
16 14
@@ -20,8 +18,14 @@ class DeliveryPlugin::Method &lt; ActiveRecord::Base @@ -20,8 +18,14 @@ class DeliveryPlugin::Method &lt; ActiveRecord::Base
20 validates_presence_of :name 18 validates_presence_of :name
21 validates_inclusion_of :delivery_type, in: Types 19 validates_inclusion_of :delivery_type, in: Types
22 20
23 - scope :pickup, conditions: {delivery_type: 'pickup'}  
24 - scope :delivery, conditions: {delivery_type: 'deliver'} 21 + scope :pickup, -> { where delivery_type: 'pickup' }
  22 + scope :delivery, -> { where delivery_type: 'deliver'}
  23 +
  24 + extend CurrencyHelper::ClassMethods
  25 + has_currency :fixed_cost
  26 + has_currency :free_over_price
  27 + has_currency :distribution_margin_percentage
  28 + has_currency :distribution_margin_fixed
25 29
26 def pickup? 30 def pickup?
27 self.delivery_type == 'pickup' 31 self.delivery_type == 'pickup'
@@ -30,22 +34,40 @@ class DeliveryPlugin::Method &lt; ActiveRecord::Base @@ -30,22 +34,40 @@ class DeliveryPlugin::Method &lt; ActiveRecord::Base
30 self.delivery_type == 'deliver' 34 self.delivery_type == 'deliver'
31 end 35 end
32 36
33 - def has_cost? order_price=nil 37 + def has_distribution_margin?
  38 + (self.distribution_margin_percentage.present? and self.distribution_margin_percentage.nonzero?) or
  39 + (self.distribution_margin_fixed.present? and self.distribution_margin_fixed.nonzero?)
  40 + end
  41 +
  42 + def has_fixed_cost? order_price=nil
34 if order_price.present? and order_price.nonzero? and self.free_over_price.present? and self.free_over_price.nonzero? 43 if order_price.present? and order_price.nonzero? and self.free_over_price.present? and self.free_over_price.nonzero?
35 order_price <= self.free_over_price 44 order_price <= self.free_over_price
36 else 45 else
37 self.fixed_cost.present? and self.fixed_cost.nonzero? 46 self.fixed_cost.present? and self.fixed_cost.nonzero?
38 end 47 end
39 end 48 end
  49 +
  50 + def distribution_margin order_price
  51 + value = 0
  52 + value += self.distribution_margin_fixed if self.distribution_margin_fixed.present?
  53 + value += order_price * (self.distribution_margin_percentage/100) if self.distribution_margin_percentage.present?
  54 + value
  55 + end
  56 +
  57 + def has_cost? order_price=nil
  58 + has_cost = self.has_distribution_margin?
  59 + has_cost ||= self.has_fixed_cost? order_price
  60 + end
40 def free? order_price=nil 61 def free? order_price=nil
41 !self.has_cost? 62 !self.has_cost?
42 end 63 end
43 64
44 def cost order_price=nil 65 def cost order_price=nil
45 - if self.has_cost?(order_price) then self.fixed_cost.to_f else 0 end 66 + value = 0
  67 + value += self.fixed_cost if self.has_fixed_cost? order_price
  68 + value += self.distribution_margin order_price if self.has_distribution_margin?
  69 + value
46 end 70 end
47 - has_currency :fixed_cost  
48 - has_currency :free_over_price  
49 has_currency :cost 71 has_currency :cost
50 72
51 protected 73 protected
plugins/delivery/public/stylesheets/delivery.scss
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 #delivery-method-edition { 3 #delivery-method-edition {
4 @extend .container-clean; 4 @extend .container-clean;
5 5
6 - .field-help { 6 + .help-block {
7 font-size: 10px; 7 font-size: 10px;
8 } 8 }
9 } 9 }
plugins/delivery/test/test_helper.rb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +require File.dirname(__FILE__) + '/../../../test/test_helper'
plugins/delivery/test/unit/delivery_plugin/method_test.rb 0 → 100644
@@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
  1 +require "#{File.dirname(__FILE__)}/../../test_helper"
  2 +
  3 +class DeliveryPlugin::MethodTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @profile = build(Profile)
  7 + end
  8 +
  9 + attr_accessor :profile
  10 +
  11 + should 'have a name and a delivery type' do
  12 + dm = DeliveryPlugin::Method.new :name => 'Delivery Deluxe', :delivery_type => 'deliver', :profile => profile
  13 + assert dm.valid?
  14 + dm = DeliveryPlugin::Method.new :profile => profile
  15 + assert !dm.valid?
  16 + end
  17 +
  18 + should 'accept only pickup and deliver as delivery types' do
  19 + dm = build(DeliveryPlugin::Method, :name => 'Delivery Deluxe', :delivery_type => 'unkown', :profile => profile)
  20 + assert !dm.valid?
  21 + dm = build(DeliveryPlugin::Method, :name => 'Delivery Deluxe', :delivery_type => 'pickup', :profile => profile)
  22 + assert dm.valid?
  23 + dm = build(DeliveryPlugin::Method, :name => 'Delivery Deluxe', :delivery_type => 'deliver', :profile => profile)
  24 + assert dm.valid?
  25 + end
  26 +
  27 + should 'filter by delivery types' do
  28 + dm_deliver = create(DeliveryPlugin::Method, :name => 'Delivery Deluxe', :delivery_type => 'deliver', :profile => profile)
  29 + dm_pickup = create(DeliveryPlugin::Method, :name => 'Delivery Deluxe', :delivery_type => 'pickup', :profile => profile)
  30 + assert_equal [dm_deliver], DeliveryPlugin::Method.delivery
  31 + assert_equal [dm_pickup], DeliveryPlugin::Method.pickup
  32 + end
  33 +
  34 + should 'have many delivery options' do
  35 + dm = create(DeliveryPlugin::Method, :name => 'Delivery Deluxe', :delivery_type => 'deliver', :profile => profile)
  36 + cycle = build(OrdersCyclePlugin::Cycle, :name => 'cycle name', :profile => profile)
  37 + option = create(DeliveryPlugin::Option, :cycle => cycle, :delivery_method => dm)
  38 +
  39 + assert_equal [option], dm.reload.delivery_options
  40 + end
  41 +
  42 +end
plugins/delivery/test/unit/delivery_plugin/option_test.rb 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +require "#{File.dirname(__FILE__)}/../../test_helper"
  2 +
  3 +class DeliveryPlugin::OptionTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @profile = build(Profile)
  7 + @cycle = build(OrdersCyclePluginCycle, :profile => @profile)
  8 + @delivery_method = build(OrdersCyclePluginMethod, :profile => @profile)
  9 + end
  10 +
  11 + attr_accessor :profile
  12 + attr_accessor :cycle
  13 + attr_accessor :delivery_method
  14 +
  15 + should 'be associated with a cycle and a delivery method' do
  16 + option = OrdersCyclePluginOption.new :cycle => @cycle, :delivery_method => @delivery_method
  17 + assert option.valid?
  18 + option = OrdersCyclePluginOption.new
  19 + :wa
  20 +
  21 + assert !option.valid?
  22 + end
  23 +
  24 +end
plugins/delivery/views/delivery_plugin/_order_select.html.slim
@@ -2,30 +2,37 @@ @@ -2,30 +2,37 @@
2 - edition = true if edition.nil? 2 - edition = true if edition.nil?
3 - readonly = !edition 3 - readonly = !edition
4 4
5 -div.order-delivery-select 5 +div.order-delivery-select id='order-#{order.id}'
6 6
7 div.supplier-delivery-data 7 div.supplier-delivery-data
8 - = labelled_form_field _('Option'),  
9 - f.select(:supplier_delivery_id, supplier_delivery_options(methods: methods), {}, disabled: readonly,  
10 - onchange: 'delivery.order.select.onChange(this)', onkeyup: 'delivery.order.select.onChange(this)')  
11 - p.instructions 8 + - if order.delivery_methods.size > 0
  9 + = labelled_form_field _('Option'),
  10 + f.select(:supplier_delivery_id, supplier_delivery_options(methods: methods, selected: order.supplier_delivery_id), {}, disabled: readonly,
  11 + onchange: 'delivery.order.select.onChange(this)', onkeyup: 'delivery.order.select.onChange(this)') + content_tag('div', '', class: 'help-block instructions')
  12 + - elsif (name = consumer_delivery_field_value order, :name).present?
  13 + = labelled_form_field _('Option'),
  14 + f.text_field(:address, value: name, readonly: true)
  15 + div class='help-block instructions' = h(consumer_delivery_field_value order, :description)
12 16
13 - div.consumer-delivery-data  
14 - = f.fields_for :consumer_delivery_data, order.consumer_delivery_data do |ff|  
15 - = labelled_form_field _('Address (street and number)'),  
16 - ff.text_field(:address, value: order.consumer_delivery_data[:address], readonly: readonly)  
17 - = labelled_form_field _('Address completion'),  
18 - ff.text_field(:address_line2, value: order.consumer_delivery_data[:address_line2], readonly: readonly)  
19 - = labelled_form_field _('Address reference'),  
20 - ff.text_field(:address_reference, value: order.consumer_delivery_data[:address_reference], readonly: readonly)  
21 - = labelled_form_field _('District'),  
22 - ff.text_field(:district, value: order.consumer_delivery_data[:district], readonly: readonly)  
23 - = labelled_form_field _('City'),  
24 - ff.text_field(:city, value: order.consumer_delivery_data[:city], readonly: readonly)  
25 - = labelled_form_field _('State'),  
26 - ff.text_field(:state, value: order.consumer_delivery_data[:state], readonly: readonly)  
27 - = labelled_form_field _('ZIP code'),  
28 - ff.text_field(:zip_code, value: order.consumer_delivery_data[:zip_code], readonly: readonly) 17 + / do not render on confirmation email (@view) if supplier_delivery is pickup
  18 + - unless (@view and order.supplier_delivery_data[:delivery_type] == 'pickup') or order.delivery_methods.size == 0
  19 + div.consumer-delivery-data
  20 + = f.fields_for :consumer_delivery_data do |ff|
  21 + = labelled_form_field _('Address (street and number)'),
  22 + ff.text_field(:address, value: consumer_delivery_field_value(order, :address), readonly: readonly)
  23 + = labelled_form_field _('Address completion'),
  24 + ff.text_field(:address_line2, value: consumer_delivery_field_value(order, :address_line2), readonly: readonly)
  25 + = labelled_form_field _('Address reference'),
  26 + ff.text_field(:address_reference, value: consumer_delivery_field_value(order, :address_reference), readonly: readonly)
  27 + = labelled_form_field _('District'),
  28 + ff.text_field(:district, value: consumer_delivery_field_value(order, :district), readonly: readonly)
  29 + = labelled_form_field _('City'),
  30 + ff.text_field(:city, value: consumer_delivery_field_value(order, :city), readonly: readonly)
  31 + = labelled_form_field _('State'),
  32 + ff.text_field(:state, value: consumer_delivery_field_value(order, :state), readonly: readonly)
  33 + = labelled_form_field _('ZIP code'),
  34 + ff.text_field(:zip_code, value: consumer_delivery_field_value(order, :zip_code), readonly: readonly)
  35 +
  36 +javascript:
  37 + delivery.order.select.onChange($('.order-delivery-select#order-#{order.id} #order_supplier_delivery_id'))
29 38
30 - javascript:  
31 - delivery.order.select.onChange($('#order_supplier_delivery_id'))  
plugins/delivery/views/delivery_plugin/admin_method/_edit.html.slim
@@ -12,15 +12,27 @@ @@ -12,15 +12,27 @@
12 = labelled_field f, :name, t('delivery_plugin.models.method.name'), f.text_field(:name), 12 = labelled_field f, :name, t('delivery_plugin.models.method.name'), f.text_field(:name),
13 help: t('delivery_plugin.models.method.name_help') 13 help: t('delivery_plugin.models.method.name_help')
14 = labelled_field f, :description, t('delivery_plugin.models.method.instructions'), 14 = labelled_field f, :description, t('delivery_plugin.models.method.instructions'),
15 - f.text_area(:description, rows: 5), help: t('delivery_plugin.models.method.instructions_help') 15 + f.text_area(:description, rows: 5, class: 'mceEditor'), help: t('delivery_plugin.models.method.instructions_help')
16 16
17 - = labelled_field f, :fixed_cost, t('delivery_plugin.models.method.fixed_cost'),  
18 - input_group_addon(environment.currency_unit){ f.text_field :fixed_cost, type: :number, step: '0.01', value: number_with_precision(delivery_method.fixed_cost, precision: 2, locale: :en)} 17 + fieldset
  18 + legend= t'delivery_plugin.models.method.costs_legend'
  19 + = labelled_field f, :fixed_cost, t('delivery_plugin.models.method.fixed_cost'),
  20 + input_group_addon(environment.currency_unit){ f.text_field :fixed_cost, type: :number, step: 'any', value: number_with_precision(delivery_method.fixed_cost, precision: 2, locale: :en)}
19 21
20 - = labelled_field f, :free_over_price, t('delivery_plugin.models.method.free_over_price'),  
21 - input_group_addon(environment.currency_unit){ f.text_field :free_over_price, type: :number, step: '0.01', value: number_with_precision(delivery_method.free_over_price, precision: 2, locale: :en)} 22 + = labelled_field f, :free_over_price, t('delivery_plugin.models.method.free_over_price'),
  23 + input_group_addon(environment.currency_unit){ f.text_field :free_over_price, type: :number, step: 'any', value: number_with_precision(delivery_method.free_over_price, precision: 2, locale: :en)}
  24 +
  25 + fieldset
  26 + legend= t'delivery_plugin.models.method.distribution_legend'
  27 + = labelled_field f, :distribution_margin_percentage, t('delivery_plugin.models.method.distribution_margin_percentage'),
  28 + input_group_addon('%'){ f.text_field :distribution_margin_percentage, type: :number, step: 'any', value: number_with_precision(delivery_method.distribution_margin_percentage, precision: 2, locale: :en)}
  29 +
  30 + = labelled_field f, :distribution_margin_fixed, t('delivery_plugin.models.method.distribution_margin_fixed'),
  31 + input_group_addon(environment.currency_unit){ f.text_field :distribution_margin_fixed, type: :number, step: 'any', value: number_with_precision(delivery_method.distribution_margin_fixed, precision: 2, locale: :en)}
22 32
23 div 33 div
24 = submit_button :save, if delivery_method.new_record? then t('delivery_plugin.views.method.edit.add') else t('delivery_plugin.views.method.edit.save') end 34 = submit_button :save, if delivery_method.new_record? then t('delivery_plugin.views.method.edit.add') else t('delivery_plugin.views.method.edit.save') end
25 = link_to_function t('delivery_plugin.views.method.edit.back'), "delivery.method.view.toggle()" 35 = link_to_function t('delivery_plugin.views.method.edit.back'), "delivery.method.view.toggle()"
26 36
  37 += render file: 'shared/tiny_mce', locals: {mode: 'simple'}
  38 +
plugins/delivery/views/delivery_plugin/admin_method/_show.html.slim
1 -td.name title="#{method.description}" 1 +td.name title="#{strip_tags method.description}"
2 = method.name 2 = method.name
3 td.actions 3 td.actions
4 - if request.GET[:select_ids].present? and not method.id.to_s.in? Array(request.GET[:selected_ids]) 4 - if request.GET[:select_ids].present? and not method.id.to_s.in? Array(request.GET[:selected_ids])
plugins/delivery/views/delivery_plugin/admin_options/_new.js.erb
1 -// FIXME: move to orders_cycle plugin  
2 -jQuery('#cycle-delivery-options').html('<%= j render('index', owner: @owner) %>'); 1 +// FIXME: use generic class
  2 +$('#cycle-delivery-options').html('<%= j render('index', owner: @owner) %>');
3 noosfero.modal.close() 3 noosfero.modal.close()
4 4
plugins/delivery/views/delivery_plugin/admin_options/select_all.js.erb 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +// FIXME: use generic class
  2 +$('#cycle-delivery-options').html('<%= j render('index', owner: @owner) %>');
  3 +
plugins/orders/controllers/myprofile/orders_plugin_admin_controller.rb
@@ -43,8 +43,8 @@ class OrdersPluginAdminController &lt; MyProfileController @@ -43,8 +43,8 @@ class OrdersPluginAdminController &lt; MyProfileController
43 @orders_method = if @actor_name == :supplier then :sales else :purchases end 43 @orders_method = if @actor_name == :supplier then :sales else :purchases end
44 44
45 @order = profile.send(@orders_method).find params[:id] 45 @order = profile.send(@orders_method).find params[:id]
46 - return render_access_denied unless @order.verify_actor? profile, @actor_name  
47 - @order.update_attributes params[:order] 46 + return render_access_denied unless @user_is_admin or @order.verify_actor? profile, @actor_name
  47 + @order.update params[:order]
48 48
49 respond_to do |format| 49 respond_to do |format|
50 format.js{ render 'orders_plugin_admin/edit' } 50 format.js{ render 'orders_plugin_admin/edit' }
plugins/orders/controllers/myprofile/orders_plugin_admin_item_controller.rb
@@ -15,7 +15,7 @@ class OrdersPluginAdminItemController &lt; MyProfileController @@ -15,7 +15,7 @@ class OrdersPluginAdminItemController &lt; MyProfileController
15 @actor_name = params[:actor_name].to_sym 15 @actor_name = params[:actor_name].to_sym
16 @order = if @actor_name == :consumer then @item.purchase else @item.sale end 16 @order = if @actor_name == :consumer then @item.purchase else @item.sale end
17 17
18 - @item.update_attributes! params[:item] 18 + @item.update! params[:item]
19 end 19 end
20 20
21 def add_search 21 def add_search
plugins/orders/controllers/myprofile/orders_plugin_item_controller.rb
@@ -23,7 +23,7 @@ class OrdersPluginItemController &lt; MyProfileController @@ -23,7 +23,7 @@ class OrdersPluginItemController &lt; MyProfileController
23 23
24 if params[:item].present? and set_quantity_consumer_ordered params[:item][:quantity_consumer_ordered] 24 if params[:item].present? and set_quantity_consumer_ordered params[:item][:quantity_consumer_ordered]
25 params[:item][:quantity_consumer_ordered] = @quantity_consumer_ordered 25 params[:item][:quantity_consumer_ordered] = @quantity_consumer_ordered
26 - @item.update_attributes! params[:item] 26 + @item.update! params[:item]
27 end 27 end
28 end 28 end
29 29
plugins/orders/controllers/profile/orders_plugin_order_controller.rb
@@ -8,6 +8,7 @@ class OrdersPluginOrderController &lt; ProfileController @@ -8,6 +8,7 @@ class OrdersPluginOrderController &lt; ProfileController
8 before_filter :load_order, except: [:new] 8 before_filter :load_order, except: [:new]
9 before_filter :check_access, only: [:confirm, :remove, :cancel] 9 before_filter :check_access, only: [:confirm, :remove, :cancel]
10 before_filter :set_actor_name 10 before_filter :set_actor_name
  11 + before_filter :disable_purechat
11 12
12 helper OrdersPlugin::TranslationHelper 13 helper OrdersPlugin::TranslationHelper
13 helper OrdersPlugin::DisplayHelper 14 helper OrdersPlugin::DisplayHelper
@@ -19,7 +20,7 @@ class OrdersPluginOrderController &lt; ProfileController @@ -19,7 +20,7 @@ class OrdersPluginOrderController &lt; ProfileController
19 20
20 def load_order 21 def load_order
21 @order = hmvc_orders_context::Sale.find_by_id params[:id] 22 @order = hmvc_orders_context::Sale.find_by_id params[:id]
22 - render_access_denied if @order.present? and not @order.may_view? user 23 + render_access_denied if @order.present? and (not @user_is_admin or not @order.may_view? user)
23 end 24 end
24 25
25 def check_access access = 'view' 26 def check_access access = 'view'
@@ -40,4 +41,8 @@ class OrdersPluginOrderController &lt; ProfileController @@ -40,4 +41,8 @@ class OrdersPluginOrderController &lt; ProfileController
40 extend HMVC::ClassMethods 41 extend HMVC::ClassMethods
41 hmvc OrdersPlugin, orders_context: OrdersPlugin 42 hmvc OrdersPlugin, orders_context: OrdersPlugin
42 43
  44 + def disable_purechat
  45 + @disable_purechat = true
  46 + end
  47 +
43 end 48 end
plugins/orders/db/migrate/20150627232432_add_status_to_orders_plugin_item.rb 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +class AddStatusToOrdersPluginItem < ActiveRecord::Migration
  2 +
  3 + def change
  4 + add_column :orders_plugin_items, :status, :string
  5 + add_column :orders_plugin_orders, :building_next_status, :boolean
  6 +
  7 + say_with_time "filling items' statuses..." do
  8 + OrdersPlugin::Item.includes(:order).find_each batch_size: 50 do |item|
  9 + next item.destroy if item.order.nil?
  10 + item.fill_status
  11 + end
  12 + end
  13 + end
  14 +
  15 +end
plugins/orders/lib/code_numbering.rb 0 → 100644
@@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
  1 +module CodeNumbering
  2 + module ClassMethods
  3 + def code_numbering field, options = {}
  4 + class_attribute :code_numbering_field
  5 + class_attribute :code_numbering_options
  6 +
  7 + self.code_numbering_field = field
  8 + self.code_numbering_options = options
  9 +
  10 + before_create :create_code_numbering
  11 +
  12 + include CodeNumbering::InstanceMethods
  13 + end
  14 + end
  15 +
  16 + module InstanceMethods
  17 +
  18 + def code
  19 + self.attributes[self.code_numbering_field.to_s]
  20 + end
  21 +
  22 + def code_scope
  23 + scope = self.code_numbering_options[:scope]
  24 + case scope
  25 + when Symbol
  26 + self.send scope
  27 + when Proc
  28 + instance_exec &scope
  29 + else
  30 + self.class
  31 + end
  32 + end
  33 +
  34 + def code_maximum
  35 + self.code_scope.maximum(self.code_numbering_field) || 0
  36 + end
  37 +
  38 + def create_code_numbering
  39 + max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start]
  40 + max = self.code_maximum
  41 + self.send "#{self.code_numbering_field}=", max+1
  42 + end
  43 +
  44 + def reset_scope_code_numbering
  45 + max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start]
  46 + max ||= 1
  47 +
  48 + self.code_scope.order(:created_at).each do |record|
  49 + record.update_column self.code_numbering_field, max
  50 + max += 1
  51 + end
  52 + self.reload
  53 + end
  54 +
  55 + end
  56 +end
  57 +
  58 +ActiveRecord::Base.extend CodeNumbering::ClassMethods
plugins/orders/lib/ext/profile.rb
1 require_dependency 'profile' 1 require_dependency 'profile'
  2 +require_dependency 'community'
2 3
3 -# FIXME move to core  
4 -class Profile  
5 -  
6 - def has_admin? person  
7 - return unless person  
8 - person.has_permission? 'edit_profile', self  
9 - end  
10 -  
11 -end  
12 -  
13 -class Profile 4 +([Profile] + Profile.descendants).each do |subclass|
  5 +subclass.class_eval do
14 6
15 # cannot use :order because of months/years named_scope 7 # cannot use :order because of months/years named_scope
16 has_many :orders, class_name: 'OrdersPlugin::Sale', foreign_key: :profile_id 8 has_many :orders, class_name: 'OrdersPlugin::Sale', foreign_key: :profile_id
17 has_many :sales, class_name: 'OrdersPlugin::Sale', foreign_key: :profile_id 9 has_many :sales, class_name: 'OrdersPlugin::Sale', foreign_key: :profile_id
18 has_many :purchases, class_name: 'OrdersPlugin::Purchase', foreign_key: :consumer_id 10 has_many :purchases, class_name: 'OrdersPlugin::Purchase', foreign_key: :consumer_id
19 11
20 - has_many :ordered_items, through: :orders, source: :items, order: 'name ASC' 12 + has_many :ordered_items, -> { order 'name ASC' }, through: :orders, source: :items
21 13
22 has_many :sales_consumers, through: :sales, source: :consumer 14 has_many :sales_consumers, through: :sales, source: :consumer
23 - has_many :purchases_consumers, through: :purchases, source: :consumer 15 + has_many :purchases_consumers, through: :sales, source: :consumer
24 16
25 has_many :sales_profiles, through: :sales, source: :profile 17 has_many :sales_profiles, through: :sales, source: :profile
26 - has_many :purchases_profiles, through: :purchases, source: :profile 18 + has_many :purchases_profiles, through: :sales, source: :profile
  19 +
  20 +end
  21 +end
  22 +
  23 +class Profile
  24 +
  25 + # FIXME move to core
  26 + def has_admin? person
  27 + return unless person
  28 + person.has_permission? 'edit_profile', self
  29 + end
27 30
28 def sales_all_consumers 31 def sales_all_consumers
29 consumers = self.sales_consumers.order 'name ASC' 32 consumers = self.sales_consumers.order 'name ASC'
30 - consumers.concat self.consumers.except_self.order('name ASC') if self.respond_to? :consumers 33 + consumers.concat self.suppliers.except_self.order('name ASC') if self.respond_to? :suppliers
31 consumers.uniq 34 consumers.uniq
32 end 35 end
33 - def purchases_all_suppliers  
34 - suppliers = self.purchases_profiles.order 'name ASC'  
35 - suppliers.concat self.suppliers.except_self.order('name ASC') if self.respond_to? :suppliers  
36 - suppliers.uniq 36 + def purchases_all_consumers
  37 + consumers = self.purchases_consumers.order 'name ASC'
  38 + consumers.concat self.consumers.except_self.order('name ASC') if self.respond_to? :consumers
  39 + consumers.uniq
37 end 40 end
38 41
39 def self.create_orders_manager_role env_id 42 def self.create_orders_manager_role env_id
plugins/orders/lib/ext/session_store.rb
1 -require 'active_record/session_store' 1 +require_dependency 'session'
2 2
3 -class ActiveRecord::SessionStore::Session 3 +class Session
4 4
5 has_many :orders, primary_key: :session_id, foreign_key: :session_id, class_name: 'OrdersPlugin::Order' 5 has_many :orders, primary_key: :session_id, foreign_key: :session_id, class_name: 'OrdersPlugin::Order'
6 6
plugins/orders/lib/orders_plugin/display_helper.rb
@@ -2,6 +2,8 @@ module OrdersPlugin::DisplayHelper @@ -2,6 +2,8 @@ module OrdersPlugin::DisplayHelper
2 2
3 protected 3 protected
4 4
  5 + include HelpHelper
  6 +
5 include OrdersPlugin::TranslationHelper 7 include OrdersPlugin::TranslationHelper
6 include OrdersPlugin::PriceHelper 8 include OrdersPlugin::PriceHelper
7 include OrdersPlugin::DateHelper 9 include OrdersPlugin::DateHelper
@@ -9,7 +11,8 @@ module OrdersPlugin::DisplayHelper @@ -9,7 +11,8 @@ module OrdersPlugin::DisplayHelper
9 include OrdersPlugin::TableHelper 11 include OrdersPlugin::TableHelper
10 include OrdersPlugin::AdminHelper 12 include OrdersPlugin::AdminHelper
11 include OrdersPlugin::JavascriptHelper 13 include OrdersPlugin::JavascriptHelper
12 - include HelpHelper 14 +
  15 + include DeliveryPlugin::DisplayHelper
13 16
14 # come on, you can't replace a rails api method (button_to_function was)! 17 # come on, you can't replace a rails api method (button_to_function was)!
15 def submit_to_function name, function, html_options={} 18 def submit_to_function name, function, html_options={}
plugins/orders/lib/orders_plugin/field_helper.rb
@@ -6,7 +6,7 @@ module OrdersPlugin::FieldHelper @@ -6,7 +6,7 @@ module OrdersPlugin::FieldHelper
6 help = options.delete(:help) 6 help = options.delete(:help)
7 content_tag :div, 7 content_tag :div,
8 if form then form.label field, label, class: 'control-label' else label_tag field, label, class: 'control-label' end + 8 if form then form.label field, label, class: 'control-label' else label_tag field, label, class: 'control-label' end +
9 - content_tag('div', help, class: 'field-help') + 9 + content_tag('div', help, class: 'help-block') +
10 content_tag('div', field_html, class: 'field-box') + 10 content_tag('div', field_html, class: 'field-box') +
11 content_tag('div', '', style: 'clear: both'), 11 content_tag('div', '', style: 'clear: both'),
12 options.merge(class: options[:class].to_s + ' field form-group') 12 options.merge(class: options[:class].to_s + ' field form-group')
plugins/orders/lib/orders_plugin/mailer.rb
@@ -4,8 +4,6 @@ class OrdersPlugin::Mailer &lt; Noosfero::Plugin::MailerBase @@ -4,8 +4,6 @@ class OrdersPlugin::Mailer &lt; Noosfero::Plugin::MailerBase
4 4
5 helper ApplicationHelper 5 helper ApplicationHelper
6 helper OrdersPlugin::DisplayHelper 6 helper OrdersPlugin::DisplayHelper
7 - helper OrdersPlugin::DateHelper  
8 - helper OrdersPlugin::TranslationHelper  
9 7
10 attr_accessor :environment 8 attr_accessor :environment
11 attr_accessor :profile 9 attr_accessor :profile
@@ -82,4 +80,10 @@ class OrdersPlugin::Mailer &lt; Noosfero::Plugin::MailerBase @@ -82,4 +80,10 @@ class OrdersPlugin::Mailer &lt; Noosfero::Plugin::MailerBase
82 end 80 end
83 end 81 end
84 82
  83 + # for order/show_simple form
  84 + def protect_against_forgery?
  85 + false
  86 + end
  87 + helper_method :protect_against_forgery?
  88 +
85 end 89 end
plugins/orders/lib/orders_plugin/report.rb
@@ -142,6 +142,7 @@ module OrdersPlugin::Report @@ -142,6 +142,7 @@ module OrdersPlugin::Report
142 productsStart = sbs+5 142 productsStart = sbs+5
143 productsEnd = 0 143 productsEnd = 0
144 selled_sum = 0 144 selled_sum = 0
  145 + total_price_without_margin = 0
145 orders.each do |order| 146 orders.each do |order|
146 147
147 sheet.add_row [t('lib.report.order_code'), t('lib.report.member_name'), '', t('lib.report.phone'), '', t('lib.report.mail'), ''], style: bluecell_b_top 148 sheet.add_row [t('lib.report.order_code'), t('lib.report.member_name'), '', t('lib.report.phone'), '', t('lib.report.mail'), ''], style: bluecell_b_top
@@ -188,6 +189,7 @@ module OrdersPlugin::Report @@ -188,6 +189,7 @@ module OrdersPlugin::Report
188 style: [default,default,default,default,default,currency,currency], 189 style: [default,default,default,default,default,currency,currency],
189 formula_values: [nil,nil,nil,nil,nil,nil,formula_value_s] 190 formula_values: [nil,nil,nil,nil,nil,nil,formula_value_s]
190 selled_sum += item.status_quantity * item.price rescue 0 191 selled_sum += item.status_quantity * item.price rescue 0
  192 + total_price_without_margin += item.price_without_margins * item.status_quantity
191 193
192 sbe += 1 194 sbe += 1
193 sum += formula_value 195 sum += formula_value
@@ -200,12 +202,11 @@ module OrdersPlugin::Report @@ -200,12 +202,11 @@ module OrdersPlugin::Report
200 sbs = sbe + 2 202 sbs = sbe + 2
201 end 203 end
202 204
203 - sheet.add_row [t('lib.report.selled_total'), '', "=SUM(G#{productsStart}:G#{productsEnd})"],  
204 - formula_values: [nil,nil, selled_sum],  
205 - style: [redcell,redcell,currency]  
206 -  
207 - ["A#{sbs}:B#{sbs}"].each{ |c| sheet.merge_cells c } 205 + sheet.add_row [t('lib.report.selled_total'), '', "=SUM(G#{productsStart}:G#{productsEnd})", t('lib.report.total_price_without_margin'),"","", total_price_without_margin],
  206 + formula_values: [nil, nil, selled_sum, nil, nil, nil, nil],
  207 + style: [redcell, redcell, currency, redcell, redcell, redcell, currency]
208 208
  209 + ["A#{sbs}:B#{sbs}", "D#{sbs}:F{sbs}"].each{ |c| sheet.merge_cells c }
209 210
210 sheet.column_widths 15,30,30,9,8,10,11 211 sheet.column_widths 15,30,30,9,8,10,11
211 end # closes spreadsheet 212 end # closes spreadsheet
plugins/orders/locales/en-US.yml
1 -"en-US": &en-US 1 +en-US: &en-US
  2 +
  3 + number:
  4 + currency:
  5 + format:
  6 + xlsx_currency: "[$$-409]* #.##0,00;[RED]-[$$-409]* #.##0,00"
2 7
3 orders_plugin: 8 orders_plugin:
4 terms: 9 terms:
@@ -77,6 +82,7 @@ @@ -77,6 +82,7 @@
77 supplier: "%{terms.supplier.singular.capitalize}" 82 supplier: "%{terms.supplier.singular.capitalize}"
78 total_parcel_value: "Total value using stock" 83 total_parcel_value: "Total value using stock"
79 total_selled_value: "Total selled value" 84 total_selled_value: "Total selled value"
  85 + total_price_without_margin: "Total price without margin"
80 total_value: "Total Value" 86 total_value: "Total Value"
81 un: un. 87 un: un.
82 value: value 88 value: value
@@ -299,8 +305,8 @@ @@ -299,8 +305,8 @@
299 supplier_product: "%{terms.supplier.singular.capitalize}/Product" 305 supplier_product: "%{terms.supplier.singular.capitalize}/Product"
300 total: "TOTAL:" 306 total: "TOTAL:"
301 307
302 -'en_US': 308 +en_US:
303 <<: *en-US 309 <<: *en-US
304 -'en': 310 +en:
305 <<: *en-US 311 <<: *en-US
306 312
plugins/orders/locales/pt-BR.yml
1 -"pt-BR": &pt-BR 1 +pt-BR: &pt-BR
  2 +
  3 + number:
  4 + currency:
  5 + format:
  6 + xlsx_currency: "[$R$-416]* #,##0.00;[RED]-[$R$-416]* #,##0.00"
2 7
3 orders_plugin: 8 orders_plugin:
4 terms: 9 terms:
@@ -78,6 +83,7 @@ @@ -78,6 +83,7 @@
78 supplier: "%{terms.supplier.singular.capitalize}" 83 supplier: "%{terms.supplier.singular.capitalize}"
79 total_parcel_value: "Valor total usando estoque" 84 total_parcel_value: "Valor total usando estoque"
80 total_selled_value: "Valor total vendido" 85 total_selled_value: "Valor total vendido"
  86 + total_price_without_margin: "Valor total sem a margem"
81 total_value: "total pago" 87 total_value: "total pago"
82 un: un. 88 un: un.
83 value: Valor 89 value: Valor
@@ -299,8 +305,8 @@ @@ -299,8 +305,8 @@
299 supplier_product: "%{terms.supplier.singular.capitalize}/Produto" 305 supplier_product: "%{terms.supplier.singular.capitalize}/Produto"
300 total: "TOTAL:" 306 total: "TOTAL:"
301 307
302 -'pt_BR': 308 +pt_BR:
303 <<: *pt-BR 309 <<: *pt-BR
304 -'pt': 310 +pt:
305 <<: *pt-BR 311 <<: *pt-BR
306 312
plugins/orders/models/orders_plugin/item.rb
@@ -7,6 +7,13 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base @@ -7,6 +7,13 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base
7 # flag used by items to compare them with products 7 # flag used by items to compare them with products
8 attr_accessor :product_diff 8 attr_accessor :product_diff
9 9
  10 + Statuses = %w[ordered accepted separated delivered received]
  11 + DbStatuses = %w[draft planned cancelled] + Statuses
  12 + UserStatuses = %w[open forgotten planned cancelled] + Statuses
  13 + StatusText = {}; UserStatuses.map do |status|
  14 + StatusText[status] = "orders_plugin.models.order.statuses.#{status}"
  15 + end
  16 +
10 # should be Order, but can't reference it here so it would create a cyclic reference 17 # should be Order, but can't reference it here so it would create a cyclic reference
11 StatusAccessMap = { 18 StatusAccessMap = {
12 'ordered' => :consumer, 19 'ordered' => :consumer,
@@ -28,9 +35,9 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base @@ -28,9 +35,9 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base
28 35
29 serialize :data 36 serialize :data
30 37
31 - belongs_to :order, class_name: 'OrdersPlugin::Order', foreign_key: :order_id, touch: true  
32 - belongs_to :sale, class_name: 'OrdersPlugin::Sale', foreign_key: :order_id, touch: true  
33 - belongs_to :purchase, class_name: 'OrdersPlugin::Purchase', foreign_key: :order_id, touch: true 38 + belongs_to :order, class_name: '::OrdersPlugin::Order', foreign_key: :order_id, touch: true
  39 + belongs_to :sale, class_name: '::OrdersPlugin::Sale', foreign_key: :order_id, touch: true
  40 + belongs_to :purchase, class_name: '::OrdersPlugin::Purchase', foreign_key: :order_id, touch: true
34 41
35 belongs_to :product 42 belongs_to :product
36 has_one :supplier, through: :product 43 has_one :supplier, through: :product
@@ -40,28 +47,30 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base @@ -40,28 +47,30 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base
40 47
41 # FIXME: don't work because of load order 48 # FIXME: don't work because of load order
42 #if defined? SuppliersPlugin 49 #if defined? SuppliersPlugin
43 - has_many :from_products, through: :product, source: :orders 50 + has_many :from_products, through: :product
  51 + has_one :from_product, through: :product
44 has_many :to_products, through: :product 52 has_many :to_products, through: :product
45 - has_many :sources_supplier_products, through: :product, source: :items  
46 - has_many :supplier_products, through: :product, source: :enterprise 53 + has_one :to_product, through: :product
  54 + has_many :sources_supplier_products, through: :product
  55 + has_one :sources_supplier_product, through: :product
  56 + has_many :supplier_products, through: :product
  57 + has_one :supplier_product, through: :product
47 has_many :suppliers, through: :product 58 has_many :suppliers, through: :product
  59 + has_one :supplier, through: :product
48 #end 60 #end
49 - def from_product  
50 - self.from_products.first  
51 - end  
52 - def supplier_product  
53 - self.supplier_products.first  
54 - end  
55 61
56 - scope :ordered, conditions: ['orders_plugin_orders.status = ?', 'ordered'], joins: [:order]  
57 - scope :for_product, lambda{ |product| {conditions: {product_id: product.id}} } 62 + scope :ordered, -> { joins(:order).where 'orders_plugin_orders.status = ?', 'ordered' }
  63 + scope :for_product, -> (product) { where product_id: product.id }
58 64
59 default_scope include: [:product] 65 default_scope include: [:product]
60 66
61 validate :has_order 67 validate :has_order
62 validates_presence_of :product 68 validates_presence_of :product
  69 + validates_inclusion_of :status, in: DbStatuses
63 70
  71 + before_validation :set_defaults
64 before_save :save_calculated_prices 72 before_save :save_calculated_prices
  73 + before_save :step_status
65 before_create :sync_fields 74 before_create :sync_fields
66 75
67 # utility for other classes 76 # utility for other classes
@@ -104,6 +113,9 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base @@ -104,6 +113,9 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base
104 def price 113 def price
105 self[:price] || (self.product.price_with_discount || 0 rescue nil) 114 self[:price] || (self.product.price_with_discount || 0 rescue nil)
106 end 115 end
  116 + def price_without_margins
  117 + self.product.price_without_margins rescue self.price
  118 + end
107 def unit 119 def unit
108 self.product.unit 120 self.product.unit
109 end 121 end
@@ -121,8 +133,15 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base @@ -121,8 +133,15 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base
121 end 133 end
122 end 134 end
123 135
124 - def status  
125 - self.order.status 136 + def calculated_status
  137 + status = self.order.status
  138 + index = Statuses.index status
  139 + next_status = Statuses[index+1] if index
  140 + next_quantity = "quantity_#{StatusDataMap[next_status]}" if next_status
  141 + if next_status and self.send next_quantity then next_status else status end
  142 + end
  143 + def on_next_status?
  144 + self.order.status != self.calculated_status
126 end 145 end
127 146
128 # product used for comparizon when repeating an order 147 # product used for comparizon when repeating an order
@@ -144,13 +163,13 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base @@ -144,13 +163,13 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base
144 163
145 def status_quantity_field 164 def status_quantity_field
146 @status_quantity_field ||= begin 165 @status_quantity_field ||= begin
147 - status = StatusDataMap[self.order.status] || 'consumer_ordered' 166 + status = StatusDataMap[self.status] || 'consumer_ordered'
148 "quantity_#{status}" 167 "quantity_#{status}"
149 end 168 end
150 end 169 end
151 def status_price_field 170 def status_price_field
152 @status_price_field ||= begin 171 @status_price_field ||= begin
153 - status = StatusDataMap[self.order.status] || 'consumer_ordered' 172 + status = StatusDataMap[self.status] || 'consumer_ordered'
154 "price_#{status}" 173 "price_#{status}"
155 end 174 end
156 end 175 end
@@ -184,10 +203,10 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base @@ -184,10 +203,10 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base
184 203
185 def quantity_price_data actor_name 204 def quantity_price_data actor_name
186 data = {flags: {}} 205 data = {flags: {}}
187 - statuses = OrdersPlugin::Order::Statuses 206 + statuses = ::OrdersPlugin::Order::Statuses
188 statuses_data = data[:statuses] = {} 207 statuses_data = data[:statuses] = {}
189 208
190 - current = statuses.index(self.order.status) || 0 209 + current = statuses.index(self.status) || 0
191 next_status = self.order.next_status actor_name 210 next_status = self.order.next_status actor_name
192 next_index = statuses.index(next_status) || current + 1 211 next_index = statuses.index(next_status) || current + 1
193 goto_next = actor_name == StatusAccessMap[next_status] 212 goto_next = actor_name == StatusAccessMap[next_status]
@@ -266,8 +285,11 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base @@ -266,8 +285,11 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base
266 285
267 # Set access 286 # Set access
268 statuses_data.each.with_index do |(status, status_data), i| 287 statuses_data.each.with_index do |(status, status_data), i|
269 - status_data[:flags][:editable] = true if StatusAccessMap[status] == actor_name  
270 - # code to only allow last status 288 + #consumer_may_edit = actor_name == :consumer and status == 'ordered' and self.order.open?
  289 + if StatusAccessMap[status] == actor_name
  290 + status_data[:flags][:editable] = true
  291 + end
  292 + # only allow last status
271 #status_data[:flags][:editable] = true if status_data[:access] == actor_name and (status_data[:flags][:admin] or self.order.open?) 293 #status_data[:flags][:editable] = true if status_data[:access] == actor_name and (status_data[:flags][:admin] or self.order.open?)
272 end 294 end
273 295
@@ -279,6 +301,14 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base @@ -279,6 +301,14 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base
279 self.save_calculated_prices 301 self.save_calculated_prices
280 end 302 end
281 303
  304 + # used by db/migrate/20150627232432_add_status_to_orders_plugin_item.rb
  305 + def fill_status
  306 + status = self.calculated_status
  307 + return if self.status == status
  308 + self.update_column :status, status
  309 + self.order.update_column :building_next_status, true if self.order.status != status and not self.order.building_next_status
  310 + end
  311 +
282 protected 312 protected
283 313
284 def save_calculated_prices 314 def save_calculated_prices
@@ -288,6 +318,17 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base @@ -288,6 +318,17 @@ class OrdersPlugin::Item &lt; ActiveRecord::Base
288 end 318 end
289 end 319 end
290 320
  321 + def set_defaults
  322 + self.status ||= Statuses.first
  323 + end
  324 +
  325 + def step_status
  326 + status = self.calculated_status
  327 + return if self.status == status
  328 + self.status = status
  329 + self.order.update_column :building_next_status, true if self.order.status != status and not self.order.building_next_status
  330 + end
  331 +
291 def has_order 332 def has_order
292 self.order or self.sale or self.purchase 333 self.order or self.sale or self.purchase
293 end 334 end
plugins/orders/models/orders_plugin/order.rb
1 class OrdersPlugin::Order < ActiveRecord::Base 1 class OrdersPlugin::Order < ActiveRecord::Base
2 2
3 - Statuses = %w[ordered accepted separated delivered received]  
4 - DbStatuses = %w[draft planned cancelled] + Statuses  
5 - UserStatuses = %w[open forgotten planned cancelled] + Statuses  
6 - StatusText = {}; UserStatuses.map do |status|  
7 - StatusText[status] = "orders_plugin.models.order.statuses.#{status}"  
8 - end 3 + # if abstract_class is true then it will trigger https://github.com/rails/rails/issues/20871
  4 + #self.abstract_class = true
  5 +
  6 + Statuses = ::OrdersPlugin::Item::Statuses
  7 + DbStatuses = ::OrdersPlugin::Item::DbStatuses
  8 + UserStatuses = ::OrdersPlugin::Item::UserStatuses
  9 + StatusText = ::OrdersPlugin::Item::StatusText
9 10
10 # oh, we need a payments plugin! 11 # oh, we need a payments plugin!
11 PaymentMethods = { 12 PaymentMethods = {
@@ -31,18 +32,14 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base @@ -31,18 +32,14 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base
31 ] 32 ]
32 33
33 # copy, for easiness. can't be declared to here to avoid cyclic reference 34 # copy, for easiness. can't be declared to here to avoid cyclic reference
34 - StatusDataMap = OrdersPlugin::Item::StatusDataMap  
35 - StatusAccessMap = OrdersPlugin::Item::StatusAccessMap 35 + StatusDataMap = ::OrdersPlugin::Item::StatusDataMap
  36 + StatusAccessMap = ::OrdersPlugin::Item::StatusAccessMap
36 37
37 StatusesByActor = { 38 StatusesByActor = {
38 consumer: StatusAccessMap.map{ |s, a| s if a == :consumer }.compact, 39 consumer: StatusAccessMap.map{ |s, a| s if a == :consumer }.compact,
39 supplier: StatusAccessMap.map{ |s, a| s if a == :supplier }.compact, 40 supplier: StatusAccessMap.map{ |s, a| s if a == :supplier }.compact,
40 } 41 }
41 42
42 - # workaround for STI  
43 - self.table_name = :orders_plugin_orders  
44 - self.abstract_class = true  
45 -  
46 attr_accessible :status, :consumer, :profile, 43 attr_accessible :status, :consumer, :profile,
47 :supplier_delivery_id, :consumer_delivery_id, :supplier_delivery_data, :consumer_delivery_data 44 :supplier_delivery_id, :consumer_delivery_id, :supplier_delivery_data, :consumer_delivery_data
48 45
@@ -51,17 +48,17 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base @@ -51,17 +48,17 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base
51 belongs_to :supplier, foreign_key: :profile_id, class_name: 'Profile' 48 belongs_to :supplier, foreign_key: :profile_id, class_name: 'Profile'
52 belongs_to :consumer, class_name: 'Profile' 49 belongs_to :consumer, class_name: 'Profile'
53 50
54 - belongs_to :session, primary_key: :session_id, foreign_key: :session_id, class_name: 'ActiveRecord::SessionStore::Session' 51 + belongs_to :session, primary_key: :session_id, foreign_key: :session_id, class_name: 'Session'
55 52
56 - has_many :items, class_name: 'OrdersPlugin::Item', foreign_key: :order_id, dependent: :destroy, order: 'name ASC' 53 + has_many :items, -> { order 'name ASC' }, class_name: 'OrdersPlugin::Item', foreign_key: :order_id, dependent: :destroy
57 has_many :products, through: :items 54 has_many :products, through: :items
58 55
59 belongs_to :supplier_delivery, class_name: 'DeliveryPlugin::Method' 56 belongs_to :supplier_delivery, class_name: 'DeliveryPlugin::Method'
60 belongs_to :consumer_delivery, class_name: 'DeliveryPlugin::Method' 57 belongs_to :consumer_delivery, class_name: 'DeliveryPlugin::Method'
61 58
62 - scope :alphabetical, -> { joins(:consumer).order 'profiles.name ASC' }  
63 - scope :latest, -> { order 'code ASC' }  
64 - scope :default_order, -> { order 'code DESC' } 59 + scope :alphabetical, -> { joins(:consumer).reorder 'profiles.name ASC' }
  60 + scope :latest, -> { reorder 'code ASC' }
  61 + scope :default_order, -> { reorder 'code DESC' }
65 62
66 scope :of_session, -> session_id { where session_id: session_id } 63 scope :of_session, -> session_id { where session_id: session_id }
67 scope :of_user, -> session_id, consumer_id=nil do 64 scope :of_user, -> session_id, consumer_id=nil do
@@ -73,53 +70,50 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base @@ -73,53 +70,50 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base
73 70
74 scope :latest, order: 'created_at DESC' 71 scope :latest, order: 'created_at DESC'
75 72
76 - scope :draft, conditions: {status: 'draft'}  
77 - scope :planned, conditions: {status: 'planned'}  
78 - scope :cancelled, conditions: {status: 'cancelled'}  
79 - scope :not_cancelled, conditions: ["status <> 'cancelled'"]  
80 - scope :ordered, conditions: ['ordered_at IS NOT NULL']  
81 - scope :confirmed, conditions: ['ordered_at IS NOT NULL']  
82 - scope :accepted, conditions: ['accepted_at IS NOT NULL']  
83 - scope :separated, conditions: ['separated_at IS NOT NULL']  
84 - scope :delivered, conditions: ['delivered_at IS NOT NULL']  
85 - scope :received, conditions: ['received_at IS NOT NULL']  
86 -  
87 - scope :for_profile, lambda{ |profile| {conditions: {profile_id: profile.id}} }  
88 - scope :for_profile_id, lambda{ |profile_id| {conditions: {profile_id: profile_id}} }  
89 - scope :for_supplier, lambda{ |profile| {conditions: {profile_id: profile.id}} }  
90 - scope :for_supplier_id, lambda{ |profile_id| {conditions: {profile_id: profile_id}} }  
91 - scope :for_consumer, lambda{ |consumer| {conditions: {consumer_id: (consumer.id rescue nil)}} }  
92 - scope :for_consumer_id, lambda{ |consumer_id| {conditions: {consumer_id: consumer_id}} }  
93 -  
94 - scope :months, select: 'DISTINCT(EXTRACT(months FROM orders_plugin_orders.created_at)) as month', order: 'month DESC'  
95 - scope :years, select: 'DISTINCT(EXTRACT(YEAR FROM orders_plugin_orders.created_at)) as year', order: 'year DESC'  
96 -  
97 - scope :by_month, lambda { |month|  
98 - where 'EXTRACT(month FROM orders_plugin_orders.created_at) <= :month AND EXTRACT(month FROM orders_plugin_orders.created_at) >= :month',{ month: month } 73 + scope :draft, -> { where status: 'draft' }
  74 + scope :planned, -> { where status: 'planned' }
  75 + scope :cancelled, -> { where status: 'cancelled' }
  76 + scope :not_cancelled, -> { where "status <> 'cancelled'" }
  77 + scope :ordered, -> { where 'ordered_at IS NOT NULL' }
  78 + scope :confirmed, -> { where 'ordered_at IS NOT NULL' }
  79 + scope :accepted, -> { where 'accepted_at IS NOT NULL' }
  80 + scope :separated, -> { where 'separated_at IS NOT NULL' }
  81 + scope :delivered, -> { where 'delivered_at IS NOT NULL' }
  82 + scope :received, -> { where 'received_at IS NOT NULL' }
  83 +
  84 + scope :for_profile, -> (profile) { where profile_id: profile.id }
  85 + scope :for_profile_id, -> (profile_id) { where profile_id: profile_id }
  86 + scope :for_supplier, -> (profile) { where profile_id: profile.id }
  87 + scope :for_supplier_id, -> (profile_id) { where profile_id: profile_id }
  88 + scope :for_consumer, -> (consumer) { where consumer_id: (consumer.id rescue nil) }
  89 + scope :for_consumer_id, -> (consumer_id) { where consumer_id: consumer_id }
  90 +
  91 + scope :months, -> { select('DISTINCT(EXTRACT(months FROM orders_plugin_orders.created_at)) as month').order('month DESC') }
  92 + scope :years, -> { select('DISTINCT(EXTRACT(YEAR FROM orders_plugin_orders.created_at)) as year').order('year DESC') }
  93 +
  94 + scope :by_month, -> (month) {
  95 + where 'EXTRACT(month FROM orders_plugin_orders.created_at) <= :month AND EXTRACT(month FROM orders_plugin_orders.created_at) >= :month', month: month
99 } 96 }
100 - scope :by_year, lambda { |year|  
101 - where 'EXTRACT(year FROM orders_plugin_orders.created_at) <= :year AND EXTRACT(year FROM orders_plugin_orders.created_at) >= :year', { year: year } 97 + scope :by_year, -> (year) {
  98 + where 'EXTRACT(year FROM orders_plugin_orders.created_at) <= :year AND EXTRACT(year FROM orders_plugin_orders.created_at) >= :year', year: year
102 } 99 }
103 - scope :by_range, lambda { |start_time, end_time|  
104 - where 'orders_plugin_orders.created_at >= :start AND orders_plugin_orders.created_at <= :end', { start: start_time, end: end_time } 100 + scope :by_range, -> (start_time, end_time) {
  101 + where 'orders_plugin_orders.created_at >= :start AND orders_plugin_orders.created_at <= :end', start: start_time, end: end_time
105 } 102 }
106 103
107 - scope :with_status, lambda { |status|  
108 - where status: status  
109 - }  
110 - scope :with_code, lambda { |code|  
111 - where code: code  
112 - } 104 + scope :with_status, -> (status) { where status: status }
  105 + scope :with_code, -> (code) { where code: code }
113 106
114 validates_presence_of :profile 107 validates_presence_of :profile
115 # consumer is optional, as orders can be made by unlogged users 108 # consumer is optional, as orders can be made by unlogged users
116 validates_inclusion_of :status, in: DbStatuses 109 validates_inclusion_of :status, in: DbStatuses
117 110
118 before_validation :check_status 111 before_validation :check_status
  112 + before_validation :change_status
119 after_save :send_notifications 113 after_save :send_notifications
120 114
121 extend CodeNumbering::ClassMethods 115 extend CodeNumbering::ClassMethods
122 - code_numbering :code, scope: proc{ self.profile.orders } 116 + code_numbering :code, scope: -> { self.profile.orders }
123 117
124 serialize :data 118 serialize :data
125 119
@@ -165,17 +159,17 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base @@ -165,17 +159,17 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base
165 # / Items 159 # / Items
166 # / \ OfferedProduct (column product_id) 160 # / \ OfferedProduct (column product_id)
167 # Order / \ SourceProduct from DistributedProduct (quantity=1, always) 161 # Order / \ SourceProduct from DistributedProduct (quantity=1, always)
168 - # \ SourceProduct from Product* (quantity be more than 1 if DistributedProduct is an agregate product) 162 + # \ SourceProduct from Product* (multiple for each if is an aggregate product)
169 # for order outside cycle we have 163 # for order outside cycle we have
170 # / Items 164 # / Items
171 # / \ SourceProduct from DistributedProduct (quantity=1, always) 165 # / \ SourceProduct from DistributedProduct (quantity=1, always)
172 - # Order / \ SourceProduct from Product* (quantity be more than 1 if DistributedProduct is an agregate product) 166 + # Order / \ SourceProduct from Product* (multiple for each if is an aggregate product)
173 # 167 #
174 # *suppliers usually don't distribute using cycles, so they only have Product 168 # *suppliers usually don't distribute using cycles, so they only have Product
175 # 169 #
176 def self.supplier_products_by_suppliers orders 170 def self.supplier_products_by_suppliers orders
177 products_by_supplier = {} 171 products_by_supplier = {}
178 - items = OrdersPlugin::Item.where(order_id: orders.map(&:id)).includes({sources_supplier_products: [:supplier, :from_product]}) 172 + items = self.parent::Item.where(order_id: orders.map(&:id)).includes(sources_supplier_products: [:supplier, :from_product])
179 items.each do |item| 173 items.each do |item|
180 if item.sources_supplier_products.present? 174 if item.sources_supplier_products.present?
181 item.sources_supplier_products.each do |source_sp| 175 item.sources_supplier_products.each do |source_sp|
@@ -358,15 +352,14 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base @@ -358,15 +352,14 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base
358 352
359 # total_price considering last state 353 # total_price considering last state
360 def total_price actor_name = :consumer, admin = false 354 def total_price actor_name = :consumer, admin = false
361 - if not self.pre_order? and admin and status = self.next_status(actor_name)  
362 - self.fill_items_data self.status, status 355 + # for admins, we want the next_status while we concluded the finish status change
  356 + if admin
  357 + price = :status_price
363 else 358 else
364 - status = self.status 359 + data = StatusDataMap[self.status] || StatusDataMap[Statuses.first]
  360 + price = "price_#{data}".to_sym
365 end 361 end
366 362
367 - data = StatusDataMap[status] || StatusDataMap[Statuses.first]  
368 - price = "price_#{data}".to_sym  
369 -  
370 items ||= (self.ordered_items rescue nil) || self.items 363 items ||= (self.ordered_items rescue nil) || self.items
371 items.collect(&price).inject(0){ |sum, p| sum + p.to_f } 364 items.collect(&price).inject(0){ |sum, p| sum + p.to_f }
372 end 365 end
@@ -379,7 +372,8 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base @@ -379,7 +372,8 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base
379 end 372 end
380 has_currency :total 373 has_currency :total
381 374
382 - def fill_items_data from_status, to_status, save = false 375 + def fill_items from_status, to_status, save = false
  376 + # check for status advance
383 return if (Statuses.index(to_status) <= Statuses.index(from_status) rescue true) 377 return if (Statuses.index(to_status) <= Statuses.index(from_status) rescue true)
384 378
385 from_data = StatusDataMap[from_status] 379 from_data = StatusDataMap[from_status]
@@ -405,15 +399,22 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base @@ -405,15 +399,22 @@ class OrdersPlugin::Order &lt; ActiveRecord::Base
405 self.status ||= 'draft' 399 self.status ||= 'draft'
406 # backwards compatibility 400 # backwards compatibility
407 self.status = 'ordered' if self.status == 'confirmed' 401 self.status = 'ordered' if self.status == 'confirmed'
  402 + end
  403 +
  404 + def change_status
  405 + return if self.status_was == self.status
408 406
409 - self.fill_items_data self.status_was, self.status, true 407 + self.fill_items self.status_was, self.status, true
  408 + self.items.update_all status: self.status
  409 + self.building_next_status = false
410 410
  411 + # fill dates on status advance
411 if self.status_on? 'ordered' 412 if self.status_on? 'ordered'
412 Statuses.each do |status| 413 Statuses.each do |status|
413 self.send "#{self.status}_at=", Time.now if self.status_was != status and self.status == status 414 self.send "#{self.status}_at=", Time.now if self.status_was != status and self.status == status
414 end 415 end
415 else 416 else
416 - # for draft, planned, forgotten, cancelled, etc 417 + # status rewind for draft, planned, forgotten, cancelled, etc
417 Statuses.each do |status| 418 Statuses.each do |status|
418 self.send "#{status}_at=", nil 419 self.send "#{status}_at=", nil
419 end 420 end
plugins/orders/models/orders_plugin/sale.rb
1 class OrdersPlugin::Sale < OrdersPlugin::Order 1 class OrdersPlugin::Sale < OrdersPlugin::Order
2 2
  3 + before_validation :fill_default_supplier_delivery
  4 +
3 def orders_name 5 def orders_name
4 'sales' 6 'sales'
5 end 7 end
@@ -19,6 +21,17 @@ class OrdersPlugin::Sale &lt; OrdersPlugin::Order @@ -19,6 +21,17 @@ class OrdersPlugin::Sale &lt; OrdersPlugin::Order
19 has_number_with_locale :purchase_quantity_total 21 has_number_with_locale :purchase_quantity_total
20 has_currency :purchase_price_total 22 has_currency :purchase_price_total
21 23
  24 + def supplier_delivery
  25 + super || (self.delivery_methods.first rescue nil)
  26 + end
  27 + def supplier_delivery_id
  28 + self[:supplier_delivery_id] || (self.supplier_delivery.id rescue nil)
  29 + end
  30 +
  31 + def fill_default_supplier_delivery
  32 + self[:supplier_delivery_id] ||= self.supplier_delivery.id if self.supplier_delivery
  33 + end
  34 +
22 protected 35 protected
23 36
24 end 37 end
plugins/orders/orders 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +/home/braulio/Projects/noosfero-ecosol/noosfero/plugins/orders
0 \ No newline at end of file 2 \ No newline at end of file
plugins/orders/public/javascripts/orders.js
@@ -139,21 +139,12 @@ orders = { @@ -139,21 +139,12 @@ orders = {
139 }, 139 },
140 }, 140 },
141 141
142 - set_orders_container_max_height: function() 142 + setOrderMaxHeight: function()
143 { 143 {
144 ordersH = $(window).height(); 144 ordersH = $(window).height();
145 - ordersH -= 100  
146 ordersH -= $('#cirandas-top-bar').outerHeight() 145 ordersH -= $('#cirandas-top-bar').outerHeight()
147 - ordersH -= $('.order-status-message').outerHeight()  
148 - ordersH -= $('.order-message-title').outerHeight()  
149 - ordersH -= $('#order-column .order-items .table-header').last().outerHeight()  
150 - ordersH -= $('#order-column .order-total').last().outerHeight()  
151 - ordersH -= $('#order-column #actor-data-box').last().outerHeight()  
152 - ordersH -= $('#order-column .delivery-box').outerHeight()  
153 - ordersH -= $('#order-column .order-message-text').outerHeight()  
154 - ordersH -= $('#order-column .order-message-actions').outerHeight()  
155 - ordersH -= $('#order-column .actions').outerHeight()  
156 - $('.order-items-container .order-items-scroll').css('max-height', ordersH); 146 + ordersH -= $('.order-view form > .actions').outerHeight(true)
  147 + $('.order-view .order-data').css('max-height', ordersH);
157 }, 148 },
158 149
159 daterangepicker: { 150 daterangepicker: {
@@ -180,6 +171,7 @@ orders = { @@ -180,6 +171,7 @@ orders = {
180 }, 171 },
181 }; 172 };
182 173
183 -$(document).ready(orders.set_orders_container_max_height);  
184 -$(window).resize(orders.set_orders_container_max_height); 174 +$(document).ready(orders.setOrderMaxHeight);
  175 +$(window).resize(orders.setOrderMaxHeight);
  176 +$('#order_supplier_delivery_id').change(orders.setOrderMaxHeight);
185 177
plugins/orders/public/public 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +/home/braulio/Projects/noosfero-ecosol/noosfero/config/plugins/orders/public
0 \ No newline at end of file 2 \ No newline at end of file
plugins/orders/public/stylesheets/_field.scss
@@ -25,9 +25,8 @@ @@ -25,9 +25,8 @@
25 float: left; 25 float: left;
26 width: 100%; 26 width: 100%;
27 } 27 }
28 - .field-help { 28 + .help-block {
29 clear: both; 29 clear: both;
30 - margin-bottom: $half-margin;  
31 font-size: 10px; 30 font-size: 10px;
32 } 31 }
33 32
plugins/orders/public/stylesheets/_items.scss
@@ -102,9 +102,6 @@ @@ -102,9 +102,6 @@
102 102
103 .table-content { 103 .table-content {
104 104
105 - .order-items-scroll {  
106 - max-height: 350px;  
107 - }  
108 .item { 105 .item {
109 106
110 &.product-unavailable { 107 &.product-unavailable {
plugins/orders/public/stylesheets/orders.scss
@@ -9,10 +9,10 @@ @@ -9,10 +9,10 @@
9 @import 'items'; 9 @import 'items';
10 10
11 .controller-profile_editor a.control-panel-orders-purchases-sales { 11 .controller-profile_editor a.control-panel-orders-purchases-sales {
12 - background-image: url("/plugins/orders/images/control-panel/purchases-sales.png") 12 + background-image: url("/plugins/orders/images/control-panel/purchases-sales.png");
13 } 13 }
14 .controller-profile_editor .msie6 a.control-panel-orders-purchases-sales { 14 .controller-profile_editor .msie6 a.control-panel-orders-purchases-sales {
15 - background-image: url("/plugins/orders/images/control-panel/purchases-sales.gif") 15 + background-image: url("/plugins/orders/images/control-panel/purchases-sales.gif");
16 } 16 }
17 17
18 .orders-admin-index { 18 .orders-admin-index {
@@ -125,14 +125,13 @@ @@ -125,14 +125,13 @@
125 } 125 }
126 126
127 .order-view { 127 .order-view {
128 -  
129 - &, .order-items-scroll, .order-items, .item { 128 + &, .order-items, .item {
130 width: $order-items-width; 129 width: $order-items-width;
131 } 130 }
132 &.admin { 131 &.admin {
133 width: $order-items-admin-width; 132 width: $order-items-admin-width;
134 133
135 - .order-items-scroll, .order-items, .item { 134 + .order-items, .item {
136 width: $order-items-admin-width - 2*$border; 135 width: $order-items-admin-width - 2*$border;
137 } 136 }
138 } 137 }
@@ -160,16 +159,14 @@ @@ -160,16 +159,14 @@
160 159
161 margin: 0; 160 margin: 0;
162 border: none; 161 border: none;
  162 +
  163 + overflow: hidden;
  164 + overflow-y: auto;
  165 +
163 &.admin { 166 &.admin {
164 border: $border solid black; 167 border: $border solid black;
165 } 168 }
166 169
167 - .order-items-scroll {  
168 - overflow-y: auto;  
169 - padding-right: $intercolumn;  
170 - box-sizing: content-box;  
171 - }  
172 -  
173 .order-header { 170 .order-header {
174 padding: $half-padding $padding; 171 padding: $half-padding $padding;
175 border-bottom: $border solid black; 172 border-bottom: $border solid black;
@@ -223,7 +220,10 @@ @@ -223,7 +220,10 @@
223 padding-bottom: 200px; 220 padding-bottom: 200px;
224 } 221 }
225 222
226 -.action-orders_cycle_plugin_order-edit .purechat {  
227 - left: 40px;  
228 - right: none; 223 +.controller-orders_cycle_plugin_order,
  224 +.controller-consumers_coop_plugin_order {
  225 + .purechat {
  226 + left: 40px;
  227 + right: none;
  228 + }
229 } 229 }
plugins/orders/test/test_helper.rb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +require File.dirname(__FILE__) + '/../../../test/test_helper'
plugins/orders/test/unit/orders_plugin/item_test.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +
  3 +class OrdersPlugin::ItemTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @item = build(OrdersPlugin::Item,
  7 + :quantity_shipped => 1.0, :quantity_consumer_ordered => 2.0, :quantity_accepted => 3.0,
  8 + :price_shipped => 10.0, :price_consumer_ordered => 20.0, :price_accepted => 30.0)
  9 + end
  10 +
  11 + should 'calculate prices' do
  12 + end
  13 +
  14 +end
plugins/orders/test/unit/orders_plugin/order_test.rb 0 → 100644
@@ -0,0 +1,121 @@ @@ -0,0 +1,121 @@
  1 +require "test_helper"
  2 +
  3 +class OrdersPlugin::OrderTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @order = build(OrdersPlugin::Order)
  7 + end
  8 +
  9 + should 'report supplier products when distributing aggregate products' do
  10 + env = Environment.create! name: 'megacoop'
  11 + supplier = Enterprise.create! identifier: 'supplier', name: 'supplier', environment: env
  12 + p1 = supplier.products.create! product_category: ProductCategory.create!(name: 'banana', environment: env)
  13 + p2 = supplier.products.create! product_category: ProductCategory.create!(name: 'aipim', environment: env)
  14 +
  15 + coop = Community.create! identifier: 'blah', name: 'blah', environment: env
  16 + coop.suppliers.create! profile: supplier, consumer: coop
  17 + aggregate_product = SuppliersPlugin::DistributedProduct.new profile: coop
  18 + aggregate_product.sources_from_products.build quantity: 1, from_product: p1, to_product: aggregate_product
  19 + aggregate_product.sources_from_products.build quantity: 5, from_product: p2, to_product: aggregate_product
  20 + aggregate_product.save!
  21 +
  22 + # hack
  23 + person = coop
  24 +
  25 + # this also create offered products
  26 + cycle = OrdersCyclePlugin::Cycle.create! name: 'blah', profile: coop, start: Time.now, finish: Time.now+1.day, delivery_start: Time.now+2.days, delivery_finish: Time.now+3.days, status: 'orders'
  27 + sale = cycle.sales.create! profile: person
  28 + sale.items.create! quantity_consumer_ordered: 3, product: aggregate_product
  29 +
  30 + r = OrdersPlugin::Order.supplier_products_by_suppliers [sale]
  31 + quantities = r.first.last.map(&:quantity_ordered).map(&:to_i)
  32 + assert_equal [3*1,3*5], quantities
  33 + end
  34 +
  35 + should 'format code with cycle code' do
  36 + @order.save!
  37 + assert_equal "#{@order.cycle.code}.#{@order.attributes['code']}", @order.code
  38 + end
  39 +
  40 + should 'use as draft default status' do
  41 + @order = create(OrdersPlugin::Order, status: nil)
  42 + assert_equal 'draft', @order.status
  43 + end
  44 +
  45 + ###
  46 + # Status
  47 + ###
  48 +
  49 + should 'define and validate list of statuses' do
  50 + @order.status = 'blah'
  51 + @order.valid?
  52 + assert @order.errors.invalid?('status')
  53 +
  54 + ['draft', 'planned', 'ordered', 'cancelled'].each do |i|
  55 + @order.status = i
  56 + @order.valid?
  57 + assert !@order.errors.invalid?('status')
  58 + end
  59 + end
  60 +
  61 + should 'define status question methods' do
  62 + ['draft', 'planned', 'ordered', 'cancelled'].each do |i|
  63 + @order.status = i
  64 + assert @order.send("#{@order.status}?")
  65 + end
  66 + end
  67 +
  68 + should 'define forgotten and open status' do
  69 + @order.status = 'draft'
  70 + assert @order.draft?
  71 + assert @order.cycle.orders?
  72 + assert @order.open?
  73 + @order.cycle.status = 'closed'
  74 + assert !@order.open?
  75 + assert @order.forgotten?
  76 + end
  77 +
  78 + should 'return current status using forgotten and open too' do
  79 + @order.status = 'draft'
  80 + assert @order.open?
  81 + assert_equal 'open', @order.current_status
  82 + @order.cycle.status = 'closed'
  83 + assert @order.forgotten?
  84 + assert_equal 'forgotten', @order.current_status
  85 + end
  86 +
  87 + should 'define status_message method' do
  88 + assert @order.respond_to?(:status_message)
  89 + end
  90 +
  91 + ###
  92 + # Delivery
  93 + ###
  94 +
  95 + should 'give default value to supplier delivery if not present' do
  96 + @order.save!
  97 + @order.profile.save!
  98 +
  99 + @order.cycle.delivery_methods = []
  100 + @order.supplier_delivery = nil
  101 + assert_nil @order.supplier_delivery
  102 +
  103 + default = @order.cycle.delivery_methods.create! profile: @order.profile, name: 'method', delivery_type: 'deliver'
  104 + assert_equal default, @order.supplier_delivery
  105 + assert_equal default.id, @order.supplier_delivery_id
  106 + end
  107 +
  108 + ###
  109 + # Totals
  110 + ###
  111 +
  112 + should 'give total price and quantity asked' do
  113 + @order.cycle.profile.save!
  114 + product = create(SuppliersPlugin::DistributedProduct, price: 2.0, profile: @order.cycle.profile, supplier: @order.cycle.profile.self_supplier)
  115 + @order.save!
  116 + @order.item.create! product: @order.cycle.products.first, quantity_consumer_ordered: 2.0
  117 + assert_equal 2.0, @order.total_quantity_consumer_ordered
  118 + assert_equal 4.0, @order.total_price_consumer_ordered
  119 + end
  120 +
  121 +end
plugins/orders/views/orders_plugin/mailer/order_confirmation.html.slim 0 → 100644
@@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
  1 +doctype html
  2 +html
  3 + head
  4 + meta content=("text/html; charset=utf-8") http-equiv="Content-Type"
  5 + = stylesheet_link_tag 'plugins/responsive/bootstrap/all.css' if defined? ResponsivePlugin
  6 + = stylesheet_link_tag 'plugins/orders/style.css'
  7 + body
  8 + p= t'orders_plugin.views.mailer.order_confirmation.dear_name', name: @consumer.name
  9 +
  10 + p= t'orders_plugin.views.mailer.order_confirmation.your_order_made_on_co',
  11 + name: @profile.name, date: day_time(@order.updated_at)
  12 +
  13 + - if @order.respond_to? :cycle
  14 + p= t'orders_plugin.views.mailer.order_confirmation.the_delivery_period_w',
  15 + date: datetime_period_with_from(@order.cycle.delivery_start, @order.cycle.delivery_finish)
  16 +
  17 + p= t'orders_plugin.views.mailer.order_confirmation.order_data_confirmed'
  18 +
  19 + = render "orders_plugin_order/show_simple", order: @order, actor_name: :consumer
  20 +
  21 + p
  22 + = t('orders_plugin.views.mailer.order_confirmation.your_order_can_be_che')
  23 + br
  24 + = link_to t('orders_plugin.views.mailer.order_confirmation.order_code_of_profile') % {code: @order.code, name: @profile.name },
  25 + {controller: :orders_cycle_plugin_order, action: :edit, profile: @profile.identifier, id: @order.id, protocol: "http"}
  26 +
  27 + p
  28 + |--
  29 + br
  30 + = t'orders_plugin.views.mailer.order_confirmation.greetings'
plugins/orders/views/orders_plugin/shared/daterangepicker/_init.html.slim
1 = content_for :head do 1 = content_for :head do
2 = stylesheet_link_tag '/assets/plugins/orders/stylesheets/daterangepicker-bs3.css' 2 = stylesheet_link_tag '/assets/plugins/orders/stylesheets/daterangepicker-bs3.css'
3 / in case it is not loaded for this theme 3 / in case it is not loaded for this theme
4 - = stylesheet_link_tag '/assets/designs/icons/awesome/scss/font-awesome.css' 4 + = stylesheet_link_tag 'designs/icons/awesome/scss/font-awesome.css'
5 = javascript_include_tag '/assets/plugins/orders/javascripts/moment-with-locales.js' 5 = javascript_include_tag '/assets/plugins/orders/javascripts/moment-with-locales.js'
6 = javascript_include_tag '/assets/plugins/orders/javascripts/daterangepicker.js' 6 = javascript_include_tag '/assets/plugins/orders/javascripts/daterangepicker.js'
7 7
plugins/orders/views/orders_plugin_admin/_filter_fields.html.slim
@@ -3,21 +3,21 @@ @@ -3,21 +3,21 @@
3 div= render 'orders_plugin/shared/daterangepicker/init' 3 div= render 'orders_plugin/shared/daterangepicker/init'
4 4
5 .field.state 5 .field.state
6 - label for="status" = t'views.filter.status' 6 + label= t'views.filter.status'
7 div= select_tag :status, 7 div= select_tag :status,
8 options_for_select([[t('views.filter.all'), ""]] + OrdersPlugin::Order::StatusText.map{ |id, name| [t(name), id] }, params[:status]) 8 options_for_select([[t('views.filter.all'), ""]] + OrdersPlugin::Order::StatusText.map{ |id, name| [t(name), id] }, params[:status])
9 9
10 .field.code 10 .field.code
11 - label for="code" = t'views.filter.code' 11 + label= t'views.filter.code'
12 div= text_field_tag :code, params[:code] 12 div= text_field_tag :code, params[:code]
13 13
14 div class="field #{actor_name}" 14 div class="field #{actor_name}"
15 - label for="#{actor_name}_id" = t"terms.#{actor_name}.singular", transformation: :capitalize 15 + label= t"terms.#{actor_name}.singular", transformation: :capitalize
16 div= select_tag "#{actor_name}_id", 16 div= select_tag "#{actor_name}_id",
17 options_for_select([[t('views.filter.all'), ""]] + actors.map{ |a| [a.name, a.id] }, params["#{actor_name}_id"]) 17 options_for_select([[t('views.filter.all'), ""]] + actors.map{ |a| [a.name, a.id] }, params["#{actor_name}_id"])
18 18
19 .field.delivery 19 .field.delivery
20 - label for="delivery_method_id" = t'views.filter.delivery' 20 + label= t'views.filter.delivery'
21 div= select_tag :delivery_method_id, 21 div= select_tag :delivery_method_id,
22 options_for_select([[t('views.filter.all'), ""]] + orders_owner.delivery_methods.map{ |dm| [dm.name, dm.id] }, params[:delivery_method_id]) 22 options_for_select([[t('views.filter.all'), ""]] + orders_owner.delivery_methods.map{ |dm| [dm.name, dm.id] }, params[:delivery_method_id])
23 23
plugins/orders/views/orders_plugin_admin/_index.html.erb
@@ -12,14 +12,14 @@ @@ -12,14 +12,14 @@
12 12
13 <% if @purchases.present? %> 13 <% if @purchases.present? %>
14 <div id='purchases' class="tab-pane"> 14 <div id='purchases' class="tab-pane">
15 - <%= render 'orders_plugin_admin/purchases', actors: profile.purchases_all_suppliers, 15 + <%= render 'orders_plugin_admin/purchases', actors: profile.sales_all_consumers,
16 orders_owner: profile, orders: @purchases, month: @purchases_month, year: @purchases_year, wireframe_size: false %> 16 orders_owner: profile, orders: @purchases, month: @purchases_month, year: @purchases_year, wireframe_size: false %>
17 </div> 17 </div>
18 <% end %> 18 <% end %>
19 19
20 <% if @sales.present? %> 20 <% if @sales.present? %>
21 <div id='sales' class="tab-pane"> 21 <div id='sales' class="tab-pane">
22 - <%= render 'orders_plugin_admin/sales', actors: profile.sales_all_consumers, 22 + <%= render 'orders_plugin_admin/sales', actors: profile.purchases_all_consumers,
23 orders_owner: profile, orders: @sales, month: @sales_month, year: @purchases_year, wireframe_size: false %> 23 orders_owner: profile, orders: @sales, month: @sales_month, year: @purchases_year, wireframe_size: false %>
24 </div> 24 </div>
25 <% end %> 25 <% end %>
plugins/orders/views/orders_plugin_admin/_order.html.slim 0 → 100644
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +- other_actor_name = if actor_name == :supplier then :consumer else :supplier end
  2 +- edit = true if edit.nil?
  3 +
  4 +div class="order value-row #{order.status}" data-id=order.id id="order-row-#{order.id}" onclick="orders.admin.load_edit(this, '#{url_for action: :edit, id: order.id, actor_name: actor_name}')" toggle-edit="orders.admin.toggle_edit();"
  5 +
  6 + .box-view.with-inner
  7 + .box-field.select toggle-ignore="" = check_box_tag "order_ids[]", order.id
  8 + .box-view-inner
  9 + span.box-field.code= order.code
  10 + span.box-field.actor-name= order.send("#{other_actor_name}_data")[:name]
  11 + span.box-field.order-date= datetime_full order.created_at
  12 + span.box-field.last-update= datetime_full order.updated_at
  13 + span.box-field.total= order.total_price_as_currency_number actor_name
  14 + span.box-field.situation= order_situation order
  15 + = edit_arrow "#order-row-#{order.id}", true, class: 'actions'
  16 + .clean
  17 +
  18 + div class="box-edit #{'loading' if not edit}"
  19 + = render 'orders_plugin_admin/edit', order: order, actor_name: actor_name, other_actor_name: other_actor_name if edit
  20 +
  21 + .clean
plugins/orders/views/orders_plugin_item/_edit_fields.html.slim
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 .box-field.product title=item.name = item.name 4 .box-field.product title=item.name = item.name
5 .box-field.quantity-price-table 5 .box-field.quantity-price-table
6 - item_data[:statuses].each do |status, status_data| 6 - item_data[:statuses].each do |status, status_data|
7 - - next if status_data[:flags][:not_modified] and not status_data[:flags][:admin] 7 + - next if status_data[:flags][:not_modified] and not status_data[:flags][:editable]
8 = render 'orders_plugin_item/quantity_price', item: item, order: order, status: status, data: item_data, status_data: status_data, actor_name: actor_name 8 = render 'orders_plugin_item/quantity_price', item: item, order: order, status: status, data: item_data, status_data: status_data, actor_name: actor_name
9 9
10 .more 10 .more
@@ -12,12 +12,15 @@ @@ -12,12 +12,15 @@
12 / actionmailer doesn't have an user, rescue error 12 / actionmailer doesn't have an user, rescue error
13 - if (order.may_edit? user, @admin rescue false) 13 - if (order.may_edit? user, @admin rescue false)
14 - if @admin 14 - if @admin
15 - = link_to_function t('views.item._edit.remove_from_order'), "orders.item.admin_remove(this, '#{url_for(controller: :orders_plugin_admin_item, action: :edit, id: item.id, actor_name: actor_name)}')", class: 'action-button'  
16 - = link_to_function t('views.item._edit.submit'), "orders.item.submit(this, '#{url_for(controller: :orders_plugin_admin_item, action: :edit, id: item.id, actor_name: actor_name)}')", class: 'submit action-button' 15 + = link_to_function t('views.item._edit.remove_from_order'),
  16 + "orders.item.admin_remove(this, '#{url_for(controller: :orders_plugin_admin_item, action: :edit, id: item.id, actor_name: actor_name)}')"
  17 + = link_to_function t('views.item._edit.submit'),
  18 + "orders.item.submit(this, '#{url_for(controller: :orders_plugin_admin_item, action: :edit, id: item.id, actor_name: actor_name)}')", class: 'submit action-button'
17 - else 19 - else
18 = link_to t('views.item._edit.remove_from_order'), {controller: :orders_plugin_item, action: :destroy, id: item.id}, 20 = link_to t('views.item._edit.remove_from_order'), {controller: :orders_plugin_item, action: :destroy, id: item.id},
19 remote: true, data: {loading: "#item-#{item.id}"} 21 remote: true, data: {loading: "#item-#{item.id}"}
20 = link_to_function t('views.item._edit.submit'), "orders.item.submit(this, '#{url_for(controller: :orders_plugin_item, action: :edit, id: item.id)}')", class: 'submit action-button' 22 = link_to_function t('views.item._edit.submit'), "orders.item.submit(this, '#{url_for(controller: :orders_plugin_item, action: :edit, id: item.id)}')", class: 'submit action-button'
21 - = price_with_unit_span item.price_as_currency_number, (item.product.unit rescue item.price_as_currency_number), nil, class: 'box-field' unless @simple 23 +
  24 + = price_with_unit_span item.price_as_currency_number, (item.product.unit rescue item.price_as_currency_number), nil, class: 'box-field' unless @view
22 25
23 .clean 26 .clean
plugins/orders/views/orders_plugin_item/_index.html.slim
@@ -13,12 +13,11 @@ div class=&quot;order-items-container #{&quot;empty&quot; if order.items.size == 0} #{&quot;admin&quot; i @@ -13,12 +13,11 @@ div class=&quot;order-items-container #{&quot;empty&quot; if order.items.size == 0} #{&quot;admin&quot; i
13 - if @admin 13 - if @admin
14 .box-field.status= t'views.item._index.status' 14 .box-field.status= t'views.item._index.status'
15 .table-content 15 .table-content
16 - .order-items-scroll  
17 - - order.items.each do |item|  
18 - = render "orders_plugin_item/edit", order: order, item: item, product: item.product, actor_name: actor_name 16 + - order.items.each do |item|
  17 + = render "orders_plugin_item/edit", order: order, item: item, product: item.product, actor_name: actor_name
19 .order-total 18 .order-total
20 .title= t'views.consumer._total.total' 19 .title= t'views.consumer._total.total'
21 - .value= price_span order.total_price_as_currency_number actor_name 20 + .value= price_span order.total_price_as_currency_number actor_name, @admin
22 21
23 - else 22 - else
24 = t'views.item._index.empty_order' 23 = t'views.item._index.empty_order'
plugins/orders/views/orders_plugin_item/_quantity_price.html.slim
@@ -6,7 +6,7 @@ div class=&quot;quantity-price-row #{status} #{status_data[:flags].keys.join &#39; &#39;}&quot; @@ -6,7 +6,7 @@ div class=&quot;quantity-price-row #{status} #{status_data[:flags].keys.join &#39; &#39;}&quot;
6 = t'views.item._edit.removed' 6 = t'views.item._edit.removed'
7 - else 7 - else
8 = quantity_localized 8 = quantity_localized
9 - - if not @simple and status_data[:flags][:editable] 9 + - if not @view and status_data[:flags][:editable]
10 = number_field_tag "item[quantity_#{status_data[:field]}]", status_data[:quantity], step: 'any', onkeydown: 'orders.item.quantity_keydown(this, event)' 10 = number_field_tag "item[quantity_#{status_data[:field]}]", status_data[:quantity], step: 'any', onkeydown: 'orders.item.quantity_keydown(this, event)'
11 - unless status_data[:flags][:removed] 11 - unless status_data[:flags][:removed]
12 |&nbsp; 12 |&nbsp;
plugins/orders/views/orders_plugin_order/_data.html.slim 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 += render "orders_plugin_item/index", order: order, actor_name: actor_name, f: f
  2 +
  3 += render 'orders_plugin_order/actor_data', order: order, f: f, actor_name: other_actor_name if @admin
  4 += render 'orders_plugin_order/delivery', order: order, f: f, actor_name: actor_name
  5 += render 'orders_plugin_order/payment', order: order
  6 +
plugins/orders/views/orders_plugin_order/_delivery.html.slim 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +/ read as: selectable or visualizable
  2 +- if order.delivery_methods.size > 0 or order.supplier_delivery_data.present?
  3 + .delivery-box.order-section
  4 + h3= _'Delivery or pickup method'
  5 +
  6 + - edition = order.may_edit?(user, @admin) && order.delivery_methods.size > 0 if edition.nil?
  7 + = render 'delivery_plugin/order_select', f: f, order: order, methods: order.delivery_methods, edition: edition
  8 +
plugins/orders/views/orders_plugin_order/_show.html.slim
@@ -30,8 +30,11 @@ div class=&quot;order-view #{&quot;editable&quot; if order.may_edit? user, @admin rescue false} @@ -30,8 +30,11 @@ div class=&quot;order-view #{&quot;editable&quot; if order.may_edit? user, @admin rescue false}
30 - elsif order.open? 30 - elsif order.open?
31 div 31 div
32 = hidden_field_tag "order[status]", 'ordered' 32 = hidden_field_tag "order[status]", 'ordered'
33 - = f.submit t('views.order._show.confirm_order'), confirm: t('views.order._show.confirming_this_order') 33 + = f.submit t('views.order._show.confirm_order'), data: {confirm: t('views.order._show.confirming_this_order')}
34 |&emsp; 34 |&emsp;
35 35
36 = link_to_function t('views.order._show.cancel_order'), "orders.order.reload(this, '#{url_for controller: :orders_plugin_order, action: :cancel, id: @order.id}')" 36 = link_to_function t('views.order._show.cancel_order'), "orders.order.reload(this, '#{url_for controller: :orders_plugin_order, action: :cancel, id: @order.id}')"
37 37
  38 +javascript:
  39 + orders.setOrderMaxHeight()
  40 +
plugins/orders/views/orders_plugin_order/_show_simple.html.slim 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +- actor_name ||= :consumer
  2 +- other_actor_name = if actor_name == :supplier then :consumer else :supplier end
  3 +- @view = true
  4 +
  5 +.order-view id="order-#{order.id}"
  6 + = form_for order, as: :order, url: '', html: {onsubmit: 'return false'} do |f|
  7 + .order-data
  8 + = render "orders_plugin_item/index", order: order, actor_name: actor_name
  9 + = render 'orders_plugin_order/delivery', order: order, actor_name: actor_name, edition: false, f: f
  10 +
  11 +javascript:
  12 + orders.setOrderMaxHeight()
plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_cycle_controller.rb
@@ -22,23 +22,24 @@ class OrdersCyclePluginCycleController &lt; OrdersPluginAdminController @@ -22,23 +22,24 @@ class OrdersCyclePluginCycleController &lt; OrdersPluginAdminController
22 end 22 end
23 23
24 def new 24 def new
25 - if request.put? 25 + if request.patch?
  26 + # can't use profile.orders_cycle here
26 @cycle = OrdersCyclePlugin::Cycle.find params[:id] 27 @cycle = OrdersCyclePlugin::Cycle.find params[:id]
27 28
28 params[:cycle][:status] = 'orders' if @open = params[:open] == '1' 29 params[:cycle][:status] = 'orders' if @open = params[:open] == '1'
29 - @success = @cycle.update_attributes params[:cycle] 30 + @success = @cycle.update params[:cycle]
30 31
31 if @success 32 if @success
32 session[:notice] = t('controllers.myprofile.cycle_controller.cycle_created') 33 session[:notice] = t('controllers.myprofile.cycle_controller.cycle_created')
33 if params[:sendmail] 34 if params[:sendmail]
34 OrdersCyclePlugin::Mailer.delay(run_at: @cycle.start).open_cycle( 35 OrdersCyclePlugin::Mailer.delay(run_at: @cycle.start).open_cycle(
35 - @cycle.profile, @cycle ,t('controllers.myprofile.cycle_controller.new_open_cycle')+": "+@cycle.name, @cycle.opening_message) 36 + @cycle.profile, @cycle, "#{t'controllers.myprofile.cycle_controller.new_open_cycle'}: #{@cycle.name}", @cycle.opening_message)
36 end 37 end
37 else 38 else
38 render action: :edit 39 render action: :edit
39 end 40 end
40 else 41 else
41 - count = OrdersCyclePlugin::Cycle.count conditions: {profile_id: profile} 42 + count = profile.orders_cycles.maximum(:code) || 1
42 @cycle = OrdersCyclePlugin::Cycle.create! profile: profile, status: 'new', 43 @cycle = OrdersCyclePlugin::Cycle.create! profile: profile, status: 'new',
43 name: t('controllers.myprofile.cycle_controller.cycle_n_n') % {n: count+1} 44 name: t('controllers.myprofile.cycle_controller.cycle_n_n') % {n: count+1}
44 end 45 end
@@ -48,13 +49,13 @@ class OrdersCyclePluginCycleController &lt; OrdersPluginAdminController @@ -48,13 +49,13 @@ class OrdersCyclePluginCycleController &lt; OrdersPluginAdminController
48 # editing an order 49 # editing an order
49 return super if params[:actor_name] 50 return super if params[:actor_name]
50 51
51 - @cycle = OrdersCyclePlugin::Cycle.find params[:id] 52 + @cycle = profile.orders_cycles.find params[:id]
52 @products = products 53 @products = products
53 54
54 if request.xhr? 55 if request.xhr?
55 if params[:commit] 56 if params[:commit]
56 params[:cycle][:status] = 'orders' if @open = params[:open] == '1' 57 params[:cycle][:status] = 'orders' if @open = params[:open] == '1'
57 - @success = @cycle.update_attributes params[:cycle] 58 + @success = @cycle.update params[:cycle]
58 59
59 if params[:sendmail] 60 if params[:sendmail]
60 OrdersCyclePlugin::Mailer.delay(run_at: @cycle.start).open_cycle(@cycle.profile, 61 OrdersCyclePlugin::Mailer.delay(run_at: @cycle.start).open_cycle(@cycle.profile,
@@ -65,7 +66,7 @@ class OrdersCyclePluginCycleController &lt; OrdersPluginAdminController @@ -65,7 +66,7 @@ class OrdersCyclePluginCycleController &lt; OrdersPluginAdminController
65 end 66 end
66 67
67 def products_load 68 def products_load
68 - @cycle = OrdersCyclePlugin::Cycle.find params[:id] 69 + @cycle = profile.orders_cycles.find params[:id]
69 @products = products 70 @products = products
70 71
71 if @cycle.add_products_job 72 if @cycle.add_products_job
@@ -76,34 +77,34 @@ class OrdersCyclePluginCycleController &lt; OrdersPluginAdminController @@ -76,34 +77,34 @@ class OrdersCyclePluginCycleController &lt; OrdersPluginAdminController
76 end 77 end
77 78
78 def destroy 79 def destroy
79 - @cycle = OrdersCyclePlugin::Cycle.find params[:id] 80 + @cycle = profile.orders_cycles.find params[:id]
80 @cycle.destroy 81 @cycle.destroy
81 redirect_to action: :index 82 redirect_to action: :index
82 end 83 end
83 84
84 def step 85 def step
85 - @cycle = OrdersCyclePlugin::Cycle.find params[:id] 86 + @cycle = profile.orders_cycles.find params[:id]
86 @cycle.step 87 @cycle.step
87 @cycle.save! 88 @cycle.save!
88 redirect_to action: :edit, id: @cycle.id 89 redirect_to action: :edit, id: @cycle.id
89 end 90 end
90 91
91 def step_back 92 def step_back
92 - @cycle = OrdersCyclePlugin::Cycle.find params[:id] 93 + @cycle = profile.orders_cycles.find params[:id]
93 @cycle.step_back 94 @cycle.step_back
94 @cycle.save! 95 @cycle.save!
95 redirect_to action: :edit, id: @cycle.id 96 redirect_to action: :edit, id: @cycle.id
96 end 97 end
97 98
98 def add_missing_products 99 def add_missing_products
99 - @cycle = OrdersCyclePlugin::Cycle.find params[:id] 100 + @cycle = profile.orders_cycles.find params[:id]
100 @cycle.add_products 101 @cycle.add_products
101 render partial: 'suppliers_plugin/shared/pagereload' 102 render partial: 'suppliers_plugin/shared/pagereload'
102 end 103 end
103 104
104 def report_products 105 def report_products
105 return super if params[:ids].present? 106 return super if params[:ids].present?
106 - @cycle = OrdersCyclePlugin::Cycle.find params[:id] 107 + @cycle = profile.orders_cycles.find params[:id]
107 report_file = report_products_by_supplier @cycle.supplier_products_by_suppliers(@cycle.sales.ordered) 108 report_file = report_products_by_supplier @cycle.supplier_products_by_suppliers(@cycle.sales.ordered)
108 109
109 send_file report_file, type: 'application/xlsx', 110 send_file report_file, type: 'application/xlsx',
@@ -114,7 +115,7 @@ class OrdersCyclePluginCycleController &lt; OrdersPluginAdminController @@ -114,7 +115,7 @@ class OrdersCyclePluginCycleController &lt; OrdersPluginAdminController
114 115
115 def report_orders 116 def report_orders
116 return super if params[:ids].present? 117 return super if params[:ids].present?
117 - @cycle = OrdersCyclePlugin::Cycle.find params[:id] 118 + @cycle = profile.orders_cycles.find params[:id]
118 report_file = report_orders_by_consumer @cycle.sales.ordered 119 report_file = report_orders_by_consumer @cycle.sales.ordered
119 120
120 send_file report_file, type: 'application/xlsx', 121 send_file report_file, type: 'application/xlsx',
plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_item_controller.rb
@@ -31,12 +31,12 @@ class OrdersCyclePluginItemController &lt; OrdersPluginItemController @@ -31,12 +31,12 @@ class OrdersCyclePluginItemController &lt; OrdersPluginItemController
31 @item.sale = @order 31 @item.sale = @order
32 @item.product = @offered_product 32 @item.product = @offered_product
33 if set_quantity_consumer_ordered(params[:quantity_consumer_ordered] || 1) 33 if set_quantity_consumer_ordered(params[:quantity_consumer_ordered] || 1)
34 - @item.update_attributes! quantity_consumer_ordered: @quantity_consumer_ordered 34 + @item.update! quantity_consumer_ordered: @quantity_consumer_ordered
35 end 35 end
36 end 36 end
37 37
38 def edit 38 def edit
39 - return redirect_to params.merge(action: :admin_edit) if @admin_edit 39 + return redirect_to url_for(params.merge action: :admin_edit) if @admin_edit
40 super 40 super
41 @offered_product = @item.product 41 @offered_product = @item.product
42 @cycle = @order.cycle 42 @cycle = @order.cycle
@@ -50,7 +50,7 @@ class OrdersCyclePluginItemController &lt; OrdersPluginItemController @@ -50,7 +50,7 @@ class OrdersCyclePluginItemController &lt; OrdersPluginItemController
50 #update on association for total 50 #update on association for total
51 @order.items.each{ |i| i.attributes = params[:item] if i.id == @item.id } 51 @order.items.each{ |i| i.attributes = params[:item] if i.id == @item.id }
52 52
53 - @item.update_attributes = params[:item] 53 + @item.update params[:item]
54 end 54 end
55 55
56 def destroy 56 def destroy
plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_product_controller.rb
@@ -25,7 +25,7 @@ class OrdersCyclePluginProductController &lt; SuppliersPlugin::ProductController @@ -25,7 +25,7 @@ class OrdersCyclePluginProductController &lt; SuppliersPlugin::ProductController
25 def cycle_edit 25 def cycle_edit
26 @product = OrdersCyclePlugin::OfferedProduct.find params[:id] 26 @product = OrdersCyclePlugin::OfferedProduct.find params[:id]
27 if request.xhr? 27 if request.xhr?
28 - @product.update_attributes! params[:product] 28 + @product.update! params[:product]
29 respond_to do |format| 29 respond_to do |format|
30 format.js 30 format.js
31 end 31 end
plugins/orders_cycle/controllers/profile/orders_cycle_plugin_order_controller.rb
@@ -38,7 +38,7 @@ class OrdersCyclePluginOrderController &lt; OrdersPluginOrderController @@ -38,7 +38,7 @@ class OrdersCyclePluginOrderController &lt; OrdersPluginOrderController
38 @order.consumer = @consumer 38 @order.consumer = @consumer
39 @order.cycle = @cycle 39 @order.cycle = @cycle
40 @order.save! 40 @order.save!
41 - redirect_to params.merge(action: :edit, id: @order.id) 41 + redirect_to url_for(params.merge action: :edit, id: @order.id)
42 end 42 end
43 end 43 end
44 44
@@ -55,7 +55,7 @@ class OrdersCyclePluginOrderController &lt; OrdersPluginOrderController @@ -55,7 +55,7 @@ class OrdersCyclePluginOrderController &lt; OrdersPluginOrderController
55 end 55 end
56 @repeat_order.supplier_delivery = @order.supplier_delivery 56 @repeat_order.supplier_delivery = @order.supplier_delivery
57 @repeat_order.save! 57 @repeat_order.save!
58 - redirect_to params.merge(action: :edit, id: @repeat_order.id) 58 + redirect_to url_for(params.merge action: :edit, id: @repeat_order.id)
59 else 59 else
60 @orders = @cycle.consumer_previous_orders(@consumer).last(5).reverse 60 @orders = @cycle.consumer_previous_orders(@consumer).last(5).reverse
61 @orders.each{ |o| o.enable_product_diff } 61 @orders.each{ |o| o.enable_product_diff }
@@ -72,7 +72,7 @@ class OrdersCyclePluginOrderController &lt; OrdersPluginOrderController @@ -72,7 +72,7 @@ class OrdersCyclePluginOrderController &lt; OrdersPluginOrderController
72 if status == 'ordered' 72 if status == 'ordered'
73 if @order.items.size > 0 73 if @order.items.size > 0
74 @order.to_yaml # most strange workaround to avoid a crash in the next line 74 @order.to_yaml # most strange workaround to avoid a crash in the next line
75 - @order.update_attributes! params[:order] 75 + @order.update! params[:order]
76 session[:notice] = t('orders_plugin.controllers.profile.consumer.order_confirmed') 76 session[:notice] = t('orders_plugin.controllers.profile.consumer.order_confirmed')
77 else 77 else
78 session[:notice] = t('orders_plugin.controllers.profile.consumer.can_not_confirm_your_') 78 session[:notice] = t('orders_plugin.controllers.profile.consumer.can_not_confirm_your_')
@@ -117,12 +117,12 @@ class OrdersCyclePluginOrderController &lt; OrdersPluginOrderController @@ -117,12 +117,12 @@ class OrdersCyclePluginOrderController &lt; OrdersPluginOrderController
117 end 117 end
118 118
119 def reopen 119 def reopen
120 - @order.update_attributes! status: 'draft' 120 + @order.update! status: 'draft'
121 render 'edit' 121 render 'edit'
122 end 122 end
123 123
124 def cancel 124 def cancel
125 - @order.update_attributes! status: 'cancelled' 125 + @order.update! status: 'cancelled'
126 session[:notice] = t('orders_plugin.controllers.profile.consumer.order_cancelled') 126 session[:notice] = t('orders_plugin.controllers.profile.consumer.order_cancelled')
127 render 'edit' 127 render 'edit'
128 end 128 end
@@ -162,7 +162,7 @@ class OrdersCyclePluginOrderController &lt; OrdersPluginOrderController @@ -162,7 +162,7 @@ class OrdersCyclePluginOrderController &lt; OrdersPluginOrderController
162 end 162 end
163 163
164 def supplier_balloon 164 def supplier_balloon
165 - @supplier = SuppliersPlugin::Supplier.find params[:id] 165 + @supplier = profile.suppliers.find params[:id]
166 end 166 end
167 def product_balloon 167 def product_balloon
168 @product = OrdersCyclePlugin::OfferedProduct.find params[:id] 168 @product = OrdersCyclePlugin::OfferedProduct.find params[:id]
plugins/orders_cycle/db/migrate/20140406155248_refactor_orders_cycle_plugin_cycle_order.rb
@@ -4,9 +4,7 @@ class RefactorOrdersCyclePluginCycleOrder &lt; ActiveRecord::Migration @@ -4,9 +4,7 @@ class RefactorOrdersCyclePluginCycleOrder &lt; ActiveRecord::Migration
4 rename_column :orders_cycle_plugin_cycle_orders, :order_id, :sale_id 4 rename_column :orders_cycle_plugin_cycle_orders, :order_id, :sale_id
5 add_column :orders_cycle_plugin_cycle_orders, :purchase_id, :integer 5 add_column :orders_cycle_plugin_cycle_orders, :purchase_id, :integer
6 6
7 - add_index :orders_cycle_plugin_cycle_orders, :sale_id  
8 add_index :orders_cycle_plugin_cycle_orders, :purchase_id 7 add_index :orders_cycle_plugin_cycle_orders, :purchase_id
9 - add_index :orders_cycle_plugin_cycle_orders, [:cycle_id, :sale_id]  
10 add_index :orders_cycle_plugin_cycle_orders, [:cycle_id, :purchase_id], name: :index_orders_cycle_plugin_cycle_orders_cycle_purchase 8 add_index :orders_cycle_plugin_cycle_orders, [:cycle_id, :purchase_id], name: :index_orders_cycle_plugin_cycle_orders_cycle_purchase
11 end 9 end
12 10
plugins/orders_cycle/lib/ext/delivery_plugin/option.rb
@@ -2,7 +2,8 @@ require_dependency &#39;delivery_plugin/option&#39; @@ -2,7 +2,8 @@ require_dependency &#39;delivery_plugin/option&#39;
2 2
3 class DeliveryPlugin::Option 3 class DeliveryPlugin::Option
4 4
5 - belongs_to :cycle, class_name: 'OrdersCyclePlugin::Cycle',  
6 - foreign_key: :owner_id, conditions: ["delivery_plugin_options.owner_type = 'OrdersCyclePlugin::Cycle'"] 5 + belongs_to :cycle, -> {
  6 + where "delivery_plugin_options.owner_type = 'OrdersCyclePlugin::Cycle'"
  7 + }, class_name: 'OrdersCyclePlugin::Cycle', foreign_key: :owner_id
7 8
8 end 9 end
plugins/orders_cycle/lib/ext/profile.rb
1 require_dependency 'profile' 1 require_dependency 'profile'
  2 +require_dependency 'community'
2 3
3 -class Profile 4 +([Profile] + Profile.descendants).each do |subclass|
  5 +subclass.class_eval do
  6 +
  7 + has_many :orders_cycles, -> {
  8 + order('created_at DESC').
  9 + where "orders_cycle_plugin_cycles.status <> 'new'"
  10 + }, foreign_key: :profile_id, class_name: 'OrdersCyclePlugin::Cycle', dependent: :destroy
4 11
5 - has_many :orders_cycles, class_name: 'OrdersCyclePlugin::Cycle', dependent: :destroy, order: 'created_at DESC',  
6 - conditions: ["orders_cycle_plugin_cycles.status <> 'new'"]  
7 - has_many :orders_cycles_without_order, class_name: 'OrdersCyclePlugin::Cycle',  
8 - conditions: ["orders_cycle_plugin_cycles.status <> 'new'"] 12 + has_many :orders_cycles_without_order, -> {
  13 + where "orders_cycle_plugin_cycles.status <> 'new'"
  14 + }, foreign_key: :profile_id, class_name: 'OrdersCyclePlugin::Cycle'
9 15
10 has_many :orders_cycles_sales, through: :orders_cycles, source: :sales 16 has_many :orders_cycles_sales, through: :orders_cycles, source: :sales
11 has_many :orders_cycles_purchases, through: :orders_cycles, source: :purchases 17 has_many :orders_cycles_purchases, through: :orders_cycles, source: :purchases
12 18
13 - has_many :offered_products, class_name: 'OrdersCyclePlugin::OfferedProduct', order: 'products.name ASC' 19 + has_many :offered_products, -> { reorder 'products.name ASC' }, class_name: 'OrdersCyclePlugin::OfferedProduct'
  20 +
  21 +end
  22 +end
  23 +
  24 +class Profile
14 25
15 def orders_cycles_closed_date_range 26 def orders_cycles_closed_date_range
16 - list = self.orders_cycles.closing.all order: 'start ASC' 27 + list = self.orders_cycles.closing.order('start ASC').all
17 return DateTime.now..DateTime.now if list.blank? 28 return DateTime.now..DateTime.now if list.blank?
18 list.first.start.to_date..list.last.finish.to_date 29 list.first.start.to_date..list.last.finish.to_date
19 end 30 end
plugins/orders_cycle/models/orders_cycle_plugin/cycle.rb
@@ -32,30 +32,32 @@ class OrdersCyclePlugin::Cycle &lt; ActiveRecord::Base @@ -32,30 +32,32 @@ class OrdersCyclePlugin::Cycle &lt; ActiveRecord::Base
32 32
33 belongs_to :profile 33 belongs_to :profile
34 34
35 - has_many :delivery_options, class_name: 'DeliveryPlugin::Option', dependent: :destroy,  
36 - as: :owner, conditions: ["delivery_plugin_options.owner_type = 'OrdersCyclePlugin::Cycle'"] 35 + has_many :delivery_options, -> {
  36 + where "delivery_plugin_options.owner_type = 'OrdersCyclePlugin::Cycle'"
  37 + }, class_name: 'DeliveryPlugin::Option', dependent: :destroy, as: :owner
37 has_many :delivery_methods, through: :delivery_options, source: :delivery_method 38 has_many :delivery_methods, through: :delivery_options, source: :delivery_method
38 39
39 - has_many :cycle_orders, class_name: 'OrdersCyclePlugin::CycleOrder', foreign_key: :cycle_id, dependent: :destroy, order: 'id ASC' 40 + has_many :cycle_orders, -> { order 'id ASC' }, class_name: 'OrdersCyclePlugin::CycleOrder', foreign_key: :cycle_id, dependent: :destroy
40 41
41 # cannot use :order because of months/years named_scope 42 # cannot use :order because of months/years named_scope
42 has_many :sales, through: :cycle_orders, source: :sale 43 has_many :sales, through: :cycle_orders, source: :sale
43 has_many :purchases, through: :cycle_orders, source: :purchase 44 has_many :purchases, through: :cycle_orders, source: :purchase
44 45
45 has_many :cycle_products, foreign_key: :cycle_id, class_name: 'OrdersCyclePlugin::CycleProduct', dependent: :destroy 46 has_many :cycle_products, foreign_key: :cycle_id, class_name: 'OrdersCyclePlugin::CycleProduct', dependent: :destroy
46 - has_many :products, through: :cycle_products, source: :product, order: 'products.name ASC',  
47 - include: [ :from_2x_products, :from_products, {profile: :domains}, ] 47 + has_many :products, -> {
  48 + includes(:from_2x_products, :from_products, {profile: :domains})
  49 + }, through: :cycle_products, class_name: 'OrdersCyclePlugin::OfferedProduct', source: :product
48 50
49 - has_many :consumers, through: :sales, source: :consumer, order: 'name ASC', uniq: true  
50 - has_many :suppliers, through: :products, source: :suppliers, order: 'suppliers_plugin_suppliers.name ASC', uniq: true  
51 - has_many :orders_suppliers, through: :sales, source: :profile, order: 'name ASC' 51 + has_many :consumers, -> { distinct.reorder 'name ASC' }, through: :sales, source: :consumer
  52 + has_many :suppliers, -> { group 'suppliers_plugin_suppliers.id' }, through: :products
  53 + has_many :orders_suppliers, -> { reorder 'name ASC' }, through: :sales, source: :profile
52 54
53 - has_many :from_products, through: :products, order: 'name ASC', uniq: true  
54 - has_many :supplier_products, through: :products, order: 'name ASC', uniq: true  
55 - has_many :product_categories, through: :products, order: 'name ASC', uniq: true 55 + has_many :from_products, -> { distinct.reorder 'name ASC' }, through: :products
  56 + has_many :supplier_products, -> { distinct.reorder 'name ASC' }, through: :products
  57 + has_many :product_categories, -> { distinct.reorder 'name ASC' }, through: :products
56 58
57 - has_many :orders_confirmed, through: :cycle_orders, source: :sale, order: 'id ASC',  
58 - conditions: ['orders_plugin_orders.ordered_at IS NOT NULL'] 59 + has_many :orders_confirmed, -> { reorder('id ASC').where 'orders_plugin_orders.ordered_at IS NOT NULL' },
  60 + through: :cycle_orders, source: :sale
59 61
60 has_many :items_selled, through: :sales, source: :items 62 has_many :items_selled, through: :sales, source: :items
61 has_many :items_purchased, through: :purchases, source: :items 63 has_many :items_purchased, through: :purchases, source: :items
@@ -64,16 +66,16 @@ class OrdersCyclePlugin::Cycle &lt; ActiveRecord::Base @@ -64,16 +66,16 @@ class OrdersCyclePlugin::Cycle &lt; ActiveRecord::Base
64 66
65 has_many :ordered_suppliers, through: :orders_confirmed, source: :suppliers 67 has_many :ordered_suppliers, through: :orders_confirmed, source: :suppliers
66 68
67 - has_many :ordered_offered_products, through: :orders_confirmed, source: :offered_products, uniq: true, include: [:suppliers]  
68 - has_many :ordered_distributed_products, through: :orders_confirmed, source: :distributed_products, uniq: true, include: [:suppliers]  
69 - has_many :ordered_supplier_products, through: :orders_confirmed, source: :supplier_products, uniq: true, include: [:suppliers] 69 + has_many :ordered_offered_products, -> { distinct.includes :suppliers }, through: :orders_confirmed, source: :offered_products
  70 + has_many :ordered_distributed_products, -> { distinct.includes :suppliers }, through: :orders_confirmed, source: :distributed_products
  71 + has_many :ordered_supplier_products, -> { distinct.includes :suppliers }, through: :orders_confirmed, source: :supplier_products
70 72
71 has_many :volunteers_periods, class_name: 'VolunteersPlugin::Period', as: :owner 73 has_many :volunteers_periods, class_name: 'VolunteersPlugin::Period', as: :owner
72 has_many :volunteers, through: :volunteers_periods, source: :profile 74 has_many :volunteers, through: :volunteers_periods, source: :profile
73 attr_accessible :volunteers_periods_attributes 75 attr_accessible :volunteers_periods_attributes
74 accepts_nested_attributes_for :volunteers_periods, allow_destroy: true 76 accepts_nested_attributes_for :volunteers_periods, allow_destroy: true
75 77
76 - scope :has_volunteers_periods, -> {uniq.joins [:volunteers_periods]} 78 + scope :has_volunteers_periods, -> { distinct.joins :volunteers_periods }
77 79
78 # status scopes 80 # status scopes
79 scope :on_edition, -> { where status: 'edition' } 81 scope :on_edition, -> { where status: 'edition' }
@@ -83,33 +85,29 @@ class OrdersCyclePlugin::Cycle &lt; ActiveRecord::Base @@ -83,33 +85,29 @@ class OrdersCyclePlugin::Cycle &lt; ActiveRecord::Base
83 scope :on_delivery, -> { where status: 'delivery' } 85 scope :on_delivery, -> { where status: 'delivery' }
84 scope :on_closing, -> { where status: 'closing' } 86 scope :on_closing, -> { where status: 'closing' }
85 87
86 - scope :defuncts, conditions: ["status = 'new' AND created_at < ?", 2.days.ago]  
87 - scope :not_new, conditions: ["status <> 'new'"]  
88 - scope :on_orders, lambda {  
89 - {conditions: ["status = 'orders' AND ( (start <= :now AND finish IS NULL) OR (start <= :now AND finish >= :now) )",  
90 - {now: DateTime.now}]} 88 + scope :defuncts, -> { where "status = 'new' AND created_at < ?", 2.days.ago }
  89 + scope :not_new, -> { where "status <> 'new'" }
  90 + scope :on_orders, -> {
  91 + where "status = 'orders' AND ( (start <= :now AND finish IS NULL) OR (start <= :now AND finish >= :now) )", now: DateTime.now
91 } 92 }
92 - scope :not_on_orders, lambda {  
93 - {conditions: ["NOT (status = 'orders' AND ( (start <= :now AND finish IS NULL) OR (start <= :now AND finish >= :now) ) )",  
94 - {now: DateTime.now}]} 93 + scope :not_on_orders, -> {
  94 + where "NOT (status = 'orders' AND ( (start <= :now AND finish IS NULL) OR (start <= :now AND finish >= :now) ) )", now: DateTime.now
95 } 95 }
96 - scope :opened, conditions: ["status <> 'new' AND status <> 'closing'"]  
97 - scope :closing, conditions: ["status = 'closing'"]  
98 - scope :by_status, lambda { |status| { conditions: {status: status} } } 96 + scope :opened, -> { where "status <> 'new' AND status <> 'closing'" }
  97 + scope :closing, -> { where "status = 'closing'" }
  98 + scope :by_status, -> (status) { where status: status }
99 99
100 - scope :months, select: 'DISTINCT(EXTRACT(months FROM start)) as month', order: 'month DESC'  
101 - scope :years, select: 'DISTINCT(EXTRACT(YEAR FROM start)) as year', order: 'year DESC' 100 + scope :months, -> { order('month DESC').select 'DISTINCT(EXTRACT(months FROM start)) as month' }
  101 + scope :years, -> { order('year DESC').select 'DISTINCT(EXTRACT(YEAR FROM start)) as year' }
102 102
103 - scope :by_month, lambda { |month| {  
104 - conditions: [ 'EXTRACT(month FROM start) <= :month AND EXTRACT(month FROM finish) >= :month', { month: month } ]} 103 + scope :by_month, -> (month) {
  104 + where 'EXTRACT(month FROM start) <= :month AND EXTRACT(month FROM finish) >= :month', month: month
105 } 105 }
106 - scope :by_year, lambda { |year| {  
107 - conditions: [ 'EXTRACT(year FROM start) <= :year AND EXTRACT(year FROM finish) >= :year', { year: year } ]} 106 + scope :by_year, -> (year) {
  107 + where 'EXTRACT(year FROM start) <= :year AND EXTRACT(year FROM finish) >= :year', year: year
108 } 108 }
109 - scope :by_range, lambda { |range| {  
110 - conditions: [ 'start BETWEEN :start AND :finish OR finish BETWEEN :start AND :finish',  
111 - { start: range.first, finish: range.last }  
112 - ]} 109 + scope :by_range, -> (range) {
  110 + where 'start BETWEEN :start AND :finish OR finish BETWEEN :start AND :finish', start: range.first, finish: range.last
113 } 111 }
114 112
115 validates_presence_of :profile 113 validates_presence_of :profile
@@ -122,7 +120,7 @@ class OrdersCyclePlugin::Cycle &lt; ActiveRecord::Base @@ -122,7 +120,7 @@ class OrdersCyclePlugin::Cycle &lt; ActiveRecord::Base
122 validate :validate_orders_dates, if: :not_new? 120 validate :validate_orders_dates, if: :not_new?
123 validate :validate_delivery_dates, if: :not_new? 121 validate :validate_delivery_dates, if: :not_new?
124 122
125 - before_validation :step_new 123 + before_save :step_new
126 before_validation :update_orders_status 124 before_validation :update_orders_status
127 before_save :add_products_on_edition_state 125 before_save :add_products_on_edition_state
128 after_create :delay_purge_profile_defuncts 126 after_create :delay_purge_profile_defuncts
@@ -212,9 +210,7 @@ class OrdersCyclePlugin::Cycle &lt; ActiveRecord::Base @@ -212,9 +210,7 @@ class OrdersCyclePlugin::Cycle &lt; ActiveRecord::Base
212 end 210 end
213 211
214 def products_for_order 212 def products_for_order
215 - # FIXME name alias conflict  
216 - #self.products.unarchived.with_price.order('products.name ASC')  
217 - self.products.unarchived.with_price 213 + self.products.unarchived.alphabetically.with_price
218 end 214 end
219 215
220 def supplier_products_by_suppliers orders = self.sales.ordered 216 def supplier_products_by_suppliers orders = self.sales.ordered
@@ -261,27 +257,27 @@ class OrdersCyclePlugin::Cycle &lt; ActiveRecord::Base @@ -261,27 +257,27 @@ class OrdersCyclePlugin::Cycle &lt; ActiveRecord::Base
261 end 257 end
262 258
263 def step_new 259 def step_new
264 - return if new_record? 260 + return if self.new_record?
265 self.step if self.new? 261 self.step if self.new?
266 end 262 end
267 263
268 def update_sales_status from, to 264 def update_sales_status from, to
269 sales = self.sales.where(status: from.to_s) 265 sales = self.sales.where(status: from.to_s)
270 sales.each do |sale| 266 sales.each do |sale|
271 - sale.update_attributes status: to.to_s 267 + sale.update status: to.to_s
272 end 268 end
273 end 269 end
274 270
275 def update_purchases_status from, to 271 def update_purchases_status from, to
276 purchases = self.purchases.where(status: from.to_s) 272 purchases = self.purchases.where(status: from.to_s)
277 purchases.each do |purchase| 273 purchases.each do |purchase|
278 - purchase.update_attributes status: to.to_s 274 + purchase.update status: to.to_s
279 end 275 end
280 end 276 end
281 277
282 def update_orders_status 278 def update_orders_status
283 - # step orders to next_status on status change  
284 - return if self.new? or self.status_was == "new" or self.status_was == self.status 279 + return if self.new? or self.status_was == "new"
  280 + return if self.status_was == self.status
285 281
286 # Don't rewind confirmed sales 282 # Don't rewind confirmed sales
287 unless self.status_was == 'orders' and self.status == 'edition' 283 unless self.status_was == 'orders' and self.status == 'edition'
plugins/orders_cycle/models/orders_cycle_plugin/offered_product.rb
1 class OrdersCyclePlugin::OfferedProduct < SuppliersPlugin::BaseProduct 1 class OrdersCyclePlugin::OfferedProduct < SuppliersPlugin::BaseProduct
2 2
  3 + # we work use frozen attributes
  4 + self.default_delegate_enable = false
  5 +
3 # FIXME: WORKAROUND for https://github.com/rails/rails/issues/6663 6 # FIXME: WORKAROUND for https://github.com/rails/rails/issues/6663
4 # OrdersCyclePlugin::Sale.find(3697).cycle.suppliers returns empty without this 7 # OrdersCyclePlugin::Sale.find(3697).cycle.suppliers returns empty without this
5 def self.finder_needs_type_condition? 8 def self.finder_needs_type_condition?
@@ -19,10 +22,10 @@ class OrdersCyclePlugin::OfferedProduct &lt; SuppliersPlugin::BaseProduct @@ -19,10 +22,10 @@ class OrdersCyclePlugin::OfferedProduct &lt; SuppliersPlugin::BaseProduct
19 has_one :sources_supplier_product, through: :from_product, source: :sources_from_product 22 has_one :sources_supplier_product, through: :from_product, source: :sources_from_product
20 # necessary only due to the override of sources_supplier_products, as rails somehow caches the old reference 23 # necessary only due to the override of sources_supplier_products, as rails somehow caches the old reference
21 # copied from suppliers/lib/ext/product 24 # copied from suppliers/lib/ext/product
22 - has_many :supplier_products, through: :sources_supplier_products, source: :from_product, order: 'id ASC'  
23 - has_one :supplier_product, through: :sources_supplier_product, source: :from_product, order: 'id ASC', autosave: true  
24 - has_many :suppliers, through: :sources_supplier_products, uniq: true, order: 'id ASC'  
25 - has_one :supplier, through: :sources_supplier_product, order: 'id ASC' 25 + has_many :supplier_products, -> { order 'id ASC' }, through: :sources_supplier_products, source: :from_product
  26 + has_one :supplier_product, -> { order 'id ASC' }, through: :sources_supplier_product, source: :from_product, autosave: true
  27 + has_many :suppliers, -> { distinct.order 'id ASC' }, through: :sources_supplier_products
  28 + has_one :supplier, -> { order 'id ASC' }, through: :sources_supplier_product
26 29
27 instance_exec &OrdersPlugin::Item::DefineTotals 30 instance_exec &OrdersPlugin::Item::DefineTotals
28 extend CurrencyHelper::ClassMethods 31 extend CurrencyHelper::ClassMethods
@@ -31,9 +34,7 @@ class OrdersCyclePlugin::OfferedProduct &lt; SuppliersPlugin::BaseProduct @@ -31,9 +34,7 @@ class OrdersCyclePlugin::OfferedProduct &lt; SuppliersPlugin::BaseProduct
31 # test this before use! 34 # test this before use!
32 #validates_presence_of :cycle 35 #validates_presence_of :cycle
33 36
34 - # remove on rails4  
35 - scope :with_price, conditions: 'products.price > 0'  
36 - scope :with_product_category_id, lambda { |id| { conditions: {product_category_id: id} } } 37 + # override SuppliersPlugin::BaseProduct
37 def self.search_scope scope, params 38 def self.search_scope scope, params
38 scope = scope.from_supplier_id params[:supplier_id] if params[:supplier_id].present? 39 scope = scope.from_supplier_id params[:supplier_id] if params[:supplier_id].present?
39 scope = scope.with_available(if params[:available] == 'true' then true else false end) if params[:available].present? 40 scope = scope.with_available(if params[:available] == 'true' then true else false end) if params[:available].present?
@@ -50,19 +51,20 @@ class OrdersCyclePlugin::OfferedProduct &lt; SuppliersPlugin::BaseProduct @@ -50,19 +51,20 @@ class OrdersCyclePlugin::OfferedProduct &lt; SuppliersPlugin::BaseProduct
50 op.profile = product.profile 51 op.profile = product.profile
51 op.type = self.name 52 op.type = self.name
52 53
53 - op.from_products << product 54 + op.from_product = product
54 cycle.products << op if cycle 55 cycle.products << op if cycle
55 56
56 op 57 op
57 end 58 end
58 59
59 # always recalculate in case something has changed 60 # always recalculate in case something has changed
  61 + # FIXME: really? it is already copied!
60 def margin_percentage 62 def margin_percentage
61 - return self['margin_percentage'] if price.nil? or buy_price.nil? or price.zero? or buy_price.zero? 63 + return super if price.nil? or buy_price.nil? or price.zero? or buy_price.zero?
62 ((price / buy_price) - 1) * 100 64 ((price / buy_price) - 1) * 100
63 end 65 end
64 def margin_percentage= value 66 def margin_percentage= value
65 - self['margin_percentage'] = value 67 + super value
66 self.price = self.price_with_margins buy_price 68 self.price = self.price_with_margins buy_price
67 end 69 end
68 70
@@ -71,22 +73,15 @@ class OrdersCyclePlugin::OfferedProduct &lt; SuppliersPlugin::BaseProduct @@ -71,22 +73,15 @@ class OrdersCyclePlugin::OfferedProduct &lt; SuppliersPlugin::BaseProduct
71 end 73 end
72 74
73 # reimplement to don't destroy this, keeping history in cycles 75 # reimplement to don't destroy this, keeping history in cycles
74 - # offered products copy attributes 76 + # as offered products copy attributes.
75 def dependent? 77 def dependent?
76 false 78 false
77 end 79 end
78 80
79 - # cycle products freezes properties and don't use the original  
80 - DEFAULT_ATTRIBUTES.each do |a|  
81 - define_method "default_#{a}" do  
82 - nil  
83 - end  
84 - end  
85 -  
86 FROOZEN_DEFAULT_ATTRIBUTES = DEFAULT_ATTRIBUTES 81 FROOZEN_DEFAULT_ATTRIBUTES = DEFAULT_ATTRIBUTES
87 def freeze_default_attributes from_product 82 def freeze_default_attributes from_product
88 FROOZEN_DEFAULT_ATTRIBUTES.each do |attr| 83 FROOZEN_DEFAULT_ATTRIBUTES.each do |attr|
89 - self[attr] = from_product.send(attr) if from_product[attr] or from_product.respond_to? attr 84 + self.send "#{attr}=", from_product.send(attr) if from_product[attr] or from_product.respond_to? attr
90 end 85 end
91 end 86 end
92 87
plugins/orders_cycle/models/orders_cycle_plugin/order_base.rb
@@ -14,26 +14,18 @@ module OrdersCyclePlugin::OrderBase @@ -14,26 +14,18 @@ module OrdersCyclePlugin::OrderBase
14 self.cycle_sales.includes(:cycle).map(&:cycle) + self.cycle_purchases.includes(:cycle).map(&:cycle) 14 self.cycle_sales.includes(:cycle).map(&:cycle) + self.cycle_purchases.includes(:cycle).map(&:cycle)
15 end 15 end
16 16
17 - # TODO: test if the has_one defined on Sale/Purchase works and these are not needed  
18 - def cycle  
19 - self.cycles.first  
20 - end  
21 - def cycle= cycle  
22 - self.cycles = [cycle]  
23 - end  
24 -  
25 scope :for_cycle, -> (cycle) { 17 scope :for_cycle, -> (cycle) {
26 where('orders_cycle_plugin_cycles.id = ?', cycle.id). 18 where('orders_cycle_plugin_cycles.id = ?', cycle.id).
27 joins(:cycles) 19 joins(:cycles)
28 } 20 }
29 21
30 - has_many :items, class_name: 'OrdersCyclePlugin::Item', foreign_key: :order_id, dependent: :destroy, order: 'name ASC' 22 + has_many :items, -> { order 'name ASC' }, class_name: 'OrdersCyclePlugin::Item', foreign_key: :order_id, dependent: :destroy
31 23
32 - has_many :offered_products, through: :items, source: :offered_product, uniq: true  
33 - has_many :distributed_products, through: :offered_products, source: :from_products, uniq: true  
34 - has_many :supplier_products, through: :distributed_products, source: :from_products, uniq: true 24 + has_many :offered_products, -> { distinct }, through: :items, source: :offered_product
  25 + has_many :distributed_products, -> { distinct }, through: :offered_products, source: :from_products
  26 + has_many :supplier_products, -> { distinct }, through: :distributed_products, source: :from_products
35 27
36 - has_many :suppliers, through: :supplier_products, uniq: true 28 + has_many :suppliers, -> { distinct }, through: :supplier_products
37 29
38 extend CodeNumbering::ClassMethods 30 extend CodeNumbering::ClassMethods
39 code_numbering :code, scope: (proc do 31 code_numbering :code, scope: (proc do
plugins/orders_cycle/models/orders_cycle_plugin/sale.rb
@@ -24,10 +24,6 @@ class OrdersCyclePlugin::Sale &lt; OrdersPlugin::Sale @@ -24,10 +24,6 @@ class OrdersCyclePlugin::Sale &lt; OrdersPlugin::Sale
24 super and self.cycle.orders? 24 super and self.cycle.orders?
25 end 25 end
26 26
27 - def supplier_delivery  
28 - super || (self.cycle.delivery_methods.first rescue nil)  
29 - end  
30 -  
31 def change_purchases 27 def change_purchases
32 return unless self.status_was.present? 28 return unless self.status_was.present?
33 if self.ordered_at_was.nil? and self.ordered_at.present? 29 if self.ordered_at_was.nil? and self.ordered_at.present?
plugins/orders_cycle/test/factories.rb 0 → 100644
@@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
  1 +module OrdersCyclePlugin::Factory
  2 +
  3 + def defaults_for_suppliers_plugin_supplier
  4 + {:profile => build(Profile),
  5 + :consumer => build(Profile)}
  6 + end
  7 +
  8 + def defaults_for_suppliers_plugin_distributed_product attrs = {}
  9 + profile = attrs[:profile] || build(Profile)
  10 + {:profile => profile, :name => "product-#{factory_num_seq}", :price => 2.0,
  11 + :product => build(Product, :enterprise => profile.profile, :price => 2.0),
  12 + :supplier => build(SuppliersPlugin::Supplier, :profile => profile, :consumer => profile)}
  13 + end
  14 +
  15 + def defaults_for_orders_cycle_plugin_offered_product attrs = {}
  16 + hash = defaults_for_orders_cycle_plugin_product(attrs)
  17 + profile = hash[:profile]
  18 + hash.merge({
  19 + :from_products => [build(SuppliersPlugin::DistributedProduct, :profile => profile)]})
  20 + end
  21 +
  22 + def defaults_for_delivery_plugin_method
  23 + {:profile => build(OrdersCyclePlugin::Profile),
  24 + :name => "My delivery #{factory_num_seq.to_s}",
  25 + :delivery_type => 'deliver'}
  26 + end
  27 +
  28 + def defaults_for_delivery_plugin_option
  29 + {:cycle => build(OrdersCyclePlugin::Cycle),
  30 + :delivery_method => build(DeliveryPlugin::Method)}
  31 + end
  32 +
  33 + def defaults_for_orders_plugin_order attrs = {}
  34 + profile = attrs[:profile] || build(OrdersCyclePlugin::Profile)
  35 + {:status => 'ordered',
  36 + :cycle => build(OrdersCyclePlugin::Cycle, :profile => profile),
  37 + :consumer => build(OrdersCyclePlugin::Profile),
  38 + :supplier_delivery => build(DeliveryPlugin::Method, :profile => profile),
  39 + :consumer_delivery => build(DeliveryPlugin::Method, :profile => profile)}
  40 + end
  41 +
  42 + def defaults_for_orders_plugin_items
  43 + {:order => build(OrdersPlugin::Order),
  44 + :product => build(OrdersCyclePlugin::OfferedProduct),
  45 + :quantity_shipped => 1.0, :quantity_ordered => 2.0, :quantity_accepted => 3.0,
  46 + :price_shipped => 10.0, :price_ordered => 20.0, :price_accepted => 30.0}
  47 + end
  48 +
  49 + def defaults_for_orders_cycle_plugin_cycle
  50 + {:profile => build(OrdersCyclePlugin::Profile), :status => 'orders',
  51 + :name => 'weekly', :start => Time.now, :finish => Time.now+1.days}
  52 + end
  53 +
  54 +end
  55 +
  56 +Noosfero::Factory.register_extension OrdersCyclePlugin::Factory
  57 +
plugins/orders_cycle/test/functional/orders_cycle_plugin/order_controller_test.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +require "#{File.dirname(__FILE__)}/../../test_helper"
  2 +
  3 +class OrdersCyclePlugin::OrderControllerTest < Test::Unit::TestCase
  4 +
  5 + def setup
  6 + @controller = OrdersCyclePluginOrderController.new
  7 + @request = ActionController::TestRequest.new
  8 + @response = ActionController::TestResponse.new
  9 + end
  10 +
  11 +
  12 +end
plugins/orders_cycle/test/functional/orders_cycle_plugin/session_controller_test.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +require "#{File.dirname(__FILE__)}/../../test_helper"
  2 +
  3 +class OrdersCyclePlugin::CycleControllerTest < Test::Unit::TestCase
  4 +
  5 + def setup
  6 + @controller = OrdersCyclePluginCycleController.new
  7 + @request = ActionController::TestRequest.new
  8 + @response = ActionController::TestResponse.new
  9 + end
  10 +
  11 + should 'create a new cycle' do
  12 + end
  13 +
  14 +end
plugins/orders_cycle/test/test_helper.rb 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +require File.dirname(__FILE__) + '/../../../test/test_helper'
  2 +require 'spec'
  3 +
  4 +class ActiveRecord::TestCase < ActiveSupport::TestCase
  5 + include OrdersCyclePluginFactory
  6 +end
plugins/orders_cycle/test/unit/orders_cycle_plugin/cycle_test.rb 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +require "#{File.dirname(__FILE__)}/../../test_helper"
  2 +
  3 +class OrdersCyclePlugin::CycleTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @profile = Enterprise.create!(:name => "trocas verdes", :identifier => "trocas-verdes")
  7 + @pc = ProductCategory.create!(:name => 'frutas', :environment_id => 1)
  8 + @profile.products = [Product.create!(:name => 'banana', :product_category => @pc),
  9 + Product.new(:name => 'mandioca', :product_category => @pc), Product.new(:name => 'alface', :product_category => @pc)]
  10 +
  11 + profile.offered_products = @profile.products.map{ |p| OrdersCyclePlugin::OfferedProduct.create!(:product => p) }
  12 + DeliveryPlugin::Method.create! :name => 'at home', :delivery_type => 'pickup', :profile => @profile
  13 + @cycle = OrdersCyclePlugin::Cycle.create!(:profile => @profile)
  14 + end
  15 +
  16 + should 'add products from profile after create' do
  17 + assert_equal @cycle.products.collect(&:product_id), @profile.products.collect(&:id)
  18 + end
  19 +
  20 + should 'have at least one delivery method unless in edition status' do
  21 + cycle = OrdersCyclePlugin::Cycle.create! :profile => @profile, :name => "Testes batidos", :start => DateTime.now, :status => 'edition'
  22 + assert cycle
  23 + cycle.status = 'orders'
  24 + assert_nil cycle.save!
  25 + end
  26 +
  27 +end
plugins/orders_cycle/test/unit/orders_cycle_plugin/offered_product_test.rb 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +require "#{File.dirname(__FILE__)}/../../test_helper"
  2 +
  3 +class OrdersCyclePlugin::OfferedProductTest < ActiveSupport::TestCase
  4 +
  5 +
  6 +end
plugins/orders_cycle/test/unit/profile_test.rb 0 → 100644
@@ -0,0 +1,127 @@ @@ -0,0 +1,127 @@
  1 +require "#{File.dirname(__FILE__)}/../../test_helper"
  2 +
  3 +class OrdersCyclePlugin::ProfileTest < ActiveRecord::TestCase
  4 +
  5 + def setup
  6 + @profile = build(Profile)
  7 + @invisible_profile = build(Enterprise, :visible => false)
  8 + @other_profile = build(Enterprise)
  9 + @profile = build(OrdersCyclePlugin::profile, :profile => @profile)
  10 + @self_supplier = build(OrdersCyclePlugin::Supplier, :consumer => @profile, :profile => @profile)
  11 + @dummy_supplier = build(OrdersCyclePlugin::Supplier, :consumer => @profile, :profile => @dummy_profile)
  12 + @other_supplier = build(OrdersCyclePlugin::Supplier, :consumer => @profile, :profile => @other_profile)
  13 + end
  14 +
  15 + attr_accessor :profile, :invisible_profile, :other_profile,
  16 + :self_supplier, :dummy_supplier, :other_supplier
  17 +
  18 + should 'respond to name methods' do
  19 + profile.expects(:name).returns('name')
  20 + assert_equal 'name', profile.name
  21 + end
  22 +
  23 + should 'respond to dummy methods' do
  24 + profile.dummy = true
  25 + assert_equal true, profile.dummy?
  26 + profile.dummy = false
  27 + assert_equal false, profile.dummy
  28 + end
  29 +
  30 + should "return closed cycles' date range" do
  31 + DateTime.expects(:now).returns(1).at_least_once
  32 + assert_equal 1..1, profile.orders_cycles_closed_date_range
  33 + s1 = create(OrdersCyclePlugin::Cycle, :profile => profile, :start => Time.now-1.days, :finish => nil)
  34 + s2 = create(OrdersCyclePlugin::Cycle, :profile => profile, :finish => Time.now+1.days, :start => Time.now)
  35 + assert_equal (s1.start.to_date..s2.finish.to_date), profile.orders_cycles_closed_date_range
  36 + end
  37 +
  38 + should 'return abbreviation or the name' do
  39 + profile.name_abbreviation = 'coll.'
  40 + profile.profile.name = 'collective'
  41 + assert_equal 'coll.', profile.abbreviation_or_name
  42 + profile.name_abbreviation = nil
  43 + assert_equal 'collective', profile.abbreviation_or_name
  44 + end
  45 +
  46 + ###
  47 + # Products
  48 + ###
  49 +
  50 + should "default products's margins when asked" do
  51 + profile.update! :margin_percentage => 10
  52 + product = create(SuppliersPlugin::DistributedProduct, :profile => profile, :supplier => profile.self_supplier,
  53 + :price => 10, :default_margin_percentage => false)
  54 + cycle = create(OrdersCyclePlugin::Cycle, :profile => profile)
  55 + sproduct = cycle.products.first
  56 + sproduct.update! :margin_percentage => 5
  57 + cycleclosed = create(OrdersCyclePlugin::Cycle, :profile => profile, :status => 'closed')
  58 +
  59 + profile.orders_cycles_products_default_margins
  60 + product.reload
  61 + sproduct.reload
  62 + assert_equal true, product.default_margin_percentage
  63 + assert_equal sproduct.margin_percentage, profile.margin_percentage
  64 + end
  65 +
  66 + should 'return not yet distributed products' do
  67 + profile.save!
  68 + other_profile.save!
  69 + other_supplier.save!
  70 + product = create(SuppliersPlugin::DistributedProduct, :profile => other_profile, :supplier => other_profile.self_supplier)
  71 + profile.add_supplier_products other_supplier
  72 + product2 = create(SuppliersPlugin::DistributedProduct, :profile => other_profile, :supplier => other_profile.self_supplier)
  73 + assert_equal [product2], profile.not_distributed_products(other_supplier)
  74 + end
  75 +
  76 + ###
  77 + # Suppliers
  78 + ###
  79 +
  80 + should 'add supplier' do
  81 + @profile.save!
  82 + @other_profile.save!
  83 +
  84 + assert_difference OrdersCyclePlugin::Supplier, :count do
  85 + @profile.add_supplier @other_profile
  86 + end
  87 + assert @profile.suppliers_profiles.include?(@other_profile)
  88 + assert @other_profile.consumers_profiles.include?(@profile)
  89 + end
  90 +
  91 + should "add all supplier's products when supplier is added" do
  92 + @profile.save!
  93 + @other_profile.save!
  94 + product = create(SuppliersPlugin::DistributedProduct, :profile => @other_profile)
  95 + @profile.add_supplier @other_profile
  96 + assert_equal [product], @profile.from_products
  97 + end
  98 +
  99 + should 'remove supplier' do
  100 + @profile.save!
  101 + @other_profile.save!
  102 +
  103 + @profile.add_supplier @other_profile
  104 + assert_difference OrdersCyclePlugin::Supplier, :count, -1 do
  105 + assert_difference RoleAssignment, :count, -1 do
  106 + @profile.remove_supplier @other_profile
  107 + end
  108 + end
  109 + assert !@profile.suppliers_profiles.include?(@other_profile)
  110 + end
  111 +
  112 + should "archive supplier's products when supplier is removed" do
  113 + @profile.save!
  114 + @other_profile.save!
  115 + product = create(SuppliersPlugin::DistributedProduct, :profile => @other_profile)
  116 + @profile.add_supplier @other_profile
  117 + @profile.remove_supplier @other_profile
  118 + assert_equal [product], @profile.from_products
  119 + assert_equal 1, @profile.distributed_products.archived.count
  120 + end
  121 +
  122 + should 'create self supplier automatically' do
  123 + profile = create(OrdersCyclePlugin::profile, :profile => @profile)
  124 + assert_equal 1, profile.suppliers.count
  125 + end
  126 +
  127 +end
plugins/orders_cycle/views/orders_cycle_plugin_cycle/_cycle_sales.html.slim
1 = render 'orders_plugin_admin/sales', actors: @cycle.consumers, orders_owner: @cycle, owner_id: @cycle.id, 1 = render 'orders_plugin_admin/sales', actors: @cycle.consumers, orders_owner: @cycle, owner_id: @cycle.id,
2 orders: @cycle.sales.default_order.paginate(per_page: 30, page: params[:page]) 2 orders: @cycle.sales.default_order.paginate(per_page: 30, page: params[:page])
  3 +
plugins/orders_cycle/views/orders_cycle_plugin_cycle/_edit_fields.html.slim
@@ -53,6 +53,5 @@ h3= t(&#39;views.cycle._edit_fields.general_settings&#39;) @@ -53,6 +53,5 @@ h3= t(&#39;views.cycle._edit_fields.general_settings&#39;)
53 = link_to t('views.cycle._edit_fields.cancel_changes'), @cycle.new? ? {action: :index} : params 53 = link_to t('views.cycle._edit_fields.cancel_changes'), @cycle.new? ? {action: :index} : params
54 - unless @cycle.new? 54 - unless @cycle.new?
55 |&nbsp; 55 |&nbsp;
56 - = link_to t('views.cycle._edit_fields.remove'), {action: :destroy, id: @cycle.id}, confirm: t('views.cycle._edit_fields.confirm_remove')  
57 - 56 + = link_to t('views.cycle._edit_fields.remove'), {action: :destroy, id: @cycle.id}, data: {confirm: t('views.cycle._edit_fields.confirm_remove')}
58 57
plugins/orders_cycle/views/orders_cycle_plugin_cycle/_product_lines.html.erb
1 <div class="cycle-products-table sortable-table"> 1 <div class="cycle-products-table sortable-table">
2 <%= pagination_links @products %> 2 <%= pagination_links @products %>
3 <div id="result-count"> 3 <div id="result-count">
4 - <small><%= t('views.cycle._product_lines.showing_pcount_produc') % {:pcount => @products.length, :allpcount => @cycle.products.count} %></small> 4 + <small><%= t('views.cycle._product_lines.showing_pcount_produc') % {pcount: @products.length, allpcount: @cycle.products.count} %></small>
5 </div> 5 </div>
6 <div class='table-header'> 6 <div class='table-header'>
7 <span class='box-field category'><%= t('views.cycle._product_lines.category') %></span> 7 <span class='box-field category'><%= t('views.cycle._product_lines.category') %></span>
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 <div class='table-content'> 17 <div class='table-content'>
18 <% @products.each do |p| %> 18 <% @products.each do |p| %>
19 <div id="cycle-product-<%=p.id%>" class='cycle-product value-row' toggle-edit="orders_cycle.offered_product.edit();"> 19 <div id="cycle-product-<%=p.id%>" class='cycle-product value-row' toggle-edit="orders_cycle.offered_product.edit();">
20 - <%= render 'orders_cycle_plugin_product/cycle_edit', :p => p %> 20 + <%= render 'orders_cycle_plugin_product/cycle_edit', p: p %>
21 </div> 21 </div>
22 <% end %> 22 <% end %>
23 <%= javascript_tag do %> 23 <%= javascript_tag do %>
plugins/orders_cycle/views/orders_cycle_plugin_cycle/_products_loading.html.erb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 <%= t('views.cycle._products_loading') %> 3 <%= t('views.cycle._products_loading') %>
4 4
5 <%= javascript_tag do %> 5 <%= javascript_tag do %>
6 - orders_cycle.cycle.products.load_url = <%= url_for(:action => :products_load, :id => @cycle.id).to_json %> 6 + orders_cycle.cycle.products.load_url = <%= url_for(action: :products_load, id: @cycle.id).to_json %>
7 orders_cycle.cycle.products.load() 7 orders_cycle.cycle.products.load()
8 <% end %> 8 <% end %>
9 </div> 9 </div>
plugins/orders_cycle/views/orders_cycle_plugin_cycle/_timeline.html.slim 0 → 100644
@@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
  1 +- actions = true if actions.nil? and @admin
  2 +- listing = false if listing.nil?
  3 +- view_status = if OrdersCyclePlugin::Cycle::Statuses.index(params[:view]) then params[:view] else cycle.status end
  4 +- status_text = t"models.cycle.statuses.#{view_status}"
  5 +
  6 +.cycle-timeline
  7 + - OrdersCyclePlugin::Cycle::UserStatuses.each do |status|
  8 + - klass = "cycle-timeline-item #{timeline_class cycle, status, view_status}"
  9 + - name = t("models.cycle.statuses.#{status}")
  10 + = link_to name, params.merge(action: :edit, id: cycle.id, view: status), class: klass
  11 +
  12 +- if listing
  13 + .dates-brief
  14 + .date
  15 + span.field-title= t'views.cycle._brief.orders'
  16 + |&emsp;
  17 + span= datetime_period_short cycle.start, cycle.finish
  18 + .date
  19 + span.field-title= t'views.cycle._brief.delivery'
  20 + |&emsp;
  21 + span= datetime_period_short cycle.delivery_start, cycle.delivery_finish
  22 +
  23 +- if actions
  24 + .actions-bar
  25 + - if cycle.status == view_status and cycle.status != 'closing'
  26 + = link_to t('views.cycle._timeline.close_status') % {status: status_text},
  27 + {action: :step, id: cycle.id, method: :post},
  28 + {confirm: t('views.cycle._timeline.are_you_sure_you_want_to_close') % {status: status_text}, class: 'action-button'}
  29 + = render "orders_cycle_plugin_cycle/actions/#{view_status}", cycle: cycle rescue nil
  30 +
plugins/orders_cycle/views/orders_cycle_plugin_cycle/actions/_closed.html.slim 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +- if cycle.status == 'closing'
  2 + = link_to t('views.cycle._timeline.reopen_orders_period'), {action: :step_back, id: cycle.id, method: :post},
  3 + id: 'cycle-open-cycle', class: 'action-button', data: {confirm: t('views.cycle._timeline.are_you_sure_you_want_to_reopen')}
  4 +
plugins/orders_cycle/views/orders_cycle_plugin_cycle/edit.js.erb
1 <% if params[:commit] %> 1 <% if params[:commit] %>
2 <% if @success and @open %> 2 <% if @success and @open %>
3 - window.location = <%= url_for(:action => :edit, :id => @cycle.id).to_json %> 3 + window.location = <%= url_for(action: :edit, id: @cycle.id).to_json %>
4 <% else %> 4 <% else %>
5 - noosfero.modal.html(<%= render('edit_popin', :cycle => @cycle).to_json %>) 5 + noosfero.modal.html(<%= render('edit_popin', cycle: @cycle).to_json %>)
6 <% end %> 6 <% end %>
7 <% else %> 7 <% else %>
8 jQuery("#cycle-products .table").replaceWith('<%= escape_javascript render('product_lines') %>') 8 jQuery("#cycle-products .table").replaceWith('<%= escape_javascript render('product_lines') %>')
plugins/orders_cycle/views/orders_cycle_plugin_gadgets/cycles.html.erb
@@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
2 2
3 <div id="cycles-gadget"> 3 <div id="cycles-gadget">
4 <% profile.orders_cycles.on_orders.each do |cycle| %> 4 <% profile.orders_cycles.on_orders.each do |cycle| %>
5 - <%= render :partial => 'orders_cycle_plugin_gadgets/cycle', :locals => {:cycle => cycle} %> 5 + <%= render 'orders_cycle_plugin_gadgets/cycle', cycle: cycle %>
6 <% end %> 6 <% end %>
7 7
8 <div> 8 <div>
9 - <%= link_to t('views.gadgets.cycles.all_cycles'), {:controller => :orders_cycle_plugin_order, :profile => profile.identifier, :action => :index}, :id => "all-cycles" %> 9 + <%= link_to t('views.gadgets.cycles.all_cycles'), {controller: :orders_cycle_plugin_order, profile: profile.identifier, action: :index}, id: "all-cycles" %>
10 <div class='clean'></div> 10 <div class='clean'></div>
11 </div> 11 </div>
12 </div> 12 </div>
plugins/orders_cycle/views/orders_cycle_plugin_order/cycle_edit.rjs
1 -page.replace_html "order-#{@order.id}", :partial => 'cycle_edit', :locals => {:order => @order}  
2 -page.replace_html "cycle-products-sums", :partial => 'orders_cycle_plugin_cycle/orders_suppliers', :locals => {:cycle => @order.cycle} 1 +page.replace_html "order-#{@order.id}", partial: 'cycle_edit', locals: {order: @order}
  2 +page.replace_html "cycle-products-sums", partial: 'orders_cycle_plugin_cycle/orders_suppliers', locals: {cycle: @order.cycle}
3 page << "toggle_edit.value_row.reload();" 3 page << "toggle_edit.value_row.reload();"
plugins/shopping_cart/controllers/shopping_cart_plugin_controller.rb
@@ -119,7 +119,8 @@ class ShoppingCartPluginController &lt; OrdersPluginController @@ -119,7 +119,8 @@ class ShoppingCartPluginController &lt; OrdersPluginController
119 @settings = cart_profile.shopping_cart_settings 119 @settings = cart_profile.shopping_cart_settings
120 @cart = cart 120 @cart = cart
121 @profile = cart_profile 121 @profile = cart_profile
122 - @order = profile.sales.build consumer: user 122 + supplier_delivery = profile.delivery_methods.first
  123 + @order = build_order self.cart[:items], supplier_delivery
123 124
124 last_delivery_option_id = session[:cart][:last_delivery_option_id] if session[:cart] 125 last_delivery_option_id = session[:cart][:last_delivery_option_id] if session[:cart]
125 @order.supplier_delivery = profile.delivery_methods.where(id: last_delivery_option_id).first if last_delivery_option_id 126 @order.supplier_delivery = profile.delivery_methods.where(id: last_delivery_option_id).first if last_delivery_option_id
@@ -192,7 +193,8 @@ class ShoppingCartPluginController &lt; OrdersPluginController @@ -192,7 +193,8 @@ class ShoppingCartPluginController &lt; OrdersPluginController
192 @profile = cart_profile 193 @profile = cart_profile
193 supplier_delivery = @profile.delivery_methods.where(id: params[:order][:supplier_delivery_id]).first 194 supplier_delivery = @profile.delivery_methods.where(id: params[:order][:supplier_delivery_id]).first
194 order = build_order self.cart[:items], supplier_delivery 195 order = build_order self.cart[:items], supplier_delivery
195 - total_price = order.total_price 196 + order.supplier_delivery = supplier_delivery
  197 + total_price = order.total
196 render json: { 198 render json: {
197 ok: true, 199 ok: true,
198 delivery_price: float_to_currency_cart(supplier_delivery.cost(total_price), environment, unit: ''), 200 delivery_price: float_to_currency_cart(supplier_delivery.cost(total_price), environment, unit: ''),
plugins/shopping_cart/db/migrate/20121022190819_move_fields_included_on_profiles_table_to_settings.rb
1 class MoveFieldsIncludedOnProfilesTableToSettings < ActiveRecord::Migration 1 class MoveFieldsIncludedOnProfilesTableToSettings < ActiveRecord::Migration
2 def self.up 2 def self.up
3 - Profile.find_each do |profile| 3 + Enterprise.find_each do |profile|
4 settings = profile.shopping_cart_settings 4 settings = profile.shopping_cart_settings
5 settings.enabled = profile.shopping_cart 5 settings.enabled = profile.shopping_cart
6 settings.delivery = profile.shopping_cart_delivery 6 settings.delivery = profile.shopping_cart_delivery
plugins/shopping_cart/db/migrate/20131226125124_move_shopping_cart_purchase_order_to_orders_plugin_order.rb
@@ -2,7 +2,7 @@ OrdersPlugin.send :remove_const, :Item if defined? OrdersPlugin::Item @@ -2,7 +2,7 @@ OrdersPlugin.send :remove_const, :Item if defined? OrdersPlugin::Item
2 OrdersPlugin.send :remove_const, :Order if defined? OrdersPlugin::Order 2 OrdersPlugin.send :remove_const, :Order if defined? OrdersPlugin::Order
3 3
4 class ShoppingCartPlugin::PurchaseOrder < ActiveRecord::Base 4 class ShoppingCartPlugin::PurchaseOrder < ActiveRecord::Base
5 - acts_as_having_settings :field => :data 5 + acts_as_having_settings field: :data
6 6
7 module Status 7 module Status
8 OPENED = 0 8 OPENED = 0
@@ -13,17 +13,17 @@ class ShoppingCartPlugin::PurchaseOrder &lt; ActiveRecord::Base @@ -13,17 +13,17 @@ class ShoppingCartPlugin::PurchaseOrder &lt; ActiveRecord::Base
13 end 13 end
14 14
15 class Profile 15 class Profile
16 - has_many :orders, :class_name => 'OrdersPlugin::Order' 16 + has_many :orders, class_name: 'OrdersPlugin::Order'
17 end 17 end
18 18
19 class OrdersPlugin::Item < ActiveRecord::Base 19 class OrdersPlugin::Item < ActiveRecord::Base
20 - belongs_to :order, :class_name => 'OrdersPlugin::Order' 20 + belongs_to :order, class_name: 'OrdersPlugin::Order'
21 end 21 end
22 class OrdersPlugin::Order < ActiveRecord::Base 22 class OrdersPlugin::Order < ActiveRecord::Base
23 - has_many :items, :class_name => 'OrdersPlugin::Item', :foreign_key => :order_id 23 + has_many :items, class_name: 'OrdersPlugin::Item', foreign_key: :order_id
24 24
25 extend CodeNumbering::ClassMethods 25 extend CodeNumbering::ClassMethods
26 - code_numbering :code, :scope => proc{ self.profile.orders } 26 + code_numbering :code, scope: proc{ self.profile.orders }
27 end 27 end
28 28
29 StatusTransform = { 29 StatusTransform = {
@@ -37,10 +37,10 @@ class MoveShoppingCartPurchaseOrderToOrdersPluginOrder &lt; ActiveRecord::Migration @@ -37,10 +37,10 @@ class MoveShoppingCartPurchaseOrderToOrdersPluginOrder &lt; ActiveRecord::Migration
37 def self.up 37 def self.up
38 OrdersPlugin::Order.record_timestamps = false 38 OrdersPlugin::Order.record_timestamps = false
39 39
40 - ShoppingCartPlugin::PurchaseOrder.all(:order => 'created_at ASC').each do |purchase_order| 40 + ShoppingCartPlugin::PurchaseOrder.order('created_at ASC').find_each do |purchase_order|
41 data = purchase_order.data 41 data = purchase_order.data
42 42
43 - order = OrdersPlugin::Order.new :profile_id => purchase_order.seller_id, :consumer_id => purchase_order.customer_id 43 + order = OrdersPlugin::Order.new profile_id: purchase_order.seller_id, consumer_id: purchase_order.customer_id
44 44
45 order.consumer_data = {} 45 order.consumer_data = {}
46 ['contact_phone','name','email'].each do |prop| 46 ['contact_phone','name','email'].each do |prop|
@@ -58,7 +58,7 @@ class MoveShoppingCartPurchaseOrderToOrdersPluginOrder &lt; ActiveRecord::Migration @@ -58,7 +58,7 @@ class MoveShoppingCartPurchaseOrderToOrdersPluginOrder &lt; ActiveRecord::Migration
58 order.supplier_delivery_data = {} 58 order.supplier_delivery_data = {}
59 59
60 data[:products_list].each do |id, data| 60 data[:products_list].each do |id, data|
61 - item = order.items.build :product_id => id, :name => data[:name], :quantity_consumer_ordered => data[:quantity], :price => data[:price] 61 + item = order.items.build product_id: id, name: data[:name], quantity_consumer_ordered: data[:quantity], price: data[:price]
62 item.order = order 62 item.order = order
63 end 63 end
64 64
plugins/shopping_cart/features/delivery_admin.feature
@@ -36,7 +36,6 @@ Feature: delivery administration @@ -36,7 +36,6 @@ Feature: delivery administration
36 And I follow "New delivery or pickup" 36 And I follow "New delivery or pickup"
37 And I select "Deliver" from "Type" 37 And I select "Deliver" from "Type"
38 And I fill in "Name" with "Bike" 38 And I fill in "Name" with "Bike"
39 - And I fill in "Description" with "Beers delivered with my old bike."  
40 And I fill in "Fixed cost" with "8.00" 39 And I fill in "Fixed cost" with "8.00"
41 And I fill in "Order's minimum price for free delivery" with "35.50" 40 And I fill in "Order's minimum price for free delivery" with "35.50"
42 When I press "Add" 41 When I press "Add"
@@ -49,7 +48,6 @@ Feature: delivery administration @@ -49,7 +48,6 @@ Feature: delivery administration
49 And I follow "New delivery or pickup" 48 And I follow "New delivery or pickup"
50 And I select "Pickup" from "Type" 49 And I select "Pickup" from "Type"
51 And I fill in "Name" with "Bar" 50 And I fill in "Name" with "Bar"
52 - And I fill in "Description" with "Come to my bar and pick it yourself."  
53 And I fill in "Fixed cost" with "0.00" 51 And I fill in "Fixed cost" with "0.00"
54 When I press "Add" 52 When I press "Add"
55 Then I should see "Bar" 53 Then I should see "Bar"
plugins/shopping_cart/features/features 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +/home/braulio/Projects/noosfero-ecosol/noosfero/config/plugins/shopping_cart/features
0 \ No newline at end of file 2 \ No newline at end of file
plugins/shopping_cart/lib/shopping_cart_plugin.rb
1 class ShoppingCartPlugin < Noosfero::Plugin 1 class ShoppingCartPlugin < Noosfero::Plugin
2 - include ModalHelper  
3 - include ActionView::Helpers::UrlHelper  
4 2
5 def self.plugin_name 3 def self.plugin_name
6 "Shopping Basket" 4 "Shopping Basket"
@@ -34,10 +32,6 @@ class ShoppingCartPlugin &lt; Noosfero::Plugin @@ -34,10 +32,6 @@ class ShoppingCartPlugin &lt; Noosfero::Plugin
34 buttons 32 buttons
35 end 33 end
36 34
37 - def controller  
38 - context  
39 - end  
40 -  
41 def add_to_cart_button item, options = {} 35 def add_to_cart_button item, options = {}
42 profile = item.profile 36 profile = item.profile
43 return unless profile.shopping_cart_enabled and item.available 37 return unless profile.shopping_cart_enabled and item.available
plugins/shopping_cart/lib/shopping_cart_plugin/cart_helper.rb
@@ -61,7 +61,8 @@ module ShoppingCartPlugin::CartHelper @@ -61,7 +61,8 @@ module ShoppingCartPlugin::CartHelper
61 61
62 def items_table(items, delivery_method = nil, by_mail = false) 62 def items_table(items, delivery_method = nil, by_mail = false)
63 # partial key needed in mailer context 63 # partial key needed in mailer context
64 - render partial: 'shopping_cart_plugin/items', locals: {order: build_order(items, delivery_method), by_mail: by_mail} 64 + order = @order || build_order(items, delivery_method)
  65 + render partial: 'shopping_cart_plugin/items', locals: {order: order, by_mail: by_mail}
65 end 66 end
66 67
67 def float_to_currency_cart value, environment, _options = {} 68 def float_to_currency_cart value, environment, _options = {}
plugins/shopping_cart/po/pt/shopping_cart.po
@@ -13,7 +13,7 @@ msgid &quot;&quot; @@ -13,7 +13,7 @@ msgid &quot;&quot;
13 msgstr "" 13 msgstr ""
14 "Project-Id-Version: 1.3~rc2-1-ga15645d\n" 14 "Project-Id-Version: 1.3~rc2-1-ga15645d\n"
15 "POT-Creation-Date: 2015-10-30 16:34-0300\n" 15 "POT-Creation-Date: 2015-10-30 16:34-0300\n"
16 -"PO-Revision-Date: 2015-09-29 20:23-0300\n" 16 +"PO-Revision-Date: 2015-11-15 18:17-0300\n"
17 "Last-Translator: Michal Čihař <michal@cihar.com>\n" 17 "Last-Translator: Michal Čihař <michal@cihar.com>\n"
18 "Language-Team: Portuguese <https://hosted.weblate.org/projects/noosfero/" 18 "Language-Team: Portuguese <https://hosted.weblate.org/projects/noosfero/"
19 "plugin-shopping-cart/pt/>\n" 19 "plugin-shopping-cart/pt/>\n"
@@ -32,6 +32,48 @@ msgstr &quot;Funcionalidade de cesto de compras para empreendimentos&quot; @@ -32,6 +32,48 @@ msgstr &quot;Funcionalidade de cesto de compras para empreendimentos&quot;
32 msgid "Shopping basket" 32 msgid "Shopping basket"
33 msgstr "Cesto de compras" 33 msgstr "Cesto de compras"
34 34
  35 +#: plugins/shopping_cart/lib/shopping_cart_plugin.rb:63
  36 +msgid "Purchase reports"
  37 +msgstr "Relatórios de compras"
  38 +
  39 +#: plugins/shopping_cart/lib/shopping_cart_plugin/purchase_order.rb:40
  40 +msgid "Opened"
  41 +msgstr "Aberto"
  42 +
  43 +#: plugins/shopping_cart/lib/shopping_cart_plugin/purchase_order.rb:40
  44 +msgid "Confirmed"
  45 +msgstr "Confirmado"
  46 +
  47 +#: plugins/shopping_cart/lib/shopping_cart_plugin/purchase_order.rb:40
  48 +msgid "Shipped"
  49 +msgstr "Enviado"
  50 +
  51 +#: plugins/shopping_cart/lib/shopping_cart_plugin/cart_helper.rb:41
  52 +msgid "Free delivery"
  53 +msgstr "Frete grátis"
  54 +
  55 +#: plugins/shopping_cart/lib/shopping_cart_plugin/cart_helper.rb:43
  56 +#: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb:7
  57 +msgid "Delivery"
  58 +msgstr "Entrega"
  59 +
  60 +#: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb:7
  61 +msgid "Delivery or pickup"
  62 +msgstr "Forma de retirada ou entrega"
  63 +
  64 +#: plugins/delivery/views/delivery_plugin/_order_select.html.slim
  65 +msgid "Instructions"
  66 +msgstr "Instruções"
  67 +
  68 +#: plugins/shopping_cart/lib/shopping_cart_plugin/cart_helper.rb:53
  69 +msgid "Item"
  70 +msgstr "Item"
  71 +
  72 +#: plugins/shopping_cart/lib/shopping_cart_plugin/cart_helper.rb:76
  73 +#: plugins/shopping_cart/views/cart.html.erb:7
  74 +msgid "Total:"
  75 +msgstr "Total:"
  76 +
35 #: plugins/shopping_cart/lib/shopping_cart_plugin/cart_helper.rb:11 77 #: plugins/shopping_cart/lib/shopping_cart_plugin/cart_helper.rb:11
36 msgid "Add to basket" 78 msgid "Add to basket"
37 msgstr "Adicionar ao cesto" 79 msgstr "Adicionar ao cesto"
@@ -112,9 +154,8 @@ msgid &quot;Shopping checkout&quot; @@ -112,9 +154,8 @@ msgid &quot;Shopping checkout&quot;
112 msgstr "Finalizar pedido" 154 msgstr "Finalizar pedido"
113 155
114 #: plugins/shopping_cart/views/public/_cart.html.erb:8 156 #: plugins/shopping_cart/views/public/_cart.html.erb:8
115 -#, fuzzy  
116 msgid "Basket is empty" 157 msgid "Basket is empty"
117 -msgstr "Cesto exibido." 158 +msgstr "Cesto vazio."
118 159
119 #: plugins/shopping_cart/views/public/_cart.html.erb:14 160 #: plugins/shopping_cart/views/public/_cart.html.erb:14
120 msgid "Basket" 161 msgid "Basket"
@@ -124,11 +165,6 @@ msgstr &quot;Cesto&quot; @@ -124,11 +165,6 @@ msgstr &quot;Cesto&quot;
124 msgid "Clean basket" 165 msgid "Clean basket"
125 msgstr "Limpar cesto" 166 msgstr "Limpar cesto"
126 167
127 -#: plugins/shopping_cart/views/public/_cart.html.erb:20  
128 -#: plugins/shopping_cart/views/shopping_cart_plugin/_items.html.erb:42  
129 -msgid "Total:"  
130 -msgstr "Total:"  
131 -  
132 #: plugins/shopping_cart/views/public/_cart.html.erb:23 168 #: plugins/shopping_cart/views/public/_cart.html.erb:23
133 msgid "Show basket" 169 msgid "Show basket"
134 msgstr "Mostrar cesto" 170 msgstr "Mostrar cesto"
@@ -163,7 +199,8 @@ msgstr &quot;Tem certeza que quer limpar seu cesto?&quot; @@ -163,7 +199,8 @@ msgstr &quot;Tem certeza que quer limpar seu cesto?&quot;
163 199
164 #: plugins/shopping_cart/views/public/_cart.html.erb:54 200 #: plugins/shopping_cart/views/public/_cart.html.erb:54
165 msgid "repeat order" 201 msgid "repeat order"
166 -msgstr "" 202 +msgstr "repetir pedido"
  203 +
167 204
168 #: plugins/shopping_cart/views/shopping_cart_plugin/_items.html.erb:7 205 #: plugins/shopping_cart/views/shopping_cart_plugin/_items.html.erb:7
169 msgid "Item name" 206 msgid "Item name"
@@ -179,39 +216,37 @@ msgid &quot;Hi %s!&quot; @@ -179,39 +216,37 @@ msgid &quot;Hi %s!&quot;
179 msgstr "Olá %s!" 216 msgstr "Olá %s!"
180 217
181 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:10 218 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:10
182 -#, fuzzy  
183 -msgid ""  
184 -"This is a notification e-mail about your buy request on the enterprise %s."  
185 -msgstr "Esse é um email de notificação sobre o seu pedido de compra em %s." 219 +msgid "This is a notification e-mail about your buy request on the enterprise %s."
  220 +msgstr "Esse é um email de notificação sobre o seu pedido de compra no empreendimento %s."
186 221
187 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:11 222 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:11
188 -#, fuzzy  
189 msgid "" 223 msgid ""
190 "The enterprise already received your buy request and will contact you for " 224 "The enterprise already received your buy request and will contact you for "
191 "confirmation." 225 "confirmation."
192 msgstr "" 226 msgstr ""
193 -"O fornecedor já recebeu o seu pedido de compra e deve te contactar para " 227 +"O empreendimento já recebeu o seu pedido de compra e entrará em contato para "
  228 +"confirmação."
  229 +
194 "confirmação." 230 "confirmação."
195 231
196 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:12 232 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:12
197 -#, fuzzy  
198 msgid "If you have any doubts about your order, write to us at: %s." 233 msgid "If you have any doubts about your order, write to us at: %s."
199 -msgstr "Se você tem alguma dúvida, nos contacte em: %s" 234 +msgstr "Se você tem alguma dúvida sobre o seu pedido, nos escreva: %s."
200 235
201 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:13 236 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:13
202 msgid "Review below the informations of your order:" 237 msgid "Review below the informations of your order:"
203 -msgstr "" 238 +msgstr "Abaixo, revise as informações do seu pedido:"
204 239
205 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:19 240 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:19
206 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:17 241 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:17
207 msgid "Phone number" 242 msgid "Phone number"
208 msgstr "" 243 msgstr ""
209 244
  245 +#: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/_orders_list.html.erb:35
210 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:22 246 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:22
211 #: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:22 247 #: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:22
212 -#, fuzzy  
213 msgid "Payment's method" 248 msgid "Payment's method"
214 -msgstr "Pagamento" 249 +msgstr "Forma de pagamento"
215 250
216 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:24 251 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:24
217 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:22 252 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:22
@@ -219,31 +254,30 @@ msgstr &quot;Pagamento&quot; @@ -219,31 +254,30 @@ msgstr &quot;Pagamento&quot;
219 msgid "shopping_cart|Change" 254 msgid "shopping_cart|Change"
220 msgstr "Troco para" 255 msgstr "Troco para"
221 256
222 -#: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:28  
223 -msgid "Delivery or pickup"  
224 -msgstr "Forma de retirada ou entrega" 257 +#: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/_products_list.html.erb:7
  258 +msgid "Quantity"
  259 +msgstr "Quantidade"
225 260
226 -#: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:63 261 +#: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:47
227 msgid "Here are the products you bought:" 262 msgid "Here are the products you bought:"
228 -msgstr "" 263 +msgstr "Aqui estão os produtos que você pediu:"
229 264
230 -#: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:67 265 +#: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:51
231 msgid "Thanks for buying with us!" 266 msgid "Thanks for buying with us!"
232 -msgstr "" 267 +msgstr "Obrigado por comprar conosco!"
233 268
234 -#: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:70  
235 -#: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:61 269 +#: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:54
  270 +#: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:51
236 msgid "A service of %s." 271 msgid "A service of %s."
237 -msgstr "" 272 +msgstr "Um serviço de %s."
238 273
239 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:10 274 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:10
240 -#, fuzzy  
241 msgid "This is a buy request made by %s." 275 msgid "This is a buy request made by %s."
242 -msgstr "[%s] Você tem um novo pedido de compra de %s." 276 +msgstr "Esse é um pedido de compra feito por %s."
243 277
244 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:11 278 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:11
245 msgid "Below follows the customer informations:" 279 msgid "Below follows the customer informations:"
246 -msgstr "" 280 +msgstr "Abaixo seguem as informações do consumidor:"
247 281
248 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:20 282 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:20
249 #: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:25 283 #: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:25
@@ -251,20 +285,18 @@ msgid &quot;Payment&quot; @@ -251,20 +285,18 @@ msgid &quot;Payment&quot;
251 msgstr "Pagamento" 285 msgstr "Pagamento"
252 286
253 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:55 287 #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:55
  288 +#: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:45
254 msgid "And here are the items bought by this customer:" 289 msgid "And here are the items bought by this customer:"
255 -msgstr "" 290 +msgstr "E aqui estão os itens pedidos por esse consumidor:"
256 291
257 -#: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:59 292 +#: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:49
258 msgid "If there are any problems with this email contact the admin of %s." 293 msgid "If there are any problems with this email contact the admin of %s."
259 msgstr "" 294 msgstr ""
  295 +"Se houver algum problema com esse email contacte o administrador de %s."
260 296
261 -#: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:4  
262 -msgid "haven't finished yet: back to shopping"  
263 -msgstr ""  
264 -  
265 -#: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:12 297 +#: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:9
266 msgid "Personal identification" 298 msgid "Personal identification"
267 -msgstr "" 299 +msgstr "Identificação pessoal"
268 300
269 #: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:15 301 #: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:15
270 msgid "Name" 302 msgid "Name"
@@ -290,36 +322,21 @@ msgstr &quot;Seu Pedido&quot; @@ -290,36 +322,21 @@ msgstr &quot;Seu Pedido&quot;
290 msgid "Send buy request" 322 msgid "Send buy request"
291 msgstr "Enviar pedido de compra" 323 msgstr "Enviar pedido de compra"
292 324
293 -#~ msgid "Purchase reports"  
294 -#~ msgstr "Relatórios de compras"  
295 -  
296 -#~ msgid "Opened"  
297 -#~ msgstr "Aberto"  
298 -  
299 -#~ msgid "Canceled"  
300 -#~ msgstr "Cancelado"  
301 -  
302 -#~ msgid "Confirmed"  
303 -#~ msgstr "Confirmado"  
304 -  
305 -#~ msgid "Shipped"  
306 -#~ msgstr "Enviado"  
307 -  
308 -#~ msgid "Free delivery"  
309 -#~ msgstr "Frete grátis"  
310 -  
311 -#~ msgid "Delivery"  
312 -#~ msgstr "Entrega"  
313 -  
314 -#~ msgid "Instructions"  
315 -#~ msgstr "Instruções" 325 +#: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:15
  326 +msgid "Address completion"
  327 +msgstr "Complemento (p.ex. apto)"
316 328
317 -#~ msgid "Option wasn't updated successfully."  
318 -#~ msgstr "Opção não foi atualizada com sucesso." 329 +#: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb
  330 +msgid "haven't finished yet: back to shopping"
  331 +msgstr "ainda não concluí: voltar às compras"
319 332
320 -#~ msgid "Request sent successfully. Check your email."  
321 -#~ msgstr "Requisição enviada com sucesso. Cheque seu email." 333 +#: plugins/shopping_cart/views/shopping_cart_plugin/_items.html.erb
  334 +msgid "Qtty"
  335 +msgstr "Qtde"
322 336
  337 +#: plugins/shopping_cart/views/shopping_cart_plugin/_items.html.erb
  338 +msgid "Unit price"
  339 +msgstr "Preço unitário"
323 #~ msgid "Can't join items from different enterprises." 340 #~ msgid "Can't join items from different enterprises."
324 #~ msgstr "Não é possível juntar itens de empreendimentos diferentes." 341 #~ msgstr "Não é possível juntar itens de empreendimentos diferentes."
325 342
plugins/shopping_cart/public/cart.js
@@ -63,12 +63,6 @@ function Cart(config) { @@ -63,12 +63,6 @@ function Cart(config) {
63 var input = $("input", li)[0]; 63 var input = $("input", li)[0];
64 input.lastValue = input.value; 64 input.lastValue = input.value;
65 input.productId = item.id; 65 input.productId = item.id;
66 - input.ajustSize = function() {  
67 - var len = this.value.toString().length;  
68 - if(len > 2) len--;  
69 - this.style.width = len+"em";  
70 - };  
71 - input.ajustSize();  
72 input.onchange = function() { 66 input.onchange = function() {
73 me.updateQuantity(this, this.productId, this.value); 67 me.updateQuantity(this, this.productId, this.value);
74 }; 68 };
plugins/shopping_cart/public/public 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +/home/braulio/Projects/noosfero-ecosol/noosfero/config/plugins/shopping_cart/public
0 \ No newline at end of file 2 \ No newline at end of file
plugins/shopping_cart/shopping_cart 0 → 120000
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +/home/braulio/Projects/noosfero-ecosol/noosfero/plugins/shopping_cart
0 \ No newline at end of file 2 \ No newline at end of file
plugins/shopping_cart/views/public/_cart.html.erb
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 <a href="cart:clean" onclick="cart.clean(); return false" class="cart-clean"><%=_('Clean basket')%></a> 16 <a href="cart:clean" onclick="cart.clean(); return false" class="cart-clean"><%=_('Clean basket')%></a>
17 <ul class="cart-items"> 17 <ul class="cart-items">
18 </ul> 18 </ul>
19 - <%= button 'cart', _('Shopping checkout'), "/plugin/shopping_cart/buy", :class => 'cart-buy modal-toggle' %> 19 + <%= button 'cart', _('Shopping checkout'), "/plugin/shopping_cart/buy", class: 'cart-buy' %>
20 <div class="cart-total"><%=_('Total:')%> <b></b></div> 20 <div class="cart-total"><%=_('Total:')%> <b></b></div>
21 </div> 21 </div>
22 <a href="#" onclick="cart.toggle(); return false" class="cart-toggle"> 22 <a href="#" onclick="cart.toggle(); return false" class="cart-toggle">
@@ -31,7 +31,7 @@ @@ -31,7 +31,7 @@
31 <div class="picture" style="background-image:url({{item.picture}})"></div> 31 <div class="picture" style="background-image:url({{item.picture}})"></div>
32 <span class="item-name">{{item.name}}</span> 32 <span class="item-name">{{item.name}}</span>
33 <div class="item-price"> 33 <div class="item-price">
34 - <input size="1" value="{{item.quantity}}" />{{item.priceTxt}} 34 + <input value="{{item.quantity}}" />{{item.priceTxt}}
35 </div> 35 </div>
36 </li> 36 </li>
37 </script> 37 </script>
plugins/shopping_cart/views/shopping_cart_plugin/_items.html.erb
@@ -3,45 +3,51 @@ @@ -3,45 +3,51 @@
3 style="<%= 'border-collapse: collapse' if by_mail %>"> 3 style="<%= 'border-collapse: collapse' if by_mail %>">
4 4
5 <tr> 5 <tr>
6 - <th>  
7 - <%= _('Item name') %> 6 + <th class='cart-table-item' <%= "align='center'" if by_mail %>>
  7 + <%= _('Item') %>
8 </th> 8 </th>
9 - <th>  
10 - <%= if by_mail then '&nbsp;#&nbsp;' else '#' end %> 9 + <th class='cart-table-quantity' <%= "align='center'" if by_mail %>>
  10 + <%= if by_mail then '&nbsp;'+_('Qtty')+'&nbsp;' else _('Qtty') end %>
11 </th> 11 </th>
12 - <th>  
13 - <%= _('Price') + " (#{@environment.currency_unit})" %> 12 + <th class='cart-table-price' <%= "align='center'" if by_mail %>>
  13 + <%= _('Unit price') + " (#{@environment.currency_unit})" %>
  14 + </th>
  15 + <th class='cart-table-price' <%= "align='center'" if by_mail %>>
  16 + <%= _('Total') + " (#{@environment.currency_unit})" %>
14 </th> 17 </th>
15 </tr> 18 </tr>
16 19
17 <% order.items.each do |item| %> 20 <% order.items.each do |item| %>
18 <tr> 21 <tr>
19 - <td> 22 + <td class='cart-table-item' <%= "align='left'" if by_mail %>>
20 <%= item.name %> 23 <%= item.name %>
21 </td> 24 </td>
22 - <td class='cart-table-quantity' align="<%= 'center' if by_mail %>">  
23 - <%= item.quantity_consumer_ordered %> 25 + <td class='cart-table-quantity' <%= "align='center'" if by_mail %>>
  26 + <%= "%03d" % item.quantity_consumer_ordered %>
  27 + </td>
  28 + <td class='cart-table-price' <%= "align='right'" if by_mail %>>
  29 + <%= get_price item.product, @environment, 1, unit: '' %>
24 </td> 30 </td>
25 - <td class='cart-table-price' align="<%= 'right' if by_mail %>"> 31 + <td class='cart-table-price' <%= "align='right'" if by_mail %>>
26 <%= get_price item.product, @environment, item.quantity_consumer_ordered, unit: '' %> 32 <%= get_price item.product, @environment, item.quantity_consumer_ordered, unit: '' %>
27 </td> 33 </td>
28 34
29 </tr> 35 </tr>
30 <% end %> 36 <% end %>
31 37
32 - <tr>  
33 - <td colspan=2 id='delivery-name'> 38 + <tr class='delivery-costs'>
  39 + <td colspan=3 id='delivery-name'>
34 <%= order.supplier_delivery.name if order.supplier_delivery %> 40 <%= order.supplier_delivery.name if order.supplier_delivery %>
35 </td> 41 </td>
36 - <td id='delivery-price' class="cart-table-price"> 42 + <td id='delivery-price' class="cart-table-price" <%= "align='right'" if by_mail %>>
37 <%= float_to_currency_cart order.supplier_delivery.cost(order.total_price), @environment, unit: '' if order.supplier_delivery %> 43 <%= float_to_currency_cart order.supplier_delivery.cost(order.total_price), @environment, unit: '' if order.supplier_delivery %>
38 </td> 44 </td>
39 </tr> 45 </tr>
40 46
41 - <th colspan=2 class="cart-table-total-label"> 47 + <th colspan=3 class="cart-table-total-label" <%= "align='right'" if by_mail %>>
42 <%= _('Total:') %> 48 <%= _('Total:') %>
43 </th> 49 </th>
44 - <th class="cart-table-total-value"> 50 + <th class="cart-table-total-value" <%= "align='right'" if by_mail %>>
45 <%= float_to_currency_cart order.total, @environment %> 51 <%= float_to_currency_cart order.total, @environment %>
46 </th> 52 </th>
47 </table> 53 </table>
plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb
1 <div id='cart-request-box' class="row"> 1 <div id='cart-request-box' class="row">
2 - <h1>  
3 - <%= _('Shopping checkout') %>  
4 - <%= button :back, _("haven't finished yet: back to shopping"), 'javascript:history.back()', class: 'cart-go-back' %>  
5 - </h1> 2 + <h1><%= _('Shopping checkout') %></h1>
  3 + <%= button :back, _("haven't finished yet: back to shopping"), 'javascript:history.back()', class: 'cart-go-back' %>
6 4
7 <%= form_for :order, url: {action: :send_request}, 5 <%= form_for :order, url: {action: :send_request},
8 html: {onsubmit: "return Cart.send_request(this)", id: 'cart-request-form'} do |f| %> 6 html: {onsubmit: "return Cart.send_request(this)", id: 'cart-request-form'} do |f| %>
9 7
10 - <div class="col-lg-6 col-md-6 col-sm-6"> 8 + <div class="col-lg-6 col-md-6 col-sm-6 col-lg-push-6 col-md-push-6 col-sm-push-6">
  9 + <fieldset>
  10 + <legend><%=s_('Your Order')%></legend>
  11 + <% supplier_delivery = @order.supplier_delivery || profile.delivery_methods.first %>
  12 + <%= items_table @cart[:items], @profile, supplier_delivery %>
  13 + </fieldset>
  14 + </div>
  15 +
  16 + <div class="col-lg-6 col-md-6 col-sm-6 col-lg-pull-6 col-md-pull-6 col-sm-pull-6">
11 <fieldset> 17 <fieldset>
12 <legend><%=_('Personal identification')%></legend> 18 <legend><%=_('Personal identification')%></legend>
13 19
@@ -30,21 +36,15 @@ @@ -30,21 +36,15 @@
30 <% if profile.delivery_methods.size > 0 %> 36 <% if profile.delivery_methods.size > 0 %>
31 <fieldset> 37 <fieldset>
32 <legend><%=_('Delivery or pickup method')%></legend> 38 <legend><%=_('Delivery or pickup method')%></legend>
  39 +
33 <%= render 'delivery_plugin/order_select', f: f, order: @order %> 40 <%= render 'delivery_plugin/order_select', f: f, order: @order %>
34 </fieldset> 41 </fieldset>
35 <% end %> 42 <% end %>
36 </div> 43 </div>
37 44
38 - <div class="col-lg-6 col-md-6 col-sm-6">  
39 - <fieldset>  
40 - <legend><%=s_('Your Order')%></legend>  
41 - <% supplier_delivery = @order.supplier_delivery || profile.delivery_methods.first %>  
42 - <%= items_table @cart[:items], supplier_delivery %>  
43 - </fieldset>  
44 - </div>  
45 -  
46 <div id="cart-form-actions" class="row"> 45 <div id="cart-form-actions" class="row">
47 - <%= submit_button(:send, _('Send buy request')) %> 46 + <%= button :back, _("haven't finished yet: back to shopping"), 'javascript:history.back()' %>
  47 + <%= submit_button(:send, _('Send buy request'), option:"success") %>
48 </div> 48 </div>
49 <% end %> 49 <% end %>
50 </div> 50 </div>
plugins/suppliers/controllers/myprofile/suppliers_plugin/basket_controller.rb
@@ -52,10 +52,12 @@ class SuppliersPlugin::BasketController &lt; MyProfileController @@ -52,10 +52,12 @@ class SuppliersPlugin::BasketController &lt; MyProfileController
52 extend HMVC::ClassMethods 52 extend HMVC::ClassMethods
53 hmvc SuppliersPlugin 53 hmvc SuppliersPlugin
54 54
55 - def default_url_options  
56 - # avoid rails' use_relative_controller!  
57 - {use_route: '/'} 55 + # inherit routes from core skipping use_relative_controller!
  56 + def url_for options
  57 + options[:controller] = "/#{options[:controller]}" if options.is_a? Hash and options[:controller] and not options[:controller].to_s.starts_with? '/'
  58 + super options
58 end 59 end
  60 + helper_method :url_for
59 61
60 def set_allowed_user 62 def set_allowed_user
61 @allowed_user = true 63 @allowed_user = true
plugins/suppliers/controllers/myprofile/suppliers_plugin/product_controller.rb
@@ -32,7 +32,7 @@ class SuppliersPlugin::ProductController &lt; MyProfileController @@ -32,7 +32,7 @@ class SuppliersPlugin::ProductController &lt; MyProfileController
32 32
33 def edit 33 def edit
34 @product = profile.products.supplied.find params[:id] 34 @product = profile.products.supplied.find params[:id]
35 - @product.update_attributes params["product_#{@product.id}"] 35 + @product.update params["product_#{@product.id}"]
36 end 36 end
37 37
38 def import 38 def import
@@ -79,6 +79,7 @@ class SuppliersPlugin::ProductController &lt; MyProfileController @@ -79,6 +79,7 @@ class SuppliersPlugin::ProductController &lt; MyProfileController
79 79
80 @supplier = SuppliersPlugin::Supplier.where(id: params[:supplier_id]).first if params[:supplier_id].present? 80 @supplier = SuppliersPlugin::Supplier.where(id: params[:supplier_id]).first if params[:supplier_id].present?
81 81
  82 + # FIXME: joins(:from_products) is hiding own products (except baskets)
82 @scope = profile.products.unarchived.joins :from_products, :suppliers 83 @scope = profile.products.unarchived.joins :from_products, :suppliers
83 @scope = SuppliersPlugin::BaseProduct.search_scope @scope, params 84 @scope = SuppliersPlugin::BaseProduct.search_scope @scope, params
84 @products_count = @scope.supplied_for_count.count 85 @products_count = @scope.supplied_for_count.count
@@ -95,9 +96,11 @@ class SuppliersPlugin::ProductController &lt; MyProfileController @@ -95,9 +96,11 @@ class SuppliersPlugin::ProductController &lt; MyProfileController
95 extend HMVC::ClassMethods 96 extend HMVC::ClassMethods
96 hmvc SuppliersPlugin 97 hmvc SuppliersPlugin
97 98
98 - def default_url_options  
99 - # avoid rails' use_relative_controller!  
100 - {use_route: '/'} 99 + # inherit routes from core skipping use_relative_controller!
  100 + def url_for options
  101 + options[:controller] = "/#{options[:controller]}" if options.is_a? Hash and options[:controller] and not options[:controller].to_s.starts_with? '/'
  102 + super options
101 end 103 end
  104 + helper_method :url_for
102 105
103 end 106 end
plugins/suppliers/controllers/myprofile/suppliers_plugin_myprofile_controller.rb
@@ -21,7 +21,7 @@ class SuppliersPluginMyprofileController &lt; MyProfileController @@ -21,7 +21,7 @@ class SuppliersPluginMyprofileController &lt; MyProfileController
21 end 21 end
22 22
23 def new 23 def new
24 - @new_supplier.update_attributes! params[:supplier] 24 + @new_supplier.update! params[:supplier]
25 @supplier = @new_supplier 25 @supplier = @new_supplier
26 session[:notice] = t('controllers.myprofile.supplier_created') 26 session[:notice] = t('controllers.myprofile.supplier_created')
27 end 27 end
@@ -33,7 +33,7 @@ class SuppliersPluginMyprofileController &lt; MyProfileController @@ -33,7 +33,7 @@ class SuppliersPluginMyprofileController &lt; MyProfileController
33 33
34 def edit 34 def edit
35 @supplier = profile.suppliers.find params[:id] 35 @supplier = profile.suppliers.find params[:id]
36 - @supplier.update_attributes params[:supplier] 36 + @supplier.update params[:supplier]
37 end 37 end
38 38
39 def margin_change 39 def margin_change
@@ -58,8 +58,8 @@ class SuppliersPluginMyprofileController &lt; MyProfileController @@ -58,8 +58,8 @@ class SuppliersPluginMyprofileController &lt; MyProfileController
58 58
59 def search 59 def search
60 @query = params[:query].downcase 60 @query = params[:query].downcase
61 - @enterprises = environment.enterprises.enabled.public.all limit: 12, order: 'name ASC',  
62 - conditions: ['LOWER(name) LIKE ? OR LOWER(name) LIKE ? OR identifier LIKE ?', "#{@query}%", "% #{@query}%", "#{@query}%"] 61 + @enterprises = environment.enterprises.enabled.is_public.limit(12).order('name ASC').
  62 + where('name ILIKE ? OR name ILIKE ? OR identifier LIKE ?', "#{@query}%", "% #{@query}%", "#{@query}%")
63 @enterprises -= profile.suppliers.collect(&:profile) 63 @enterprises -= profile.suppliers.collect(&:profile)
64 end 64 end
65 65
plugins/suppliers/lib/default_delegate.rb
@@ -15,6 +15,9 @@ module DefaultDelegate @@ -15,6 +15,9 @@ module DefaultDelegate
15 15
16 # TODO: add some documentation about the methods being added 16 # TODO: add some documentation about the methods being added
17 def default_delegate field, options = {} 17 def default_delegate field, options = {}
  18 + class_attribute :default_delegate_enable unless respond_to? :default_delegate_enable
  19 + self.default_delegate_enable = true if self.default_delegate_enable.nil?
  20 +
18 # rake db:migrate run? 21 # rake db:migrate run?
19 return unless self.table_exists? 22 return unless self.table_exists?
20 23
@@ -91,6 +94,8 @@ module DefaultDelegate @@ -91,6 +94,8 @@ module DefaultDelegate
91 end 94 end
92 95
93 define_method "#{field}_with_default" do 96 define_method "#{field}_with_default" do
  97 + return self.send own_field unless self.default_delegate_enable
  98 +
94 if self.send default_setting 99 if self.send default_setting
95 # delegated_field may return nil, so use own instead 100 # delegated_field may return nil, so use own instead
96 # this is the case with some associations (e.g. Product#product_qualifiers) 101 # this is the case with some associations (e.g. Product#product_qualifiers)
@@ -101,6 +106,8 @@ module DefaultDelegate @@ -101,6 +106,8 @@ module DefaultDelegate
101 end 106 end
102 end 107 end
103 define_method "#{field}_with_default=" do |*args| 108 define_method "#{field}_with_default=" do |*args|
  109 + return self.send "#{own_field}=", *args unless self.default_delegate_enable
  110 +
104 own = self.send "#{own_field}=", *args 111 own = self.send "#{own_field}=", *args
105 # break/set the default setting automatically, used for interfaces 112 # break/set the default setting automatically, used for interfaces
106 # that don't have the default setting (e.g. manage_products) 113 # that don't have the default setting (e.g. manage_products)