Commit d663bb672ef8861404f5d2b1d9b025aeaf7dc3cd
1 parent
0f263193
Exists in
master
and in
20 other branches
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 | 14 | |
15 | 15 | def edit |
16 | 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 | 18 | render partial: 'list' |
19 | 19 | else |
20 | 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 | 8 | before_filter :load_owner |
9 | 9 | |
10 | 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 | 18 | end |
13 | 19 | |
14 | 20 | def new | ... | ... |
plugins/delivery/db/migrate/20150623125525_add_distribution_margin_to_delivery_plugin_method.rb
0 → 100644
... | ... | @@ -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 | 9 | methods = options[:methods] || profile.delivery_methods |
10 | 10 | |
11 | 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 | 13 | text = if cost.present? then "#{method.name} (#{cost})" else method.name end |
14 | 14 | |
15 | 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 | 18 | end.join |
19 | 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 | 30 | def delivery_context |
22 | 31 | @delivery_context || 'delivery_plugin/admin_method' |
23 | 32 | end | ... | ... |
plugins/delivery/lib/ext/profile.rb
1 | 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 | 8 | end |
9 | +end | ... | ... |
plugins/delivery/locales/en-US.yml
... | ... | @@ -12,16 +12,23 @@ |
12 | 12 | delivery_type: 'Type' |
13 | 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 | 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 | 25 | instructions: Description |
19 | 26 | instructions_help: "Write the address and other important informations about the place of this consumption place.<br> This text will be available" |
20 | 27 | views: |
21 | - delivery_option: | |
22 | - select: | |
28 | + delivery_option: | |
29 | + select: | |
23 | 30 | add: Add selected |
24 | - _select_content: | |
31 | + _select_content: | |
25 | 32 | add: Add option |
26 | 33 | add_new: "add new" |
27 | 34 | are_you_sure_you_want: "Are you sure you want to remove?" |
... | ... | @@ -29,14 +36,14 @@ |
29 | 36 | choose_a_delivery_met: "Choose a delivery method from the list" |
30 | 37 | edit_this: "Edit" |
31 | 38 | remove_method: "Remove" |
32 | - _show: | |
39 | + _show: | |
33 | 40 | x: X |
34 | - select: | |
41 | + select: | |
35 | 42 | add_a_delivery_method: "Add a delivery method to the Orders' Cycle" |
36 | 43 | method: |
37 | 44 | index: |
38 | 45 | new: "New delivery or pickup" |
39 | - edit: | |
46 | + edit: | |
40 | 47 | add: Add |
41 | 48 | back: back |
42 | 49 | save: Save | ... | ... |
plugins/delivery/locales/pt-BR.yml
... | ... | @@ -13,15 +13,21 @@ |
13 | 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 | 14 | name: Nome |
15 | 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 | 24 | instructions: Descrição |
19 | 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 | 26 | views: |
21 | - delivery_option: | |
22 | - select: | |
27 | + delivery_option: | |
28 | + select: | |
23 | 29 | add: "Adicionar selecionados" |
24 | - _select_content: | |
30 | + _select_content: | |
25 | 31 | add: Adicionar opção |
26 | 32 | add_new: "adicionar novo" |
27 | 33 | are_you_sure_you_want: "Tem certeza de que quer remover?" |
... | ... | @@ -29,14 +35,14 @@ |
29 | 35 | choose_a_delivery_met: "Escolha um método de entrega da lista" |
30 | 36 | edit_this: Editar |
31 | 37 | remove_method: "Remover" |
32 | - _show: | |
38 | + _show: | |
33 | 39 | x: X |
34 | - select: | |
40 | + select: | |
35 | 41 | add_a_delivery_method: "Adicionar um método de entrega ao ciclo de pedidos" |
36 | 42 | method: |
37 | 43 | index: |
38 | 44 | new: "Nova forma de entrega ou retirada" |
39 | - edit: | |
45 | + edit: | |
40 | 46 | add: Adicionar |
41 | 47 | back: voltar |
42 | 48 | save: Salvar | ... | ... |
plugins/delivery/models/delivery_plugin/method.rb
1 | 1 | class DeliveryPlugin::Method < ActiveRecord::Base |
2 | 2 | |
3 | - extend CurrencyHelper::ClassMethods | |
4 | - | |
5 | 3 | Types = ['pickup', 'deliver'] |
6 | 4 | |
7 | 5 | # see also: Profile::LOCATION_FIELDS |
... | ... | @@ -10,7 +8,7 @@ class DeliveryPlugin::Method < ActiveRecord::Base |
10 | 8 | ].map(&:to_sym) |
11 | 9 | |
12 | 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 | 13 | belongs_to :profile |
16 | 14 | |
... | ... | @@ -20,8 +18,14 @@ class DeliveryPlugin::Method < ActiveRecord::Base |
20 | 18 | validates_presence_of :name |
21 | 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 | 30 | def pickup? |
27 | 31 | self.delivery_type == 'pickup' |
... | ... | @@ -30,22 +34,40 @@ class DeliveryPlugin::Method < ActiveRecord::Base |
30 | 34 | self.delivery_type == 'deliver' |
31 | 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 | 43 | if order_price.present? and order_price.nonzero? and self.free_over_price.present? and self.free_over_price.nonzero? |
35 | 44 | order_price <= self.free_over_price |
36 | 45 | else |
37 | 46 | self.fixed_cost.present? and self.fixed_cost.nonzero? |
38 | 47 | end |
39 | 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 | 61 | def free? order_price=nil |
41 | 62 | !self.has_cost? |
42 | 63 | end |
43 | 64 | |
44 | 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 | 70 | end |
47 | - has_currency :fixed_cost | |
48 | - has_currency :free_over_price | |
49 | 71 | has_currency :cost |
50 | 72 | |
51 | 73 | protected | ... | ... |
plugins/delivery/public/stylesheets/delivery.scss
... | ... | @@ -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 @@ |
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 @@ |
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 | 2 | - edition = true if edition.nil? |
3 | 3 | - readonly = !edition |
4 | 4 | |
5 | -div.order-delivery-select | |
5 | +div.order-delivery-select id='order-#{order.id}' | |
6 | 6 | |
7 | 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 | 12 | = labelled_field f, :name, t('delivery_plugin.models.method.name'), f.text_field(:name), |
13 | 13 | help: t('delivery_plugin.models.method.name_help') |
14 | 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 | 33 | div |
24 | 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 | 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
plugins/delivery/views/delivery_plugin/admin_options/_new.js.erb
plugins/delivery/views/delivery_plugin/admin_options/select_all.js.erb
0 → 100644
plugins/orders/controllers/myprofile/orders_plugin_admin_controller.rb
... | ... | @@ -43,8 +43,8 @@ class OrdersPluginAdminController < MyProfileController |
43 | 43 | @orders_method = if @actor_name == :supplier then :sales else :purchases end |
44 | 44 | |
45 | 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 | 49 | respond_to do |format| |
50 | 50 | format.js{ render 'orders_plugin_admin/edit' } | ... | ... |
plugins/orders/controllers/myprofile/orders_plugin_admin_item_controller.rb
... | ... | @@ -15,7 +15,7 @@ class OrdersPluginAdminItemController < MyProfileController |
15 | 15 | @actor_name = params[:actor_name].to_sym |
16 | 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 | 19 | end |
20 | 20 | |
21 | 21 | def add_search | ... | ... |
plugins/orders/controllers/myprofile/orders_plugin_item_controller.rb
... | ... | @@ -23,7 +23,7 @@ class OrdersPluginItemController < MyProfileController |
23 | 23 | |
24 | 24 | if params[:item].present? and set_quantity_consumer_ordered params[:item][:quantity_consumer_ordered] |
25 | 25 | params[:item][:quantity_consumer_ordered] = @quantity_consumer_ordered |
26 | - @item.update_attributes! params[:item] | |
26 | + @item.update! params[:item] | |
27 | 27 | end |
28 | 28 | end |
29 | 29 | ... | ... |
plugins/orders/controllers/profile/orders_plugin_order_controller.rb
... | ... | @@ -8,6 +8,7 @@ class OrdersPluginOrderController < ProfileController |
8 | 8 | before_filter :load_order, except: [:new] |
9 | 9 | before_filter :check_access, only: [:confirm, :remove, :cancel] |
10 | 10 | before_filter :set_actor_name |
11 | + before_filter :disable_purechat | |
11 | 12 | |
12 | 13 | helper OrdersPlugin::TranslationHelper |
13 | 14 | helper OrdersPlugin::DisplayHelper |
... | ... | @@ -19,7 +20,7 @@ class OrdersPluginOrderController < ProfileController |
19 | 20 | |
20 | 21 | def load_order |
21 | 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 | 24 | end |
24 | 25 | |
25 | 26 | def check_access access = 'view' |
... | ... | @@ -40,4 +41,8 @@ class OrdersPluginOrderController < ProfileController |
40 | 41 | extend HMVC::ClassMethods |
41 | 42 | hmvc OrdersPlugin, orders_context: OrdersPlugin |
42 | 43 | |
44 | + def disable_purechat | |
45 | + @disable_purechat = true | |
46 | + end | |
47 | + | |
43 | 48 | end | ... | ... |
plugins/orders/db/migrate/20150627232432_add_status_to_orders_plugin_item.rb
0 → 100644
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 | 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 | 7 | # cannot use :order because of months/years named_scope |
16 | 8 | has_many :orders, class_name: 'OrdersPlugin::Sale', foreign_key: :profile_id |
17 | 9 | has_many :sales, class_name: 'OrdersPlugin::Sale', foreign_key: :profile_id |
18 | 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 | 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 | 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 | 31 | def sales_all_consumers |
29 | 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 | 34 | consumers.uniq |
32 | 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 | 40 | end |
38 | 41 | |
39 | 42 | def self.create_orders_manager_role env_id | ... | ... |
plugins/orders/lib/ext/session_store.rb
plugins/orders/lib/orders_plugin/display_helper.rb
... | ... | @@ -2,6 +2,8 @@ module OrdersPlugin::DisplayHelper |
2 | 2 | |
3 | 3 | protected |
4 | 4 | |
5 | + include HelpHelper | |
6 | + | |
5 | 7 | include OrdersPlugin::TranslationHelper |
6 | 8 | include OrdersPlugin::PriceHelper |
7 | 9 | include OrdersPlugin::DateHelper |
... | ... | @@ -9,7 +11,8 @@ module OrdersPlugin::DisplayHelper |
9 | 11 | include OrdersPlugin::TableHelper |
10 | 12 | include OrdersPlugin::AdminHelper |
11 | 13 | include OrdersPlugin::JavascriptHelper |
12 | - include HelpHelper | |
14 | + | |
15 | + include DeliveryPlugin::DisplayHelper | |
13 | 16 | |
14 | 17 | # come on, you can't replace a rails api method (button_to_function was)! |
15 | 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 | 6 | help = options.delete(:help) |
7 | 7 | content_tag :div, |
8 | 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 | 10 | content_tag('div', field_html, class: 'field-box') + |
11 | 11 | content_tag('div', '', style: 'clear: both'), |
12 | 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 < Noosfero::Plugin::MailerBase |
4 | 4 | |
5 | 5 | helper ApplicationHelper |
6 | 6 | helper OrdersPlugin::DisplayHelper |
7 | - helper OrdersPlugin::DateHelper | |
8 | - helper OrdersPlugin::TranslationHelper | |
9 | 7 | |
10 | 8 | attr_accessor :environment |
11 | 9 | attr_accessor :profile |
... | ... | @@ -82,4 +80,10 @@ class OrdersPlugin::Mailer < Noosfero::Plugin::MailerBase |
82 | 80 | end |
83 | 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 | 89 | end | ... | ... |
plugins/orders/lib/orders_plugin/report.rb
... | ... | @@ -142,6 +142,7 @@ module OrdersPlugin::Report |
142 | 142 | productsStart = sbs+5 |
143 | 143 | productsEnd = 0 |
144 | 144 | selled_sum = 0 |
145 | + total_price_without_margin = 0 | |
145 | 146 | orders.each do |order| |
146 | 147 | |
147 | 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 | 189 | style: [default,default,default,default,default,currency,currency], |
189 | 190 | formula_values: [nil,nil,nil,nil,nil,nil,formula_value_s] |
190 | 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 | 194 | sbe += 1 |
193 | 195 | sum += formula_value |
... | ... | @@ -200,12 +202,11 @@ module OrdersPlugin::Report |
200 | 202 | sbs = sbe + 2 |
201 | 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 | 211 | sheet.column_widths 15,30,30,9,8,10,11 |
211 | 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 | 8 | orders_plugin: |
4 | 9 | terms: |
... | ... | @@ -77,6 +82,7 @@ |
77 | 82 | supplier: "%{terms.supplier.singular.capitalize}" |
78 | 83 | total_parcel_value: "Total value using stock" |
79 | 84 | total_selled_value: "Total selled value" |
85 | + total_price_without_margin: "Total price without margin" | |
80 | 86 | total_value: "Total Value" |
81 | 87 | un: un. |
82 | 88 | value: value |
... | ... | @@ -299,8 +305,8 @@ |
299 | 305 | supplier_product: "%{terms.supplier.singular.capitalize}/Product" |
300 | 306 | total: "TOTAL:" |
301 | 307 | |
302 | -'en_US': | |
308 | +en_US: | |
303 | 309 | <<: *en-US |
304 | -'en': | |
310 | +en: | |
305 | 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 | 8 | orders_plugin: |
4 | 9 | terms: |
... | ... | @@ -78,6 +83,7 @@ |
78 | 83 | supplier: "%{terms.supplier.singular.capitalize}" |
79 | 84 | total_parcel_value: "Valor total usando estoque" |
80 | 85 | total_selled_value: "Valor total vendido" |
86 | + total_price_without_margin: "Valor total sem a margem" | |
81 | 87 | total_value: "total pago" |
82 | 88 | un: un. |
83 | 89 | value: Valor |
... | ... | @@ -299,8 +305,8 @@ |
299 | 305 | supplier_product: "%{terms.supplier.singular.capitalize}/Produto" |
300 | 306 | total: "TOTAL:" |
301 | 307 | |
302 | -'pt_BR': | |
308 | +pt_BR: | |
303 | 309 | <<: *pt-BR |
304 | -'pt': | |
310 | +pt: | |
305 | 311 | <<: *pt-BR |
306 | 312 | ... | ... |
plugins/orders/models/orders_plugin/item.rb
... | ... | @@ -7,6 +7,13 @@ class OrdersPlugin::Item < ActiveRecord::Base |
7 | 7 | # flag used by items to compare them with products |
8 | 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 | 17 | # should be Order, but can't reference it here so it would create a cyclic reference |
11 | 18 | StatusAccessMap = { |
12 | 19 | 'ordered' => :consumer, |
... | ... | @@ -28,9 +35,9 @@ class OrdersPlugin::Item < ActiveRecord::Base |
28 | 35 | |
29 | 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 | 42 | belongs_to :product |
36 | 43 | has_one :supplier, through: :product |
... | ... | @@ -40,28 +47,30 @@ class OrdersPlugin::Item < ActiveRecord::Base |
40 | 47 | |
41 | 48 | # FIXME: don't work because of load order |
42 | 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 | 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 | 58 | has_many :suppliers, through: :product |
59 | + has_one :supplier, through: :product | |
48 | 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 | 65 | default_scope include: [:product] |
60 | 66 | |
61 | 67 | validate :has_order |
62 | 68 | validates_presence_of :product |
69 | + validates_inclusion_of :status, in: DbStatuses | |
63 | 70 | |
71 | + before_validation :set_defaults | |
64 | 72 | before_save :save_calculated_prices |
73 | + before_save :step_status | |
65 | 74 | before_create :sync_fields |
66 | 75 | |
67 | 76 | # utility for other classes |
... | ... | @@ -104,6 +113,9 @@ class OrdersPlugin::Item < ActiveRecord::Base |
104 | 113 | def price |
105 | 114 | self[:price] || (self.product.price_with_discount || 0 rescue nil) |
106 | 115 | end |
116 | + def price_without_margins | |
117 | + self.product.price_without_margins rescue self.price | |
118 | + end | |
107 | 119 | def unit |
108 | 120 | self.product.unit |
109 | 121 | end |
... | ... | @@ -121,8 +133,15 @@ class OrdersPlugin::Item < ActiveRecord::Base |
121 | 133 | end |
122 | 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 | 145 | end |
127 | 146 | |
128 | 147 | # product used for comparizon when repeating an order |
... | ... | @@ -144,13 +163,13 @@ class OrdersPlugin::Item < ActiveRecord::Base |
144 | 163 | |
145 | 164 | def status_quantity_field |
146 | 165 | @status_quantity_field ||= begin |
147 | - status = StatusDataMap[self.order.status] || 'consumer_ordered' | |
166 | + status = StatusDataMap[self.status] || 'consumer_ordered' | |
148 | 167 | "quantity_#{status}" |
149 | 168 | end |
150 | 169 | end |
151 | 170 | def status_price_field |
152 | 171 | @status_price_field ||= begin |
153 | - status = StatusDataMap[self.order.status] || 'consumer_ordered' | |
172 | + status = StatusDataMap[self.status] || 'consumer_ordered' | |
154 | 173 | "price_#{status}" |
155 | 174 | end |
156 | 175 | end |
... | ... | @@ -184,10 +203,10 @@ class OrdersPlugin::Item < ActiveRecord::Base |
184 | 203 | |
185 | 204 | def quantity_price_data actor_name |
186 | 205 | data = {flags: {}} |
187 | - statuses = OrdersPlugin::Order::Statuses | |
206 | + statuses = ::OrdersPlugin::Order::Statuses | |
188 | 207 | statuses_data = data[:statuses] = {} |
189 | 208 | |
190 | - current = statuses.index(self.order.status) || 0 | |
209 | + current = statuses.index(self.status) || 0 | |
191 | 210 | next_status = self.order.next_status actor_name |
192 | 211 | next_index = statuses.index(next_status) || current + 1 |
193 | 212 | goto_next = actor_name == StatusAccessMap[next_status] |
... | ... | @@ -266,8 +285,11 @@ class OrdersPlugin::Item < ActiveRecord::Base |
266 | 285 | |
267 | 286 | # Set access |
268 | 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 | 293 | #status_data[:flags][:editable] = true if status_data[:access] == actor_name and (status_data[:flags][:admin] or self.order.open?) |
272 | 294 | end |
273 | 295 | |
... | ... | @@ -279,6 +301,14 @@ class OrdersPlugin::Item < ActiveRecord::Base |
279 | 301 | self.save_calculated_prices |
280 | 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 | 312 | protected |
283 | 313 | |
284 | 314 | def save_calculated_prices |
... | ... | @@ -288,6 +318,17 @@ class OrdersPlugin::Item < ActiveRecord::Base |
288 | 318 | end |
289 | 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 | 332 | def has_order |
292 | 333 | self.order or self.sale or self.purchase |
293 | 334 | end | ... | ... |
plugins/orders/models/orders_plugin/order.rb
1 | 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 | 11 | # oh, we need a payments plugin! |
11 | 12 | PaymentMethods = { |
... | ... | @@ -31,18 +32,14 @@ class OrdersPlugin::Order < ActiveRecord::Base |
31 | 32 | ] |
32 | 33 | |
33 | 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 | 38 | StatusesByActor = { |
38 | 39 | consumer: StatusAccessMap.map{ |s, a| s if a == :consumer }.compact, |
39 | 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 | 43 | attr_accessible :status, :consumer, :profile, |
47 | 44 | :supplier_delivery_id, :consumer_delivery_id, :supplier_delivery_data, :consumer_delivery_data |
48 | 45 | |
... | ... | @@ -51,17 +48,17 @@ class OrdersPlugin::Order < ActiveRecord::Base |
51 | 48 | belongs_to :supplier, foreign_key: :profile_id, class_name: 'Profile' |
52 | 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 | 54 | has_many :products, through: :items |
58 | 55 | |
59 | 56 | belongs_to :supplier_delivery, class_name: 'DeliveryPlugin::Method' |
60 | 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 | 63 | scope :of_session, -> session_id { where session_id: session_id } |
67 | 64 | scope :of_user, -> session_id, consumer_id=nil do |
... | ... | @@ -73,53 +70,50 @@ class OrdersPlugin::Order < ActiveRecord::Base |
73 | 70 | |
74 | 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 | 107 | validates_presence_of :profile |
115 | 108 | # consumer is optional, as orders can be made by unlogged users |
116 | 109 | validates_inclusion_of :status, in: DbStatuses |
117 | 110 | |
118 | 111 | before_validation :check_status |
112 | + before_validation :change_status | |
119 | 113 | after_save :send_notifications |
120 | 114 | |
121 | 115 | extend CodeNumbering::ClassMethods |
122 | - code_numbering :code, scope: proc{ self.profile.orders } | |
116 | + code_numbering :code, scope: -> { self.profile.orders } | |
123 | 117 | |
124 | 118 | serialize :data |
125 | 119 | |
... | ... | @@ -165,17 +159,17 @@ class OrdersPlugin::Order < ActiveRecord::Base |
165 | 159 | # / Items |
166 | 160 | # / \ OfferedProduct (column product_id) |
167 | 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 | 163 | # for order outside cycle we have |
170 | 164 | # / Items |
171 | 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 | 168 | # *suppliers usually don't distribute using cycles, so they only have Product |
175 | 169 | # |
176 | 170 | def self.supplier_products_by_suppliers orders |
177 | 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 | 173 | items.each do |item| |
180 | 174 | if item.sources_supplier_products.present? |
181 | 175 | item.sources_supplier_products.each do |source_sp| |
... | ... | @@ -358,15 +352,14 @@ class OrdersPlugin::Order < ActiveRecord::Base |
358 | 352 | |
359 | 353 | # total_price considering last state |
360 | 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 | 358 | else |
364 | - status = self.status | |
359 | + data = StatusDataMap[self.status] || StatusDataMap[Statuses.first] | |
360 | + price = "price_#{data}".to_sym | |
365 | 361 | end |
366 | 362 | |
367 | - data = StatusDataMap[status] || StatusDataMap[Statuses.first] | |
368 | - price = "price_#{data}".to_sym | |
369 | - | |
370 | 363 | items ||= (self.ordered_items rescue nil) || self.items |
371 | 364 | items.collect(&price).inject(0){ |sum, p| sum + p.to_f } |
372 | 365 | end |
... | ... | @@ -379,7 +372,8 @@ class OrdersPlugin::Order < ActiveRecord::Base |
379 | 372 | end |
380 | 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 | 377 | return if (Statuses.index(to_status) <= Statuses.index(from_status) rescue true) |
384 | 378 | |
385 | 379 | from_data = StatusDataMap[from_status] |
... | ... | @@ -405,15 +399,22 @@ class OrdersPlugin::Order < ActiveRecord::Base |
405 | 399 | self.status ||= 'draft' |
406 | 400 | # backwards compatibility |
407 | 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 | 412 | if self.status_on? 'ordered' |
412 | 413 | Statuses.each do |status| |
413 | 414 | self.send "#{self.status}_at=", Time.now if self.status_was != status and self.status == status |
414 | 415 | end |
415 | 416 | else |
416 | - # for draft, planned, forgotten, cancelled, etc | |
417 | + # status rewind for draft, planned, forgotten, cancelled, etc | |
417 | 418 | Statuses.each do |status| |
418 | 419 | self.send "#{status}_at=", nil |
419 | 420 | end | ... | ... |
plugins/orders/models/orders_plugin/sale.rb
1 | 1 | class OrdersPlugin::Sale < OrdersPlugin::Order |
2 | 2 | |
3 | + before_validation :fill_default_supplier_delivery | |
4 | + | |
3 | 5 | def orders_name |
4 | 6 | 'sales' |
5 | 7 | end |
... | ... | @@ -19,6 +21,17 @@ class OrdersPlugin::Sale < OrdersPlugin::Order |
19 | 21 | has_number_with_locale :purchase_quantity_total |
20 | 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 | 35 | protected |
23 | 36 | |
24 | 37 | end | ... | ... |
plugins/orders/public/javascripts/orders.js
... | ... | @@ -139,21 +139,12 @@ orders = { |
139 | 139 | }, |
140 | 140 | }, |
141 | 141 | |
142 | - set_orders_container_max_height: function() | |
142 | + setOrderMaxHeight: function() | |
143 | 143 | { |
144 | 144 | ordersH = $(window).height(); |
145 | - ordersH -= 100 | |
146 | 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 | 150 | daterangepicker: { |
... | ... | @@ -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/stylesheets/_field.scss
plugins/orders/public/stylesheets/_items.scss
plugins/orders/public/stylesheets/orders.scss
... | ... | @@ -9,10 +9,10 @@ |
9 | 9 | @import 'items'; |
10 | 10 | |
11 | 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 | 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 | 18 | .orders-admin-index { |
... | ... | @@ -125,14 +125,13 @@ |
125 | 125 | } |
126 | 126 | |
127 | 127 | .order-view { |
128 | - | |
129 | - &, .order-items-scroll, .order-items, .item { | |
128 | + &, .order-items, .item { | |
130 | 129 | width: $order-items-width; |
131 | 130 | } |
132 | 131 | &.admin { |
133 | 132 | width: $order-items-admin-width; |
134 | 133 | |
135 | - .order-items-scroll, .order-items, .item { | |
134 | + .order-items, .item { | |
136 | 135 | width: $order-items-admin-width - 2*$border; |
137 | 136 | } |
138 | 137 | } |
... | ... | @@ -160,16 +159,14 @@ |
160 | 159 | |
161 | 160 | margin: 0; |
162 | 161 | border: none; |
162 | + | |
163 | + overflow: hidden; | |
164 | + overflow-y: auto; | |
165 | + | |
163 | 166 | &.admin { |
164 | 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 | 170 | .order-header { |
174 | 171 | padding: $half-padding $padding; |
175 | 172 | border-bottom: $border solid black; |
... | ... | @@ -223,7 +220,10 @@ |
223 | 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 | } | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +require File.dirname(__FILE__) + '/../../../test/test_helper' | ... | ... |
... | ... | @@ -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 | ... | ... |
... | ... | @@ -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 @@ |
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 | 1 | = content_for :head do |
2 | 2 | = stylesheet_link_tag '/assets/plugins/orders/stylesheets/daterangepicker-bs3.css' |
3 | 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 | 5 | = javascript_include_tag '/assets/plugins/orders/javascripts/moment-with-locales.js' |
6 | 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 | 3 | div= render 'orders_plugin/shared/daterangepicker/init' |
4 | 4 | |
5 | 5 | .field.state |
6 | - label for="status" = t'views.filter.status' | |
6 | + label= t'views.filter.status' | |
7 | 7 | div= select_tag :status, |
8 | 8 | options_for_select([[t('views.filter.all'), ""]] + OrdersPlugin::Order::StatusText.map{ |id, name| [t(name), id] }, params[:status]) |
9 | 9 | |
10 | 10 | .field.code |
11 | - label for="code" = t'views.filter.code' | |
11 | + label= t'views.filter.code' | |
12 | 12 | div= text_field_tag :code, params[:code] |
13 | 13 | |
14 | 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 | 16 | div= select_tag "#{actor_name}_id", |
17 | 17 | options_for_select([[t('views.filter.all'), ""]] + actors.map{ |a| [a.name, a.id] }, params["#{actor_name}_id"]) |
18 | 18 | |
19 | 19 | .field.delivery |
20 | - label for="delivery_method_id" = t'views.filter.delivery' | |
20 | + label= t'views.filter.delivery' | |
21 | 21 | div= select_tag :delivery_method_id, |
22 | 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 | 12 | |
13 | 13 | <% if @purchases.present? %> |
14 | 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 | 16 | orders_owner: profile, orders: @purchases, month: @purchases_month, year: @purchases_year, wireframe_size: false %> |
17 | 17 | </div> |
18 | 18 | <% end %> |
19 | 19 | |
20 | 20 | <% if @sales.present? %> |
21 | 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 | 23 | orders_owner: profile, orders: @sales, month: @sales_month, year: @purchases_year, wireframe_size: false %> |
24 | 24 | </div> |
25 | 25 | <% end %> | ... | ... |
plugins/orders/views/orders_plugin_admin/_order.html.slim
0 → 100644
... | ... | @@ -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 | 4 | .box-field.product title=item.name = item.name |
5 | 5 | .box-field.quantity-price-table |
6 | 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 | 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 | 10 | .more |
... | ... | @@ -12,12 +12,15 @@ |
12 | 12 | / actionmailer doesn't have an user, rescue error |
13 | 13 | - if (order.may_edit? user, @admin rescue false) |
14 | 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 | 19 | - else |
18 | 20 | = link_to t('views.item._edit.remove_from_order'), {controller: :orders_plugin_item, action: :destroy, id: item.id}, |
19 | 21 | remote: true, data: {loading: "#item-#{item.id}"} |
20 | 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 | 26 | .clean | ... | ... |
plugins/orders/views/orders_plugin_item/_index.html.slim
... | ... | @@ -13,12 +13,11 @@ div class="order-items-container #{"empty" if order.items.size == 0} #{"admin" i |
13 | 13 | - if @admin |
14 | 14 | .box-field.status= t'views.item._index.status' |
15 | 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 | 18 | .order-total |
20 | 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 | 22 | - else |
24 | 23 | = t'views.item._index.empty_order' | ... | ... |
plugins/orders/views/orders_plugin_item/_quantity_price.html.slim
... | ... | @@ -6,7 +6,7 @@ div class="quantity-price-row #{status} #{status_data[:flags].keys.join ' '}" |
6 | 6 | = t'views.item._edit.removed' |
7 | 7 | - else |
8 | 8 | = quantity_localized |
9 | - - if not @simple and status_data[:flags][:editable] | |
9 | + - if not @view and status_data[:flags][:editable] | |
10 | 10 | = number_field_tag "item[quantity_#{status_data[:field]}]", status_data[:quantity], step: 'any', onkeydown: 'orders.item.quantity_keydown(this, event)' |
11 | 11 | - unless status_data[:flags][:removed] |
12 | 12 | | | ... | ... |
plugins/orders/views/orders_plugin_order/_data.html.slim
0 → 100644
... | ... | @@ -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 @@ |
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="order-view #{"editable" if order.may_edit? user, @admin rescue false} |
30 | 30 | - elsif order.open? |
31 | 31 | div |
32 | 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 | 34 | |  |
35 | 35 | |
36 | 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 @@ |
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 < OrdersPluginAdminController |
22 | 22 | end |
23 | 23 | |
24 | 24 | def new |
25 | - if request.put? | |
25 | + if request.patch? | |
26 | + # can't use profile.orders_cycle here | |
26 | 27 | @cycle = OrdersCyclePlugin::Cycle.find params[:id] |
27 | 28 | |
28 | 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 | 32 | if @success |
32 | 33 | session[:notice] = t('controllers.myprofile.cycle_controller.cycle_created') |
33 | 34 | if params[:sendmail] |
34 | 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 | 37 | end |
37 | 38 | else |
38 | 39 | render action: :edit |
39 | 40 | end |
40 | 41 | else |
41 | - count = OrdersCyclePlugin::Cycle.count conditions: {profile_id: profile} | |
42 | + count = profile.orders_cycles.maximum(:code) || 1 | |
42 | 43 | @cycle = OrdersCyclePlugin::Cycle.create! profile: profile, status: 'new', |
43 | 44 | name: t('controllers.myprofile.cycle_controller.cycle_n_n') % {n: count+1} |
44 | 45 | end |
... | ... | @@ -48,13 +49,13 @@ class OrdersCyclePluginCycleController < OrdersPluginAdminController |
48 | 49 | # editing an order |
49 | 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 | 53 | @products = products |
53 | 54 | |
54 | 55 | if request.xhr? |
55 | 56 | if params[:commit] |
56 | 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 | 60 | if params[:sendmail] |
60 | 61 | OrdersCyclePlugin::Mailer.delay(run_at: @cycle.start).open_cycle(@cycle.profile, |
... | ... | @@ -65,7 +66,7 @@ class OrdersCyclePluginCycleController < OrdersPluginAdminController |
65 | 66 | end |
66 | 67 | |
67 | 68 | def products_load |
68 | - @cycle = OrdersCyclePlugin::Cycle.find params[:id] | |
69 | + @cycle = profile.orders_cycles.find params[:id] | |
69 | 70 | @products = products |
70 | 71 | |
71 | 72 | if @cycle.add_products_job |
... | ... | @@ -76,34 +77,34 @@ class OrdersCyclePluginCycleController < OrdersPluginAdminController |
76 | 77 | end |
77 | 78 | |
78 | 79 | def destroy |
79 | - @cycle = OrdersCyclePlugin::Cycle.find params[:id] | |
80 | + @cycle = profile.orders_cycles.find params[:id] | |
80 | 81 | @cycle.destroy |
81 | 82 | redirect_to action: :index |
82 | 83 | end |
83 | 84 | |
84 | 85 | def step |
85 | - @cycle = OrdersCyclePlugin::Cycle.find params[:id] | |
86 | + @cycle = profile.orders_cycles.find params[:id] | |
86 | 87 | @cycle.step |
87 | 88 | @cycle.save! |
88 | 89 | redirect_to action: :edit, id: @cycle.id |
89 | 90 | end |
90 | 91 | |
91 | 92 | def step_back |
92 | - @cycle = OrdersCyclePlugin::Cycle.find params[:id] | |
93 | + @cycle = profile.orders_cycles.find params[:id] | |
93 | 94 | @cycle.step_back |
94 | 95 | @cycle.save! |
95 | 96 | redirect_to action: :edit, id: @cycle.id |
96 | 97 | end |
97 | 98 | |
98 | 99 | def add_missing_products |
99 | - @cycle = OrdersCyclePlugin::Cycle.find params[:id] | |
100 | + @cycle = profile.orders_cycles.find params[:id] | |
100 | 101 | @cycle.add_products |
101 | 102 | render partial: 'suppliers_plugin/shared/pagereload' |
102 | 103 | end |
103 | 104 | |
104 | 105 | def report_products |
105 | 106 | return super if params[:ids].present? |
106 | - @cycle = OrdersCyclePlugin::Cycle.find params[:id] | |
107 | + @cycle = profile.orders_cycles.find params[:id] | |
107 | 108 | report_file = report_products_by_supplier @cycle.supplier_products_by_suppliers(@cycle.sales.ordered) |
108 | 109 | |
109 | 110 | send_file report_file, type: 'application/xlsx', |
... | ... | @@ -114,7 +115,7 @@ class OrdersCyclePluginCycleController < OrdersPluginAdminController |
114 | 115 | |
115 | 116 | def report_orders |
116 | 117 | return super if params[:ids].present? |
117 | - @cycle = OrdersCyclePlugin::Cycle.find params[:id] | |
118 | + @cycle = profile.orders_cycles.find params[:id] | |
118 | 119 | report_file = report_orders_by_consumer @cycle.sales.ordered |
119 | 120 | |
120 | 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 < OrdersPluginItemController |
31 | 31 | @item.sale = @order |
32 | 32 | @item.product = @offered_product |
33 | 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 | 35 | end |
36 | 36 | end |
37 | 37 | |
38 | 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 | 40 | super |
41 | 41 | @offered_product = @item.product |
42 | 42 | @cycle = @order.cycle |
... | ... | @@ -50,7 +50,7 @@ class OrdersCyclePluginItemController < OrdersPluginItemController |
50 | 50 | #update on association for total |
51 | 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 | 54 | end |
55 | 55 | |
56 | 56 | def destroy | ... | ... |
plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_product_controller.rb
... | ... | @@ -25,7 +25,7 @@ class OrdersCyclePluginProductController < SuppliersPlugin::ProductController |
25 | 25 | def cycle_edit |
26 | 26 | @product = OrdersCyclePlugin::OfferedProduct.find params[:id] |
27 | 27 | if request.xhr? |
28 | - @product.update_attributes! params[:product] | |
28 | + @product.update! params[:product] | |
29 | 29 | respond_to do |format| |
30 | 30 | format.js |
31 | 31 | end | ... | ... |
plugins/orders_cycle/controllers/profile/orders_cycle_plugin_order_controller.rb
... | ... | @@ -38,7 +38,7 @@ class OrdersCyclePluginOrderController < OrdersPluginOrderController |
38 | 38 | @order.consumer = @consumer |
39 | 39 | @order.cycle = @cycle |
40 | 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 | 42 | end |
43 | 43 | end |
44 | 44 | |
... | ... | @@ -55,7 +55,7 @@ class OrdersCyclePluginOrderController < OrdersPluginOrderController |
55 | 55 | end |
56 | 56 | @repeat_order.supplier_delivery = @order.supplier_delivery |
57 | 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 | 59 | else |
60 | 60 | @orders = @cycle.consumer_previous_orders(@consumer).last(5).reverse |
61 | 61 | @orders.each{ |o| o.enable_product_diff } |
... | ... | @@ -72,7 +72,7 @@ class OrdersCyclePluginOrderController < OrdersPluginOrderController |
72 | 72 | if status == 'ordered' |
73 | 73 | if @order.items.size > 0 |
74 | 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 | 76 | session[:notice] = t('orders_plugin.controllers.profile.consumer.order_confirmed') |
77 | 77 | else |
78 | 78 | session[:notice] = t('orders_plugin.controllers.profile.consumer.can_not_confirm_your_') |
... | ... | @@ -117,12 +117,12 @@ class OrdersCyclePluginOrderController < OrdersPluginOrderController |
117 | 117 | end |
118 | 118 | |
119 | 119 | def reopen |
120 | - @order.update_attributes! status: 'draft' | |
120 | + @order.update! status: 'draft' | |
121 | 121 | render 'edit' |
122 | 122 | end |
123 | 123 | |
124 | 124 | def cancel |
125 | - @order.update_attributes! status: 'cancelled' | |
125 | + @order.update! status: 'cancelled' | |
126 | 126 | session[:notice] = t('orders_plugin.controllers.profile.consumer.order_cancelled') |
127 | 127 | render 'edit' |
128 | 128 | end |
... | ... | @@ -162,7 +162,7 @@ class OrdersCyclePluginOrderController < OrdersPluginOrderController |
162 | 162 | end |
163 | 163 | |
164 | 164 | def supplier_balloon |
165 | - @supplier = SuppliersPlugin::Supplier.find params[:id] | |
165 | + @supplier = profile.suppliers.find params[:id] | |
166 | 166 | end |
167 | 167 | def product_balloon |
168 | 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 < ActiveRecord::Migration |
4 | 4 | rename_column :orders_cycle_plugin_cycle_orders, :order_id, :sale_id |
5 | 5 | add_column :orders_cycle_plugin_cycle_orders, :purchase_id, :integer |
6 | 6 | |
7 | - add_index :orders_cycle_plugin_cycle_orders, :sale_id | |
8 | 7 | add_index :orders_cycle_plugin_cycle_orders, :purchase_id |
9 | - add_index :orders_cycle_plugin_cycle_orders, [:cycle_id, :sale_id] | |
10 | 8 | add_index :orders_cycle_plugin_cycle_orders, [:cycle_id, :purchase_id], name: :index_orders_cycle_plugin_cycle_orders_cycle_purchase |
11 | 9 | end |
12 | 10 | ... | ... |
plugins/orders_cycle/lib/ext/delivery_plugin/option.rb
... | ... | @@ -2,7 +2,8 @@ require_dependency 'delivery_plugin/option' |
2 | 2 | |
3 | 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 | 9 | end | ... | ... |
plugins/orders_cycle/lib/ext/profile.rb
1 | 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 | 16 | has_many :orders_cycles_sales, through: :orders_cycles, source: :sales |
11 | 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 | 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 | 28 | return DateTime.now..DateTime.now if list.blank? |
18 | 29 | list.first.start.to_date..list.last.finish.to_date |
19 | 30 | end | ... | ... |
plugins/orders_cycle/models/orders_cycle_plugin/cycle.rb
... | ... | @@ -32,30 +32,32 @@ class OrdersCyclePlugin::Cycle < ActiveRecord::Base |
32 | 32 | |
33 | 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 | 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 | 42 | # cannot use :order because of months/years named_scope |
42 | 43 | has_many :sales, through: :cycle_orders, source: :sale |
43 | 44 | has_many :purchases, through: :cycle_orders, source: :purchase |
44 | 45 | |
45 | 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 | 62 | has_many :items_selled, through: :sales, source: :items |
61 | 63 | has_many :items_purchased, through: :purchases, source: :items |
... | ... | @@ -64,16 +66,16 @@ class OrdersCyclePlugin::Cycle < ActiveRecord::Base |
64 | 66 | |
65 | 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 | 73 | has_many :volunteers_periods, class_name: 'VolunteersPlugin::Period', as: :owner |
72 | 74 | has_many :volunteers, through: :volunteers_periods, source: :profile |
73 | 75 | attr_accessible :volunteers_periods_attributes |
74 | 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 | 80 | # status scopes |
79 | 81 | scope :on_edition, -> { where status: 'edition' } |
... | ... | @@ -83,33 +85,29 @@ class OrdersCyclePlugin::Cycle < ActiveRecord::Base |
83 | 85 | scope :on_delivery, -> { where status: 'delivery' } |
84 | 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 | 113 | validates_presence_of :profile |
... | ... | @@ -122,7 +120,7 @@ class OrdersCyclePlugin::Cycle < ActiveRecord::Base |
122 | 120 | validate :validate_orders_dates, if: :not_new? |
123 | 121 | validate :validate_delivery_dates, if: :not_new? |
124 | 122 | |
125 | - before_validation :step_new | |
123 | + before_save :step_new | |
126 | 124 | before_validation :update_orders_status |
127 | 125 | before_save :add_products_on_edition_state |
128 | 126 | after_create :delay_purge_profile_defuncts |
... | ... | @@ -212,9 +210,7 @@ class OrdersCyclePlugin::Cycle < ActiveRecord::Base |
212 | 210 | end |
213 | 211 | |
214 | 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 | 214 | end |
219 | 215 | |
220 | 216 | def supplier_products_by_suppliers orders = self.sales.ordered |
... | ... | @@ -261,27 +257,27 @@ class OrdersCyclePlugin::Cycle < ActiveRecord::Base |
261 | 257 | end |
262 | 258 | |
263 | 259 | def step_new |
264 | - return if new_record? | |
260 | + return if self.new_record? | |
265 | 261 | self.step if self.new? |
266 | 262 | end |
267 | 263 | |
268 | 264 | def update_sales_status from, to |
269 | 265 | sales = self.sales.where(status: from.to_s) |
270 | 266 | sales.each do |sale| |
271 | - sale.update_attributes status: to.to_s | |
267 | + sale.update status: to.to_s | |
272 | 268 | end |
273 | 269 | end |
274 | 270 | |
275 | 271 | def update_purchases_status from, to |
276 | 272 | purchases = self.purchases.where(status: from.to_s) |
277 | 273 | purchases.each do |purchase| |
278 | - purchase.update_attributes status: to.to_s | |
274 | + purchase.update status: to.to_s | |
279 | 275 | end |
280 | 276 | end |
281 | 277 | |
282 | 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 | 282 | # Don't rewind confirmed sales |
287 | 283 | unless self.status_was == 'orders' and self.status == 'edition' | ... | ... |
plugins/orders_cycle/models/orders_cycle_plugin/offered_product.rb
1 | 1 | class OrdersCyclePlugin::OfferedProduct < SuppliersPlugin::BaseProduct |
2 | 2 | |
3 | + # we work use frozen attributes | |
4 | + self.default_delegate_enable = false | |
5 | + | |
3 | 6 | # FIXME: WORKAROUND for https://github.com/rails/rails/issues/6663 |
4 | 7 | # OrdersCyclePlugin::Sale.find(3697).cycle.suppliers returns empty without this |
5 | 8 | def self.finder_needs_type_condition? |
... | ... | @@ -19,10 +22,10 @@ class OrdersCyclePlugin::OfferedProduct < SuppliersPlugin::BaseProduct |
19 | 22 | has_one :sources_supplier_product, through: :from_product, source: :sources_from_product |
20 | 23 | # necessary only due to the override of sources_supplier_products, as rails somehow caches the old reference |
21 | 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 | 30 | instance_exec &OrdersPlugin::Item::DefineTotals |
28 | 31 | extend CurrencyHelper::ClassMethods |
... | ... | @@ -31,9 +34,7 @@ class OrdersCyclePlugin::OfferedProduct < SuppliersPlugin::BaseProduct |
31 | 34 | # test this before use! |
32 | 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 | 38 | def self.search_scope scope, params |
38 | 39 | scope = scope.from_supplier_id params[:supplier_id] if params[:supplier_id].present? |
39 | 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 < SuppliersPlugin::BaseProduct |
50 | 51 | op.profile = product.profile |
51 | 52 | op.type = self.name |
52 | 53 | |
53 | - op.from_products << product | |
54 | + op.from_product = product | |
54 | 55 | cycle.products << op if cycle |
55 | 56 | |
56 | 57 | op |
57 | 58 | end |
58 | 59 | |
59 | 60 | # always recalculate in case something has changed |
61 | + # FIXME: really? it is already copied! | |
60 | 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 | 64 | ((price / buy_price) - 1) * 100 |
63 | 65 | end |
64 | 66 | def margin_percentage= value |
65 | - self['margin_percentage'] = value | |
67 | + super value | |
66 | 68 | self.price = self.price_with_margins buy_price |
67 | 69 | end |
68 | 70 | |
... | ... | @@ -71,22 +73,15 @@ class OrdersCyclePlugin::OfferedProduct < SuppliersPlugin::BaseProduct |
71 | 73 | end |
72 | 74 | |
73 | 75 | # reimplement to don't destroy this, keeping history in cycles |
74 | - # offered products copy attributes | |
76 | + # as offered products copy attributes. | |
75 | 77 | def dependent? |
76 | 78 | false |
77 | 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 | 81 | FROOZEN_DEFAULT_ATTRIBUTES = DEFAULT_ATTRIBUTES |
87 | 82 | def freeze_default_attributes from_product |
88 | 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 | 85 | end |
91 | 86 | end |
92 | 87 | ... | ... |
plugins/orders_cycle/models/orders_cycle_plugin/order_base.rb
... | ... | @@ -14,26 +14,18 @@ module OrdersCyclePlugin::OrderBase |
14 | 14 | self.cycle_sales.includes(:cycle).map(&:cycle) + self.cycle_purchases.includes(:cycle).map(&:cycle) |
15 | 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 | 17 | scope :for_cycle, -> (cycle) { |
26 | 18 | where('orders_cycle_plugin_cycles.id = ?', cycle.id). |
27 | 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 | 30 | extend CodeNumbering::ClassMethods |
39 | 31 | code_numbering :code, scope: (proc do | ... | ... |
plugins/orders_cycle/models/orders_cycle_plugin/sale.rb
... | ... | @@ -24,10 +24,6 @@ class OrdersCyclePlugin::Sale < OrdersPlugin::Sale |
24 | 24 | super and self.cycle.orders? |
25 | 25 | end |
26 | 26 | |
27 | - def supplier_delivery | |
28 | - super || (self.cycle.delivery_methods.first rescue nil) | |
29 | - end | |
30 | - | |
31 | 27 | def change_purchases |
32 | 28 | return unless self.status_was.present? |
33 | 29 | if self.ordered_at_was.nil? and self.ordered_at.present? | ... | ... |
... | ... | @@ -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 @@ |
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 @@ |
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/unit/orders_cycle_plugin/cycle_test.rb
0 → 100644
... | ... | @@ -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,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
plugins/orders_cycle/views/orders_cycle_plugin_cycle/_edit_fields.html.slim
... | ... | @@ -53,6 +53,5 @@ h3= t('views.cycle._edit_fields.general_settings') |
53 | 53 | = link_to t('views.cycle._edit_fields.cancel_changes'), @cycle.new? ? {action: :index} : params |
54 | 54 | - unless @cycle.new? |
55 | 55 | | |
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 | 1 | <div class="cycle-products-table sortable-table"> |
2 | 2 | <%= pagination_links @products %> |
3 | 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 | 5 | </div> |
6 | 6 | <div class='table-header'> |
7 | 7 | <span class='box-field category'><%= t('views.cycle._product_lines.category') %></span> |
... | ... | @@ -17,7 +17,7 @@ |
17 | 17 | <div class='table-content'> |
18 | 18 | <% @products.each do |p| %> |
19 | 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 | 21 | </div> |
22 | 22 | <% end %> |
23 | 23 | <%= javascript_tag do %> | ... | ... |
plugins/orders_cycle/views/orders_cycle_plugin_cycle/_products_loading.html.erb
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | <%= t('views.cycle._products_loading') %> |
4 | 4 | |
5 | 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 | 7 | orders_cycle.cycle.products.load() |
8 | 8 | <% end %> |
9 | 9 | </div> | ... | ... |
plugins/orders_cycle/views/orders_cycle_plugin_cycle/_timeline.html.slim
0 → 100644
... | ... | @@ -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 | + |  | |
17 | + span= datetime_period_short cycle.start, cycle.finish | |
18 | + .date | |
19 | + span.field-title= t'views.cycle._brief.delivery' | |
20 | + |  | |
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 @@ |
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 | 1 | <% if params[:commit] %> |
2 | 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 | 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 | 6 | <% end %> |
7 | 7 | <% else %> |
8 | 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 | 2 | |
3 | 3 | <div id="cycles-gadget"> |
4 | 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 | 6 | <% end %> |
7 | 7 | |
8 | 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 | 10 | <div class='clean'></div> |
11 | 11 | </div> |
12 | 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 | 3 | page << "toggle_edit.value_row.reload();" | ... | ... |
plugins/shopping_cart/controllers/shopping_cart_plugin_controller.rb
... | ... | @@ -119,7 +119,8 @@ class ShoppingCartPluginController < OrdersPluginController |
119 | 119 | @settings = cart_profile.shopping_cart_settings |
120 | 120 | @cart = cart |
121 | 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 | 125 | last_delivery_option_id = session[:cart][:last_delivery_option_id] if session[:cart] |
125 | 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 < OrdersPluginController |
192 | 193 | @profile = cart_profile |
193 | 194 | supplier_delivery = @profile.delivery_methods.where(id: params[:order][:supplier_delivery_id]).first |
194 | 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 | 198 | render json: { |
197 | 199 | ok: true, |
198 | 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 | 1 | class MoveFieldsIncludedOnProfilesTableToSettings < ActiveRecord::Migration |
2 | 2 | def self.up |
3 | - Profile.find_each do |profile| | |
3 | + Enterprise.find_each do |profile| | |
4 | 4 | settings = profile.shopping_cart_settings |
5 | 5 | settings.enabled = profile.shopping_cart |
6 | 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 | 2 | OrdersPlugin.send :remove_const, :Order if defined? OrdersPlugin::Order |
3 | 3 | |
4 | 4 | class ShoppingCartPlugin::PurchaseOrder < ActiveRecord::Base |
5 | - acts_as_having_settings :field => :data | |
5 | + acts_as_having_settings field: :data | |
6 | 6 | |
7 | 7 | module Status |
8 | 8 | OPENED = 0 |
... | ... | @@ -13,17 +13,17 @@ class ShoppingCartPlugin::PurchaseOrder < ActiveRecord::Base |
13 | 13 | end |
14 | 14 | |
15 | 15 | class Profile |
16 | - has_many :orders, :class_name => 'OrdersPlugin::Order' | |
16 | + has_many :orders, class_name: 'OrdersPlugin::Order' | |
17 | 17 | end |
18 | 18 | |
19 | 19 | class OrdersPlugin::Item < ActiveRecord::Base |
20 | - belongs_to :order, :class_name => 'OrdersPlugin::Order' | |
20 | + belongs_to :order, class_name: 'OrdersPlugin::Order' | |
21 | 21 | end |
22 | 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 | 25 | extend CodeNumbering::ClassMethods |
26 | - code_numbering :code, :scope => proc{ self.profile.orders } | |
26 | + code_numbering :code, scope: proc{ self.profile.orders } | |
27 | 27 | end |
28 | 28 | |
29 | 29 | StatusTransform = { |
... | ... | @@ -37,10 +37,10 @@ class MoveShoppingCartPurchaseOrderToOrdersPluginOrder < ActiveRecord::Migration |
37 | 37 | def self.up |
38 | 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 | 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 | 45 | order.consumer_data = {} |
46 | 46 | ['contact_phone','name','email'].each do |prop| |
... | ... | @@ -58,7 +58,7 @@ class MoveShoppingCartPurchaseOrderToOrdersPluginOrder < ActiveRecord::Migration |
58 | 58 | order.supplier_delivery_data = {} |
59 | 59 | |
60 | 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 | 62 | item.order = order |
63 | 63 | end |
64 | 64 | ... | ... |
plugins/shopping_cart/features/delivery_admin.feature
... | ... | @@ -36,7 +36,6 @@ Feature: delivery administration |
36 | 36 | And I follow "New delivery or pickup" |
37 | 37 | And I select "Deliver" from "Type" |
38 | 38 | And I fill in "Name" with "Bike" |
39 | - And I fill in "Description" with "Beers delivered with my old bike." | |
40 | 39 | And I fill in "Fixed cost" with "8.00" |
41 | 40 | And I fill in "Order's minimum price for free delivery" with "35.50" |
42 | 41 | When I press "Add" |
... | ... | @@ -49,7 +48,6 @@ Feature: delivery administration |
49 | 48 | And I follow "New delivery or pickup" |
50 | 49 | And I select "Pickup" from "Type" |
51 | 50 | And I fill in "Name" with "Bar" |
52 | - And I fill in "Description" with "Come to my bar and pick it yourself." | |
53 | 51 | And I fill in "Fixed cost" with "0.00" |
54 | 52 | When I press "Add" |
55 | 53 | Then I should see "Bar" | ... | ... |
plugins/shopping_cart/lib/shopping_cart_plugin.rb
1 | 1 | class ShoppingCartPlugin < Noosfero::Plugin |
2 | - include ModalHelper | |
3 | - include ActionView::Helpers::UrlHelper | |
4 | 2 | |
5 | 3 | def self.plugin_name |
6 | 4 | "Shopping Basket" |
... | ... | @@ -34,10 +32,6 @@ class ShoppingCartPlugin < Noosfero::Plugin |
34 | 32 | buttons |
35 | 33 | end |
36 | 34 | |
37 | - def controller | |
38 | - context | |
39 | - end | |
40 | - | |
41 | 35 | def add_to_cart_button item, options = {} |
42 | 36 | profile = item.profile |
43 | 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 | 61 | |
62 | 62 | def items_table(items, delivery_method = nil, by_mail = false) |
63 | 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 | 66 | end |
66 | 67 | |
67 | 68 | def float_to_currency_cart value, environment, _options = {} | ... | ... |
plugins/shopping_cart/po/pt/shopping_cart.po
... | ... | @@ -13,7 +13,7 @@ msgid "" |
13 | 13 | msgstr "" |
14 | 14 | "Project-Id-Version: 1.3~rc2-1-ga15645d\n" |
15 | 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 | 17 | "Last-Translator: Michal Čihař <michal@cihar.com>\n" |
18 | 18 | "Language-Team: Portuguese <https://hosted.weblate.org/projects/noosfero/" |
19 | 19 | "plugin-shopping-cart/pt/>\n" |
... | ... | @@ -32,6 +32,48 @@ msgstr "Funcionalidade de cesto de compras para empreendimentos" |
32 | 32 | msgid "Shopping basket" |
33 | 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 | 77 | #: plugins/shopping_cart/lib/shopping_cart_plugin/cart_helper.rb:11 |
36 | 78 | msgid "Add to basket" |
37 | 79 | msgstr "Adicionar ao cesto" |
... | ... | @@ -112,9 +154,8 @@ msgid "Shopping checkout" |
112 | 154 | msgstr "Finalizar pedido" |
113 | 155 | |
114 | 156 | #: plugins/shopping_cart/views/public/_cart.html.erb:8 |
115 | -#, fuzzy | |
116 | 157 | msgid "Basket is empty" |
117 | -msgstr "Cesto exibido." | |
158 | +msgstr "Cesto vazio." | |
118 | 159 | |
119 | 160 | #: plugins/shopping_cart/views/public/_cart.html.erb:14 |
120 | 161 | msgid "Basket" |
... | ... | @@ -124,11 +165,6 @@ msgstr "Cesto" |
124 | 165 | msgid "Clean basket" |
125 | 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 | 168 | #: plugins/shopping_cart/views/public/_cart.html.erb:23 |
133 | 169 | msgid "Show basket" |
134 | 170 | msgstr "Mostrar cesto" |
... | ... | @@ -163,7 +199,8 @@ msgstr "Tem certeza que quer limpar seu cesto?" |
163 | 199 | |
164 | 200 | #: plugins/shopping_cart/views/public/_cart.html.erb:54 |
165 | 201 | msgid "repeat order" |
166 | -msgstr "" | |
202 | +msgstr "repetir pedido" | |
203 | + | |
167 | 204 | |
168 | 205 | #: plugins/shopping_cart/views/shopping_cart_plugin/_items.html.erb:7 |
169 | 206 | msgid "Item name" |
... | ... | @@ -179,39 +216,37 @@ msgid "Hi %s!" |
179 | 216 | msgstr "Olá %s!" |
180 | 217 | |
181 | 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 | 222 | #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:11 |
188 | -#, fuzzy | |
189 | 223 | msgid "" |
190 | 224 | "The enterprise already received your buy request and will contact you for " |
191 | 225 | "confirmation." |
192 | 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 | 230 | "confirmação." |
195 | 231 | |
196 | 232 | #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:12 |
197 | -#, fuzzy | |
198 | 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 | 236 | #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:13 |
202 | 237 | msgid "Review below the informations of your order:" |
203 | -msgstr "" | |
238 | +msgstr "Abaixo, revise as informações do seu pedido:" | |
204 | 239 | |
205 | 240 | #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:19 |
206 | 241 | #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:17 |
207 | 242 | msgid "Phone number" |
208 | 243 | msgstr "" |
209 | 244 | |
245 | +#: plugins/shopping_cart/views/shopping_cart_plugin_myprofile/_orders_list.html.erb:35 | |
210 | 246 | #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:22 |
211 | 247 | #: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:22 |
212 | -#, fuzzy | |
213 | 248 | msgid "Payment's method" |
214 | -msgstr "Pagamento" | |
249 | +msgstr "Forma de pagamento" | |
215 | 250 | |
216 | 251 | #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb:24 |
217 | 252 | #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:22 |
... | ... | @@ -219,31 +254,30 @@ msgstr "Pagamento" |
219 | 254 | msgid "shopping_cart|Change" |
220 | 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 | 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 | 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 | 271 | msgid "A service of %s." |
237 | -msgstr "" | |
272 | +msgstr "Um serviço de %s." | |
238 | 273 | |
239 | 274 | #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:10 |
240 | -#, fuzzy | |
241 | 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 | 278 | #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:11 |
245 | 279 | msgid "Below follows the customer informations:" |
246 | -msgstr "" | |
280 | +msgstr "Abaixo seguem as informações do consumidor:" | |
247 | 281 | |
248 | 282 | #: plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb:20 |
249 | 283 | #: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:25 |
... | ... | @@ -251,20 +285,18 @@ msgid "Payment" |
251 | 285 | msgstr "Pagamento" |
252 | 286 | |
253 | 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 | 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 | 293 | msgid "If there are any problems with this email contact the admin of %s." |
259 | 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 | 298 | msgid "Personal identification" |
267 | -msgstr "" | |
299 | +msgstr "Identificação pessoal" | |
268 | 300 | |
269 | 301 | #: plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb:15 |
270 | 302 | msgid "Name" |
... | ... | @@ -290,36 +322,21 @@ msgstr "Seu Pedido" |
290 | 322 | msgid "Send buy request" |
291 | 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 | 340 | #~ msgid "Can't join items from different enterprises." |
324 | 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 | 63 | var input = $("input", li)[0]; |
64 | 64 | input.lastValue = input.value; |
65 | 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 | 66 | input.onchange = function() { |
73 | 67 | me.updateQuantity(this, this.productId, this.value); |
74 | 68 | }; | ... | ... |
plugins/shopping_cart/views/public/_cart.html.erb
... | ... | @@ -16,7 +16,7 @@ |
16 | 16 | <a href="cart:clean" onclick="cart.clean(); return false" class="cart-clean"><%=_('Clean basket')%></a> |
17 | 17 | <ul class="cart-items"> |
18 | 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 | 20 | <div class="cart-total"><%=_('Total:')%> <b></b></div> |
21 | 21 | </div> |
22 | 22 | <a href="#" onclick="cart.toggle(); return false" class="cart-toggle"> |
... | ... | @@ -31,7 +31,7 @@ |
31 | 31 | <div class="picture" style="background-image:url({{item.picture}})"></div> |
32 | 32 | <span class="item-name">{{item.name}}</span> |
33 | 33 | <div class="item-price"> |
34 | - <input size="1" value="{{item.quantity}}" />{{item.priceTxt}} | |
34 | + <input value="{{item.quantity}}" />{{item.priceTxt}} | |
35 | 35 | </div> |
36 | 36 | </li> |
37 | 37 | </script> | ... | ... |
plugins/shopping_cart/views/shopping_cart_plugin/_items.html.erb
... | ... | @@ -3,45 +3,51 @@ |
3 | 3 | style="<%= 'border-collapse: collapse' if by_mail %>"> |
4 | 4 | |
5 | 5 | <tr> |
6 | - <th> | |
7 | - <%= _('Item name') %> | |
6 | + <th class='cart-table-item' <%= "align='center'" if by_mail %>> | |
7 | + <%= _('Item') %> | |
8 | 8 | </th> |
9 | - <th> | |
10 | - <%= if by_mail then ' # ' else '#' end %> | |
9 | + <th class='cart-table-quantity' <%= "align='center'" if by_mail %>> | |
10 | + <%= if by_mail then ' '+_('Qtty')+' ' else _('Qtty') end %> | |
11 | 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 | 17 | </th> |
15 | 18 | </tr> |
16 | 19 | |
17 | 20 | <% order.items.each do |item| %> |
18 | 21 | <tr> |
19 | - <td> | |
22 | + <td class='cart-table-item' <%= "align='left'" if by_mail %>> | |
20 | 23 | <%= item.name %> |
21 | 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 | 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 | 32 | <%= get_price item.product, @environment, item.quantity_consumer_ordered, unit: '' %> |
27 | 33 | </td> |
28 | 34 | |
29 | 35 | </tr> |
30 | 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 | 40 | <%= order.supplier_delivery.name if order.supplier_delivery %> |
35 | 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 | 43 | <%= float_to_currency_cart order.supplier_delivery.cost(order.total_price), @environment, unit: '' if order.supplier_delivery %> |
38 | 44 | </td> |
39 | 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 | 48 | <%= _('Total:') %> |
43 | 49 | </th> |
44 | - <th class="cart-table-total-value"> | |
50 | + <th class="cart-table-total-value" <%= "align='right'" if by_mail %>> | |
45 | 51 | <%= float_to_currency_cart order.total, @environment %> |
46 | 52 | </th> |
47 | 53 | </table> | ... | ... |
plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb
1 | 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 | 5 | <%= form_for :order, url: {action: :send_request}, |
8 | 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 | 17 | <fieldset> |
12 | 18 | <legend><%=_('Personal identification')%></legend> |
13 | 19 | |
... | ... | @@ -30,21 +36,15 @@ |
30 | 36 | <% if profile.delivery_methods.size > 0 %> |
31 | 37 | <fieldset> |
32 | 38 | <legend><%=_('Delivery or pickup method')%></legend> |
39 | + | |
33 | 40 | <%= render 'delivery_plugin/order_select', f: f, order: @order %> |
34 | 41 | </fieldset> |
35 | 42 | <% end %> |
36 | 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 | 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 | 48 | </div> |
49 | 49 | <% end %> |
50 | 50 | </div> | ... | ... |
plugins/suppliers/controllers/myprofile/suppliers_plugin/basket_controller.rb
... | ... | @@ -52,10 +52,12 @@ class SuppliersPlugin::BasketController < MyProfileController |
52 | 52 | extend HMVC::ClassMethods |
53 | 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 | 59 | end |
60 | + helper_method :url_for | |
59 | 61 | |
60 | 62 | def set_allowed_user |
61 | 63 | @allowed_user = true | ... | ... |
plugins/suppliers/controllers/myprofile/suppliers_plugin/product_controller.rb
... | ... | @@ -32,7 +32,7 @@ class SuppliersPlugin::ProductController < MyProfileController |
32 | 32 | |
33 | 33 | def edit |
34 | 34 | @product = profile.products.supplied.find params[:id] |
35 | - @product.update_attributes params["product_#{@product.id}"] | |
35 | + @product.update params["product_#{@product.id}"] | |
36 | 36 | end |
37 | 37 | |
38 | 38 | def import |
... | ... | @@ -79,6 +79,7 @@ class SuppliersPlugin::ProductController < MyProfileController |
79 | 79 | |
80 | 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 | 83 | @scope = profile.products.unarchived.joins :from_products, :suppliers |
83 | 84 | @scope = SuppliersPlugin::BaseProduct.search_scope @scope, params |
84 | 85 | @products_count = @scope.supplied_for_count.count |
... | ... | @@ -95,9 +96,11 @@ class SuppliersPlugin::ProductController < MyProfileController |
95 | 96 | extend HMVC::ClassMethods |
96 | 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 | 103 | end |
104 | + helper_method :url_for | |
102 | 105 | |
103 | 106 | end | ... | ... |
plugins/suppliers/controllers/myprofile/suppliers_plugin_myprofile_controller.rb
... | ... | @@ -21,7 +21,7 @@ class SuppliersPluginMyprofileController < MyProfileController |
21 | 21 | end |
22 | 22 | |
23 | 23 | def new |
24 | - @new_supplier.update_attributes! params[:supplier] | |
24 | + @new_supplier.update! params[:supplier] | |
25 | 25 | @supplier = @new_supplier |
26 | 26 | session[:notice] = t('controllers.myprofile.supplier_created') |
27 | 27 | end |
... | ... | @@ -33,7 +33,7 @@ class SuppliersPluginMyprofileController < MyProfileController |
33 | 33 | |
34 | 34 | def edit |
35 | 35 | @supplier = profile.suppliers.find params[:id] |
36 | - @supplier.update_attributes params[:supplier] | |
36 | + @supplier.update params[:supplier] | |
37 | 37 | end |
38 | 38 | |
39 | 39 | def margin_change |
... | ... | @@ -58,8 +58,8 @@ class SuppliersPluginMyprofileController < MyProfileController |
58 | 58 | |
59 | 59 | def search |
60 | 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 | 63 | @enterprises -= profile.suppliers.collect(&:profile) |
64 | 64 | end |
65 | 65 | ... | ... |
plugins/suppliers/lib/default_delegate.rb
... | ... | @@ -15,6 +15,9 @@ module DefaultDelegate |
15 | 15 | |
16 | 16 | # TODO: add some documentation about the methods being added |
17 | 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 | 21 | # rake db:migrate run? |
19 | 22 | return unless self.table_exists? |
20 | 23 | |
... | ... | @@ -91,6 +94,8 @@ module DefaultDelegate |
91 | 94 | end |
92 | 95 | |
93 | 96 | define_method "#{field}_with_default" do |
97 | + return self.send own_field unless self.default_delegate_enable | |
98 | + | |
94 | 99 | if self.send default_setting |
95 | 100 | # delegated_field may return nil, so use own instead |
96 | 101 | # this is the case with some associations (e.g. Product#product_qualifiers) |
... | ... | @@ -101,6 +106,8 @@ module DefaultDelegate |
101 | 106 | end |
102 | 107 | end |
103 | 108 | define_method "#{field}_with_default=" do |*args| |
109 | + return self.send "#{own_field}=", *args unless self.default_delegate_enable | |
110 | + | |
104 | 111 | own = self.send "#{own_field}=", *args |
105 | 112 | # break/set the default setting automatically, used for interfaces |
106 | 113 | # that don't have the default setting (e.g. manage_products) | ... | ... |