-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
stock_item.rb
128 lines (103 loc) · 4.11 KB
/
stock_item.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# frozen_string_literal: true
require 'discard'
module Spree
class StockItem < Spree::Base
acts_as_paranoid
include Spree::ParanoiaDeprecations
include Discard::Model
self.discard_column = :deleted_at
belongs_to :stock_location, class_name: 'Spree::StockLocation', inverse_of: :stock_items
belongs_to :variant, -> { with_deleted }, class_name: 'Spree::Variant', inverse_of: :stock_items
has_many :stock_movements, inverse_of: :stock_item
validates :stock_location, :variant, presence: true
validates :variant_id, uniqueness: { scope: [:stock_location_id, :deleted_at] }, allow_blank: true, unless: :deleted_at
validates :count_on_hand, numericality: { greater_than_or_equal_to: 0 }, unless: :backorderable?
delegate :weight, :should_track_inventory?, to: :variant
# @return [String] the name of this stock item's variant
delegate :name, to: :variant, prefix: true
after_save :conditional_variant_touch, if: :saved_changes?
after_touch { variant.touch }
self.whitelisted_ransackable_attributes = ['count_on_hand', 'stock_location_id']
# @return [Array<Spree::InventoryUnit>] the backordered inventory units
# associated with this stock item
def backordered_inventory_units
Spree::InventoryUnit.backordered_for_stock_item(self)
end
# Adjusts the count on hand by a given value.
#
# @note This will cause backorders to be processed.
# @param value [Fixnum] the amount to change the count on hand by, positive
# or negative values are valid
def adjust_count_on_hand(value)
with_lock do
self.count_on_hand = count_on_hand + value
process_backorders(count_on_hand - count_on_hand_was)
save!
end
end
# Sets this stock item's count on hand.
#
# @note This will cause backorders to be processed.
# @param value [Fixnum] the desired count on hand
def set_count_on_hand(value)
self.count_on_hand = value
process_backorders(count_on_hand - count_on_hand_was)
save!
end
# @return [Boolean] true if this stock item's count on hand is not zero
def in_stock?
count_on_hand > 0
end
# @return [Boolean] true if this stock item can be included in a shipment
def available?
in_stock? || backorderable?
end
# Sets the count on hand to zero if it not already zero.
#
# @note This processes backorders if the count on hand is not zero.
def reduce_count_on_hand_to_zero
set_count_on_hand(0) if count_on_hand > 0
end
def fill_status(quantity)
if count_on_hand >= quantity
on_hand = quantity
backordered = 0
else
on_hand = count_on_hand
on_hand = 0 if on_hand < 0
backordered = backorderable? ? (quantity - on_hand) : 0
end
[on_hand, backordered]
end
private
def count_on_hand=(value)
write_attribute(:count_on_hand, value)
end
# Process backorders based on amount of stock received
# If stock was -20 and is now -15 (increase of 5 units), then we should process 5 inventory orders.
# If stock was -20 but then was -25 (decrease of 5 units), do nothing.
def process_backorders(number)
if number > 0
backordered_inventory_units.first(number).each(&:fill_backorder)
end
end
def conditional_variant_touch
variant.touch if inventory_cache_threshold.nil? || should_touch_variant?
end
def should_touch_variant?
# the variant_id changes from nil when a new stock location is added
inventory_cache_threshold &&
(saved_change_to_count_on_hand && saved_change_to_count_on_hand.any? { |c| c < inventory_cache_threshold }) ||
saved_change_to_variant_id?
end
def inventory_cache_threshold
# only warn if store is setting binary_inventory_cache (default = false)
@cache_threshold ||= if Spree::Config.binary_inventory_cache
Spree::Deprecation.warn "Spree::Config.binary_inventory_cache=true is DEPRECATED. Instead use Spree::Config.inventory_cache_threshold=1"
1
else
Spree::Config.inventory_cache_threshold
end
end
end
end