Skip to content
31 changes: 27 additions & 4 deletions app/classes/woo/products.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ class Woo::Products < Woo::Base
# 2. update stock of products in webstore

# Create products to woocommerce
def create
def create(all: false)
created_count = 0

products.each do |product|
products_to_create(all: all).each do |product|
if get_sku(product.tuoteno)
logger.info "Tuote #{product.tuoteno} on jo verkkokaupassa"

Expand All @@ -16,14 +16,16 @@ def create
created_count += create_product(product)
end

Keyword::WooCheckpoint.update_timestamp(:create)

logger.info "Lisättiin #{created_count} tuotetta verkkokauppaan"
end

# Update product stock quantity
def update
def update(all: false)
updated_count = 0

products.each do |product|
products_to_update(all: all).each do |product|
woo_product = get_sku(product.tuoteno)

unless woo_product
Expand All @@ -35,6 +37,8 @@ def update
updated_count += update_stock(woo_product['id'], product)
end

Keyword::WooCheckpoint.update_timestamp(:update)

logger.info "Päivitettiin #{updated_count} tuotteen saldot"
end

Expand All @@ -46,6 +50,25 @@ def products
Product.where(status: %w(A P)).where(hinnastoon: 'W')
end

def products_to_create(all: false)
timestamp = all ? nil : Keyword::WooCheckpoint.last_run_at(:create)

return products unless timestamp

products.where('luontiaika >= ?', timestamp)
end

def products_to_update(all: false)
timestamp = all ? nil : Keyword::WooCheckpoint.last_run_at(:update)

return products unless timestamp

products.select do |product|
product.rows.where('laadittu >= ?', timestamp).any? ||
product.transactions.where('laadittu >= ?', timestamp).any?
end
end

def product_hash(product)
defaults = {
name: product.nimitys,
Expand Down
1 change: 1 addition & 0 deletions app/models/keyword.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ def self.child_class_names
VARASTOLUOKKA: Keyword,
VARASTORYHMA: Keyword,
VARTOIMTULOSTIN: Keyword,
WOO_CHECKPOINT: Keyword::WooCheckpoint,
WOO_FIELD: Keyword::WooField,
Y: Keyword,
}.stringify_keys
Expand Down
21 changes: 21 additions & 0 deletions app/models/keyword/woo_checkpoint.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class Keyword::WooCheckpoint < Keyword
def self.sti_name
:WOO_CHECKPOINT
end

def self.update_timestamp(run_type)
checkpoint = last || new
timestamps = checkpoint.selite.present? ? JSON.parse(checkpoint.selite, symbolize_names: true) : {}
timestamps[run_type.to_sym] = Time.current.change(usec: 0)
checkpoint.selite = timestamps.to_json
checkpoint.save!
end

def self.last_run_at(run_type)
checkpoint = last
return unless checkpoint
timestamp = JSON.parse(checkpoint.selite, symbolize_names: true)[run_type.to_sym]
return unless timestamp
Time.zone.parse(timestamp)
end
end
2 changes: 2 additions & 0 deletions app/models/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ class Product < BaseModel
o.has_many :manufacture_rows, class_name: 'ManufactureOrder::Row'
o.has_many :product_suppliers, class_name: 'Product::Supplier'
o.has_many :purchase_order_rows, class_name: 'PurchaseOrder::Row'
o.has_many :rows, class_name: 'Row'
o.has_many :sales_order_rows, class_name: 'SalesOrder::Row'
o.has_many :shelf_locations
o.has_many :stock_transfer_rows, class_name: 'StockTransfer::Row'
o.has_many :transactions, class_name: 'Product::Transaction'
end

has_many :warehouses, through: :shelf_locations
Expand Down
7 changes: 7 additions & 0 deletions app/models/product/transaction.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Product::Transaction < BaseModel
belongs_to :product, foreign_key: :tuoteno, primary_key: :tuoteno

self.table_name = :tapahtuma
self.primary_key = :tunnus
self.record_timestamps = false
end
210 changes: 210 additions & 0 deletions test/classes/woo/products_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
class Woo::ProductsTest < ActiveSupport::TestCase
fixtures %w(
products
sales_order/rows
)

setup do
Expand All @@ -16,6 +17,9 @@ class Woo::ProductsTest < ActiveSupport::TestCase

Product.update_all(hinnastoon: '')
products(:ski).update(hinnastoon: 'w')

Keyword::WooCheckpoint.delete_all
Product::Transaction.delete_all
end

test 'should initialize' do
Expand Down Expand Up @@ -103,4 +107,210 @@ class Woo::ProductsTest < ActiveSupport::TestCase
product = @woocommerce.send(:products).first
assert_equal response, @woocommerce.send(:product_hash, product)
end

