diff --git a/plugins/delivery/controllers/myprofile/delivery_plugin/admin_method_controller.rb b/plugins/delivery/controllers/myprofile/delivery_plugin/admin_method_controller.rb
index 81c3c0b..0262f43 100644
--- a/plugins/delivery/controllers/myprofile/delivery_plugin/admin_method_controller.rb
+++ b/plugins/delivery/controllers/myprofile/delivery_plugin/admin_method_controller.rb
@@ -14,7 +14,7 @@ class DeliveryPlugin::AdminMethodController < MyProfileController
def edit
@delivery_method ||= profile.delivery_methods.find_by_id params[:id]
- if params[:delivery_method].present? and @delivery_method.update_attributes params[:delivery_method]
+ if params[:delivery_method].present? and @delivery_method.update params[:delivery_method]
render partial: 'list'
else
render partial: 'edit', locals: {delivery_method: @delivery_method}
diff --git a/plugins/delivery/controllers/myprofile/delivery_plugin/admin_options_controller.rb b/plugins/delivery/controllers/myprofile/delivery_plugin/admin_options_controller.rb
index c837073..64ef7d3 100644
--- a/plugins/delivery/controllers/myprofile/delivery_plugin/admin_options_controller.rb
+++ b/plugins/delivery/controllers/myprofile/delivery_plugin/admin_options_controller.rb
@@ -8,7 +8,13 @@ class DeliveryPlugin::AdminOptionsController < DeliveryPlugin::AdminMethodContro
before_filter :load_owner
def select
+ end
+ def select_all
+ missing_methods = profile.delivery_methods - @owner.delivery_methods
+ missing_methods.each do |dm|
+ DeliveryPlugin::Option.create! owner_id: @owner.id, owner_type: @owner.class.name, delivery_method: dm
+ end
end
def new
diff --git a/plugins/delivery/db/migrate/20150623125525_add_distribution_margin_to_delivery_plugin_method.rb b/plugins/delivery/db/migrate/20150623125525_add_distribution_margin_to_delivery_plugin_method.rb
new file mode 100644
index 0000000..edcd7b5
--- /dev/null
+++ b/plugins/delivery/db/migrate/20150623125525_add_distribution_margin_to_delivery_plugin_method.rb
@@ -0,0 +1,8 @@
+class AddDistributionMarginToDeliveryPluginMethod < ActiveRecord::Migration
+
+ def change
+ add_column :delivery_plugin_methods, :distribution_margin_fixed, :decimal
+ add_column :delivery_plugin_methods, :distribution_margin_percentage, :decimal
+ end
+
+end
diff --git a/plugins/delivery/lib/delivery_plugin/display_helper.rb b/plugins/delivery/lib/delivery_plugin/display_helper.rb
index 1a02e1e..0af6c1e 100644
--- a/plugins/delivery/lib/delivery_plugin/display_helper.rb
+++ b/plugins/delivery/lib/delivery_plugin/display_helper.rb
@@ -9,15 +9,24 @@ module DeliveryPlugin::DisplayHelper
methods = options[:methods] || profile.delivery_methods
options = methods.map do |method|
- cost = if method.fixed_cost.present? and method.fixed_cost > 0 then float_to_currency_cart(method.fixed_cost, environment) else nil end
+ cost = if method.fixed_cost.present? and method.fixed_cost > 0 then method.fixed_cost_as_currency else nil end
text = if cost.present? then "#{method.name} (#{cost})" else method.name end
content_tag :option, text, value: method.id,
- data: {label: method.name, type: method.delivery_type, instructions: method.description.to_s},
- selected: if method == selected then 'selected' else nil end
+ data: {label: method.name, type: method.delivery_type, instructions: CGI::escapeHTML(method.description.to_s)},
+ selected: if method.id == selected then 'selected' else nil end
end.join
end
+ def consumer_delivery_field_value order, field
+ # BLACK OR WHITE: do not mix existing delivery data with user's location
+ if order.consumer_delivery_data.present?
+ order.consumer_delivery_data[field]
+ elsif user
+ user.send field
+ end
+ end
+
def delivery_context
@delivery_context || 'delivery_plugin/admin_method'
end
diff --git a/plugins/delivery/lib/ext/profile.rb b/plugins/delivery/lib/ext/profile.rb
index a40e513..ebcd856 100644
--- a/plugins/delivery/lib/ext/profile.rb
+++ b/plugins/delivery/lib/ext/profile.rb
@@ -1,7 +1,9 @@
require_dependency 'profile'
-class Profile
+([Profile] + Profile.descendants).each do |subclass|
+subclass.class_eval do
- has_many :delivery_methods, class_name: 'DeliveryPlugin::Method', foreign_key: :profile_id, dependent: :destroy, order: 'id ASC'
+ has_many :delivery_methods, -> { order 'id ASC' }, class_name: 'DeliveryPlugin::Method', foreign_key: :profile_id, dependent: :destroy
end
+end
diff --git a/plugins/delivery/locales/en-US.yml b/plugins/delivery/locales/en-US.yml
index a9aba50..f21f262 100644
--- a/plugins/delivery/locales/en-US.yml
+++ b/plugins/delivery/locales/en-US.yml
@@ -12,16 +12,23 @@
delivery_type: 'Type'
delivery_type_help: 'Pickup: the products will be delivered in the consumption place.
Delivery: the products will be delivered in the address asked by the consumer.'
name: Name
- name_help: Write the name of the Consumption Place or the
- fixed_cost: Fixed cost
- free_over_price: Order's minimum price for free delivery
+ name_help: Write the name of the Consumption Place or the
+
+ costs_legend: Delivery's costs
+ fixed_cost: Fixed cost of delivery
+ free_over_price: Order's minimum value for free delivery
+
+ distribution_legend: Distribution's costs
+ distribution_margin_percentage: Distribution's margin
+ distribution_margin_fixed: Distribution's margin (fixed)
+
instructions: Description
instructions_help: "Write the address and other important informations about the place of this consumption place.
This text will be available"
views:
- delivery_option:
- select:
+ delivery_option:
+ select:
add: Add selected
- _select_content:
+ _select_content:
add: Add option
add_new: "add new"
are_you_sure_you_want: "Are you sure you want to remove?"
@@ -29,14 +36,14 @@
choose_a_delivery_met: "Choose a delivery method from the list"
edit_this: "Edit"
remove_method: "Remove"
- _show:
+ _show:
x: X
- select:
+ select:
add_a_delivery_method: "Add a delivery method to the Orders' Cycle"
method:
index:
new: "New delivery or pickup"
- edit:
+ edit:
add: Add
back: back
save: Save
diff --git a/plugins/delivery/locales/pt-BR.yml b/plugins/delivery/locales/pt-BR.yml
index 26d1e2b..da5b9c4 100644
--- a/plugins/delivery/locales/pt-BR.yml
+++ b/plugins/delivery/locales/pt-BR.yml
@@ -13,15 +13,21 @@
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.
Entrega: os produtos serão entregues no endereço solicitado pelo(a) consumidor(a)."
name: Nome
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.
Para a opção Entrega: escreva o nome do local, (uma cidade ou região) ou a forma de entrega (Correios, transportadora)"
- fixed_cost: Custo
- free_over_price: "Preço mínimo do pedido para Entrega Grátis"
+
+ costs_legend: Custos de entrega
+ fixed_cost: Custo de entrega
+ free_over_price: "Valor mínimo do pedido para Entrega Grátis"
+ distribution_legend: Custos de distribuição
+ distribution_margin_percentage: Margem de distribuição
+ distribution_margin_fixed: Margem de distribuição (valor fixo)
+
instructions: Descrição
instructions_help: "Escreva informações importantes sobre esta opção de Retirada ou Entrega.
Por exemplo, o endereço completo do Núcleo de Consumo, a abrangência da região de entrega.
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."
views:
- delivery_option:
- select:
+ delivery_option:
+ select:
add: "Adicionar selecionados"
- _select_content:
+ _select_content:
add: Adicionar opção
add_new: "adicionar novo"
are_you_sure_you_want: "Tem certeza de que quer remover?"
@@ -29,14 +35,14 @@
choose_a_delivery_met: "Escolha um método de entrega da lista"
edit_this: Editar
remove_method: "Remover"
- _show:
+ _show:
x: X
- select:
+ select:
add_a_delivery_method: "Adicionar um método de entrega ao ciclo de pedidos"
method:
index:
new: "Nova forma de entrega ou retirada"
- edit:
+ edit:
add: Adicionar
back: voltar
save: Salvar
diff --git a/plugins/delivery/models/delivery_plugin/method.rb b/plugins/delivery/models/delivery_plugin/method.rb
index 05398ed..9f03c00 100644
--- a/plugins/delivery/models/delivery_plugin/method.rb
+++ b/plugins/delivery/models/delivery_plugin/method.rb
@@ -1,7 +1,5 @@
class DeliveryPlugin::Method < ActiveRecord::Base
- extend CurrencyHelper::ClassMethods
-
Types = ['pickup', 'deliver']
# see also: Profile::LOCATION_FIELDS
@@ -10,7 +8,7 @@ class DeliveryPlugin::Method < ActiveRecord::Base
].map(&:to_sym)
attr_accessible :profile, :delivery_type, :name, :description,
- :fixed_cost, :free_over_price
+ :fixed_cost, :free_over_price, :distribution_margin_percentage, :distribution_margin_fixed
belongs_to :profile
@@ -20,8 +18,14 @@ class DeliveryPlugin::Method < ActiveRecord::Base
validates_presence_of :name
validates_inclusion_of :delivery_type, in: Types
- scope :pickup, conditions: {delivery_type: 'pickup'}
- scope :delivery, conditions: {delivery_type: 'deliver'}
+ scope :pickup, -> { where delivery_type: 'pickup' }
+ scope :delivery, -> { where delivery_type: 'deliver'}
+
+ extend CurrencyHelper::ClassMethods
+ has_currency :fixed_cost
+ has_currency :free_over_price
+ has_currency :distribution_margin_percentage
+ has_currency :distribution_margin_fixed
def pickup?
self.delivery_type == 'pickup'
@@ -30,22 +34,40 @@ class DeliveryPlugin::Method < ActiveRecord::Base
self.delivery_type == 'deliver'
end
- def has_cost? order_price=nil
+ def has_distribution_margin?
+ (self.distribution_margin_percentage.present? and self.distribution_margin_percentage.nonzero?) or
+ (self.distribution_margin_fixed.present? and self.distribution_margin_fixed.nonzero?)
+ end
+
+ def has_fixed_cost? order_price=nil
if order_price.present? and order_price.nonzero? and self.free_over_price.present? and self.free_over_price.nonzero?
order_price <= self.free_over_price
else
self.fixed_cost.present? and self.fixed_cost.nonzero?
end
end
+
+ def distribution_margin order_price
+ value = 0
+ value += self.distribution_margin_fixed if self.distribution_margin_fixed.present?
+ value += order_price * (self.distribution_margin_percentage/100) if self.distribution_margin_percentage.present?
+ value
+ end
+
+ def has_cost? order_price=nil
+ has_cost = self.has_distribution_margin?
+ has_cost ||= self.has_fixed_cost? order_price
+ end
def free? order_price=nil
!self.has_cost?
end
def cost order_price=nil
- if self.has_cost?(order_price) then self.fixed_cost.to_f else 0 end
+ value = 0
+ value += self.fixed_cost if self.has_fixed_cost? order_price
+ value += self.distribution_margin order_price if self.has_distribution_margin?
+ value
end
- has_currency :fixed_cost
- has_currency :free_over_price
has_currency :cost
protected
diff --git a/plugins/delivery/public/stylesheets/delivery.scss b/plugins/delivery/public/stylesheets/delivery.scss
index a38aac1..1117c65 100644
--- a/plugins/delivery/public/stylesheets/delivery.scss
+++ b/plugins/delivery/public/stylesheets/delivery.scss
@@ -3,7 +3,7 @@
#delivery-method-edition {
@extend .container-clean;
- .field-help {
+ .help-block {
font-size: 10px;
}
}
diff --git a/plugins/delivery/test/test_helper.rb b/plugins/delivery/test/test_helper.rb
new file mode 100644
index 0000000..cca1fd3
--- /dev/null
+++ b/plugins/delivery/test/test_helper.rb
@@ -0,0 +1 @@
+require File.dirname(__FILE__) + '/../../../test/test_helper'
diff --git a/plugins/delivery/test/unit/delivery_plugin/method_test.rb b/plugins/delivery/test/unit/delivery_plugin/method_test.rb
new file mode 100644
index 0000000..9dec65e
--- /dev/null
+++ b/plugins/delivery/test/unit/delivery_plugin/method_test.rb
@@ -0,0 +1,42 @@
+require "#{File.dirname(__FILE__)}/../../test_helper"
+
+class DeliveryPlugin::MethodTest < ActiveSupport::TestCase
+
+ def setup
+ @profile = build(Profile)
+ end
+
+ attr_accessor :profile
+
+ should 'have a name and a delivery type' do
+ dm = DeliveryPlugin::Method.new :name => 'Delivery Deluxe', :delivery_type => 'deliver', :profile => profile
+ assert dm.valid?
+ dm = DeliveryPlugin::Method.new :profile => profile
+ assert !dm.valid?
+ end
+
+ should 'accept only pickup and deliver as delivery types' do
+ dm = build(DeliveryPlugin::Method, :name => 'Delivery Deluxe', :delivery_type => 'unkown', :profile => profile)
+ assert !dm.valid?
+ dm = build(DeliveryPlugin::Method, :name => 'Delivery Deluxe', :delivery_type => 'pickup', :profile => profile)
+ assert dm.valid?
+ dm = build(DeliveryPlugin::Method, :name => 'Delivery Deluxe', :delivery_type => 'deliver', :profile => profile)
+ assert dm.valid?
+ end
+
+ should 'filter by delivery types' do
+ dm_deliver = create(DeliveryPlugin::Method, :name => 'Delivery Deluxe', :delivery_type => 'deliver', :profile => profile)
+ dm_pickup = create(DeliveryPlugin::Method, :name => 'Delivery Deluxe', :delivery_type => 'pickup', :profile => profile)
+ assert_equal [dm_deliver], DeliveryPlugin::Method.delivery
+ assert_equal [dm_pickup], DeliveryPlugin::Method.pickup
+ end
+
+ should 'have many delivery options' do
+ dm = create(DeliveryPlugin::Method, :name => 'Delivery Deluxe', :delivery_type => 'deliver', :profile => profile)
+ cycle = build(OrdersCyclePlugin::Cycle, :name => 'cycle name', :profile => profile)
+ option = create(DeliveryPlugin::Option, :cycle => cycle, :delivery_method => dm)
+
+ assert_equal [option], dm.reload.delivery_options
+ end
+
+end
diff --git a/plugins/delivery/test/unit/delivery_plugin/option_test.rb b/plugins/delivery/test/unit/delivery_plugin/option_test.rb
new file mode 100644
index 0000000..f8a3617
--- /dev/null
+++ b/plugins/delivery/test/unit/delivery_plugin/option_test.rb
@@ -0,0 +1,24 @@
+require "#{File.dirname(__FILE__)}/../../test_helper"
+
+class DeliveryPlugin::OptionTest < ActiveSupport::TestCase
+
+ def setup
+ @profile = build(Profile)
+ @cycle = build(OrdersCyclePluginCycle, :profile => @profile)
+ @delivery_method = build(OrdersCyclePluginMethod, :profile => @profile)
+ end
+
+ attr_accessor :profile
+ attr_accessor :cycle
+ attr_accessor :delivery_method
+
+ should 'be associated with a cycle and a delivery method' do
+ option = OrdersCyclePluginOption.new :cycle => @cycle, :delivery_method => @delivery_method
+ assert option.valid?
+ option = OrdersCyclePluginOption.new
+ :wa
+
+ assert !option.valid?
+ end
+
+end
diff --git a/plugins/delivery/views/delivery_plugin/_order_select.html.slim b/plugins/delivery/views/delivery_plugin/_order_select.html.slim
index 4acc741..4574406 100644
--- a/plugins/delivery/views/delivery_plugin/_order_select.html.slim
+++ b/plugins/delivery/views/delivery_plugin/_order_select.html.slim
@@ -2,30 +2,37 @@
- edition = true if edition.nil?
- readonly = !edition
-div.order-delivery-select
+div.order-delivery-select id='order-#{order.id}'
div.supplier-delivery-data
- = labelled_form_field _('Option'),
- f.select(:supplier_delivery_id, supplier_delivery_options(methods: methods), {}, disabled: readonly,
- onchange: 'delivery.order.select.onChange(this)', onkeyup: 'delivery.order.select.onChange(this)')
- p.instructions
+ - if order.delivery_methods.size > 0
+ = labelled_form_field _('Option'),
+ f.select(:supplier_delivery_id, supplier_delivery_options(methods: methods, selected: order.supplier_delivery_id), {}, disabled: readonly,
+ onchange: 'delivery.order.select.onChange(this)', onkeyup: 'delivery.order.select.onChange(this)') + content_tag('div', '', class: 'help-block instructions')
+ - elsif (name = consumer_delivery_field_value order, :name).present?
+ = labelled_form_field _('Option'),
+ f.text_field(:address, value: name, readonly: true)
+ div class='help-block instructions' = h(consumer_delivery_field_value order, :description)
- div.consumer-delivery-data
- = f.fields_for :consumer_delivery_data, order.consumer_delivery_data do |ff|
- = labelled_form_field _('Address (street and number)'),
- ff.text_field(:address, value: order.consumer_delivery_data[:address], readonly: readonly)
- = labelled_form_field _('Address completion'),
- ff.text_field(:address_line2, value: order.consumer_delivery_data[:address_line2], readonly: readonly)
- = labelled_form_field _('Address reference'),
- ff.text_field(:address_reference, value: order.consumer_delivery_data[:address_reference], readonly: readonly)
- = labelled_form_field _('District'),
- ff.text_field(:district, value: order.consumer_delivery_data[:district], readonly: readonly)
- = labelled_form_field _('City'),
- ff.text_field(:city, value: order.consumer_delivery_data[:city], readonly: readonly)
- = labelled_form_field _('State'),
- ff.text_field(:state, value: order.consumer_delivery_data[:state], readonly: readonly)
- = labelled_form_field _('ZIP code'),
- ff.text_field(:zip_code, value: order.consumer_delivery_data[:zip_code], readonly: readonly)
+ / do not render on confirmation email (@view) if supplier_delivery is pickup
+ - unless (@view and order.supplier_delivery_data[:delivery_type] == 'pickup') or order.delivery_methods.size == 0
+ div.consumer-delivery-data
+ = f.fields_for :consumer_delivery_data do |ff|
+ = labelled_form_field _('Address (street and number)'),
+ ff.text_field(:address, value: consumer_delivery_field_value(order, :address), readonly: readonly)
+ = labelled_form_field _('Address completion'),
+ ff.text_field(:address_line2, value: consumer_delivery_field_value(order, :address_line2), readonly: readonly)
+ = labelled_form_field _('Address reference'),
+ ff.text_field(:address_reference, value: consumer_delivery_field_value(order, :address_reference), readonly: readonly)
+ = labelled_form_field _('District'),
+ ff.text_field(:district, value: consumer_delivery_field_value(order, :district), readonly: readonly)
+ = labelled_form_field _('City'),
+ ff.text_field(:city, value: consumer_delivery_field_value(order, :city), readonly: readonly)
+ = labelled_form_field _('State'),
+ ff.text_field(:state, value: consumer_delivery_field_value(order, :state), readonly: readonly)
+ = labelled_form_field _('ZIP code'),
+ ff.text_field(:zip_code, value: consumer_delivery_field_value(order, :zip_code), readonly: readonly)
+
+javascript:
+ delivery.order.select.onChange($('.order-delivery-select#order-#{order.id} #order_supplier_delivery_id'))
- javascript:
- delivery.order.select.onChange($('#order_supplier_delivery_id'))
diff --git a/plugins/delivery/views/delivery_plugin/admin_method/_edit.html.slim b/plugins/delivery/views/delivery_plugin/admin_method/_edit.html.slim
index 717bfd1..a1f5b24 100644
--- a/plugins/delivery/views/delivery_plugin/admin_method/_edit.html.slim
+++ b/plugins/delivery/views/delivery_plugin/admin_method/_edit.html.slim
@@ -12,15 +12,27 @@
= labelled_field f, :name, t('delivery_plugin.models.method.name'), f.text_field(:name),
help: t('delivery_plugin.models.method.name_help')
= labelled_field f, :description, t('delivery_plugin.models.method.instructions'),
- f.text_area(:description, rows: 5), help: t('delivery_plugin.models.method.instructions_help')
+ f.text_area(:description, rows: 5, class: 'mceEditor'), help: t('delivery_plugin.models.method.instructions_help')
- = labelled_field f, :fixed_cost, t('delivery_plugin.models.method.fixed_cost'),
- 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)}
+ fieldset
+ legend= t'delivery_plugin.models.method.costs_legend'
+ = labelled_field f, :fixed_cost, t('delivery_plugin.models.method.fixed_cost'),
+ 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)}
- = labelled_field f, :free_over_price, t('delivery_plugin.models.method.free_over_price'),
- 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)}
+ = labelled_field f, :free_over_price, t('delivery_plugin.models.method.free_over_price'),
+ 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)}
+
+ fieldset
+ legend= t'delivery_plugin.models.method.distribution_legend'
+ = labelled_field f, :distribution_margin_percentage, t('delivery_plugin.models.method.distribution_margin_percentage'),
+ 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)}
+
+ = labelled_field f, :distribution_margin_fixed, t('delivery_plugin.models.method.distribution_margin_fixed'),
+ 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)}
div
= 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
= link_to_function t('delivery_plugin.views.method.edit.back'), "delivery.method.view.toggle()"
+= render file: 'shared/tiny_mce', locals: {mode: 'simple'}
+
diff --git a/plugins/delivery/views/delivery_plugin/admin_method/_show.html.slim b/plugins/delivery/views/delivery_plugin/admin_method/_show.html.slim
index d9bf24f..2a52072 100644
--- a/plugins/delivery/views/delivery_plugin/admin_method/_show.html.slim
+++ b/plugins/delivery/views/delivery_plugin/admin_method/_show.html.slim
@@ -1,4 +1,4 @@
-td.name title="#{method.description}"
+td.name title="#{strip_tags method.description}"
= method.name
td.actions
- if request.GET[:select_ids].present? and not method.id.to_s.in? Array(request.GET[:selected_ids])
diff --git a/plugins/delivery/views/delivery_plugin/admin_options/_new.js.erb b/plugins/delivery/views/delivery_plugin/admin_options/_new.js.erb
index 56977ec..688733d 100644
--- a/plugins/delivery/views/delivery_plugin/admin_options/_new.js.erb
+++ b/plugins/delivery/views/delivery_plugin/admin_options/_new.js.erb
@@ -1,4 +1,4 @@
-// FIXME: move to orders_cycle plugin
-jQuery('#cycle-delivery-options').html('<%= j render('index', owner: @owner) %>');
+// FIXME: use generic class
+$('#cycle-delivery-options').html('<%= j render('index', owner: @owner) %>');
noosfero.modal.close()
diff --git a/plugins/delivery/views/delivery_plugin/admin_options/select_all.js.erb b/plugins/delivery/views/delivery_plugin/admin_options/select_all.js.erb
new file mode 100644
index 0000000..ea430d1
--- /dev/null
+++ b/plugins/delivery/views/delivery_plugin/admin_options/select_all.js.erb
@@ -0,0 +1,3 @@
+// FIXME: use generic class
+$('#cycle-delivery-options').html('<%= j render('index', owner: @owner) %>');
+
diff --git a/plugins/orders/controllers/myprofile/orders_plugin_admin_controller.rb b/plugins/orders/controllers/myprofile/orders_plugin_admin_controller.rb
index e5989fd..9021d22 100644
--- a/plugins/orders/controllers/myprofile/orders_plugin_admin_controller.rb
+++ b/plugins/orders/controllers/myprofile/orders_plugin_admin_controller.rb
@@ -43,8 +43,8 @@ class OrdersPluginAdminController < MyProfileController
@orders_method = if @actor_name == :supplier then :sales else :purchases end
@order = profile.send(@orders_method).find params[:id]
- return render_access_denied unless @order.verify_actor? profile, @actor_name
- @order.update_attributes params[:order]
+ return render_access_denied unless @user_is_admin or @order.verify_actor? profile, @actor_name
+ @order.update params[:order]
respond_to do |format|
format.js{ render 'orders_plugin_admin/edit' }
diff --git a/plugins/orders/controllers/myprofile/orders_plugin_admin_item_controller.rb b/plugins/orders/controllers/myprofile/orders_plugin_admin_item_controller.rb
index 0085a19..0cc3d32 100644
--- a/plugins/orders/controllers/myprofile/orders_plugin_admin_item_controller.rb
+++ b/plugins/orders/controllers/myprofile/orders_plugin_admin_item_controller.rb
@@ -15,7 +15,7 @@ class OrdersPluginAdminItemController < MyProfileController
@actor_name = params[:actor_name].to_sym
@order = if @actor_name == :consumer then @item.purchase else @item.sale end
- @item.update_attributes! params[:item]
+ @item.update! params[:item]
end
def add_search
diff --git a/plugins/orders/controllers/myprofile/orders_plugin_item_controller.rb b/plugins/orders/controllers/myprofile/orders_plugin_item_controller.rb
index 66180e6..f1d5a70 100644
--- a/plugins/orders/controllers/myprofile/orders_plugin_item_controller.rb
+++ b/plugins/orders/controllers/myprofile/orders_plugin_item_controller.rb
@@ -23,7 +23,7 @@ class OrdersPluginItemController < MyProfileController
if params[:item].present? and set_quantity_consumer_ordered params[:item][:quantity_consumer_ordered]
params[:item][:quantity_consumer_ordered] = @quantity_consumer_ordered
- @item.update_attributes! params[:item]
+ @item.update! params[:item]
end
end
diff --git a/plugins/orders/controllers/profile/orders_plugin_order_controller.rb b/plugins/orders/controllers/profile/orders_plugin_order_controller.rb
index ea9d691..606a186 100644
--- a/plugins/orders/controllers/profile/orders_plugin_order_controller.rb
+++ b/plugins/orders/controllers/profile/orders_plugin_order_controller.rb
@@ -8,6 +8,7 @@ class OrdersPluginOrderController < ProfileController
before_filter :load_order, except: [:new]
before_filter :check_access, only: [:confirm, :remove, :cancel]
before_filter :set_actor_name
+ before_filter :disable_purechat
helper OrdersPlugin::TranslationHelper
helper OrdersPlugin::DisplayHelper
@@ -19,7 +20,7 @@ class OrdersPluginOrderController < ProfileController
def load_order
@order = hmvc_orders_context::Sale.find_by_id params[:id]
- render_access_denied if @order.present? and not @order.may_view? user
+ render_access_denied if @order.present? and (not @user_is_admin or not @order.may_view? user)
end
def check_access access = 'view'
@@ -40,4 +41,8 @@ class OrdersPluginOrderController < ProfileController
extend HMVC::ClassMethods
hmvc OrdersPlugin, orders_context: OrdersPlugin
+ def disable_purechat
+ @disable_purechat = true
+ end
+
end
diff --git a/plugins/orders/db/migrate/20150627232432_add_status_to_orders_plugin_item.rb b/plugins/orders/db/migrate/20150627232432_add_status_to_orders_plugin_item.rb
new file mode 100644
index 0000000..bbef9aa
--- /dev/null
+++ b/plugins/orders/db/migrate/20150627232432_add_status_to_orders_plugin_item.rb
@@ -0,0 +1,15 @@
+class AddStatusToOrdersPluginItem < ActiveRecord::Migration
+
+ def change
+ add_column :orders_plugin_items, :status, :string
+ add_column :orders_plugin_orders, :building_next_status, :boolean
+
+ say_with_time "filling items' statuses..." do
+ OrdersPlugin::Item.includes(:order).find_each batch_size: 50 do |item|
+ next item.destroy if item.order.nil?
+ item.fill_status
+ end
+ end
+ end
+
+end
diff --git a/plugins/orders/lib/code_numbering.rb b/plugins/orders/lib/code_numbering.rb
new file mode 100644
index 0000000..843cc33
--- /dev/null
+++ b/plugins/orders/lib/code_numbering.rb
@@ -0,0 +1,58 @@
+module CodeNumbering
+ module ClassMethods
+ def code_numbering field, options = {}
+ class_attribute :code_numbering_field
+ class_attribute :code_numbering_options
+
+ self.code_numbering_field = field
+ self.code_numbering_options = options
+
+ before_create :create_code_numbering
+
+ include CodeNumbering::InstanceMethods
+ end
+ end
+
+ module InstanceMethods
+
+ def code
+ self.attributes[self.code_numbering_field.to_s]
+ end
+
+ def code_scope
+ scope = self.code_numbering_options[:scope]
+ case scope
+ when Symbol
+ self.send scope
+ when Proc
+ instance_exec &scope
+ else
+ self.class
+ end
+ end
+
+ def code_maximum
+ self.code_scope.maximum(self.code_numbering_field) || 0
+ end
+
+ def create_code_numbering
+ max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start]
+ max = self.code_maximum
+ self.send "#{self.code_numbering_field}=", max+1
+ end
+
+ def reset_scope_code_numbering
+ max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start]
+ max ||= 1
+
+ self.code_scope.order(:created_at).each do |record|
+ record.update_column self.code_numbering_field, max
+ max += 1
+ end
+ self.reload
+ end
+
+ end
+end
+
+ActiveRecord::Base.extend CodeNumbering::ClassMethods
diff --git a/plugins/orders/lib/ext/profile.rb b/plugins/orders/lib/ext/profile.rb
index e78a842..03cdcff 100644
--- a/plugins/orders/lib/ext/profile.rb
+++ b/plugins/orders/lib/ext/profile.rb
@@ -1,39 +1,42 @@
require_dependency 'profile'
+require_dependency 'community'
-# FIXME move to core
-class Profile
-
- def has_admin? person
- return unless person
- person.has_permission? 'edit_profile', self
- end
-
-end
-
-class Profile
+([Profile] + Profile.descendants).each do |subclass|
+subclass.class_eval do
# cannot use :order because of months/years named_scope
has_many :orders, class_name: 'OrdersPlugin::Sale', foreign_key: :profile_id
has_many :sales, class_name: 'OrdersPlugin::Sale', foreign_key: :profile_id
has_many :purchases, class_name: 'OrdersPlugin::Purchase', foreign_key: :consumer_id
- has_many :ordered_items, through: :orders, source: :items, order: 'name ASC'
+ has_many :ordered_items, -> { order 'name ASC' }, through: :orders, source: :items
has_many :sales_consumers, through: :sales, source: :consumer
- has_many :purchases_consumers, through: :purchases, source: :consumer
+ has_many :purchases_consumers, through: :sales, source: :consumer
has_many :sales_profiles, through: :sales, source: :profile
- has_many :purchases_profiles, through: :purchases, source: :profile
+ has_many :purchases_profiles, through: :sales, source: :profile
+
+end
+end
+
+class Profile
+
+ # FIXME move to core
+ def has_admin? person
+ return unless person
+ person.has_permission? 'edit_profile', self
+ end
def sales_all_consumers
consumers = self.sales_consumers.order 'name ASC'
- consumers.concat self.consumers.except_self.order('name ASC') if self.respond_to? :consumers
+ consumers.concat self.suppliers.except_self.order('name ASC') if self.respond_to? :suppliers
consumers.uniq
end
- def purchases_all_suppliers
- suppliers = self.purchases_profiles.order 'name ASC'
- suppliers.concat self.suppliers.except_self.order('name ASC') if self.respond_to? :suppliers
- suppliers.uniq
+ def purchases_all_consumers
+ consumers = self.purchases_consumers.order 'name ASC'
+ consumers.concat self.consumers.except_self.order('name ASC') if self.respond_to? :consumers
+ consumers.uniq
end
def self.create_orders_manager_role env_id
diff --git a/plugins/orders/lib/ext/session_store.rb b/plugins/orders/lib/ext/session_store.rb
index 678e4c5..a8617b1 100644
--- a/plugins/orders/lib/ext/session_store.rb
+++ b/plugins/orders/lib/ext/session_store.rb
@@ -1,6 +1,6 @@
-require 'active_record/session_store'
+require_dependency 'session'
-class ActiveRecord::SessionStore::Session
+class Session
has_many :orders, primary_key: :session_id, foreign_key: :session_id, class_name: 'OrdersPlugin::Order'
diff --git a/plugins/orders/lib/orders_plugin/display_helper.rb b/plugins/orders/lib/orders_plugin/display_helper.rb
index 46220d8..a45bb24 100644
--- a/plugins/orders/lib/orders_plugin/display_helper.rb
+++ b/plugins/orders/lib/orders_plugin/display_helper.rb
@@ -2,6 +2,8 @@ module OrdersPlugin::DisplayHelper
protected
+ include HelpHelper
+
include OrdersPlugin::TranslationHelper
include OrdersPlugin::PriceHelper
include OrdersPlugin::DateHelper
@@ -9,7 +11,8 @@ module OrdersPlugin::DisplayHelper
include OrdersPlugin::TableHelper
include OrdersPlugin::AdminHelper
include OrdersPlugin::JavascriptHelper
- include HelpHelper
+
+ include DeliveryPlugin::DisplayHelper
# come on, you can't replace a rails api method (button_to_function was)!
def submit_to_function name, function, html_options={}
diff --git a/plugins/orders/lib/orders_plugin/field_helper.rb b/plugins/orders/lib/orders_plugin/field_helper.rb
index 13216a4..2ab0287 100644
--- a/plugins/orders/lib/orders_plugin/field_helper.rb
+++ b/plugins/orders/lib/orders_plugin/field_helper.rb
@@ -6,7 +6,7 @@ module OrdersPlugin::FieldHelper
help = options.delete(:help)
content_tag :div,
if form then form.label field, label, class: 'control-label' else label_tag field, label, class: 'control-label' end +
- content_tag('div', help, class: 'field-help') +
+ content_tag('div', help, class: 'help-block') +
content_tag('div', field_html, class: 'field-box') +
content_tag('div', '', style: 'clear: both'),
options.merge(class: options[:class].to_s + ' field form-group')
diff --git a/plugins/orders/lib/orders_plugin/mailer.rb b/plugins/orders/lib/orders_plugin/mailer.rb
index 7cf4cd7..4d45f47 100644
--- a/plugins/orders/lib/orders_plugin/mailer.rb
+++ b/plugins/orders/lib/orders_plugin/mailer.rb
@@ -4,8 +4,6 @@ class OrdersPlugin::Mailer < Noosfero::Plugin::MailerBase
helper ApplicationHelper
helper OrdersPlugin::DisplayHelper
- helper OrdersPlugin::DateHelper
- helper OrdersPlugin::TranslationHelper
attr_accessor :environment
attr_accessor :profile
@@ -82,4 +80,10 @@ class OrdersPlugin::Mailer < Noosfero::Plugin::MailerBase
end
end
+ # for order/show_simple form
+ def protect_against_forgery?
+ false
+ end
+ helper_method :protect_against_forgery?
+
end
diff --git a/plugins/orders/lib/orders_plugin/report.rb b/plugins/orders/lib/orders_plugin/report.rb
index 779b274..ba6145b 100644
--- a/plugins/orders/lib/orders_plugin/report.rb
+++ b/plugins/orders/lib/orders_plugin/report.rb
@@ -142,6 +142,7 @@ module OrdersPlugin::Report
productsStart = sbs+5
productsEnd = 0
selled_sum = 0
+ total_price_without_margin = 0
orders.each do |order|
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
style: [default,default,default,default,default,currency,currency],
formula_values: [nil,nil,nil,nil,nil,nil,formula_value_s]
selled_sum += item.status_quantity * item.price rescue 0
+ total_price_without_margin += item.price_without_margins * item.status_quantity
sbe += 1
sum += formula_value
@@ -200,12 +202,11 @@ module OrdersPlugin::Report
sbs = sbe + 2
end
- sheet.add_row [t('lib.report.selled_total'), '', "=SUM(G#{productsStart}:G#{productsEnd})"],
- formula_values: [nil,nil, selled_sum],
- style: [redcell,redcell,currency]
-
- ["A#{sbs}:B#{sbs}"].each{ |c| sheet.merge_cells c }
+ sheet.add_row [t('lib.report.selled_total'), '', "=SUM(G#{productsStart}:G#{productsEnd})", t('lib.report.total_price_without_margin'),"","", total_price_without_margin],
+ formula_values: [nil, nil, selled_sum, nil, nil, nil, nil],
+ style: [redcell, redcell, currency, redcell, redcell, redcell, currency]
+ ["A#{sbs}:B#{sbs}", "D#{sbs}:F{sbs}"].each{ |c| sheet.merge_cells c }
sheet.column_widths 15,30,30,9,8,10,11
end # closes spreadsheet
diff --git a/plugins/orders/locales/en-US.yml b/plugins/orders/locales/en-US.yml
index d7c3858..6fd6a81 100644
--- a/plugins/orders/locales/en-US.yml
+++ b/plugins/orders/locales/en-US.yml
@@ -1,4 +1,9 @@
-"en-US": &en-US
+en-US: &en-US
+
+ number:
+ currency:
+ format:
+ xlsx_currency: "[$$-409]* #.##0,00;[RED]-[$$-409]* #.##0,00"
orders_plugin:
terms:
@@ -77,6 +82,7 @@
supplier: "%{terms.supplier.singular.capitalize}"
total_parcel_value: "Total value using stock"
total_selled_value: "Total selled value"
+ total_price_without_margin: "Total price without margin"
total_value: "Total Value"
un: un.
value: value
@@ -299,8 +305,8 @@
supplier_product: "%{terms.supplier.singular.capitalize}/Product"
total: "TOTAL:"
-'en_US':
+en_US:
<<: *en-US
-'en':
+en:
<<: *en-US
diff --git a/plugins/orders/locales/pt-BR.yml b/plugins/orders/locales/pt-BR.yml
index afc983d..1680442 100644
--- a/plugins/orders/locales/pt-BR.yml
+++ b/plugins/orders/locales/pt-BR.yml
@@ -1,4 +1,9 @@
-"pt-BR": &pt-BR
+pt-BR: &pt-BR
+
+ number:
+ currency:
+ format:
+ xlsx_currency: "[$R$-416]* #,##0.00;[RED]-[$R$-416]* #,##0.00"
orders_plugin:
terms:
@@ -78,6 +83,7 @@
supplier: "%{terms.supplier.singular.capitalize}"
total_parcel_value: "Valor total usando estoque"
total_selled_value: "Valor total vendido"
+ total_price_without_margin: "Valor total sem a margem"
total_value: "total pago"
un: un.
value: Valor
@@ -299,8 +305,8 @@
supplier_product: "%{terms.supplier.singular.capitalize}/Produto"
total: "TOTAL:"
-'pt_BR':
+pt_BR:
<<: *pt-BR
-'pt':
+pt:
<<: *pt-BR
diff --git a/plugins/orders/models/orders_plugin/item.rb b/plugins/orders/models/orders_plugin/item.rb
index 7f0c3ba..add5f13 100644
--- a/plugins/orders/models/orders_plugin/item.rb
+++ b/plugins/orders/models/orders_plugin/item.rb
@@ -7,6 +7,13 @@ class OrdersPlugin::Item < ActiveRecord::Base
# flag used by items to compare them with products
attr_accessor :product_diff
+ Statuses = %w[ordered accepted separated delivered received]
+ DbStatuses = %w[draft planned cancelled] + Statuses
+ UserStatuses = %w[open forgotten planned cancelled] + Statuses
+ StatusText = {}; UserStatuses.map do |status|
+ StatusText[status] = "orders_plugin.models.order.statuses.#{status}"
+ end
+
# should be Order, but can't reference it here so it would create a cyclic reference
StatusAccessMap = {
'ordered' => :consumer,
@@ -28,9 +35,9 @@ class OrdersPlugin::Item < ActiveRecord::Base
serialize :data
- belongs_to :order, class_name: 'OrdersPlugin::Order', foreign_key: :order_id, touch: true
- belongs_to :sale, class_name: 'OrdersPlugin::Sale', foreign_key: :order_id, touch: true
- belongs_to :purchase, class_name: 'OrdersPlugin::Purchase', foreign_key: :order_id, touch: true
+ belongs_to :order, class_name: '::OrdersPlugin::Order', foreign_key: :order_id, touch: true
+ belongs_to :sale, class_name: '::OrdersPlugin::Sale', foreign_key: :order_id, touch: true
+ belongs_to :purchase, class_name: '::OrdersPlugin::Purchase', foreign_key: :order_id, touch: true
belongs_to :product
has_one :supplier, through: :product
@@ -40,28 +47,30 @@ class OrdersPlugin::Item < ActiveRecord::Base
# FIXME: don't work because of load order
#if defined? SuppliersPlugin
- has_many :from_products, through: :product, source: :orders
+ has_many :from_products, through: :product
+ has_one :from_product, through: :product
has_many :to_products, through: :product
- has_many :sources_supplier_products, through: :product, source: :items
- has_many :supplier_products, through: :product, source: :enterprise
+ has_one :to_product, through: :product
+ has_many :sources_supplier_products, through: :product
+ has_one :sources_supplier_product, through: :product
+ has_many :supplier_products, through: :product
+ has_one :supplier_product, through: :product
has_many :suppliers, through: :product
+ has_one :supplier, through: :product
#end
- def from_product
- self.from_products.first
- end
- def supplier_product
- self.supplier_products.first
- end
- scope :ordered, conditions: ['orders_plugin_orders.status = ?', 'ordered'], joins: [:order]
- scope :for_product, lambda{ |product| {conditions: {product_id: product.id}} }
+ scope :ordered, -> { joins(:order).where 'orders_plugin_orders.status = ?', 'ordered' }
+ scope :for_product, -> (product) { where product_id: product.id }
default_scope include: [:product]
validate :has_order
validates_presence_of :product
+ validates_inclusion_of :status, in: DbStatuses
+ before_validation :set_defaults
before_save :save_calculated_prices
+ before_save :step_status
before_create :sync_fields
# utility for other classes
@@ -104,6 +113,9 @@ class OrdersPlugin::Item < ActiveRecord::Base
def price
self[:price] || (self.product.price_with_discount || 0 rescue nil)
end
+ def price_without_margins
+ self.product.price_without_margins rescue self.price
+ end
def unit
self.product.unit
end
@@ -121,8 +133,15 @@ class OrdersPlugin::Item < ActiveRecord::Base
end
end
- def status
- self.order.status
+ def calculated_status
+ status = self.order.status
+ index = Statuses.index status
+ next_status = Statuses[index+1] if index
+ next_quantity = "quantity_#{StatusDataMap[next_status]}" if next_status
+ if next_status and self.send next_quantity then next_status else status end
+ end
+ def on_next_status?
+ self.order.status != self.calculated_status
end
# product used for comparizon when repeating an order
@@ -144,13 +163,13 @@ class OrdersPlugin::Item < ActiveRecord::Base
def status_quantity_field
@status_quantity_field ||= begin
- status = StatusDataMap[self.order.status] || 'consumer_ordered'
+ status = StatusDataMap[self.status] || 'consumer_ordered'
"quantity_#{status}"
end
end
def status_price_field
@status_price_field ||= begin
- status = StatusDataMap[self.order.status] || 'consumer_ordered'
+ status = StatusDataMap[self.status] || 'consumer_ordered'
"price_#{status}"
end
end
@@ -184,10 +203,10 @@ class OrdersPlugin::Item < ActiveRecord::Base
def quantity_price_data actor_name
data = {flags: {}}
- statuses = OrdersPlugin::Order::Statuses
+ statuses = ::OrdersPlugin::Order::Statuses
statuses_data = data[:statuses] = {}
- current = statuses.index(self.order.status) || 0
+ current = statuses.index(self.status) || 0
next_status = self.order.next_status actor_name
next_index = statuses.index(next_status) || current + 1
goto_next = actor_name == StatusAccessMap[next_status]
@@ -266,8 +285,11 @@ class OrdersPlugin::Item < ActiveRecord::Base
# Set access
statuses_data.each.with_index do |(status, status_data), i|
- status_data[:flags][:editable] = true if StatusAccessMap[status] == actor_name
- # code to only allow last status
+ #consumer_may_edit = actor_name == :consumer and status == 'ordered' and self.order.open?
+ if StatusAccessMap[status] == actor_name
+ status_data[:flags][:editable] = true
+ end
+ # only allow last status
#status_data[:flags][:editable] = true if status_data[:access] == actor_name and (status_data[:flags][:admin] or self.order.open?)
end
@@ -279,6 +301,14 @@ class OrdersPlugin::Item < ActiveRecord::Base
self.save_calculated_prices
end
+ # used by db/migrate/20150627232432_add_status_to_orders_plugin_item.rb
+ def fill_status
+ status = self.calculated_status
+ return if self.status == status
+ self.update_column :status, status
+ self.order.update_column :building_next_status, true if self.order.status != status and not self.order.building_next_status
+ end
+
protected
def save_calculated_prices
@@ -288,6 +318,17 @@ class OrdersPlugin::Item < ActiveRecord::Base
end
end
+ def set_defaults
+ self.status ||= Statuses.first
+ end
+
+ def step_status
+ status = self.calculated_status
+ return if self.status == status
+ self.status = status
+ self.order.update_column :building_next_status, true if self.order.status != status and not self.order.building_next_status
+ end
+
def has_order
self.order or self.sale or self.purchase
end
diff --git a/plugins/orders/models/orders_plugin/order.rb b/plugins/orders/models/orders_plugin/order.rb
index 66f991a..72a0378 100644
--- a/plugins/orders/models/orders_plugin/order.rb
+++ b/plugins/orders/models/orders_plugin/order.rb
@@ -1,11 +1,12 @@
class OrdersPlugin::Order < ActiveRecord::Base
- Statuses = %w[ordered accepted separated delivered received]
- DbStatuses = %w[draft planned cancelled] + Statuses
- UserStatuses = %w[open forgotten planned cancelled] + Statuses
- StatusText = {}; UserStatuses.map do |status|
- StatusText[status] = "orders_plugin.models.order.statuses.#{status}"
- end
+ # if abstract_class is true then it will trigger https://github.com/rails/rails/issues/20871
+ #self.abstract_class = true
+
+ Statuses = ::OrdersPlugin::Item::Statuses
+ DbStatuses = ::OrdersPlugin::Item::DbStatuses
+ UserStatuses = ::OrdersPlugin::Item::UserStatuses
+ StatusText = ::OrdersPlugin::Item::StatusText
# oh, we need a payments plugin!
PaymentMethods = {
@@ -31,18 +32,14 @@ class OrdersPlugin::Order < ActiveRecord::Base
]
# copy, for easiness. can't be declared to here to avoid cyclic reference
- StatusDataMap = OrdersPlugin::Item::StatusDataMap
- StatusAccessMap = OrdersPlugin::Item::StatusAccessMap
+ StatusDataMap = ::OrdersPlugin::Item::StatusDataMap
+ StatusAccessMap = ::OrdersPlugin::Item::StatusAccessMap
StatusesByActor = {
consumer: StatusAccessMap.map{ |s, a| s if a == :consumer }.compact,
supplier: StatusAccessMap.map{ |s, a| s if a == :supplier }.compact,
}
- # workaround for STI
- self.table_name = :orders_plugin_orders
- self.abstract_class = true
-
attr_accessible :status, :consumer, :profile,
:supplier_delivery_id, :consumer_delivery_id, :supplier_delivery_data, :consumer_delivery_data
@@ -51,17 +48,17 @@ class OrdersPlugin::Order < ActiveRecord::Base
belongs_to :supplier, foreign_key: :profile_id, class_name: 'Profile'
belongs_to :consumer, class_name: 'Profile'
- belongs_to :session, primary_key: :session_id, foreign_key: :session_id, class_name: 'ActiveRecord::SessionStore::Session'
+ belongs_to :session, primary_key: :session_id, foreign_key: :session_id, class_name: 'Session'
- has_many :items, class_name: 'OrdersPlugin::Item', foreign_key: :order_id, dependent: :destroy, order: 'name ASC'
+ has_many :items, -> { order 'name ASC' }, class_name: 'OrdersPlugin::Item', foreign_key: :order_id, dependent: :destroy
has_many :products, through: :items
belongs_to :supplier_delivery, class_name: 'DeliveryPlugin::Method'
belongs_to :consumer_delivery, class_name: 'DeliveryPlugin::Method'
- scope :alphabetical, -> { joins(:consumer).order 'profiles.name ASC' }
- scope :latest, -> { order 'code ASC' }
- scope :default_order, -> { order 'code DESC' }
+ scope :alphabetical, -> { joins(:consumer).reorder 'profiles.name ASC' }
+ scope :latest, -> { reorder 'code ASC' }
+ scope :default_order, -> { reorder 'code DESC' }
scope :of_session, -> session_id { where session_id: session_id }
scope :of_user, -> session_id, consumer_id=nil do
@@ -73,53 +70,50 @@ class OrdersPlugin::Order < ActiveRecord::Base
scope :latest, order: 'created_at DESC'
- scope :draft, conditions: {status: 'draft'}
- scope :planned, conditions: {status: 'planned'}
- scope :cancelled, conditions: {status: 'cancelled'}
- scope :not_cancelled, conditions: ["status <> 'cancelled'"]
- scope :ordered, conditions: ['ordered_at IS NOT NULL']
- scope :confirmed, conditions: ['ordered_at IS NOT NULL']
- scope :accepted, conditions: ['accepted_at IS NOT NULL']
- scope :separated, conditions: ['separated_at IS NOT NULL']
- scope :delivered, conditions: ['delivered_at IS NOT NULL']
- scope :received, conditions: ['received_at IS NOT NULL']
-
- scope :for_profile, lambda{ |profile| {conditions: {profile_id: profile.id}} }
- scope :for_profile_id, lambda{ |profile_id| {conditions: {profile_id: profile_id}} }
- scope :for_supplier, lambda{ |profile| {conditions: {profile_id: profile.id}} }
- scope :for_supplier_id, lambda{ |profile_id| {conditions: {profile_id: profile_id}} }
- scope :for_consumer, lambda{ |consumer| {conditions: {consumer_id: (consumer.id rescue nil)}} }
- scope :for_consumer_id, lambda{ |consumer_id| {conditions: {consumer_id: consumer_id}} }
-
- scope :months, select: 'DISTINCT(EXTRACT(months FROM orders_plugin_orders.created_at)) as month', order: 'month DESC'
- scope :years, select: 'DISTINCT(EXTRACT(YEAR FROM orders_plugin_orders.created_at)) as year', order: 'year DESC'
-
- scope :by_month, lambda { |month|
- where 'EXTRACT(month FROM orders_plugin_orders.created_at) <= :month AND EXTRACT(month FROM orders_plugin_orders.created_at) >= :month',{ month: month }
+ scope :draft, -> { where status: 'draft' }
+ scope :planned, -> { where status: 'planned' }
+ scope :cancelled, -> { where status: 'cancelled' }
+ scope :not_cancelled, -> { where "status <> 'cancelled'" }
+ scope :ordered, -> { where 'ordered_at IS NOT NULL' }
+ scope :confirmed, -> { where 'ordered_at IS NOT NULL' }
+ scope :accepted, -> { where 'accepted_at IS NOT NULL' }
+ scope :separated, -> { where 'separated_at IS NOT NULL' }
+ scope :delivered, -> { where 'delivered_at IS NOT NULL' }
+ scope :received, -> { where 'received_at IS NOT NULL' }
+
+ scope :for_profile, -> (profile) { where profile_id: profile.id }
+ scope :for_profile_id, -> (profile_id) { where profile_id: profile_id }
+ scope :for_supplier, -> (profile) { where profile_id: profile.id }
+ scope :for_supplier_id, -> (profile_id) { where profile_id: profile_id }
+ scope :for_consumer, -> (consumer) { where consumer_id: (consumer.id rescue nil) }
+ scope :for_consumer_id, -> (consumer_id) { where consumer_id: consumer_id }
+
+ scope :months, -> { select('DISTINCT(EXTRACT(months FROM orders_plugin_orders.created_at)) as month').order('month DESC') }
+ scope :years, -> { select('DISTINCT(EXTRACT(YEAR FROM orders_plugin_orders.created_at)) as year').order('year DESC') }
+
+ scope :by_month, -> (month) {
+ where 'EXTRACT(month FROM orders_plugin_orders.created_at) <= :month AND EXTRACT(month FROM orders_plugin_orders.created_at) >= :month', month: month
}
- scope :by_year, lambda { |year|
- where 'EXTRACT(year FROM orders_plugin_orders.created_at) <= :year AND EXTRACT(year FROM orders_plugin_orders.created_at) >= :year', { year: year }
+ scope :by_year, -> (year) {
+ where 'EXTRACT(year FROM orders_plugin_orders.created_at) <= :year AND EXTRACT(year FROM orders_plugin_orders.created_at) >= :year', year: year
}
- scope :by_range, lambda { |start_time, end_time|
- where 'orders_plugin_orders.created_at >= :start AND orders_plugin_orders.created_at <= :end', { start: start_time, end: end_time }
+ scope :by_range, -> (start_time, end_time) {
+ where 'orders_plugin_orders.created_at >= :start AND orders_plugin_orders.created_at <= :end', start: start_time, end: end_time
}
- scope :with_status, lambda { |status|
- where status: status
- }
- scope :with_code, lambda { |code|
- where code: code
- }
+ scope :with_status, -> (status) { where status: status }
+ scope :with_code, -> (code) { where code: code }
validates_presence_of :profile
# consumer is optional, as orders can be made by unlogged users
validates_inclusion_of :status, in: DbStatuses
before_validation :check_status
+ before_validation :change_status
after_save :send_notifications
extend CodeNumbering::ClassMethods
- code_numbering :code, scope: proc{ self.profile.orders }
+ code_numbering :code, scope: -> { self.profile.orders }
serialize :data
@@ -165,17 +159,17 @@ class OrdersPlugin::Order < ActiveRecord::Base
# / Items
# / \ OfferedProduct (column product_id)
# Order / \ SourceProduct from DistributedProduct (quantity=1, always)
- # \ SourceProduct from Product* (quantity be more than 1 if DistributedProduct is an agregate product)
+ # \ SourceProduct from Product* (multiple for each if is an aggregate product)
# for order outside cycle we have
# / Items
# / \ SourceProduct from DistributedProduct (quantity=1, always)
- # Order / \ SourceProduct from Product* (quantity be more than 1 if DistributedProduct is an agregate product)
+ # Order / \ SourceProduct from Product* (multiple for each if is an aggregate product)
#
# *suppliers usually don't distribute using cycles, so they only have Product
#
def self.supplier_products_by_suppliers orders
products_by_supplier = {}
- items = OrdersPlugin::Item.where(order_id: orders.map(&:id)).includes({sources_supplier_products: [:supplier, :from_product]})
+ items = self.parent::Item.where(order_id: orders.map(&:id)).includes(sources_supplier_products: [:supplier, :from_product])
items.each do |item|
if item.sources_supplier_products.present?
item.sources_supplier_products.each do |source_sp|
@@ -358,15 +352,14 @@ class OrdersPlugin::Order < ActiveRecord::Base
# total_price considering last state
def total_price actor_name = :consumer, admin = false
- if not self.pre_order? and admin and status = self.next_status(actor_name)
- self.fill_items_data self.status, status
+ # for admins, we want the next_status while we concluded the finish status change
+ if admin
+ price = :status_price
else
- status = self.status
+ data = StatusDataMap[self.status] || StatusDataMap[Statuses.first]
+ price = "price_#{data}".to_sym
end
- data = StatusDataMap[status] || StatusDataMap[Statuses.first]
- price = "price_#{data}".to_sym
-
items ||= (self.ordered_items rescue nil) || self.items
items.collect(&price).inject(0){ |sum, p| sum + p.to_f }
end
@@ -379,7 +372,8 @@ class OrdersPlugin::Order < ActiveRecord::Base
end
has_currency :total
- def fill_items_data from_status, to_status, save = false
+ def fill_items from_status, to_status, save = false
+ # check for status advance
return if (Statuses.index(to_status) <= Statuses.index(from_status) rescue true)
from_data = StatusDataMap[from_status]
@@ -405,15 +399,22 @@ class OrdersPlugin::Order < ActiveRecord::Base
self.status ||= 'draft'
# backwards compatibility
self.status = 'ordered' if self.status == 'confirmed'
+ end
+
+ def change_status
+ return if self.status_was == self.status
- self.fill_items_data self.status_was, self.status, true
+ self.fill_items self.status_was, self.status, true
+ self.items.update_all status: self.status
+ self.building_next_status = false
+ # fill dates on status advance
if self.status_on? 'ordered'
Statuses.each do |status|
self.send "#{self.status}_at=", Time.now if self.status_was != status and self.status == status
end
else
- # for draft, planned, forgotten, cancelled, etc
+ # status rewind for draft, planned, forgotten, cancelled, etc
Statuses.each do |status|
self.send "#{status}_at=", nil
end
diff --git a/plugins/orders/models/orders_plugin/sale.rb b/plugins/orders/models/orders_plugin/sale.rb
index b8dd778..f59b1b3 100644
--- a/plugins/orders/models/orders_plugin/sale.rb
+++ b/plugins/orders/models/orders_plugin/sale.rb
@@ -1,5 +1,7 @@
class OrdersPlugin::Sale < OrdersPlugin::Order
+ before_validation :fill_default_supplier_delivery
+
def orders_name
'sales'
end
@@ -19,6 +21,17 @@ class OrdersPlugin::Sale < OrdersPlugin::Order
has_number_with_locale :purchase_quantity_total
has_currency :purchase_price_total
+ def supplier_delivery
+ super || (self.delivery_methods.first rescue nil)
+ end
+ def supplier_delivery_id
+ self[:supplier_delivery_id] || (self.supplier_delivery.id rescue nil)
+ end
+
+ def fill_default_supplier_delivery
+ self[:supplier_delivery_id] ||= self.supplier_delivery.id if self.supplier_delivery
+ end
+
protected
end
diff --git a/plugins/orders/orders b/plugins/orders/orders
new file mode 120000
index 0000000..cd47dfd
--- /dev/null
+++ b/plugins/orders/orders
@@ -0,0 +1 @@
+/home/braulio/Projects/noosfero-ecosol/noosfero/plugins/orders
\ No newline at end of file
diff --git a/plugins/orders/public/javascripts/orders.js b/plugins/orders/public/javascripts/orders.js
index 5f5e070..e5b4738 100644
--- a/plugins/orders/public/javascripts/orders.js
+++ b/plugins/orders/public/javascripts/orders.js
@@ -139,21 +139,12 @@ orders = {
},
},
- set_orders_container_max_height: function()
+ setOrderMaxHeight: function()
{
ordersH = $(window).height();
- ordersH -= 100
ordersH -= $('#cirandas-top-bar').outerHeight()
- ordersH -= $('.order-status-message').outerHeight()
- ordersH -= $('.order-message-title').outerHeight()
- ordersH -= $('#order-column .order-items .table-header').last().outerHeight()
- ordersH -= $('#order-column .order-total').last().outerHeight()
- ordersH -= $('#order-column #actor-data-box').last().outerHeight()
- ordersH -= $('#order-column .delivery-box').outerHeight()
- ordersH -= $('#order-column .order-message-text').outerHeight()
- ordersH -= $('#order-column .order-message-actions').outerHeight()
- ordersH -= $('#order-column .actions').outerHeight()
- $('.order-items-container .order-items-scroll').css('max-height', ordersH);
+ ordersH -= $('.order-view form > .actions').outerHeight(true)
+ $('.order-view .order-data').css('max-height', ordersH);
},
daterangepicker: {
@@ -180,6 +171,7 @@ orders = {
},
};
-$(document).ready(orders.set_orders_container_max_height);
-$(window).resize(orders.set_orders_container_max_height);
+$(document).ready(orders.setOrderMaxHeight);
+$(window).resize(orders.setOrderMaxHeight);
+$('#order_supplier_delivery_id').change(orders.setOrderMaxHeight);
diff --git a/plugins/orders/public/public b/plugins/orders/public/public
new file mode 120000
index 0000000..20e6770
--- /dev/null
+++ b/plugins/orders/public/public
@@ -0,0 +1 @@
+/home/braulio/Projects/noosfero-ecosol/noosfero/config/plugins/orders/public
\ No newline at end of file
diff --git a/plugins/orders/public/stylesheets/_field.scss b/plugins/orders/public/stylesheets/_field.scss
index aadadf4..32d1dcd 100644
--- a/plugins/orders/public/stylesheets/_field.scss
+++ b/plugins/orders/public/stylesheets/_field.scss
@@ -25,9 +25,8 @@
float: left;
width: 100%;
}
- .field-help {
+ .help-block {
clear: both;
- margin-bottom: $half-margin;
font-size: 10px;
}
diff --git a/plugins/orders/public/stylesheets/_items.scss b/plugins/orders/public/stylesheets/_items.scss
index ff1d9a1..413cb91 100644
--- a/plugins/orders/public/stylesheets/_items.scss
+++ b/plugins/orders/public/stylesheets/_items.scss
@@ -102,9 +102,6 @@
.table-content {
- .order-items-scroll {
- max-height: 350px;
- }
.item {
&.product-unavailable {
diff --git a/plugins/orders/public/stylesheets/orders.scss b/plugins/orders/public/stylesheets/orders.scss
index eeb00ef..b4149f0 100644
--- a/plugins/orders/public/stylesheets/orders.scss
+++ b/plugins/orders/public/stylesheets/orders.scss
@@ -9,10 +9,10 @@
@import 'items';
.controller-profile_editor a.control-panel-orders-purchases-sales {
- background-image: url("/plugins/orders/images/control-panel/purchases-sales.png")
+ background-image: url("/plugins/orders/images/control-panel/purchases-sales.png");
}
.controller-profile_editor .msie6 a.control-panel-orders-purchases-sales {
- background-image: url("/plugins/orders/images/control-panel/purchases-sales.gif")
+ background-image: url("/plugins/orders/images/control-panel/purchases-sales.gif");
}
.orders-admin-index {
@@ -125,14 +125,13 @@
}
.order-view {
-
- &, .order-items-scroll, .order-items, .item {
+ &, .order-items, .item {
width: $order-items-width;
}
&.admin {
width: $order-items-admin-width;
- .order-items-scroll, .order-items, .item {
+ .order-items, .item {
width: $order-items-admin-width - 2*$border;
}
}
@@ -160,16 +159,14 @@
margin: 0;
border: none;
+
+ overflow: hidden;
+ overflow-y: auto;
+
&.admin {
border: $border solid black;
}
- .order-items-scroll {
- overflow-y: auto;
- padding-right: $intercolumn;
- box-sizing: content-box;
- }
-
.order-header {
padding: $half-padding $padding;
border-bottom: $border solid black;
@@ -223,7 +220,10 @@
padding-bottom: 200px;
}
-.action-orders_cycle_plugin_order-edit .purechat {
- left: 40px;
- right: none;
+.controller-orders_cycle_plugin_order,
+.controller-consumers_coop_plugin_order {
+ .purechat {
+ left: 40px;
+ right: none;
+ }
}
diff --git a/plugins/orders/test/test_helper.rb b/plugins/orders/test/test_helper.rb
new file mode 100644
index 0000000..cca1fd3
--- /dev/null
+++ b/plugins/orders/test/test_helper.rb
@@ -0,0 +1 @@
+require File.dirname(__FILE__) + '/../../../test/test_helper'
diff --git a/plugins/orders/test/unit/orders_plugin/item_test.rb b/plugins/orders/test/unit/orders_plugin/item_test.rb
new file mode 100644
index 0000000..b96de82
--- /dev/null
+++ b/plugins/orders/test/unit/orders_plugin/item_test.rb
@@ -0,0 +1,14 @@
+require File.dirname(__FILE__) + '/../../../../test/test_helper'
+
+class OrdersPlugin::ItemTest < ActiveSupport::TestCase
+
+ def setup
+ @item = build(OrdersPlugin::Item,
+ :quantity_shipped => 1.0, :quantity_consumer_ordered => 2.0, :quantity_accepted => 3.0,
+ :price_shipped => 10.0, :price_consumer_ordered => 20.0, :price_accepted => 30.0)
+ end
+
+ should 'calculate prices' do
+ end
+
+end
diff --git a/plugins/orders/test/unit/orders_plugin/order_test.rb b/plugins/orders/test/unit/orders_plugin/order_test.rb
new file mode 100644
index 0000000..bd771b2
--- /dev/null
+++ b/plugins/orders/test/unit/orders_plugin/order_test.rb
@@ -0,0 +1,121 @@
+require "test_helper"
+
+class OrdersPlugin::OrderTest < ActiveSupport::TestCase
+
+ def setup
+ @order = build(OrdersPlugin::Order)
+ end
+
+ should 'report supplier products when distributing aggregate products' do
+ env = Environment.create! name: 'megacoop'
+ supplier = Enterprise.create! identifier: 'supplier', name: 'supplier', environment: env
+ p1 = supplier.products.create! product_category: ProductCategory.create!(name: 'banana', environment: env)
+ p2 = supplier.products.create! product_category: ProductCategory.create!(name: 'aipim', environment: env)
+
+ coop = Community.create! identifier: 'blah', name: 'blah', environment: env
+ coop.suppliers.create! profile: supplier, consumer: coop
+ aggregate_product = SuppliersPlugin::DistributedProduct.new profile: coop
+ aggregate_product.sources_from_products.build quantity: 1, from_product: p1, to_product: aggregate_product
+ aggregate_product.sources_from_products.build quantity: 5, from_product: p2, to_product: aggregate_product
+ aggregate_product.save!
+
+ # hack
+ person = coop
+
+ # this also create offered products
+ 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'
+ sale = cycle.sales.create! profile: person
+ sale.items.create! quantity_consumer_ordered: 3, product: aggregate_product
+
+ r = OrdersPlugin::Order.supplier_products_by_suppliers [sale]
+ quantities = r.first.last.map(&:quantity_ordered).map(&:to_i)
+ assert_equal [3*1,3*5], quantities
+ end
+
+ should 'format code with cycle code' do
+ @order.save!
+ assert_equal "#{@order.cycle.code}.#{@order.attributes['code']}", @order.code
+ end
+
+ should 'use as draft default status' do
+ @order = create(OrdersPlugin::Order, status: nil)
+ assert_equal 'draft', @order.status
+ end
+
+ ###
+ # Status
+ ###
+
+ should 'define and validate list of statuses' do
+ @order.status = 'blah'
+ @order.valid?
+ assert @order.errors.invalid?('status')
+
+ ['draft', 'planned', 'ordered', 'cancelled'].each do |i|
+ @order.status = i
+ @order.valid?
+ assert !@order.errors.invalid?('status')
+ end
+ end
+
+ should 'define status question methods' do
+ ['draft', 'planned', 'ordered', 'cancelled'].each do |i|
+ @order.status = i
+ assert @order.send("#{@order.status}?")
+ end
+ end
+
+ should 'define forgotten and open status' do
+ @order.status = 'draft'
+ assert @order.draft?
+ assert @order.cycle.orders?
+ assert @order.open?
+ @order.cycle.status = 'closed'
+ assert !@order.open?
+ assert @order.forgotten?
+ end
+
+ should 'return current status using forgotten and open too' do
+ @order.status = 'draft'
+ assert @order.open?
+ assert_equal 'open', @order.current_status
+ @order.cycle.status = 'closed'
+ assert @order.forgotten?
+ assert_equal 'forgotten', @order.current_status
+ end
+
+ should 'define status_message method' do
+ assert @order.respond_to?(:status_message)
+ end
+
+ ###
+ # Delivery
+ ###
+
+ should 'give default value to supplier delivery if not present' do
+ @order.save!
+ @order.profile.save!
+
+ @order.cycle.delivery_methods = []
+ @order.supplier_delivery = nil
+ assert_nil @order.supplier_delivery
+
+ default = @order.cycle.delivery_methods.create! profile: @order.profile, name: 'method', delivery_type: 'deliver'
+ assert_equal default, @order.supplier_delivery
+ assert_equal default.id, @order.supplier_delivery_id
+ end
+
+ ###
+ # Totals
+ ###
+
+ should 'give total price and quantity asked' do
+ @order.cycle.profile.save!
+ product = create(SuppliersPlugin::DistributedProduct, price: 2.0, profile: @order.cycle.profile, supplier: @order.cycle.profile.self_supplier)
+ @order.save!
+ @order.item.create! product: @order.cycle.products.first, quantity_consumer_ordered: 2.0
+ assert_equal 2.0, @order.total_quantity_consumer_ordered
+ assert_equal 4.0, @order.total_price_consumer_ordered
+ end
+
+end
diff --git a/plugins/orders/views/orders_plugin/mailer/order_confirmation.html.slim b/plugins/orders/views/orders_plugin/mailer/order_confirmation.html.slim
new file mode 100644
index 0000000..3631aaf
--- /dev/null
+++ b/plugins/orders/views/orders_plugin/mailer/order_confirmation.html.slim
@@ -0,0 +1,30 @@
+doctype html
+html
+ head
+ meta content=("text/html; charset=utf-8") http-equiv="Content-Type"
+ = stylesheet_link_tag 'plugins/responsive/bootstrap/all.css' if defined? ResponsivePlugin
+ = stylesheet_link_tag 'plugins/orders/style.css'
+ body
+ p= t'orders_plugin.views.mailer.order_confirmation.dear_name', name: @consumer.name
+
+ p= t'orders_plugin.views.mailer.order_confirmation.your_order_made_on_co',
+ name: @profile.name, date: day_time(@order.updated_at)
+
+ - if @order.respond_to? :cycle
+ p= t'orders_plugin.views.mailer.order_confirmation.the_delivery_period_w',
+ date: datetime_period_with_from(@order.cycle.delivery_start, @order.cycle.delivery_finish)
+
+ p= t'orders_plugin.views.mailer.order_confirmation.order_data_confirmed'
+
+ = render "orders_plugin_order/show_simple", order: @order, actor_name: :consumer
+
+ p
+ = t('orders_plugin.views.mailer.order_confirmation.your_order_can_be_che')
+ br
+ = link_to t('orders_plugin.views.mailer.order_confirmation.order_code_of_profile') % {code: @order.code, name: @profile.name },
+ {controller: :orders_cycle_plugin_order, action: :edit, profile: @profile.identifier, id: @order.id, protocol: "http"}
+
+ p
+ |--
+ br
+ = t'orders_plugin.views.mailer.order_confirmation.greetings'
diff --git a/plugins/orders/views/orders_plugin/shared/daterangepicker/_init.html.slim b/plugins/orders/views/orders_plugin/shared/daterangepicker/_init.html.slim
index c32fbb8..924fdec 100644
--- a/plugins/orders/views/orders_plugin/shared/daterangepicker/_init.html.slim
+++ b/plugins/orders/views/orders_plugin/shared/daterangepicker/_init.html.slim
@@ -1,7 +1,7 @@
= content_for :head do
= stylesheet_link_tag '/assets/plugins/orders/stylesheets/daterangepicker-bs3.css'
/ in case it is not loaded for this theme
- = stylesheet_link_tag '/assets/designs/icons/awesome/scss/font-awesome.css'
+ = stylesheet_link_tag 'designs/icons/awesome/scss/font-awesome.css'
= javascript_include_tag '/assets/plugins/orders/javascripts/moment-with-locales.js'
= javascript_include_tag '/assets/plugins/orders/javascripts/daterangepicker.js'
diff --git a/plugins/orders/views/orders_plugin_admin/_filter_fields.html.slim b/plugins/orders/views/orders_plugin_admin/_filter_fields.html.slim
index 0407471..6750f0d 100644
--- a/plugins/orders/views/orders_plugin_admin/_filter_fields.html.slim
+++ b/plugins/orders/views/orders_plugin_admin/_filter_fields.html.slim
@@ -3,21 +3,21 @@
div= render 'orders_plugin/shared/daterangepicker/init'
.field.state
- label for="status" = t'views.filter.status'
+ label= t'views.filter.status'
div= select_tag :status,
options_for_select([[t('views.filter.all'), ""]] + OrdersPlugin::Order::StatusText.map{ |id, name| [t(name), id] }, params[:status])
.field.code
- label for="code" = t'views.filter.code'
+ label= t'views.filter.code'
div= text_field_tag :code, params[:code]
div class="field #{actor_name}"
- label for="#{actor_name}_id" = t"terms.#{actor_name}.singular", transformation: :capitalize
+ label= t"terms.#{actor_name}.singular", transformation: :capitalize
div= select_tag "#{actor_name}_id",
options_for_select([[t('views.filter.all'), ""]] + actors.map{ |a| [a.name, a.id] }, params["#{actor_name}_id"])
.field.delivery
- label for="delivery_method_id" = t'views.filter.delivery'
+ label= t'views.filter.delivery'
div= select_tag :delivery_method_id,
options_for_select([[t('views.filter.all'), ""]] + orders_owner.delivery_methods.map{ |dm| [dm.name, dm.id] }, params[:delivery_method_id])
diff --git a/plugins/orders/views/orders_plugin_admin/_index.html.erb b/plugins/orders/views/orders_plugin_admin/_index.html.erb
index 5ac36b3..12ca3ce 100644
--- a/plugins/orders/views/orders_plugin_admin/_index.html.erb
+++ b/plugins/orders/views/orders_plugin_admin/_index.html.erb
@@ -12,14 +12,14 @@
<% if @purchases.present? %>
- <%= render 'orders_plugin_admin/purchases', actors: profile.purchases_all_suppliers,
+ <%= render 'orders_plugin_admin/purchases', actors: profile.sales_all_consumers,
orders_owner: profile, orders: @purchases, month: @purchases_month, year: @purchases_year, wireframe_size: false %>
<% end %>
<% if @sales.present? %>
- <%= render 'orders_plugin_admin/sales', actors: profile.sales_all_consumers,
+ <%= render 'orders_plugin_admin/sales', actors: profile.purchases_all_consumers,
orders_owner: profile, orders: @sales, month: @sales_month, year: @purchases_year, wireframe_size: false %>
<% end %>
diff --git a/plugins/orders/views/orders_plugin_admin/_order.html.slim b/plugins/orders/views/orders_plugin_admin/_order.html.slim
new file mode 100644
index 0000000..1bbaa9c
--- /dev/null
+++ b/plugins/orders/views/orders_plugin_admin/_order.html.slim
@@ -0,0 +1,21 @@
+- other_actor_name = if actor_name == :supplier then :consumer else :supplier end
+- edit = true if edit.nil?
+
+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();"
+
+ .box-view.with-inner
+ .box-field.select toggle-ignore="" = check_box_tag "order_ids[]", order.id
+ .box-view-inner
+ span.box-field.code= order.code
+ span.box-field.actor-name= order.send("#{other_actor_name}_data")[:name]
+ span.box-field.order-date= datetime_full order.created_at
+ span.box-field.last-update= datetime_full order.updated_at
+ span.box-field.total= order.total_price_as_currency_number actor_name
+ span.box-field.situation= order_situation order
+ = edit_arrow "#order-row-#{order.id}", true, class: 'actions'
+ .clean
+
+ div class="box-edit #{'loading' if not edit}"
+ = render 'orders_plugin_admin/edit', order: order, actor_name: actor_name, other_actor_name: other_actor_name if edit
+
+ .clean
diff --git a/plugins/orders/views/orders_plugin_item/_edit_fields.html.slim b/plugins/orders/views/orders_plugin_item/_edit_fields.html.slim
index 8a468fb..41a3a5f 100644
--- a/plugins/orders/views/orders_plugin_item/_edit_fields.html.slim
+++ b/plugins/orders/views/orders_plugin_item/_edit_fields.html.slim
@@ -4,7 +4,7 @@
.box-field.product title=item.name = item.name
.box-field.quantity-price-table
- item_data[:statuses].each do |status, status_data|
- - next if status_data[:flags][:not_modified] and not status_data[:flags][:admin]
+ - next if status_data[:flags][:not_modified] and not status_data[:flags][:editable]
= render 'orders_plugin_item/quantity_price', item: item, order: order, status: status, data: item_data, status_data: status_data, actor_name: actor_name
.more
@@ -12,12 +12,15 @@
/ actionmailer doesn't have an user, rescue error
- if (order.may_edit? user, @admin rescue false)
- if @admin
- = 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'
- = 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'
+ = 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)}')"
+ = 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'
- else
= link_to t('views.item._edit.remove_from_order'), {controller: :orders_plugin_item, action: :destroy, id: item.id},
remote: true, data: {loading: "#item-#{item.id}"}
= 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'
- = price_with_unit_span item.price_as_currency_number, (item.product.unit rescue item.price_as_currency_number), nil, class: 'box-field' unless @simple
+
+ = price_with_unit_span item.price_as_currency_number, (item.product.unit rescue item.price_as_currency_number), nil, class: 'box-field' unless @view
.clean
diff --git a/plugins/orders/views/orders_plugin_item/_index.html.slim b/plugins/orders/views/orders_plugin_item/_index.html.slim
index 8a73ad2..310c9cf 100644
--- a/plugins/orders/views/orders_plugin_item/_index.html.slim
+++ b/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
- if @admin
.box-field.status= t'views.item._index.status'
.table-content
- .order-items-scroll
- - order.items.each do |item|
- = render "orders_plugin_item/edit", order: order, item: item, product: item.product, actor_name: actor_name
+ - order.items.each do |item|
+ = render "orders_plugin_item/edit", order: order, item: item, product: item.product, actor_name: actor_name
.order-total
.title= t'views.consumer._total.total'
- .value= price_span order.total_price_as_currency_number actor_name
+ .value= price_span order.total_price_as_currency_number actor_name, @admin
- else
= t'views.item._index.empty_order'
diff --git a/plugins/orders/views/orders_plugin_item/_quantity_price.html.slim b/plugins/orders/views/orders_plugin_item/_quantity_price.html.slim
index d0fc075..54c148c 100644
--- a/plugins/orders/views/orders_plugin_item/_quantity_price.html.slim
+++ b/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 ' '}"
= t'views.item._edit.removed'
- else
= quantity_localized
- - if not @simple and status_data[:flags][:editable]
+ - if not @view and status_data[:flags][:editable]
= number_field_tag "item[quantity_#{status_data[:field]}]", status_data[:quantity], step: 'any', onkeydown: 'orders.item.quantity_keydown(this, event)'
- unless status_data[:flags][:removed]
|
diff --git a/plugins/orders/views/orders_plugin_order/_data.html.slim b/plugins/orders/views/orders_plugin_order/_data.html.slim
new file mode 100644
index 0000000..0b4c10a
--- /dev/null
+++ b/plugins/orders/views/orders_plugin_order/_data.html.slim
@@ -0,0 +1,6 @@
+= render "orders_plugin_item/index", order: order, actor_name: actor_name, f: f
+
+= render 'orders_plugin_order/actor_data', order: order, f: f, actor_name: other_actor_name if @admin
+= render 'orders_plugin_order/delivery', order: order, f: f, actor_name: actor_name
+= render 'orders_plugin_order/payment', order: order
+
diff --git a/plugins/orders/views/orders_plugin_order/_delivery.html.slim b/plugins/orders/views/orders_plugin_order/_delivery.html.slim
new file mode 100644
index 0000000..93f73d0
--- /dev/null
+++ b/plugins/orders/views/orders_plugin_order/_delivery.html.slim
@@ -0,0 +1,8 @@
+/ read as: selectable or visualizable
+- if order.delivery_methods.size > 0 or order.supplier_delivery_data.present?
+ .delivery-box.order-section
+ h3= _'Delivery or pickup method'
+
+ - edition = order.may_edit?(user, @admin) && order.delivery_methods.size > 0 if edition.nil?
+ = render 'delivery_plugin/order_select', f: f, order: order, methods: order.delivery_methods, edition: edition
+
diff --git a/plugins/orders/views/orders_plugin_order/_show.html.slim b/plugins/orders/views/orders_plugin_order/_show.html.slim
index fc73edf..f38e316 100644
--- a/plugins/orders/views/orders_plugin_order/_show.html.slim
+++ b/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}
- elsif order.open?
div
= hidden_field_tag "order[status]", 'ordered'
- = f.submit t('views.order._show.confirm_order'), confirm: t('views.order._show.confirming_this_order')
+ = f.submit t('views.order._show.confirm_order'), data: {confirm: t('views.order._show.confirming_this_order')}
|
= link_to_function t('views.order._show.cancel_order'), "orders.order.reload(this, '#{url_for controller: :orders_plugin_order, action: :cancel, id: @order.id}')"
+javascript:
+ orders.setOrderMaxHeight()
+
diff --git a/plugins/orders/views/orders_plugin_order/_show_simple.html.slim b/plugins/orders/views/orders_plugin_order/_show_simple.html.slim
new file mode 100644
index 0000000..6085f4d
--- /dev/null
+++ b/plugins/orders/views/orders_plugin_order/_show_simple.html.slim
@@ -0,0 +1,12 @@
+- actor_name ||= :consumer
+- other_actor_name = if actor_name == :supplier then :consumer else :supplier end
+- @view = true
+
+.order-view id="order-#{order.id}"
+ = form_for order, as: :order, url: '', html: {onsubmit: 'return false'} do |f|
+ .order-data
+ = render "orders_plugin_item/index", order: order, actor_name: actor_name
+ = render 'orders_plugin_order/delivery', order: order, actor_name: actor_name, edition: false, f: f
+
+javascript:
+ orders.setOrderMaxHeight()
diff --git a/plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_cycle_controller.rb b/plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_cycle_controller.rb
index a9f94d8..8a71fe1 100644
--- a/plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_cycle_controller.rb
+++ b/plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_cycle_controller.rb
@@ -22,23 +22,24 @@ class OrdersCyclePluginCycleController < OrdersPluginAdminController
end
def new
- if request.put?
+ if request.patch?
+ # can't use profile.orders_cycle here
@cycle = OrdersCyclePlugin::Cycle.find params[:id]
params[:cycle][:status] = 'orders' if @open = params[:open] == '1'
- @success = @cycle.update_attributes params[:cycle]
+ @success = @cycle.update params[:cycle]
if @success
session[:notice] = t('controllers.myprofile.cycle_controller.cycle_created')
if params[:sendmail]
OrdersCyclePlugin::Mailer.delay(run_at: @cycle.start).open_cycle(
- @cycle.profile, @cycle ,t('controllers.myprofile.cycle_controller.new_open_cycle')+": "+@cycle.name, @cycle.opening_message)
+ @cycle.profile, @cycle, "#{t'controllers.myprofile.cycle_controller.new_open_cycle'}: #{@cycle.name}", @cycle.opening_message)
end
else
render action: :edit
end
else
- count = OrdersCyclePlugin::Cycle.count conditions: {profile_id: profile}
+ count = profile.orders_cycles.maximum(:code) || 1
@cycle = OrdersCyclePlugin::Cycle.create! profile: profile, status: 'new',
name: t('controllers.myprofile.cycle_controller.cycle_n_n') % {n: count+1}
end
@@ -48,13 +49,13 @@ class OrdersCyclePluginCycleController < OrdersPluginAdminController
# editing an order
return super if params[:actor_name]
- @cycle = OrdersCyclePlugin::Cycle.find params[:id]
+ @cycle = profile.orders_cycles.find params[:id]
@products = products
if request.xhr?
if params[:commit]
params[:cycle][:status] = 'orders' if @open = params[:open] == '1'
- @success = @cycle.update_attributes params[:cycle]
+ @success = @cycle.update params[:cycle]
if params[:sendmail]
OrdersCyclePlugin::Mailer.delay(run_at: @cycle.start).open_cycle(@cycle.profile,
@@ -65,7 +66,7 @@ class OrdersCyclePluginCycleController < OrdersPluginAdminController
end
def products_load
- @cycle = OrdersCyclePlugin::Cycle.find params[:id]
+ @cycle = profile.orders_cycles.find params[:id]
@products = products
if @cycle.add_products_job
@@ -76,34 +77,34 @@ class OrdersCyclePluginCycleController < OrdersPluginAdminController
end
def destroy
- @cycle = OrdersCyclePlugin::Cycle.find params[:id]
+ @cycle = profile.orders_cycles.find params[:id]
@cycle.destroy
redirect_to action: :index
end
def step
- @cycle = OrdersCyclePlugin::Cycle.find params[:id]
+ @cycle = profile.orders_cycles.find params[:id]
@cycle.step
@cycle.save!
redirect_to action: :edit, id: @cycle.id
end
def step_back
- @cycle = OrdersCyclePlugin::Cycle.find params[:id]
+ @cycle = profile.orders_cycles.find params[:id]
@cycle.step_back
@cycle.save!
redirect_to action: :edit, id: @cycle.id
end
def add_missing_products
- @cycle = OrdersCyclePlugin::Cycle.find params[:id]
+ @cycle = profile.orders_cycles.find params[:id]
@cycle.add_products
render partial: 'suppliers_plugin/shared/pagereload'
end
def report_products
return super if params[:ids].present?
- @cycle = OrdersCyclePlugin::Cycle.find params[:id]
+ @cycle = profile.orders_cycles.find params[:id]
report_file = report_products_by_supplier @cycle.supplier_products_by_suppliers(@cycle.sales.ordered)
send_file report_file, type: 'application/xlsx',
@@ -114,7 +115,7 @@ class OrdersCyclePluginCycleController < OrdersPluginAdminController
def report_orders
return super if params[:ids].present?
- @cycle = OrdersCyclePlugin::Cycle.find params[:id]
+ @cycle = profile.orders_cycles.find params[:id]
report_file = report_orders_by_consumer @cycle.sales.ordered
send_file report_file, type: 'application/xlsx',
diff --git a/plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_item_controller.rb b/plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_item_controller.rb
index 0599094..6cfc8a9 100644
--- a/plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_item_controller.rb
+++ b/plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_item_controller.rb
@@ -31,12 +31,12 @@ class OrdersCyclePluginItemController < OrdersPluginItemController
@item.sale = @order
@item.product = @offered_product
if set_quantity_consumer_ordered(params[:quantity_consumer_ordered] || 1)
- @item.update_attributes! quantity_consumer_ordered: @quantity_consumer_ordered
+ @item.update! quantity_consumer_ordered: @quantity_consumer_ordered
end
end
def edit
- return redirect_to params.merge(action: :admin_edit) if @admin_edit
+ return redirect_to url_for(params.merge action: :admin_edit) if @admin_edit
super
@offered_product = @item.product
@cycle = @order.cycle
@@ -50,7 +50,7 @@ class OrdersCyclePluginItemController < OrdersPluginItemController
#update on association for total
@order.items.each{ |i| i.attributes = params[:item] if i.id == @item.id }
- @item.update_attributes = params[:item]
+ @item.update params[:item]
end
def destroy
diff --git a/plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_product_controller.rb b/plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_product_controller.rb
index 8769e80..2e5a10f 100644
--- a/plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_product_controller.rb
+++ b/plugins/orders_cycle/controllers/myprofile/orders_cycle_plugin_product_controller.rb
@@ -25,7 +25,7 @@ class OrdersCyclePluginProductController < SuppliersPlugin::ProductController
def cycle_edit
@product = OrdersCyclePlugin::OfferedProduct.find params[:id]
if request.xhr?
- @product.update_attributes! params[:product]
+ @product.update! params[:product]
respond_to do |format|
format.js
end
diff --git a/plugins/orders_cycle/controllers/profile/orders_cycle_plugin_order_controller.rb b/plugins/orders_cycle/controllers/profile/orders_cycle_plugin_order_controller.rb
index b4974b6..f162835 100644
--- a/plugins/orders_cycle/controllers/profile/orders_cycle_plugin_order_controller.rb
+++ b/plugins/orders_cycle/controllers/profile/orders_cycle_plugin_order_controller.rb
@@ -38,7 +38,7 @@ class OrdersCyclePluginOrderController < OrdersPluginOrderController
@order.consumer = @consumer
@order.cycle = @cycle
@order.save!
- redirect_to params.merge(action: :edit, id: @order.id)
+ redirect_to url_for(params.merge action: :edit, id: @order.id)
end
end
@@ -55,7 +55,7 @@ class OrdersCyclePluginOrderController < OrdersPluginOrderController
end
@repeat_order.supplier_delivery = @order.supplier_delivery
@repeat_order.save!
- redirect_to params.merge(action: :edit, id: @repeat_order.id)
+ redirect_to url_for(params.merge action: :edit, id: @repeat_order.id)
else
@orders = @cycle.consumer_previous_orders(@consumer).last(5).reverse
@orders.each{ |o| o.enable_product_diff }
@@ -72,7 +72,7 @@ class OrdersCyclePluginOrderController < OrdersPluginOrderController
if status == 'ordered'
if @order.items.size > 0
@order.to_yaml # most strange workaround to avoid a crash in the next line
- @order.update_attributes! params[:order]
+ @order.update! params[:order]
session[:notice] = t('orders_plugin.controllers.profile.consumer.order_confirmed')
else
session[:notice] = t('orders_plugin.controllers.profile.consumer.can_not_confirm_your_')
@@ -117,12 +117,12 @@ class OrdersCyclePluginOrderController < OrdersPluginOrderController
end
def reopen
- @order.update_attributes! status: 'draft'
+ @order.update! status: 'draft'
render 'edit'
end
def cancel
- @order.update_attributes! status: 'cancelled'
+ @order.update! status: 'cancelled'
session[:notice] = t('orders_plugin.controllers.profile.consumer.order_cancelled')
render 'edit'
end
@@ -162,7 +162,7 @@ class OrdersCyclePluginOrderController < OrdersPluginOrderController
end
def supplier_balloon
- @supplier = SuppliersPlugin::Supplier.find params[:id]
+ @supplier = profile.suppliers.find params[:id]
end
def product_balloon
@product = OrdersCyclePlugin::OfferedProduct.find params[:id]
diff --git a/plugins/orders_cycle/db/migrate/20140406155248_refactor_orders_cycle_plugin_cycle_order.rb b/plugins/orders_cycle/db/migrate/20140406155248_refactor_orders_cycle_plugin_cycle_order.rb
index e63742f..a73d0dd 100644
--- a/plugins/orders_cycle/db/migrate/20140406155248_refactor_orders_cycle_plugin_cycle_order.rb
+++ b/plugins/orders_cycle/db/migrate/20140406155248_refactor_orders_cycle_plugin_cycle_order.rb
@@ -4,9 +4,7 @@ class RefactorOrdersCyclePluginCycleOrder < ActiveRecord::Migration
rename_column :orders_cycle_plugin_cycle_orders, :order_id, :sale_id
add_column :orders_cycle_plugin_cycle_orders, :purchase_id, :integer
- add_index :orders_cycle_plugin_cycle_orders, :sale_id
add_index :orders_cycle_plugin_cycle_orders, :purchase_id
- add_index :orders_cycle_plugin_cycle_orders, [:cycle_id, :sale_id]
add_index :orders_cycle_plugin_cycle_orders, [:cycle_id, :purchase_id], name: :index_orders_cycle_plugin_cycle_orders_cycle_purchase
end
diff --git a/plugins/orders_cycle/lib/ext/delivery_plugin/option.rb b/plugins/orders_cycle/lib/ext/delivery_plugin/option.rb
index 33787fc..b3a8471 100644
--- a/plugins/orders_cycle/lib/ext/delivery_plugin/option.rb
+++ b/plugins/orders_cycle/lib/ext/delivery_plugin/option.rb
@@ -2,7 +2,8 @@ require_dependency 'delivery_plugin/option'
class DeliveryPlugin::Option
- belongs_to :cycle, class_name: 'OrdersCyclePlugin::Cycle',
- foreign_key: :owner_id, conditions: ["delivery_plugin_options.owner_type = 'OrdersCyclePlugin::Cycle'"]
+ belongs_to :cycle, -> {
+ where "delivery_plugin_options.owner_type = 'OrdersCyclePlugin::Cycle'"
+ }, class_name: 'OrdersCyclePlugin::Cycle', foreign_key: :owner_id
end
diff --git a/plugins/orders_cycle/lib/ext/profile.rb b/plugins/orders_cycle/lib/ext/profile.rb
index 953dcc7..cdd91b5 100644
--- a/plugins/orders_cycle/lib/ext/profile.rb
+++ b/plugins/orders_cycle/lib/ext/profile.rb
@@ -1,19 +1,30 @@
require_dependency 'profile'
+require_dependency 'community'
-class Profile
+([Profile] + Profile.descendants).each do |subclass|
+subclass.class_eval do
+
+ has_many :orders_cycles, -> {
+ order('created_at DESC').
+ where "orders_cycle_plugin_cycles.status <> 'new'"
+ }, foreign_key: :profile_id, class_name: 'OrdersCyclePlugin::Cycle', dependent: :destroy
- has_many :orders_cycles, class_name: 'OrdersCyclePlugin::Cycle', dependent: :destroy, order: 'created_at DESC',
- conditions: ["orders_cycle_plugin_cycles.status <> 'new'"]
- has_many :orders_cycles_without_order, class_name: 'OrdersCyclePlugin::Cycle',
- conditions: ["orders_cycle_plugin_cycles.status <> 'new'"]
+ has_many :orders_cycles_without_order, -> {
+ where "orders_cycle_plugin_cycles.status <> 'new'"
+ }, foreign_key: :profile_id, class_name: 'OrdersCyclePlugin::Cycle'
has_many :orders_cycles_sales, through: :orders_cycles, source: :sales
has_many :orders_cycles_purchases, through: :orders_cycles, source: :purchases
- has_many :offered_products, class_name: 'OrdersCyclePlugin::OfferedProduct', order: 'products.name ASC'
+ has_many :offered_products, -> { reorder 'products.name ASC' }, class_name: 'OrdersCyclePlugin::OfferedProduct'
+
+end
+end
+
+class Profile
def orders_cycles_closed_date_range
- list = self.orders_cycles.closing.all order: 'start ASC'
+ list = self.orders_cycles.closing.order('start ASC').all
return DateTime.now..DateTime.now if list.blank?
list.first.start.to_date..list.last.finish.to_date
end
diff --git a/plugins/orders_cycle/models/orders_cycle_plugin/cycle.rb b/plugins/orders_cycle/models/orders_cycle_plugin/cycle.rb
index 5d3f178..d6a1269 100644
--- a/plugins/orders_cycle/models/orders_cycle_plugin/cycle.rb
+++ b/plugins/orders_cycle/models/orders_cycle_plugin/cycle.rb
@@ -32,30 +32,32 @@ class OrdersCyclePlugin::Cycle < ActiveRecord::Base
belongs_to :profile
- has_many :delivery_options, class_name: 'DeliveryPlugin::Option', dependent: :destroy,
- as: :owner, conditions: ["delivery_plugin_options.owner_type = 'OrdersCyclePlugin::Cycle'"]
+ has_many :delivery_options, -> {
+ where "delivery_plugin_options.owner_type = 'OrdersCyclePlugin::Cycle'"
+ }, class_name: 'DeliveryPlugin::Option', dependent: :destroy, as: :owner
has_many :delivery_methods, through: :delivery_options, source: :delivery_method
- has_many :cycle_orders, class_name: 'OrdersCyclePlugin::CycleOrder', foreign_key: :cycle_id, dependent: :destroy, order: 'id ASC'
+ has_many :cycle_orders, -> { order 'id ASC' }, class_name: 'OrdersCyclePlugin::CycleOrder', foreign_key: :cycle_id, dependent: :destroy
# cannot use :order because of months/years named_scope
has_many :sales, through: :cycle_orders, source: :sale
has_many :purchases, through: :cycle_orders, source: :purchase
has_many :cycle_products, foreign_key: :cycle_id, class_name: 'OrdersCyclePlugin::CycleProduct', dependent: :destroy
- has_many :products, through: :cycle_products, source: :product, order: 'products.name ASC',
- include: [ :from_2x_products, :from_products, {profile: :domains}, ]
+ has_many :products, -> {
+ includes(:from_2x_products, :from_products, {profile: :domains})
+ }, through: :cycle_products, class_name: 'OrdersCyclePlugin::OfferedProduct', source: :product
- has_many :consumers, through: :sales, source: :consumer, order: 'name ASC', uniq: true
- has_many :suppliers, through: :products, source: :suppliers, order: 'suppliers_plugin_suppliers.name ASC', uniq: true
- has_many :orders_suppliers, through: :sales, source: :profile, order: 'name ASC'
+ has_many :consumers, -> { distinct.reorder 'name ASC' }, through: :sales, source: :consumer
+ has_many :suppliers, -> { group 'suppliers_plugin_suppliers.id' }, through: :products
+ has_many :orders_suppliers, -> { reorder 'name ASC' }, through: :sales, source: :profile
- has_many :from_products, through: :products, order: 'name ASC', uniq: true
- has_many :supplier_products, through: :products, order: 'name ASC', uniq: true
- has_many :product_categories, through: :products, order: 'name ASC', uniq: true
+ has_many :from_products, -> { distinct.reorder 'name ASC' }, through: :products
+ has_many :supplier_products, -> { distinct.reorder 'name ASC' }, through: :products
+ has_many :product_categories, -> { distinct.reorder 'name ASC' }, through: :products
- has_many :orders_confirmed, through: :cycle_orders, source: :sale, order: 'id ASC',
- conditions: ['orders_plugin_orders.ordered_at IS NOT NULL']
+ has_many :orders_confirmed, -> { reorder('id ASC').where 'orders_plugin_orders.ordered_at IS NOT NULL' },
+ through: :cycle_orders, source: :sale
has_many :items_selled, through: :sales, source: :items
has_many :items_purchased, through: :purchases, source: :items
@@ -64,16 +66,16 @@ class OrdersCyclePlugin::Cycle < ActiveRecord::Base
has_many :ordered_suppliers, through: :orders_confirmed, source: :suppliers
- has_many :ordered_offered_products, through: :orders_confirmed, source: :offered_products, uniq: true, include: [:suppliers]
- has_many :ordered_distributed_products, through: :orders_confirmed, source: :distributed_products, uniq: true, include: [:suppliers]
- has_many :ordered_supplier_products, through: :orders_confirmed, source: :supplier_products, uniq: true, include: [:suppliers]
+ has_many :ordered_offered_products, -> { distinct.includes :suppliers }, through: :orders_confirmed, source: :offered_products
+ has_many :ordered_distributed_products, -> { distinct.includes :suppliers }, through: :orders_confirmed, source: :distributed_products
+ has_many :ordered_supplier_products, -> { distinct.includes :suppliers }, through: :orders_confirmed, source: :supplier_products
has_many :volunteers_periods, class_name: 'VolunteersPlugin::Period', as: :owner
has_many :volunteers, through: :volunteers_periods, source: :profile
attr_accessible :volunteers_periods_attributes
accepts_nested_attributes_for :volunteers_periods, allow_destroy: true
- scope :has_volunteers_periods, -> {uniq.joins [:volunteers_periods]}
+ scope :has_volunteers_periods, -> { distinct.joins :volunteers_periods }
# status scopes
scope :on_edition, -> { where status: 'edition' }
@@ -83,33 +85,29 @@ class OrdersCyclePlugin::Cycle < ActiveRecord::Base
scope :on_delivery, -> { where status: 'delivery' }
scope :on_closing, -> { where status: 'closing' }
- scope :defuncts, conditions: ["status = 'new' AND created_at < ?", 2.days.ago]
- scope :not_new, conditions: ["status <> 'new'"]
- scope :on_orders, lambda {
- {conditions: ["status = 'orders' AND ( (start <= :now AND finish IS NULL) OR (start <= :now AND finish >= :now) )",
- {now: DateTime.now}]}
+ scope :defuncts, -> { where "status = 'new' AND created_at < ?", 2.days.ago }
+ scope :not_new, -> { where "status <> 'new'" }
+ scope :on_orders, -> {
+ where "status = 'orders' AND ( (start <= :now AND finish IS NULL) OR (start <= :now AND finish >= :now) )", now: DateTime.now
}
- scope :not_on_orders, lambda {
- {conditions: ["NOT (status = 'orders' AND ( (start <= :now AND finish IS NULL) OR (start <= :now AND finish >= :now) ) )",
- {now: DateTime.now}]}
+ scope :not_on_orders, -> {
+ where "NOT (status = 'orders' AND ( (start <= :now AND finish IS NULL) OR (start <= :now AND finish >= :now) ) )", now: DateTime.now
}
- scope :opened, conditions: ["status <> 'new' AND status <> 'closing'"]
- scope :closing, conditions: ["status = 'closing'"]
- scope :by_status, lambda { |status| { conditions: {status: status} } }
+ scope :opened, -> { where "status <> 'new' AND status <> 'closing'" }
+ scope :closing, -> { where "status = 'closing'" }
+ scope :by_status, -> (status) { where status: status }
- scope :months, select: 'DISTINCT(EXTRACT(months FROM start)) as month', order: 'month DESC'
- scope :years, select: 'DISTINCT(EXTRACT(YEAR FROM start)) as year', order: 'year DESC'
+ scope :months, -> { order('month DESC').select 'DISTINCT(EXTRACT(months FROM start)) as month' }
+ scope :years, -> { order('year DESC').select 'DISTINCT(EXTRACT(YEAR FROM start)) as year' }
- scope :by_month, lambda { |month| {
- conditions: [ 'EXTRACT(month FROM start) <= :month AND EXTRACT(month FROM finish) >= :month', { month: month } ]}
+ scope :by_month, -> (month) {
+ where 'EXTRACT(month FROM start) <= :month AND EXTRACT(month FROM finish) >= :month', month: month
}
- scope :by_year, lambda { |year| {
- conditions: [ 'EXTRACT(year FROM start) <= :year AND EXTRACT(year FROM finish) >= :year', { year: year } ]}
+ scope :by_year, -> (year) {
+ where 'EXTRACT(year FROM start) <= :year AND EXTRACT(year FROM finish) >= :year', year: year
}
- scope :by_range, lambda { |range| {
- conditions: [ 'start BETWEEN :start AND :finish OR finish BETWEEN :start AND :finish',
- { start: range.first, finish: range.last }
- ]}
+ scope :by_range, -> (range) {
+ where 'start BETWEEN :start AND :finish OR finish BETWEEN :start AND :finish', start: range.first, finish: range.last
}
validates_presence_of :profile
@@ -122,7 +120,7 @@ class OrdersCyclePlugin::Cycle < ActiveRecord::Base
validate :validate_orders_dates, if: :not_new?
validate :validate_delivery_dates, if: :not_new?
- before_validation :step_new
+ before_save :step_new
before_validation :update_orders_status
before_save :add_products_on_edition_state
after_create :delay_purge_profile_defuncts
@@ -212,9 +210,7 @@ class OrdersCyclePlugin::Cycle < ActiveRecord::Base
end
def products_for_order
- # FIXME name alias conflict
- #self.products.unarchived.with_price.order('products.name ASC')
- self.products.unarchived.with_price
+ self.products.unarchived.alphabetically.with_price
end
def supplier_products_by_suppliers orders = self.sales.ordered
@@ -261,27 +257,27 @@ class OrdersCyclePlugin::Cycle < ActiveRecord::Base
end
def step_new
- return if new_record?
+ return if self.new_record?
self.step if self.new?
end
def update_sales_status from, to
sales = self.sales.where(status: from.to_s)
sales.each do |sale|
- sale.update_attributes status: to.to_s
+ sale.update status: to.to_s
end
end
def update_purchases_status from, to
purchases = self.purchases.where(status: from.to_s)
purchases.each do |purchase|
- purchase.update_attributes status: to.to_s
+ purchase.update status: to.to_s
end
end
def update_orders_status
- # step orders to next_status on status change
- return if self.new? or self.status_was == "new" or self.status_was == self.status
+ return if self.new? or self.status_was == "new"
+ return if self.status_was == self.status
# Don't rewind confirmed sales
unless self.status_was == 'orders' and self.status == 'edition'
diff --git a/plugins/orders_cycle/models/orders_cycle_plugin/offered_product.rb b/plugins/orders_cycle/models/orders_cycle_plugin/offered_product.rb
index 3affbcc..704fdb0 100644
--- a/plugins/orders_cycle/models/orders_cycle_plugin/offered_product.rb
+++ b/plugins/orders_cycle/models/orders_cycle_plugin/offered_product.rb
@@ -1,5 +1,8 @@
class OrdersCyclePlugin::OfferedProduct < SuppliersPlugin::BaseProduct
+ # we work use frozen attributes
+ self.default_delegate_enable = false
+
# FIXME: WORKAROUND for https://github.com/rails/rails/issues/6663
# OrdersCyclePlugin::Sale.find(3697).cycle.suppliers returns empty without this
def self.finder_needs_type_condition?
@@ -19,10 +22,10 @@ class OrdersCyclePlugin::OfferedProduct < SuppliersPlugin::BaseProduct
has_one :sources_supplier_product, through: :from_product, source: :sources_from_product
# necessary only due to the override of sources_supplier_products, as rails somehow caches the old reference
# copied from suppliers/lib/ext/product
- has_many :supplier_products, through: :sources_supplier_products, source: :from_product, order: 'id ASC'
- has_one :supplier_product, through: :sources_supplier_product, source: :from_product, order: 'id ASC', autosave: true
- has_many :suppliers, through: :sources_supplier_products, uniq: true, order: 'id ASC'
- has_one :supplier, through: :sources_supplier_product, order: 'id ASC'
+ has_many :supplier_products, -> { order 'id ASC' }, through: :sources_supplier_products, source: :from_product
+ has_one :supplier_product, -> { order 'id ASC' }, through: :sources_supplier_product, source: :from_product, autosave: true
+ has_many :suppliers, -> { distinct.order 'id ASC' }, through: :sources_supplier_products
+ has_one :supplier, -> { order 'id ASC' }, through: :sources_supplier_product
instance_exec &OrdersPlugin::Item::DefineTotals
extend CurrencyHelper::ClassMethods
@@ -31,9 +34,7 @@ class OrdersCyclePlugin::OfferedProduct < SuppliersPlugin::BaseProduct
# test this before use!
#validates_presence_of :cycle
- # remove on rails4
- scope :with_price, conditions: 'products.price > 0'
- scope :with_product_category_id, lambda { |id| { conditions: {product_category_id: id} } }
+ # override SuppliersPlugin::BaseProduct
def self.search_scope scope, params
scope = scope.from_supplier_id params[:supplier_id] if params[:supplier_id].present?
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
op.profile = product.profile
op.type = self.name
- op.from_products << product
+ op.from_product = product
cycle.products << op if cycle
op
end
# always recalculate in case something has changed
+ # FIXME: really? it is already copied!
def margin_percentage
- return self['margin_percentage'] if price.nil? or buy_price.nil? or price.zero? or buy_price.zero?
+ return super if price.nil? or buy_price.nil? or price.zero? or buy_price.zero?
((price / buy_price) - 1) * 100
end
def margin_percentage= value
- self['margin_percentage'] = value
+ super value
self.price = self.price_with_margins buy_price
end
@@ -71,22 +73,15 @@ class OrdersCyclePlugin::OfferedProduct < SuppliersPlugin::BaseProduct
end
# reimplement to don't destroy this, keeping history in cycles
- # offered products copy attributes
+ # as offered products copy attributes.
def dependent?
false
end
- # cycle products freezes properties and don't use the original
- DEFAULT_ATTRIBUTES.each do |a|
- define_method "default_#{a}" do
- nil
- end
- end
-
FROOZEN_DEFAULT_ATTRIBUTES = DEFAULT_ATTRIBUTES
def freeze_default_attributes from_product
FROOZEN_DEFAULT_ATTRIBUTES.each do |attr|
- self[attr] = from_product.send(attr) if from_product[attr] or from_product.respond_to? attr
+ self.send "#{attr}=", from_product.send(attr) if from_product[attr] or from_product.respond_to? attr
end
end
diff --git a/plugins/orders_cycle/models/orders_cycle_plugin/order_base.rb b/plugins/orders_cycle/models/orders_cycle_plugin/order_base.rb
index 5446b18..9f47b3b 100644
--- a/plugins/orders_cycle/models/orders_cycle_plugin/order_base.rb
+++ b/plugins/orders_cycle/models/orders_cycle_plugin/order_base.rb
@@ -14,26 +14,18 @@ module OrdersCyclePlugin::OrderBase
self.cycle_sales.includes(:cycle).map(&:cycle) + self.cycle_purchases.includes(:cycle).map(&:cycle)
end
- # TODO: test if the has_one defined on Sale/Purchase works and these are not needed
- def cycle
- self.cycles.first
- end
- def cycle= cycle
- self.cycles = [cycle]
- end
-
scope :for_cycle, -> (cycle) {
where('orders_cycle_plugin_cycles.id = ?', cycle.id).
joins(:cycles)
}
- has_many :items, class_name: 'OrdersCyclePlugin::Item', foreign_key: :order_id, dependent: :destroy, order: 'name ASC'
+ has_many :items, -> { order 'name ASC' }, class_name: 'OrdersCyclePlugin::Item', foreign_key: :order_id, dependent: :destroy
- has_many :offered_products, through: :items, source: :offered_product, uniq: true
- has_many :distributed_products, through: :offered_products, source: :from_products, uniq: true
- has_many :supplier_products, through: :distributed_products, source: :from_products, uniq: true
+ has_many :offered_products, -> { distinct }, through: :items, source: :offered_product
+ has_many :distributed_products, -> { distinct }, through: :offered_products, source: :from_products
+ has_many :supplier_products, -> { distinct }, through: :distributed_products, source: :from_products
- has_many :suppliers, through: :supplier_products, uniq: true
+ has_many :suppliers, -> { distinct }, through: :supplier_products
extend CodeNumbering::ClassMethods
code_numbering :code, scope: (proc do
diff --git a/plugins/orders_cycle/models/orders_cycle_plugin/sale.rb b/plugins/orders_cycle/models/orders_cycle_plugin/sale.rb
index 1b1ccc2..eca127d 100644
--- a/plugins/orders_cycle/models/orders_cycle_plugin/sale.rb
+++ b/plugins/orders_cycle/models/orders_cycle_plugin/sale.rb
@@ -24,10 +24,6 @@ class OrdersCyclePlugin::Sale < OrdersPlugin::Sale
super and self.cycle.orders?
end
- def supplier_delivery
- super || (self.cycle.delivery_methods.first rescue nil)
- end
-
def change_purchases
return unless self.status_was.present?
if self.ordered_at_was.nil? and self.ordered_at.present?
diff --git a/plugins/orders_cycle/test/factories.rb b/plugins/orders_cycle/test/factories.rb
new file mode 100644
index 0000000..021fdaf
--- /dev/null
+++ b/plugins/orders_cycle/test/factories.rb
@@ -0,0 +1,57 @@
+module OrdersCyclePlugin::Factory
+
+ def defaults_for_suppliers_plugin_supplier
+ {:profile => build(Profile),
+ :consumer => build(Profile)}
+ end
+
+ def defaults_for_suppliers_plugin_distributed_product attrs = {}
+ profile = attrs[:profile] || build(Profile)
+ {:profile => profile, :name => "product-#{factory_num_seq}", :price => 2.0,
+ :product => build(Product, :enterprise => profile.profile, :price => 2.0),
+ :supplier => build(SuppliersPlugin::Supplier, :profile => profile, :consumer => profile)}
+ end
+
+ def defaults_for_orders_cycle_plugin_offered_product attrs = {}
+ hash = defaults_for_orders_cycle_plugin_product(attrs)
+ profile = hash[:profile]
+ hash.merge({
+ :from_products => [build(SuppliersPlugin::DistributedProduct, :profile => profile)]})
+ end
+
+ def defaults_for_delivery_plugin_method
+ {:profile => build(OrdersCyclePlugin::Profile),
+ :name => "My delivery #{factory_num_seq.to_s}",
+ :delivery_type => 'deliver'}
+ end
+
+ def defaults_for_delivery_plugin_option
+ {:cycle => build(OrdersCyclePlugin::Cycle),
+ :delivery_method => build(DeliveryPlugin::Method)}
+ end
+
+ def defaults_for_orders_plugin_order attrs = {}
+ profile = attrs[:profile] || build(OrdersCyclePlugin::Profile)
+ {:status => 'ordered',
+ :cycle => build(OrdersCyclePlugin::Cycle, :profile => profile),
+ :consumer => build(OrdersCyclePlugin::Profile),
+ :supplier_delivery => build(DeliveryPlugin::Method, :profile => profile),
+ :consumer_delivery => build(DeliveryPlugin::Method, :profile => profile)}
+ end
+
+ def defaults_for_orders_plugin_items
+ {:order => build(OrdersPlugin::Order),
+ :product => build(OrdersCyclePlugin::OfferedProduct),
+ :quantity_shipped => 1.0, :quantity_ordered => 2.0, :quantity_accepted => 3.0,
+ :price_shipped => 10.0, :price_ordered => 20.0, :price_accepted => 30.0}
+ end
+
+ def defaults_for_orders_cycle_plugin_cycle
+ {:profile => build(OrdersCyclePlugin::Profile), :status => 'orders',
+ :name => 'weekly', :start => Time.now, :finish => Time.now+1.days}
+ end
+
+end
+
+Noosfero::Factory.register_extension OrdersCyclePlugin::Factory
+
diff --git a/plugins/orders_cycle/test/functional/orders_cycle_plugin/order_controller_test.rb b/plugins/orders_cycle/test/functional/orders_cycle_plugin/order_controller_test.rb
new file mode 100644
index 0000000..9a93fce
--- /dev/null
+++ b/plugins/orders_cycle/test/functional/orders_cycle_plugin/order_controller_test.rb
@@ -0,0 +1,12 @@
+require "#{File.dirname(__FILE__)}/../../test_helper"
+
+class OrdersCyclePlugin::OrderControllerTest < Test::Unit::TestCase
+
+ def setup
+ @controller = OrdersCyclePluginOrderController.new
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ end
+
+
+end
diff --git a/plugins/orders_cycle/test/functional/orders_cycle_plugin/session_controller_test.rb b/plugins/orders_cycle/test/functional/orders_cycle_plugin/session_controller_test.rb
new file mode 100644
index 0000000..7ab2402
--- /dev/null
+++ b/plugins/orders_cycle/test/functional/orders_cycle_plugin/session_controller_test.rb
@@ -0,0 +1,14 @@
+require "#{File.dirname(__FILE__)}/../../test_helper"
+
+class OrdersCyclePlugin::CycleControllerTest < Test::Unit::TestCase
+
+ def setup
+ @controller = OrdersCyclePluginCycleController.new
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ end
+
+ should 'create a new cycle' do
+ end
+
+end
diff --git a/plugins/orders_cycle/test/test_helper.rb b/plugins/orders_cycle/test/test_helper.rb
new file mode 100644
index 0000000..3f0b088
--- /dev/null
+++ b/plugins/orders_cycle/test/test_helper.rb
@@ -0,0 +1,6 @@
+require File.dirname(__FILE__) + '/../../../test/test_helper'
+require 'spec'
+
+class ActiveRecord::TestCase < ActiveSupport::TestCase
+ include OrdersCyclePluginFactory
+end
diff --git a/plugins/orders_cycle/test/unit/orders_cycle_plugin/cycle_test.rb b/plugins/orders_cycle/test/unit/orders_cycle_plugin/cycle_test.rb
new file mode 100644
index 0000000..7c09b02
--- /dev/null
+++ b/plugins/orders_cycle/test/unit/orders_cycle_plugin/cycle_test.rb
@@ -0,0 +1,27 @@
+require "#{File.dirname(__FILE__)}/../../test_helper"
+
+class OrdersCyclePlugin::CycleTest < ActiveSupport::TestCase
+
+ def setup
+ @profile = Enterprise.create!(:name => "trocas verdes", :identifier => "trocas-verdes")
+ @pc = ProductCategory.create!(:name => 'frutas', :environment_id => 1)
+ @profile.products = [Product.create!(:name => 'banana', :product_category => @pc),
+ Product.new(:name => 'mandioca', :product_category => @pc), Product.new(:name => 'alface', :product_category => @pc)]
+
+ profile.offered_products = @profile.products.map{ |p| OrdersCyclePlugin::OfferedProduct.create!(:product => p) }
+ DeliveryPlugin::Method.create! :name => 'at home', :delivery_type => 'pickup', :profile => @profile
+ @cycle = OrdersCyclePlugin::Cycle.create!(:profile => @profile)
+ end
+
+ should 'add products from profile after create' do
+ assert_equal @cycle.products.collect(&:product_id), @profile.products.collect(&:id)
+ end
+
+ should 'have at least one delivery method unless in edition status' do
+ cycle = OrdersCyclePlugin::Cycle.create! :profile => @profile, :name => "Testes batidos", :start => DateTime.now, :status => 'edition'
+ assert cycle
+ cycle.status = 'orders'
+ assert_nil cycle.save!
+ end
+
+end
diff --git a/plugins/orders_cycle/test/unit/orders_cycle_plugin/offered_product_test.rb b/plugins/orders_cycle/test/unit/orders_cycle_plugin/offered_product_test.rb
new file mode 100644
index 0000000..7a92fde
--- /dev/null
+++ b/plugins/orders_cycle/test/unit/orders_cycle_plugin/offered_product_test.rb
@@ -0,0 +1,6 @@
+require "#{File.dirname(__FILE__)}/../../test_helper"
+
+class OrdersCyclePlugin::OfferedProductTest < ActiveSupport::TestCase
+
+
+end
diff --git a/plugins/orders_cycle/test/unit/profile_test.rb b/plugins/orders_cycle/test/unit/profile_test.rb
new file mode 100644
index 0000000..2d656fb
--- /dev/null
+++ b/plugins/orders_cycle/test/unit/profile_test.rb
@@ -0,0 +1,127 @@
+require "#{File.dirname(__FILE__)}/../../test_helper"
+
+class OrdersCyclePlugin::ProfileTest < ActiveRecord::TestCase
+
+ def setup
+ @profile = build(Profile)
+ @invisible_profile = build(Enterprise, :visible => false)
+ @other_profile = build(Enterprise)
+ @profile = build(OrdersCyclePlugin::profile, :profile => @profile)
+ @self_supplier = build(OrdersCyclePlugin::Supplier, :consumer => @profile, :profile => @profile)
+ @dummy_supplier = build(OrdersCyclePlugin::Supplier, :consumer => @profile, :profile => @dummy_profile)
+ @other_supplier = build(OrdersCyclePlugin::Supplier, :consumer => @profile, :profile => @other_profile)
+ end
+
+ attr_accessor :profile, :invisible_profile, :other_profile,
+ :self_supplier, :dummy_supplier, :other_supplier
+
+ should 'respond to name methods' do
+ profile.expects(:name).returns('name')
+ assert_equal 'name', profile.name
+ end
+
+ should 'respond to dummy methods' do
+ profile.dummy = true
+ assert_equal true, profile.dummy?
+ profile.dummy = false
+ assert_equal false, profile.dummy
+ end
+
+ should "return closed cycles' date range" do
+ DateTime.expects(:now).returns(1).at_least_once
+ assert_equal 1..1, profile.orders_cycles_closed_date_range
+ s1 = create(OrdersCyclePlugin::Cycle, :profile => profile, :start => Time.now-1.days, :finish => nil)
+ s2 = create(OrdersCyclePlugin::Cycle, :profile => profile, :finish => Time.now+1.days, :start => Time.now)
+ assert_equal (s1.start.to_date..s2.finish.to_date), profile.orders_cycles_closed_date_range
+ end
+
+ should 'return abbreviation or the name' do
+ profile.name_abbreviation = 'coll.'
+ profile.profile.name = 'collective'
+ assert_equal 'coll.', profile.abbreviation_or_name
+ profile.name_abbreviation = nil
+ assert_equal 'collective', profile.abbreviation_or_name
+ end
+
+ ###
+ # Products
+ ###
+
+ should "default products's margins when asked" do
+ profile.update! :margin_percentage => 10
+ product = create(SuppliersPlugin::DistributedProduct, :profile => profile, :supplier => profile.self_supplier,
+ :price => 10, :default_margin_percentage => false)
+ cycle = create(OrdersCyclePlugin::Cycle, :profile => profile)
+ sproduct = cycle.products.first
+ sproduct.update! :margin_percentage => 5
+ cycleclosed = create(OrdersCyclePlugin::Cycle, :profile => profile, :status => 'closed')
+
+ profile.orders_cycles_products_default_margins
+ product.reload
+ sproduct.reload
+ assert_equal true, product.default_margin_percentage
+ assert_equal sproduct.margin_percentage, profile.margin_percentage
+ end
+
+ should 'return not yet distributed products' do
+ profile.save!
+ other_profile.save!
+ other_supplier.save!
+ product = create(SuppliersPlugin::DistributedProduct, :profile => other_profile, :supplier => other_profile.self_supplier)
+ profile.add_supplier_products other_supplier
+ product2 = create(SuppliersPlugin::DistributedProduct, :profile => other_profile, :supplier => other_profile.self_supplier)
+ assert_equal [product2], profile.not_distributed_products(other_supplier)
+ end
+
+ ###
+ # Suppliers
+ ###
+
+ should 'add supplier' do
+ @profile.save!
+ @other_profile.save!
+
+ assert_difference OrdersCyclePlugin::Supplier, :count do
+ @profile.add_supplier @other_profile
+ end
+ assert @profile.suppliers_profiles.include?(@other_profile)
+ assert @other_profile.consumers_profiles.include?(@profile)
+ end
+
+ should "add all supplier's products when supplier is added" do
+ @profile.save!
+ @other_profile.save!
+ product = create(SuppliersPlugin::DistributedProduct, :profile => @other_profile)
+ @profile.add_supplier @other_profile
+ assert_equal [product], @profile.from_products
+ end
+
+ should 'remove supplier' do
+ @profile.save!
+ @other_profile.save!
+
+ @profile.add_supplier @other_profile
+ assert_difference OrdersCyclePlugin::Supplier, :count, -1 do
+ assert_difference RoleAssignment, :count, -1 do
+ @profile.remove_supplier @other_profile
+ end
+ end
+ assert !@profile.suppliers_profiles.include?(@other_profile)
+ end
+
+ should "archive supplier's products when supplier is removed" do
+ @profile.save!
+ @other_profile.save!
+ product = create(SuppliersPlugin::DistributedProduct, :profile => @other_profile)
+ @profile.add_supplier @other_profile
+ @profile.remove_supplier @other_profile
+ assert_equal [product], @profile.from_products
+ assert_equal 1, @profile.distributed_products.archived.count
+ end
+
+ should 'create self supplier automatically' do
+ profile = create(OrdersCyclePlugin::profile, :profile => @profile)
+ assert_equal 1, profile.suppliers.count
+ end
+
+end
diff --git a/plugins/orders_cycle/views/orders_cycle_plugin_cycle/_cycle_sales.html.slim b/plugins/orders_cycle/views/orders_cycle_plugin_cycle/_cycle_sales.html.slim
index 052c676..550e7ac 100644
--- a/plugins/orders_cycle/views/orders_cycle_plugin_cycle/_cycle_sales.html.slim
+++ b/plugins/orders_cycle/views/orders_cycle_plugin_cycle/_cycle_sales.html.slim
@@ -1,2 +1,3 @@
= render 'orders_plugin_admin/sales', actors: @cycle.consumers, orders_owner: @cycle, owner_id: @cycle.id,
orders: @cycle.sales.default_order.paginate(per_page: 30, page: params[:page])
+
diff --git a/plugins/orders_cycle/views/orders_cycle_plugin_cycle/_edit_fields.html.slim b/plugins/orders_cycle/views/orders_cycle_plugin_cycle/_edit_fields.html.slim
index 2e10b03..241b9a2 100644
--- a/plugins/orders_cycle/views/orders_cycle_plugin_cycle/_edit_fields.html.slim
+++ b/plugins/orders_cycle/views/orders_cycle_plugin_cycle/_edit_fields.html.slim
@@ -53,6 +53,5 @@ h3= t('views.cycle._edit_fields.general_settings')
= link_to t('views.cycle._edit_fields.cancel_changes'), @cycle.new? ? {action: :index} : params
- unless @cycle.new?
|
- = link_to t('views.cycle._edit_fields.remove'), {action: :destroy, id: @cycle.id}, confirm: t('views.cycle._edit_fields.confirm_remove')
-
+ = link_to t('views.cycle._edit_fields.remove'), {action: :destroy, id: @cycle.id}, data: {confirm: t('views.cycle._edit_fields.confirm_remove')}
diff --git a/plugins/orders_cycle/views/orders_cycle_plugin_cycle/_product_lines.html.erb b/plugins/orders_cycle/views/orders_cycle_plugin_cycle/_product_lines.html.erb
index 36591fb..47ae96d 100644
--- a/plugins/orders_cycle/views/orders_cycle_plugin_cycle/_product_lines.html.erb
+++ b/plugins/orders_cycle/views/orders_cycle_plugin_cycle/_product_lines.html.erb
@@ -1,7 +1,7 @@
<%= pagination_links @products %>
- <%= t('views.cycle._product_lines.showing_pcount_produc') % {:pcount => @products.length, :allpcount => @cycle.products.count} %>
+ <%= t('views.cycle._product_lines.showing_pcount_produc') % {pcount: @products.length, allpcount: @cycle.products.count} %>
@@ -31,7 +31,7 @@
{{item.name}}
- {{item.priceTxt}}
+ {{item.priceTxt}}
diff --git a/plugins/shopping_cart/views/shopping_cart_plugin/_items.html.erb b/plugins/shopping_cart/views/shopping_cart_plugin/_items.html.erb
index ebc5cec..fe6184d 100644
--- a/plugins/shopping_cart/views/shopping_cart_plugin/_items.html.erb
+++ b/plugins/shopping_cart/views/shopping_cart_plugin/_items.html.erb
@@ -3,45 +3,51 @@
style="<%= 'border-collapse: collapse' if by_mail %>">
-
- <%= _('Item name') %>
+ | >
+ <%= _('Item') %>
|
-
- <%= if by_mail then ' # ' else '#' end %>
+ | >
+ <%= if by_mail then ' '+_('Qtty')+' ' else _('Qtty') end %>
|
-
- <%= _('Price') + " (#{@environment.currency_unit})" %>
+ | >
+ <%= _('Unit price') + " (#{@environment.currency_unit})" %>
+ |
+ >
+ <%= _('Total') + " (#{@environment.currency_unit})" %>
|
<% order.items.each do |item| %>
-
+ | >
<%= item.name %>
|
-
- <%= item.quantity_consumer_ordered %>
+ | >
+ <%= "%03d" % item.quantity_consumer_ordered %>
+ |
+ >
+ <%= get_price item.product, @environment, 1, unit: '' %>
|
-
+ | >
<%= get_price item.product, @environment, item.quantity_consumer_ordered, unit: '' %>
|
<% end %>
-
-
+ |
+
<%= order.supplier_delivery.name if order.supplier_delivery %>
|
-
+ | >
<%= float_to_currency_cart order.supplier_delivery.cost(order.total_price), @environment, unit: '' if order.supplier_delivery %>
|
-
+ | >
<%= _('Total:') %>
|
-
+ | >
<%= float_to_currency_cart order.total, @environment %>
|
diff --git a/plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb b/plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb
index 245db4a..c7d23c8 100644
--- a/plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb
+++ b/plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb
@@ -1,13 +1,19 @@
-
- <%= _('Shopping checkout') %>
- <%= button :back, _("haven't finished yet: back to shopping"), 'javascript:history.back()', class: 'cart-go-back' %>
-
+
<%= _('Shopping checkout') %>
+ <%= button :back, _("haven't finished yet: back to shopping"), 'javascript:history.back()', class: 'cart-go-back' %>
<%= form_for :order, url: {action: :send_request},
html: {onsubmit: "return Cart.send_request(this)", id: 'cart-request-form'} do |f| %>
-
+
+
+
+
+
-
-
-
- <% supplier_delivery = @order.supplier_delivery || profile.delivery_methods.first %>
- <%= items_table @cart[:items], supplier_delivery %>
-
-
-
- <%= submit_button(:send, _('Send buy request')) %>
+ <%= button :back, _("haven't finished yet: back to shopping"), 'javascript:history.back()' %>
+ <%= submit_button(:send, _('Send buy request'), option:"success") %>
<% end %>
diff --git a/plugins/suppliers/controllers/myprofile/suppliers_plugin/basket_controller.rb b/plugins/suppliers/controllers/myprofile/suppliers_plugin/basket_controller.rb
index d403709..27434f9 100644
--- a/plugins/suppliers/controllers/myprofile/suppliers_plugin/basket_controller.rb
+++ b/plugins/suppliers/controllers/myprofile/suppliers_plugin/basket_controller.rb
@@ -52,10 +52,12 @@ class SuppliersPlugin::BasketController < MyProfileController
extend HMVC::ClassMethods
hmvc SuppliersPlugin
- def default_url_options
- # avoid rails' use_relative_controller!
- {use_route: '/'}
+ # inherit routes from core skipping use_relative_controller!
+ def url_for options
+ options[:controller] = "/#{options[:controller]}" if options.is_a? Hash and options[:controller] and not options[:controller].to_s.starts_with? '/'
+ super options
end
+ helper_method :url_for
def set_allowed_user
@allowed_user = true
diff --git a/plugins/suppliers/controllers/myprofile/suppliers_plugin/product_controller.rb b/plugins/suppliers/controllers/myprofile/suppliers_plugin/product_controller.rb
index 3fef0de..76b03a9 100644
--- a/plugins/suppliers/controllers/myprofile/suppliers_plugin/product_controller.rb
+++ b/plugins/suppliers/controllers/myprofile/suppliers_plugin/product_controller.rb
@@ -32,7 +32,7 @@ class SuppliersPlugin::ProductController < MyProfileController
def edit
@product = profile.products.supplied.find params[:id]
- @product.update_attributes params["product_#{@product.id}"]
+ @product.update params["product_#{@product.id}"]
end
def import
@@ -79,6 +79,7 @@ class SuppliersPlugin::ProductController < MyProfileController
@supplier = SuppliersPlugin::Supplier.where(id: params[:supplier_id]).first if params[:supplier_id].present?
+ # FIXME: joins(:from_products) is hiding own products (except baskets)
@scope = profile.products.unarchived.joins :from_products, :suppliers
@scope = SuppliersPlugin::BaseProduct.search_scope @scope, params
@products_count = @scope.supplied_for_count.count
@@ -95,9 +96,11 @@ class SuppliersPlugin::ProductController < MyProfileController
extend HMVC::ClassMethods
hmvc SuppliersPlugin
- def default_url_options
- # avoid rails' use_relative_controller!
- {use_route: '/'}
+ # inherit routes from core skipping use_relative_controller!
+ def url_for options
+ options[:controller] = "/#{options[:controller]}" if options.is_a? Hash and options[:controller] and not options[:controller].to_s.starts_with? '/'
+ super options
end
+ helper_method :url_for
end
diff --git a/plugins/suppliers/controllers/myprofile/suppliers_plugin_myprofile_controller.rb b/plugins/suppliers/controllers/myprofile/suppliers_plugin_myprofile_controller.rb
index 3266894..9ebb945 100644
--- a/plugins/suppliers/controllers/myprofile/suppliers_plugin_myprofile_controller.rb
+++ b/plugins/suppliers/controllers/myprofile/suppliers_plugin_myprofile_controller.rb
@@ -21,7 +21,7 @@ class SuppliersPluginMyprofileController < MyProfileController
end
def new
- @new_supplier.update_attributes! params[:supplier]
+ @new_supplier.update! params[:supplier]
@supplier = @new_supplier
session[:notice] = t('controllers.myprofile.supplier_created')
end
@@ -33,7 +33,7 @@ class SuppliersPluginMyprofileController < MyProfileController
def edit
@supplier = profile.suppliers.find params[:id]
- @supplier.update_attributes params[:supplier]
+ @supplier.update params[:supplier]
end
def margin_change
@@ -58,8 +58,8 @@ class SuppliersPluginMyprofileController < MyProfileController
def search
@query = params[:query].downcase
- @enterprises = environment.enterprises.enabled.public.all limit: 12, order: 'name ASC',
- conditions: ['LOWER(name) LIKE ? OR LOWER(name) LIKE ? OR identifier LIKE ?', "#{@query}%", "% #{@query}%", "#{@query}%"]
+ @enterprises = environment.enterprises.enabled.is_public.limit(12).order('name ASC').
+ where('name ILIKE ? OR name ILIKE ? OR identifier LIKE ?', "#{@query}%", "% #{@query}%", "#{@query}%")
@enterprises -= profile.suppliers.collect(&:profile)
end
diff --git a/plugins/suppliers/lib/default_delegate.rb b/plugins/suppliers/lib/default_delegate.rb
index 02bdfbe..ce7b8b1 100644
--- a/plugins/suppliers/lib/default_delegate.rb
+++ b/plugins/suppliers/lib/default_delegate.rb
@@ -15,6 +15,9 @@ module DefaultDelegate
# TODO: add some documentation about the methods being added
def default_delegate field, options = {}
+ class_attribute :default_delegate_enable unless respond_to? :default_delegate_enable
+ self.default_delegate_enable = true if self.default_delegate_enable.nil?
+
# rake db:migrate run?
return unless self.table_exists?
@@ -91,6 +94,8 @@ module DefaultDelegate
end
define_method "#{field}_with_default" do
+ return self.send own_field unless self.default_delegate_enable
+
if self.send default_setting
# delegated_field may return nil, so use own instead
# this is the case with some associations (e.g. Product#product_qualifiers)
@@ -101,6 +106,8 @@ module DefaultDelegate
end
end
define_method "#{field}_with_default=" do |*args|
+ return self.send "#{own_field}=", *args unless self.default_delegate_enable
+
own = self.send "#{own_field}=", *args
# break/set the default setting automatically, used for interfaces
# that don't have the default setting (e.g. manage_products)
diff --git a/plugins/suppliers/lib/ext/product.rb b/plugins/suppliers/lib/ext/product.rb
index 4207159..75ad780 100644
--- a/plugins/suppliers/lib/ext/product.rb
+++ b/plugins/suppliers/lib/ext/product.rb
@@ -7,20 +7,22 @@ class Product
has_currency :price
has_currency :discount
- scope :available, conditions: {available: true}
- scope :unavailable, conditions: ['products.available <> true']
- scope :archived, conditions: {archived: true}
- scope :unarchived, conditions: ['products.archived <> true']
+ scope :alphabetically, -> { order 'products.name ASC' }
- scope :with_available, lambda { |available| where available: available }
- scope :with_price, conditions: 'products.price > 0'
- scope :with_product_category_id, lambda { |id| { conditions: {product_category_id: id} } }
+ scope :available, -> { where available: true }
+ scope :unavailable, -> { where 'products.available <> true' }
+ scope :archived, -> { where archived: true }
+ scope :unarchived, -> { where 'products.archived <> true' }
+
+ scope :with_available, -> (available) { where available: available }
+ scope :with_price, -> { where 'products.price > 0' }
# FIXME: transliterate input and name column
- scope :name_like, lambda { |name| { conditions: ["LOWER(products.name) LIKE ?", "%#{name}%"] } }
+ scope :name_like, -> (name) { where "name ILIKE ?", "%#{name}%" }
+ scope :with_product_category_id, -> (id) { where product_category_id: id }
- scope :by_profile, lambda { |profile| { conditions: {profile_id: profile.id} } }
- scope :by_profile_id, lambda { |profile_id| { conditions: {profile_id: profile_id} } }
+ scope :by_profile, -> (profile) { where profile_id: profile.id }
+ scope :by_profile_id, -> (profile_id) { where profile_id: profile_id }
def self.product_categories_of products
ProductCategory.find products.collect(&:product_category_id).compact.select{ |id| not id.zero? }
@@ -36,16 +38,16 @@ end
class Product
- attr_accessible :from_products, :supplier_id, :supplier
+ attr_accessible :from_products, :from_product, :supplier_id, :supplier
has_many :sources_from_products, foreign_key: :to_product_id, class_name: 'SuppliersPlugin::SourceProduct', dependent: :destroy
has_one :sources_from_product, foreign_key: :to_product_id, class_name: 'SuppliersPlugin::SourceProduct'
has_many :sources_to_products, foreign_key: :from_product_id, class_name: 'SuppliersPlugin::SourceProduct', dependent: :destroy
has_one :sources_to_product, foreign_key: :from_product_id, class_name: 'SuppliersPlugin::SourceProduct'
- has_many :to_products, through: :sources_to_products, order: 'id ASC'
- has_one :to_product, through: :sources_to_product, order: 'id ASC', autosave: true
- has_many :from_products, through: :sources_from_products, order: 'id ASC'
- has_one :from_product, through: :sources_from_product, order: 'id ASC', autosave: true
+ has_many :to_products, -> { order 'id ASC' }, through: :sources_to_products
+ has_one :to_product, -> { order 'id ASC' }, through: :sources_to_product, autosave: true
+ has_many :from_products, -> { order 'id ASC' }, through: :sources_from_products
+ has_one :from_product, -> { order 'id ASC' }, through: :sources_from_product, autosave: true
has_many :sources_from_2x_products, through: :from_products, source: :sources_from_products
has_one :sources_from_2x_product, through: :from_product, source: :sources_from_product
@@ -59,15 +61,15 @@ class Product
# semantic alias for supplier_from_product(s)
has_many :sources_supplier_products, foreign_key: :to_product_id, class_name: 'SuppliersPlugin::SourceProduct'
has_one :sources_supplier_product, foreign_key: :to_product_id, class_name: 'SuppliersPlugin::SourceProduct'
- has_many :supplier_products, through: :sources_supplier_products, source: :from_product, order: 'id ASC'
- has_one :supplier_product, through: :sources_supplier_product, source: :from_product, order: 'id ASC', autosave: true
- has_many :suppliers, through: :sources_supplier_products, uniq: true, order: 'id ASC'
- has_one :supplier, through: :sources_supplier_product, order: 'id ASC'
+ has_many :supplier_products, -> { order 'id ASC' }, through: :sources_supplier_products, source: :from_product
+ has_one :supplier_product, -> { order 'id ASC' }, through: :sources_supplier_product, source: :from_product, autosave: true
+ has_many :suppliers, -> { distinct.order 'id ASC' }, through: :sources_supplier_products
+ has_one :supplier, -> { order 'id ASC' }, through: :sources_supplier_product
- has_many :consumers, through: :to_products, source: :profile, uniq: true, order: 'id ASC'
- has_one :consumer, through: :to_product, source: :profile, order: 'id ASC'
+ has_many :consumers, -> { distinct.order 'id ASC' }, through: :to_products, source: :profile
+ has_one :consumer, -> { order 'id ASC' }, through: :to_product, source: :profile
- # overhide original
+ # overhide original, FIXME: rename to available_and_supplier_active
scope :available, -> {
joins(:suppliers).
where 'products.available = ? AND suppliers_plugin_suppliers.active = ?', true, true
@@ -81,23 +83,24 @@ class Product
where "products.available #{op} ? #{cond} suppliers_plugin_suppliers.active #{op} ?", true, true
}
- scope :name_like, lambda { |name| where "from_products_products.name ILIKE ?", "%#{name}%" }
- scope :with_product_category_id, lambda { |id| where 'from_products_products.product_category_id = ?', id }
+ scope :fp_name_like, -> (name) { where "from_products_products.name ILIKE ?", "%#{name}%" }
+ scope :fp_with_product_category_id, -> (id) { where 'from_products_products.product_category_id = ?', id }
# prefer distributed_products has_many to use DistributedProduct scopes and eager loading
scope :distributed, -> { where type: 'SuppliersPlugin::DistributedProduct'}
scope :own, -> { where type: nil }
scope :supplied, -> {
- where(type: [nil, 'SuppliersPlugin::DistributedProduct']).
- # this allow duplicates and sorting on the fields
- group('products.id')
+ # this remove duplicates and allow sorting on the fields, unlike distinct
+ group('products.id').
+ where type: [nil, 'SuppliersPlugin::DistributedProduct']
}
scope :supplied_for_count, -> {
- where(type: [nil, 'SuppliersPlugin::DistributedProduct']).uniq
+ distinct.
+ where type: [nil, 'SuppliersPlugin::DistributedProduct']
}
- scope :from_supplier, lambda { |supplier| { conditions: ['suppliers_plugin_suppliers.id = ?', supplier.id] } }
- scope :from_supplier_id, lambda { |supplier_id| { conditions: ['suppliers_plugin_suppliers.id = ?', supplier_id] } }
+ scope :from_supplier, -> (supplier) { joins(:suppliers).where 'suppliers_plugin_suppliers.id = ?', supplier.id }
+ scope :from_supplier_id, -> (supplier_id) { joins(:suppliers).where 'suppliers_plugin_suppliers.id = ?', supplier_id }
after_create :distribute_to_consumers
@@ -132,8 +135,8 @@ class Product
def distribute_to_consumer consumer, attrs = {}
distributed_product = consumer.distributed_products.where(profile_id: consumer.id, from_products_products: {id: self.id}).first
- distributed_product ||= SuppliersPlugin::DistributedProduct.create! profile: consumer, from_products: [self]
- distributed_product.update_attributes! attrs if attrs.present?
+ distributed_product ||= SuppliersPlugin::DistributedProduct.create! profile: consumer, from_product: self
+ distributed_product.update! attrs if attrs.present?
distributed_product
end
diff --git a/plugins/suppliers/lib/ext/profile.rb b/plugins/suppliers/lib/ext/profile.rb
index be25627..5092560 100644
--- a/plugins/suppliers/lib/ext/profile.rb
+++ b/plugins/suppliers/lib/ext/profile.rb
@@ -1,20 +1,25 @@
require_dependency 'profile'
+require_dependency 'community'
-# FIXME: The lines bellow should be on the core
-class Profile
+# FIXME: should be on the core
+([Profile] + Profile.descendants).each do |subclass|
+subclass.class_eval do
- has_many :products
+ has_many :products, foreign_key: :profile_id
+end
+end
+class Profile
def create_product?
true
end
-
end
-class Profile
+([Profile] + Profile.descendants).each do |subclass|
+subclass.class_eval do
# use profile.products.supplied to include own products
- has_many :distributed_products, class_name: 'SuppliersPlugin::DistributedProduct'
+ has_many :distributed_products, class_name: 'SuppliersPlugin::DistributedProduct', foreign_key: :profile_id
has_many :from_products, through: :products
has_many :to_products, through: :products
@@ -24,6 +29,11 @@ class Profile
has_many :consumers, class_name: 'SuppliersPlugin::Consumer', foreign_key: :profile_id, dependent: :destroy,
include: [{profile: [:domains], consumer: [:domains]}], order: 'name ASC'
+end
+end
+
+class Profile
+
def supplier_settings
@supplier_settings ||= Noosfero::Plugin::Settings.new self, SuppliersPlugin
end
diff --git a/plugins/suppliers/lib/suppliers_plugin/import.rb b/plugins/suppliers/lib/suppliers_plugin/import.rb
index 0b57ee8..590593b 100644
--- a/plugins/suppliers/lib/suppliers_plugin/import.rb
+++ b/plugins/suppliers/lib/suppliers_plugin/import.rb
@@ -123,11 +123,11 @@ class SuppliersPlugin::Import
product ||= supplier.profile.products.build attrs
# let update happen only on dummy suppliers
if product.persisted? and supplier.dummy?
- product.update_attributes! attrs
+ product.update! attrs
elsif product.new_record?
# create products as not available
attrs[:available] = false if not supplier.dummy?
- product.update_attributes! attrs
+ product.update! attrs
end
distributed_product = product.distribute_to_consumer consumer, distributed_attrs
diff --git a/plugins/suppliers/models/suppliers_plugin/base_product.rb b/plugins/suppliers/models/suppliers_plugin/base_product.rb
index 842b76d..4d76305 100644
--- a/plugins/suppliers/models/suppliers_plugin/base_product.rb
+++ b/plugins/suppliers/models/suppliers_plugin/base_product.rb
@@ -19,7 +19,8 @@ class SuppliersPlugin::BaseProduct < Product
}
]
- self.abstract_class = true
+ # if abstract_class is true then it will trigger https://github.com/rails/rails/issues/20871
+ #self.abstract_class = true
settings_items :minimum_selleable, type: Float, default: nil
settings_items :margin_percentage, type: Float, default: nil
@@ -75,11 +76,12 @@ class SuppliersPlugin::BaseProduct < Product
Unit.new(singular: I18n.t('suppliers_plugin.models.product.unit'), plural: I18n.t('suppliers_plugin.models.product.units'))
end
+ # override SuppliersPlugin::BaseProduct
def self.search_scope scope, params
scope = scope.from_supplier_id params[:supplier_id] if params[:supplier_id].present?
scope = scope.with_available(if params[:available] == 'true' then true else false end) if params[:available].present?
- scope = scope.name_like params[:name] if params[:name].present?
- scope = scope.with_product_category_id params[:category_id] if params[:category_id].present?
+ scope = scope.fp_name_like params[:name] if params[:name].present?
+ scope = scope.fp_with_product_category_id params[:category_id] if params[:category_id].present?
scope
end
@@ -98,7 +100,7 @@ SQL
def self.archive_orphans
self.where(id: self.orphans_ids).find_each batch_size: 50 do |product|
# need full save to trigger search index
- product.update_attributes archived: true
+ product.update archived: true
end
end
@@ -173,10 +175,10 @@ SQL
# FIXME: move to core
def archive
- self.update_attributes! archived: true
+ self.update! archived: true
end
def unarchive
- self.update_attributes! archived: false
+ self.update! archived: false
end
protected
diff --git a/plugins/suppliers/models/suppliers_plugin/supplier.rb b/plugins/suppliers/models/suppliers_plugin/supplier.rb
index a601012..e3ac8cd 100644
--- a/plugins/suppliers/models/suppliers_plugin/supplier.rb
+++ b/plugins/suppliers/models/suppliers_plugin/supplier.rb
@@ -16,21 +16,21 @@ class SuppliersPlugin::Supplier < ActiveRecord::Base
scope :alphabetical, -> { order 'name ASC' }
- scope :active, conditions: {active: true}
+ scope :active, -> { where active: true }
scope :dummy, -> { joins(:profile).where profiles: {visible: false} }
- scope :of_profile, lambda { |p| { conditions: {profile_id: p.id} } }
- scope :of_profile_id, lambda { |id| { conditions: {profile_id: id} } }
- scope :of_consumer, lambda { |c| { conditions: {consumer_id: c.id} } }
- scope :of_consumer_id, lambda { |id| { conditions: {consumer_id: id} } }
+ scope :of_profile, -> (p) { where profile_id: p.id }
+ scope :of_profile_id, -> (id) { where profile_id: id }
+ scope :of_consumer, -> (c) { where consumer_id: c.id }
+ scope :of_consumer_id, -> (id) { where consumer_id: id }
- scope :from_supplier_id, lambda { |supplier_id| { conditions: ['suppliers_plugin_suppliers.id = ?', supplier_id] } }
+ scope :from_supplier_id, -> (supplier_id) { where 'suppliers_plugin_suppliers.id = ?', supplier_id }
- scope :with_name, lambda { |name| if name then {conditions: ["LOWER(suppliers_plugin_suppliers.name) LIKE ?","%#{name.downcase}%"]} else {} end }
- scope :by_active, lambda { |active| if active then {conditions: {active: active}} else {} end }
+ scope :with_name, -> (name) { where "suppliers_plugin_suppliers.name ILIKE ?", "%#{name.downcase}%" if name }
+ scope :by_active, -> (active) { where active: active if active }
- scope :except_people, { conditions: ['profiles.type <> ?', Person.name], joins: [:consumer] }
- scope :except_self, { conditions: 'profile_id <> consumer_id' }
+ scope :except_people, -> { joins(:consumer).where 'profiles.type <> ?', Person.name }
+ scope :except_self, -> { where 'profile_id <> consumer_id' }
after_create :add_admins, if: :dummy?
after_create :save_profile, if: :dummy?
diff --git a/plugins/suppliers/test/test_helper.rb b/plugins/suppliers/test/test_helper.rb
new file mode 100644
index 0000000..cca1fd3
--- /dev/null
+++ b/plugins/suppliers/test/test_helper.rb
@@ -0,0 +1 @@
+require File.dirname(__FILE__) + '/../../../test/test_helper'
diff --git a/plugins/suppliers/test/unit/code_numbering_test.rb b/plugins/suppliers/test/unit/code_numbering_test.rb
new file mode 100644
index 0000000..0fcb79a
--- /dev/null
+++ b/plugins/suppliers/test/unit/code_numbering_test.rb
@@ -0,0 +1,7 @@
+require File.dirname(__FILE__) + '/../../../../test/test_helper'
+
+class CodeNumberingTest < ActiveSupport::TestCase
+
+
+end
+
diff --git a/plugins/suppliers/test/unit/default_delegate_test.rb b/plugins/suppliers/test/unit/default_delegate_test.rb
new file mode 100644
index 0000000..525796d
--- /dev/null
+++ b/plugins/suppliers/test/unit/default_delegate_test.rb
@@ -0,0 +1,6 @@
+require 'test_helper'
+
+class DefaultDelegateTest < ActiveSupport::TestCase
+
+
+end
diff --git a/plugins/suppliers/test/unit/suppliers_plugin/distributed_product_test.rb b/plugins/suppliers/test/unit/suppliers_plugin/distributed_product_test.rb
new file mode 100644
index 0000000..ddcd396
--- /dev/null
+++ b/plugins/suppliers/test/unit/suppliers_plugin/distributed_product_test.rb
@@ -0,0 +1,108 @@
+require "#{File.dirname(__FILE__)}/../../test_helper"
+
+class SuppliersPlugin::DistributedProductTest < ActiveSupport::TestCase
+
+ def setup
+ @product_category = create(ProductCategory, :name => 'parent')
+ @profile = build(Enterprise)
+ @invisible_profile = build(Enterprise, :visible => false)
+ @other_profile = build(Enterprise)
+ @self_supplier = build(SuppliersPlugin::Supplier, :consumer => @profile, :profile => @profile)
+ @dummy_supplier = build(SuppliersPlugin::Supplier, :consumer => @profile, :profile => @dummy_profile)
+ @other_supplier = build(SuppliersPlugin::Supplier, :consumer => @profile, :profile => @other_profile)
+ end
+
+ attr_accessor :product_category,
+ :profile, :invisible_profile, :other_profile,
+ :profile, :dummy_profile, :other_profile, :self_supplier, :dummy_supplier, :other_supplier
+
+ should 'return default settings considering dummy supplier' do
+ product = build(SuppliersPlugin::DistributedProduct, :profile => @profile, :supplier => @dummy_supplier)
+ assert_equal nil, product.default_name
+ assert_equal nil, product.default_description
+ product = build(SuppliersPlugin::DistributedProduct, :profile => @profile, :supplier => @other_supplier)
+ assert_equal true, product.default_name
+ assert_equal true, product.default_description
+ end
+
+ should 'return price without margins if it is own product' do
+ product = build(SuppliersPlugin::DistributedProduct, :price => 10, :margin_percentage => 10, :profile => @profile, :supplier => @self_supplier)
+ assert_equal 10.0, product.price.to_f
+ end
+
+ should 'return price without margins if supplier product has no price' do
+ supplier_product = build(SuppliersPlugin::DistributedProduct, :profile => @other_profile, :supplier => @other_profile.self_supplier)
+ product = build(SuppliersPlugin::DistributedProduct, :price => 10, :margin_percentage => 10, :profile => @profile, :supplier => @other_supplier)
+ assert_equal 10.0, product.price.to_f
+ end
+
+ should 'return price with margins' do
+ supplier_product = build(SuppliersPlugin::DistributedProduct, :price => 10, :margin_percentage => 10, :profile => @other_profile, :supplier => @other_profile.self_supplier)
+ product = build(SuppliersPlugin::DistributedProduct, :price => 10, :margin_percentage => 10, :supplier_product => supplier_product, :profile => @profile, :supplier => @other_supplier)
+
+ product.default_margin_percentage = false
+ assert_equal 11.0, product.price.to_f
+ profile.margin_percentage = 20
+ product.default_margin_percentage = true
+ assert_equal 12.0, product.price.to_f
+ end
+
+ should 'allow set of supplier product' do
+ product = build(SuppliersPlugin::DistributedProduct, :price => 10, :margin_percentage => 10, :profile => @profile, :supplier => @self_supplier)
+
+ product.from_product = build(SuppliersPlugin::DistributedProduct, :profile => @profile, :supplier => @self_supplier)
+ assert_nothing_raised do
+ product.supplier_product = {:price => 10, :margin_percentage => 10}
+ product.supplier_product = SuppliersPlugin::DistributedProduct.new :price => 5
+ end
+ end
+
+ should 'create a supplier product for a dummy supplier' do
+ product = build(SuppliersPlugin::DistributedProduct, :profile => @profile, :supplier => @dummy_supplier)
+ assert product.supplier_product
+ # negative assertion
+ product = build(SuppliersPlugin::DistributedProduct, :profile => @profile, :supplier => @other_supplier)
+ assert !product.supplier_product
+ end
+
+ should 'respond to supplier_product_id setter and getter' do
+ product = create(SuppliersPlugin::DistributedProduct, :profile => @profile, :supplier => @dummy_supplier)
+ assert_equal product.supplier_product.id, product.supplier_product_id
+ product.expects(:distribute_from)
+ product.supplier_product_id = 1
+ end
+
+ should 'respond to distribute_from' do
+ product = create(SuppliersPlugin::DistributedProduct, :profile => @profile, :supplier => @profile.self_supplier)
+
+ assert_raise RuntimeError do
+ supplier_product = build(SuppliersPlugin::DistributedProduct, :profile => @other_profile)
+ product.distribute_from(supplier_product)
+ end
+
+ supplier_product = create(SuppliersPlugin::DistributedProduct, :profile => @other_profile)
+ product.profile.add_supplier @other_profile
+ product.distribute_from supplier_product
+ assert_equal product.supplier.profile, supplier_product.profile
+ assert_equal product.supplier.profile, supplier_product.profile
+ end
+
+ should 'return json for category hierarchy' do
+ grandparent = create(ProductCategory, :name => 'grand parent')
+ parent = create(ProductCategory, :name => 'parent')
+ child = product_category
+
+ product = SuppliersPlugin::DistributedProduct.new :category => parent
+ hash = {:own_name => "parent", :id => "2", :subcats => [], :name => "parent",
+ :hierarchy => [{:own_name => "parent", :subcats => [], :name => "parent", :id => "2"}]}
+ assert_equal hash, product.json_for_category
+ end
+
+ should 'block own product distribution' do
+ product = Product.create :enterprise => @profile, :product_category => product_category
+ distributed = SuppliersPlugin::DistributedProduct.new :enterprise => @profile, :from_products => [product]
+
+ assert distributed.invalid?
+ end
+
+end
diff --git a/plugins/suppliers/test/unit/suppliers_plugin/product_test.rb b/plugins/suppliers/test/unit/suppliers_plugin/product_test.rb
new file mode 100644
index 0000000..947ba74
--- /dev/null
+++ b/plugins/suppliers/test/unit/suppliers_plugin/product_test.rb
@@ -0,0 +1,49 @@
+require "test_helper"
+
+class SuppliersPlugin::ProductTest < ActiveSupport::TestCase
+
+ def setup
+ @product = build(SuppliersPlugin::BaseProduct)
+ end
+
+ should 'return first from product as supplier product' do
+ fp = build(SuppliersPlugin::BaseProduct, :profile => @product.profile)
+ @product.from_products = [fp]
+ assert_equal fp, @product.from_product
+ assert_equal fp, @product.supplier_product
+ end
+
+ should 'respond to dummy and own' do
+ assert !@product.dummy?
+ assert @product.own?
+ end
+
+ should 'return price with margins' do
+ supplier_product = build(SuppliersPlugin::DistributedProduct, :price => 10, :margin_percentage => 10, :profile => @product.profile, :supplier => @product.profile.self_supplier)
+ product = build(SuppliersPlugin::DistributedProduct, :price => 10, :margin_percentage => 10, :supplier_product => supplier_product, :profile => @product.profile, :supplier => @product.profile.self_supplier)
+
+ product.default_margin_percentage = false
+ assert_equal 11.0, product.price_with_margins
+ @product.profile.margin_percentage = 20
+ product.default_margin_percentage = true
+ assert_equal 12.0, product.price_with_margins
+ end
+
+ should 'build default unit if none exists' do
+ assert_equal 0, Unit.count
+ assert 'unit', @product.unit.singular
+ end
+
+ should 'avoid destroy by raising an exception' do
+ assert_raise RuntimeError do
+ @product.destroy
+ end
+ end
+
+ should 'accept price in different formats' do
+ @product.price = '2,45'
+ assert_equal 2.45, @product.price
+ end
+
+
+end
diff --git a/plugins/suppliers/test/unit/suppliers_plugin/source_product_test.rb b/plugins/suppliers/test/unit/suppliers_plugin/source_product_test.rb
new file mode 100644
index 0000000..a043536
--- /dev/null
+++ b/plugins/suppliers/test/unit/suppliers_plugin/source_product_test.rb
@@ -0,0 +1,8 @@
+require "#{File.dirname(__FILE__)}/../../test_helper"
+
+class SuppliersPlugin::SourceProductTest < ActiveSupport::TestCase
+
+ def setup
+ end
+
+end
diff --git a/plugins/suppliers/test/unit/suppliers_plugin/supplier_test.rb b/plugins/suppliers/test/unit/suppliers_plugin/supplier_test.rb
new file mode 100644
index 0000000..f3d53c9
--- /dev/null
+++ b/plugins/suppliers/test/unit/suppliers_plugin/supplier_test.rb
@@ -0,0 +1,8 @@
+require "#{File.dirname(__FILE__)}/../../test_helper"
+
+class SuppliersPlugin::SupplierTest < ActiveSupport::TestCase
+
+ def setup
+ end
+
+end
diff --git a/plugins/suppliers/views/suppliers_plugin_myprofile/margin_change.html.slim b/plugins/suppliers/views/suppliers_plugin_myprofile/margin_change.html.slim
new file mode 100644
index 0000000..ad19eac
--- /dev/null
+++ b/plugins/suppliers/views/suppliers_plugin_myprofile/margin_change.html.slim
@@ -0,0 +1,17 @@
+#suppliers-plugin-margin-change.popin
+ h1= t'views.myprofile.margin_change.change_default_margin'
+
+ = form_for @profile, as: :profile_data, remote: true, url: {controller: :suppliers_plugin_myprofile, action: :margin_change} do |f|
+ div= t'views.myprofile.margin_change.notice'
+
+ = labelled_field f, :margin_percentage, t('views.myprofile.margin_change.new_margin'),
+ input_group_addon(t'views.myprofile.margin_change.%'){ f.number_field :margin_percentage, step: 'any' }
+
+ .checkbox
+ label name='apply_to_all'
+ = check_box_tag :apply_to_all, 1, false
+ = t'views.myprofile.margin_change.apply_to_all'
+ .clean
+
+ = submit_button :save, t('views.myprofile.margin_change.confirm')
+ = modal_close_link t('views.myprofile.margin_change.cancel')
--
libgit2 0.21.2