diff --git a/app/controllers/administration/online_stores_controller.rb b/app/controllers/administration/online_stores_controller.rb new file mode 100644 index 000000000..edeb5caea --- /dev/null +++ b/app/controllers/administration/online_stores_controller.rb @@ -0,0 +1,52 @@ +class Administration::OnlineStoresController < AdministrationController + def index + @online_stores = OnlineStore.all + end + + def show + render :edit + end + + def new + @online_store = OnlineStore.new + end + + def edit; end + + def create + @online_store = OnlineStore.new(online_store_params) + + if @online_store.save + redirect_to online_stores_url, notice: t('.success') + else + render :new + end + end + + def update + if @online_store.update(online_store_params) + redirect_to online_stores_url, notice: t('.success') + else + render :edit + end + end + + def destroy + @online_store.destroy + + redirect_to online_stores_url, notice: t('.success') + end + + private + + def find_resource + @online_store = OnlineStore.find(params[:id]) + end + + def online_store_params + params.require(:online_store).permit(:name, + :online_store_theme_id, + { product_ids: [] }, + :type) + end +end diff --git a/app/models/company.rb b/app/models/company.rb index f4a25f0a8..66ac4e10b 100644 --- a/app/models/company.rb +++ b/app/models/company.rb @@ -73,6 +73,7 @@ class Company < ActiveRecord::Base has_many :customer_transports, through: :customers, source: :transports has_many :mail_servers has_many :incoming_mails, through: :mail_servers + has_many :online_stores accepts_nested_attributes_for :bank_accounts, :users diff --git a/app/models/online_store.rb b/app/models/online_store.rb new file mode 100644 index 000000000..5d499df10 --- /dev/null +++ b/app/models/online_store.rb @@ -0,0 +1,22 @@ +class OnlineStore < BaseModel + include PupenextSingleTableInheritance + + belongs_to :company + belongs_to :theme, foreign_key: :online_store_theme_id, class_name: 'OnlineStoreTheme' + + has_and_belongs_to_many :products, join_table: :online_stores_products + + validates :name, presence: true, length: { in: 1..255 } + + def to_s + name + end + + def self.child_class_names + [ + OnlineStore::Magento, + OnlineStore::PrestaShop, + OnlineStore::Pupeshop + ].index_by(&:to_s) + end +end diff --git a/app/models/online_store/magento.rb b/app/models/online_store/magento.rb new file mode 100644 index 000000000..661a962be --- /dev/null +++ b/app/models/online_store/magento.rb @@ -0,0 +1,5 @@ +class OnlineStore::Magento < OnlineStore + def self.model_name + OnlineStore.model_name + end +end diff --git a/app/models/online_store/presta_shop.rb b/app/models/online_store/presta_shop.rb new file mode 100644 index 000000000..8a597dbe5 --- /dev/null +++ b/app/models/online_store/presta_shop.rb @@ -0,0 +1,5 @@ +class OnlineStore::PrestaShop < OnlineStore + def self.model_name + OnlineStore.model_name + end +end diff --git a/app/models/online_store/pupeshop.rb b/app/models/online_store/pupeshop.rb new file mode 100644 index 000000000..444351eac --- /dev/null +++ b/app/models/online_store/pupeshop.rb @@ -0,0 +1,5 @@ +class OnlineStore::Pupeshop < OnlineStore + def self.model_name + OnlineStore.model_name + end +end diff --git a/app/models/online_store_theme.rb b/app/models/online_store_theme.rb new file mode 100644 index 000000000..43ea278c7 --- /dev/null +++ b/app/models/online_store_theme.rb @@ -0,0 +1,9 @@ +class OnlineStoreTheme < ActiveRecord::Base + has_many :online_stores + + validates :name, presence: true, length: { in: 1..255 } + + def to_s + name + end +end diff --git a/app/models/product.rb b/app/models/product.rb index e8fd9fc7d..556abf6f4 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -22,6 +22,8 @@ class Product < BaseModel o.has_one :cover_thumbnail, -> { where(kayttotarkoitus: :th).order(:jarjestys, :tunnus) } end + has_and_belongs_to_many :online_stores, join_table: :online_stores_products + delegate :images, to: :attachments delegate :thumbnails, to: :attachments @@ -131,6 +133,10 @@ def contract_price?(target) end end + def to_s + "#{tuoteno}: #{nimitys}" + end + private def defaults diff --git a/app/views/administration/online_stores/_form.html.erb b/app/views/administration/online_stores/_form.html.erb new file mode 100644 index 000000000..b2e724b67 --- /dev/null +++ b/app/views/administration/online_stores/_form.html.erb @@ -0,0 +1,22 @@ +<%= render 'administration/form_errors', resource: @online_store %> + +<%= simple_form_for @online_store, + builder: AdminFormBuilder, + defaults: { input_html: { class: :large } }, + alias_set: params[:alias_set] do |f| %> + + + <%= f.input :name %> + <%= f.association :theme %> + <%= f.input :type, collection: OnlineStore.child_class_names.keys, + label_method: :demodulize, + include_blank: false %> + <%= f.association :products, collection: Product.active, + input_html: { class: %w(large chosen-select) } %> +
+ +
+ + <%= f.button :submit %> + +<% end %> diff --git a/app/views/administration/online_stores/edit.html.erb b/app/views/administration/online_stores/edit.html.erb new file mode 100644 index 000000000..fcc73a443 --- /dev/null +++ b/app/views/administration/online_stores/edit.html.erb @@ -0,0 +1,11 @@ +<%= return_link(t('administration.online_stores.index.header'), online_stores_path) %> + +<%= render 'administration/header', text: t('administration.online_stores.index.header') %> +<%= render 'form' %> + +
+ +<%= button_to(t('.button_remove'), + @online_store, + data: { confirm: t('administration.online_stores.edit.confirm_remove') }, + method: 'delete') %> diff --git a/app/views/administration/online_stores/index.html.erb b/app/views/administration/online_stores/index.html.erb new file mode 100644 index 000000000..9cc1bfd47 --- /dev/null +++ b/app/views/administration/online_stores/index.html.erb @@ -0,0 +1,27 @@ +<%= render 'administration/header', text: t('.header') %> + +
+ + + + + + + + + + + + <% @online_stores.each do |online_store| %> + + + + + + <% end %> + +
<%= OnlineStore.human_attribute_name(:name) %><%= OnlineStore.human_attribute_name(:theme) %><%= OnlineStore.human_attribute_name(:type) %>
<%= link_to online_store, online_store %><%= online_store.theme %><%= online_store.type.demodulize %>
+ +
+ +<%= button_to_new 'online_store', new_online_store_path %> diff --git a/app/views/administration/online_stores/new.html.erb b/app/views/administration/online_stores/new.html.erb new file mode 100644 index 000000000..fb3e7ddc0 --- /dev/null +++ b/app/views/administration/online_stores/new.html.erb @@ -0,0 +1,4 @@ +<%= return_link(t('administration.online_stores.index.header'), online_stores_path) %> + +<%= render 'administration/header', text: t('administration.online_stores.index.header') %> +<%= render 'form' %> diff --git a/config/locales/fi.yml b/config/locales/fi.yml index e6620513b..0351515bc 100644 --- a/config/locales/fi.yml +++ b/config/locales/fi.yml @@ -222,6 +222,11 @@ fi: smtp_password: SMPT-palvelimen salasana smtp_server: SMPT-palvelin smtp_username: SMPT-palvelimen käyttäjätunnus + online_store: + name: Nimi + products: Tuotteet + theme: Teema + type: Tyyppi package: erikoispakkaus: Erikoispakkaus jarjestys: Järjestys @@ -395,6 +400,7 @@ fi: keyword/customer_subcategory: Asiakasryhmä keyword/revenue_expenditure: Vaihtoehtoinen meno mail_server: Sähköpostipalvelin + online_store: Verkkokauppa package: Pakkaus package_code: Pakkauskoodi packing_area: Pakkaamo @@ -570,6 +576,18 @@ fi: header: Sähköpostipalvelimet new: header: Uusi sähköpostipalvelin + online_stores: + create: + success: Verkkokauppa luotiin onnistuneesti + destroy: + success: Verkkokauppa poistettiin onnistuneesti + edit: + button_remove: Poista verkkokauppa + confirm_remove: Haluatko varmasti poistaa tämän verkkokakupan? + index: + header: Verkkokaupat + update: + success: Verkkokauppa päivitettiin onnistuneesti packages: create: create_success: Pakkaus lisättiin onnistuneesti diff --git a/config/routes.rb b/config/routes.rb index 5954d4b7c..c59bd7322 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -57,6 +57,7 @@ resources :fiscal_years, except: :destroy resources :incoming_mails, only: :index resources :mail_servers + resources :online_stores resources :packages resources :packing_areas resources :printers diff --git a/db/migrate/20151118134711_create_online_store_themes.rb b/db/migrate/20151118134711_create_online_store_themes.rb new file mode 100644 index 000000000..b50937050 --- /dev/null +++ b/db/migrate/20151118134711_create_online_store_themes.rb @@ -0,0 +1,9 @@ +class CreateOnlineStoreThemes < ActiveRecord::Migration + def change + create_table :online_store_themes do |t| + t.string :name + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20151123071517_create_online_stores.rb b/db/migrate/20151123071517_create_online_stores.rb new file mode 100644 index 000000000..c2af2b9a4 --- /dev/null +++ b/db/migrate/20151123071517_create_online_stores.rb @@ -0,0 +1,12 @@ +class CreateOnlineStores < ActiveRecord::Migration + def change + create_table :online_stores do |t| + t.string :name + t.string :type + t.references :online_store_theme, index: true, foreign_key: true + t.references :company, index: true, foreign_key: true + + t.timestamps null: false + end + end +end diff --git a/db/migrate/20151123074934_create_online_stores_products.rb b/db/migrate/20151123074934_create_online_stores_products.rb new file mode 100644 index 000000000..a52d574f0 --- /dev/null +++ b/db/migrate/20151123074934_create_online_stores_products.rb @@ -0,0 +1,8 @@ +class CreateOnlineStoresProducts < ActiveRecord::Migration + def change + create_table :online_stores_products do |t| + t.references :online_store, index: true, foreign_key: true + t.references :product, index: true, foreign_key: true + end + end +end diff --git a/db/migrate/20151123084500_add_online_stores_menu.rb b/db/migrate/20151123084500_add_online_stores_menu.rb new file mode 100644 index 000000000..72880504a --- /dev/null +++ b/db/migrate/20151123084500_add_online_stores_menu.rb @@ -0,0 +1,18 @@ +require File.expand_path('test/permission_helper') +include PermissionHelper + +class AddOnlineStoresMenu < ActiveRecord::Migration + def up + PermissionHelper.add_item( + program: 'Tuotehallinta', + name: 'Verkkokaupat', + uri: 'pupenext/online_stores' + ) + end + + def down + PermissionHelper.remove_all( + uri: 'pupenext/online_stores' + ) + end +end diff --git a/db/schema.rb b/db/schema.rb index 7ab16e386..37e7de974 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1705,6 +1705,32 @@ add_index "oikeu", ["yhtio", "kuka", "sovellus"], name: "sovellus_index", using: :btree add_index "oikeu", ["yhtio", "sovellus", "nimi", "alanimi"], name: "menut_index", using: :btree + create_table "online_store_themes", force: :cascade do |t| + t.string "name", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "online_stores", force: :cascade do |t| + t.string "name", limit: 255 + t.string "type", limit: 255 + t.integer "online_store_theme_id", limit: 4 + t.integer "company_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "online_stores", ["company_id"], name: "index_online_stores_on_company_id", using: :btree + add_index "online_stores", ["online_store_theme_id"], name: "index_online_stores_on_online_store_theme_id", using: :btree + + create_table "online_stores_products", force: :cascade do |t| + t.integer "online_store_id", limit: 4 + t.integer "product_id", limit: 4 + end + + add_index "online_stores_products", ["online_store_id"], name: "index_online_stores_products_on_online_store_id", using: :btree + add_index "online_stores_products", ["product_id"], name: "index_online_stores_products_on_product_id", using: :btree + create_table "pakkaamo", primary_key: "tunnus", force: :cascade do |t| t.string "yhtio", limit: 5, default: "", null: false t.string "nimi", limit: 150, default: "", null: false diff --git a/test/controllers/administration/online_stores_controller_test.rb b/test/controllers/administration/online_stores_controller_test.rb new file mode 100644 index 000000000..984d220e5 --- /dev/null +++ b/test/controllers/administration/online_stores_controller_test.rb @@ -0,0 +1,70 @@ +require 'test_helper' + +class Administration::OnlineStoresControllerTest < ActionController::TestCase + fixtures %w( + online_store_themes + online_stores + ) + + setup do + login users(:bob) + + @theme_one = online_store_themes(:one) + @theme_two = online_store_themes(:two) + + @pupeshop = online_stores(:pupeshop) + @magento = online_stores(:magento) + end + + test "index works" do + get :index + + assert_response :success + assert_not_nil assigns(:online_stores) + end + + test "new works" do + get :new + + assert_response :success + end + + test "create works" do + assert_difference('OnlineStore.count', 1) do + post :create, online_store: { name: 'Test name 1', + online_store_theme_id: @theme_one.id, + type: 'OnlineStore::Pupeshop'} + end + + assert_redirected_to online_stores_url + end + + test "show renders edit" do + get :show, id: @pupeshop + + assert_response :success + assert_template :edit + end + + test "edit works" do + get :edit, id: @pupeshop + + assert_response :success + end + + test "update works" do + patch :update, id: @pupeshop, online_store: { name: 'Updated name', + online_store_theme_id: @theme_two.id, + type: 'OnlineStore::Magento'} + + assert_redirected_to online_stores_url + end + + test "destroy works" do + assert_difference('OnlineStore.count', -1) do + delete :destroy, id: @pupeshop + end + + assert_redirected_to online_stores_path + end +end diff --git a/test/fixtures/online_store_themes.yml b/test/fixtures/online_store_themes.yml new file mode 100644 index 000000000..62e345966 --- /dev/null +++ b/test/fixtures/online_store_themes.yml @@ -0,0 +1,5 @@ +one: + name: Theme 1 + +two: + name: Theme 2 diff --git a/test/fixtures/online_stores.yml b/test/fixtures/online_stores.yml new file mode 100644 index 000000000..f24a8ea2b --- /dev/null +++ b/test/fixtures/online_stores.yml @@ -0,0 +1,13 @@ +pupeshop: + company: acme + name: Pupeshop + type: OnlineStore::Pupeshop + theme: one + products: hammer, helmet + +magento: + company: acme + name: Magento + type: OnlineStore::Magento + theme: two + products: helmet diff --git a/test/fixtures/permissions.yml b/test/fixtures/permissions.yml index e8efd459d..a4afea01c 100644 --- a/test/fixtures/permissions.yml +++ b/test/fixtures/permissions.yml @@ -23,6 +23,7 @@ full_installments incoming_mails mail_servers + online_stores packages packing_areas pending_product_updates diff --git a/test/models/company_test.rb b/test/models/company_test.rb index c51f1a5ef..03a46fb69 100644 --- a/test/models/company_test.rb +++ b/test/models/company_test.rb @@ -54,6 +54,7 @@ class CompanyTest < ActiveSupport::TestCase assert @acme.warehouses.count > 0 assert @acme.incoming_mails.count > 0 assert @acme.permissions.count > 0 + assert @acme.online_stores.count > 0 assert_equal 1, @acme.menus.count assert_equal menus(:acme_menu_1), @acme.menus.first diff --git a/test/models/online_store_test.rb b/test/models/online_store_test.rb new file mode 100644 index 000000000..765aff0a2 --- /dev/null +++ b/test/models/online_store_test.rb @@ -0,0 +1,38 @@ +require 'test_helper' + +class OnlineStoreTest < ActiveSupport::TestCase + fixtures %w( + online_store_themes + online_stores + products + ) + + setup do + @pupeshop = online_stores(:pupeshop) + @magento = online_stores(:magento) + + @theme_one = online_store_themes(:one) + @theme_two = online_store_themes(:two) + end + + test 'fixtures are valid' do + assert @pupeshop.valid?, @pupeshop.errors.full_messages + assert @magento.valid?, @magento.errors.full_messages + end + + test 'associations work' do + assert_equal @theme_one, @pupeshop.theme + assert_equal @theme_two, @magento.theme + + assert_not_empty @pupeshop.products + assert_not_empty @magento.products + + assert_equal companies(:acme), @pupeshop.company + assert_equal companies(:acme), @magento.company + end + + test 'STI works' do + assert_instance_of OnlineStore::Pupeshop, @pupeshop + assert_instance_of OnlineStore::Magento, @magento + end +end diff --git a/test/models/online_store_theme_test.rb b/test/models/online_store_theme_test.rb new file mode 100644 index 000000000..4735fe72e --- /dev/null +++ b/test/models/online_store_theme_test.rb @@ -0,0 +1,22 @@ +require 'test_helper' + +class OnlineStoreThemeTest < ActiveSupport::TestCase + fixtures %w( + online_store_themes + ) + + setup do + @one = online_store_themes(:one) + @two = online_store_themes(:two) + end + + test 'fixtures are valid' do + assert @one.valid?, @one.errors.full_messages + assert @two.valid?, @two.errors.full_messages + end + + test 'associations work' do + assert_not_empty @one.online_stores + assert_not_empty @two.online_stores + end +end diff --git a/test/models/product_test.rb b/test/models/product_test.rb index 9631b666a..cb624f863 100644 --- a/test/models/product_test.rb +++ b/test/models/product_test.rb @@ -11,6 +11,7 @@ class ProductTest < ActiveSupport::TestCase keyword/customer_subcategories keywords manufacture_order/rows + online_stores pending_updates product/keywords product/suppliers @@ -52,6 +53,201 @@ class ProductTest < ActiveSupport::TestCase assert_includes @product.product_links, category_links(:product_category_shirts_hammer) assert_includes @product.product_categories, category_products(:product_category_shirts) assert @product.warehouses.count > 0 + assert_not_empty @product.online_stores + end + + test 'product stock' do + stock = @product.stock + assert stock > 0 + + loc = @product.shelf_locations.first.dup + loc.saldo = 100 + loc.hyllytaso = 'foo' + loc.save! + + assert_equal stock + 100, @product.stock + + @product.update_attribute :ei_saldoa, :no_inventory_management + assert_equal 0, @product.stock + end + + test 'product reserved stock' do + # these rows should affect reserved stock, let's zero them out + @product.sales_order_rows.update_all(varattu: 0) + @product.manufacture_rows.update_all(varattu: 0) + @product.stock_transfer_rows.update_all(varattu: 0) + assert_equal 0, @product.stock_reserved + + brand = keywords :brand_tools + assert_equal brand.name, @product.brand.name + + @product.sales_order_rows.first.update!(varattu: 10) + assert_equal 10, @product.stock_reserved + + @product.manufacture_rows.first.update!(varattu: 5) + assert_equal 15, @product.stock_reserved + + @product.stock_transfer_rows.first.update!(varattu: 6) + assert_equal 21, @product.stock_reserved + + @product.update_attribute :ei_saldoa, :no_inventory_management + assert_equal 0, @product.stock_reserved + end + + test 'product stock available' do + # these should affect stock available, let's zero them out + @product.shelf_locations.update_all(saldo: 0) + @product.sales_order_rows.update_all(varattu: 0) + @product.manufacture_rows.update_all(varattu: 0) + @product.stock_transfer_rows.update_all(varattu: 0) + assert_equal 0, @product.stock_available + + @product.sales_order_rows.first.update!(varattu: 10) + assert_equal -10, @product.stock_available + + @product.shelf_locations.first.update!(saldo: 100) + assert_equal 90, @product.stock_available + + @product.update_attribute :ei_saldoa, :no_inventory_management + assert_equal 0, @product.stock_available + end + + test 'sales_order_rows product stock reserved by pick date' do + # set stock management by pick date + @product.company.parameter.update! saldo_kasittely: :stock_management_by_pick_date + assert_equal 0, @product.stock_reserved + + one = @product.sales_order_rows.first.dup + two = @product.sales_order_rows.first.dup + + # SO rows due to be picked today or in the past, should reserve stock (picked or not picked) + one.update! kerayspvm: Date.today, varattu: 10, keratty: '' + two.update! kerayspvm: Date.today, varattu: 10, keratty: 'joe' + assert_equal 20, @product.stock_reserved + + # SO rows due to be picked in the future, should not affect reserve stock, unless picked + one.update! kerayspvm: 1.day.from_now, varattu: 5, keratty: '' + two.update! kerayspvm: 1.day.from_now, varattu: 15, keratty: 'joe' + assert_equal 15, @product.stock_reserved + end + + test 'manufacture_rows product stock reserved by pick date' do + # set stock management by pick date + @product.company.parameter.update! saldo_kasittely: :stock_management_by_pick_date + assert_equal 0, @product.stock_reserved + + one = @product.manufacture_rows.first.dup + two = @product.manufacture_rows.first.dup + + # MF rows due to be picked today or in the past, should reserve stock (picked or not picked) + one.update! kerayspvm: Date.today, varattu: 10, keratty: '' + two.update! kerayspvm: Date.today, varattu: 10, keratty: 'joe' + assert_equal 20, @product.stock_reserved + + # MF rows due to be picked in the future, should not affect reserve stock, unless picked + one.update! kerayspvm: 1.day.from_now, varattu: 5, keratty: '' + two.update! kerayspvm: 1.day.from_now, varattu: 15, keratty: 'joe' + assert_equal 15, @product.stock_reserved + end + + test 'stock_transfer_rows product stock reserved by pick date' do + # set stock management by pick date + @product.company.parameter.update! saldo_kasittely: :stock_management_by_pick_date + assert_equal 0, @product.stock_reserved + + one = @product.stock_transfer_rows.first.dup + two = @product.stock_transfer_rows.first.dup + + # ST rows due to be picked today or in the past, should reserve stock (picked or not picked) + one.update! kerayspvm: Date.today, varattu: 10, keratty: '' + two.update! kerayspvm: Date.today, varattu: 10, keratty: 'joe' + assert_equal 20, @product.stock_reserved + + # ST rows due to be picked in the future, should not affect reserve stock, unless picked + one.update! kerayspvm: 1.day.from_now, varattu: 5, keratty: '' + two.update! kerayspvm: 1.day.from_now, varattu: 15, keratty: 'joe' + assert_equal 15, @product.stock_reserved + end + + test 'manufacture_composite_rows product stock reserved by pick date' do + # set stock management by pick date + @product.company.parameter.update! saldo_kasittely: :stock_management_by_pick_date + assert_equal 0, @product.stock_reserved + + # MF composite rows due to be picked today or earlier, should decrease stock reservation + @product.manufacture_composite_rows.first.update! kerayspvm: Date.today, varattu: 10, keratty: '' + assert_equal -10, @product.stock_reserved + + # MF composite rows due to be picked in the future, should not affect reserve stock + @product.manufacture_composite_rows.first.update! kerayspvm: 1.day.from_now, varattu: 10, keratty: '' + assert_equal 0, @product.stock_reserved + end + + test 'manufacture_recursive_composite_rows product stock reserved by pick date' do + # set stock management by pick date + @product.company.parameter.update! saldo_kasittely: :stock_management_by_pick_date + assert_equal 0, @product.stock_reserved + + # MF recursive composite rows due to be picked today or earlier, should decrease stock reservation + @product.manufacture_recursive_composite_rows.first.update! kerayspvm: Date.today, varattu: 10, keratty: '' + assert_equal -10, @product.stock_reserved + + # MF recursive composite rows due to be picked in the future, should not reserve stock + @product.manufacture_recursive_composite_rows.first.update! kerayspvm: 1.day.from_now, varattu: 10, keratty: '' + assert_equal 0, @product.stock_reserved + end + + test 'purchase_order_rows product stock reserved by pick date' do + # set stock management by pick date + @product.company.parameter.update! saldo_kasittely: :stock_management_by_pick_date + assert_equal 0, @product.stock_reserved + + # PO rows due in today or earlier, should decrease stock reservation + @product.purchase_order_rows.first.update! toimaika: Date.today, varattu: 10 + assert_equal -10, @product.stock_reserved + + # PO rows in the future, should not affect reserve stock + @product.purchase_order_rows.first.update! toimaika: 1.day.from_now, varattu: 10 + assert_equal 0, @product.reload.stock_reserved + end + + test 'product stock reserved by pick date with future reservations' do + # set stock management by pick date with future reservations + # this uses same logic as stock_management_by_pick_date, so we don't need to test everything again + # this returns the "worst case" stock reserve, se we'll never sell out our stock + @product.company.parameter.update! saldo_kasittely: :stock_management_by_pick_date_and_with_future_reservations + assert_equal 0, @product.stock_reserved + + one = @product.stock_transfer_rows.first + two = @product.stock_transfer_rows.first.dup + po_one = @product.purchase_order_rows.first + + # sell 100 day one, we have 100 reserved no matter what date + one.update! varattu: 100, kerayspvm: 1.day.from_now + assert_equal 100, @product.stock_reserved(stock_date: 1.day.ago) + assert_equal 100, @product.stock_reserved + assert_equal 100, @product.stock_reserved(stock_date: 1.day.from_now) + assert_equal 100, @product.stock_reserved(stock_date: 2.day.from_now) + assert_equal 100, @product.stock_reserved(stock_date: 3.day.from_now) + assert_equal 100, @product.stock_reserved(stock_date: 9.day.from_now) + + # purchase 60 day three, we have 100 reserved before purchase, and 40 after + po_one.update! varattu: 60, toimaika: 3.day.from_now + assert_equal 100, @product.stock_reserved(stock_date: 1.day.ago) + assert_equal 100, @product.stock_reserved + assert_equal 100, @product.stock_reserved(stock_date: 1.day.from_now) + assert_equal 100, @product.stock_reserved(stock_date: 2.day.from_now) + assert_equal 40, @product.stock_reserved(stock_date: 3.day.from_now) + assert_equal 40, @product.stock_reserved(stock_date: 9.day.from_now) + + # sell 30 day five, we have 100 reserved before puchase, and 70 after + two.update! varattu: 30, kerayspvm: 5.day.from_now + assert_equal 100, @product.stock_reserved(stock_date: 1.day.ago) + assert_equal 100, @product.stock_reserved + assert_equal 100, @product.stock_reserved(stock_date: 1.day.from_now) + assert_equal 100, @product.stock_reserved(stock_date: 2.day.from_now) + assert_equal 70, @product.stock_reserved(stock_date: 3.day.from_now) + assert_equal 70, @product.stock_reserved(stock_date: 9.day.from_now) end test 'valid status' do