test 'checkpoint is created after first create run' do
@woocommerce.stub :get_sku, nil do
@woocommerce.stub :woo_post, 'id' => 1 do
assert_difference 'Keyword::WooCheckpoint.count' do
@woocommerce.create
end
end
end

assert_in_delta Keyword::WooCheckpoint.last_run_at(:create), Time.current, 10
end

test 'checkpoint is updated if already present when creating products' do
@woocommerce.stub :get_sku, nil do
@woocommerce.stub :woo_post, 'id' => 1 do
assert_difference 'Keyword::WooCheckpoint.count' do
2.times { @woocommerce.create }
end
end
end

assert_in_delta Keyword::WooCheckpoint.last_run_at(:create), Time.current, 10
end

test 'checkpoint is updated after updating stocks' do
@woocommerce.stub :get_sku, {} do
@woocommerce.stub :woo_put, 'id' => 1 do
assert_difference 'Keyword::WooCheckpoint.count' do
2.times { @woocommerce.update }
end
end
end

assert_in_delta Keyword::WooCheckpoint.last_run_at(:update), Time.current, 10
end

test 'different timestamps in checkpoint work independently' do
@woocommerce.stub :get_sku, nil do
@woocommerce.stub :woo_post, 'id' => 1 do
assert_difference 'Keyword::WooCheckpoint.count' do
travel(-1.day) { @woocommerce.create }
@woocommerce.update
end
end
end

refute_in_delta Keyword::WooCheckpoint.last_run_at(:create), Time.current, 10
assert_in_delta Keyword::WooCheckpoint.last_run_at(:update), Time.current, 10
end

test 'all products are created if no create timestamp in checkpoint' do
counter = 0

block = proc do
counter += 1
{ 'id' => 1 }
end

@woocommerce.stub :get_sku, nil do
@woocommerce.stub :woo_post, block do
@woocommerce.create
end
end

assert_equal 1, counter
end

test 'only new products are created when create timestamp is found' do
products(:ski).update!(luontiaika: 1.second.ago)

Keyword::WooCheckpoint.update_timestamp(:create)

counter = 0

block = proc do
counter += 1
{ 'id' => 1 }
end

@woocommerce.stub :get_sku, nil do
@woocommerce.stub :woo_post, block do
@woocommerce.create
end
end

assert_equal 0, counter
end

test 'all products can be created by passing option even when timestamp is found' do
products(:ski).update!(luontiaika: 1.second.ago)

Keyword::WooCheckpoint.update_timestamp(:create)

counter = 0

block = proc do
counter += 1
{ 'id' => 1 }
end

@woocommerce.stub :get_sku, nil do
@woocommerce.stub :woo_post, block do
@woocommerce.create(all: true)
end
end

assert_equal 1, counter
end

test 'all products are updated if no update timestamp in checkpoint' do
counter = 0

block = proc do
counter += 1
{ 'id' => 1 }
end

@woocommerce.stub :get_sku, {} do
@woocommerce.stub :woo_put, block do
@woocommerce.update
end
end

assert_equal 1, counter
end

test 'only products with new rows are updated when update timestamp is found' do
Keyword::WooCheckpoint.update_timestamp(:update)

counter = 0

block = proc do
counter += 1
{ 'id' => 1 }
end

@woocommerce.stub :get_sku, {} do
@woocommerce.stub :woo_put, block do
@woocommerce.update
end
end

assert_equal 0, counter
end

test 'products with new rows are updated when timestamp is found' do
Keyword::WooCheckpoint.update_timestamp(:update)

products(:ski).sales_order_rows.create!(laadittu: 1.second.from_now)

counter = 0

block = proc do
counter += 1
{ 'id' => 1 }
end

@woocommerce.stub :get_sku, {} do
@woocommerce.stub :woo_put, block do
@woocommerce.update
end
end

assert_equal 1, counter
end

test 'products with new transactions are updated when timestamp is found' do
Keyword::WooCheckpoint.update_timestamp(:update)

products(:ski).transactions.create!(laadittu: 1.second.from_now)

counter = 0

block = proc do
counter += 1
{ 'id' => 1 }
end

@woocommerce.stub :get_sku, {} do
@woocommerce.stub :woo_put, block do
@woocommerce.update
end
end

assert_equal 1, counter
end

test 'all products can be updated by passing option even when timestamp is found' do
Keyword::WooCheckpoint.update_timestamp(:update)

counter = 0

block = proc do
counter += 1
{ 'id' => 1 }
end

@woocommerce.stub :get_sku, {} do
@woocommerce.stub :woo_put, block do
@woocommerce.update(all: true)
end
end

assert_equal 1, counter
end
end