Class: SerialNumber

Inherits:
ApplicationRecord show all
Includes:
Models::Auditable
Defined in:
app/models/serial_number.rb

Overview

== Schema Information

Table name: serial_numbers
Database name: primary

id :integer not null, primary key
number :string(255)
print_state :string
qty :integer
shipped_count :integer
state :string
created_at :datetime
updated_at :datetime
line_item_id :integer
parent_serial_number_id :integer
shipment_receipt_item_id :integer
store_item_id :integer

Indexes

idx_serial_numbers_store_item_id (store_item_id)
index_serial_numbers_on_line_item_id (line_item_id)

Constant Summary collapse

STATES =
%w[available shipped].freeze
%w[pending_print printed].freeze

Constants included from Models::Auditable

Models::Auditable::ALWAYS_IGNORED

Instance Attribute Summary collapse

Belongs to collapse

Methods included from Models::Auditable

#creator, #updater

Has many collapse

Has and belongs to many collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Models::Auditable

#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record

Methods inherited from ApplicationRecord

ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation

Methods included from Models::EventPublishable

#publish_event

Instance Attribute Details

#numberObject (readonly)



43
# File 'app/models/serial_number.rb', line 43

validates :number, presence: true, uniqueness: { scope: :store_item_id }

#qtyObject (readonly)



44
# File 'app/models/serial_number.rb', line 44

validates :store_item, :qty, presence: true

Class Method Details

.availableActiveRecord::Relation<SerialNumber>

A relation of SerialNumbers that are available. Active Record Scope

Returns:

See Also:



46
47
48
# File 'app/models/serial_number.rb', line 46

scope :available, -> {
  joins('LEFT JOIN reserved_serial_numbers ON (reserved_serial_numbers.serial_number_id = serial_numbers.id and reserved_serial_numbers.is_committed = true)').having('serial_numbers.qty > coalesce(sum(reserved_serial_numbers.qty),0)').where("state = 'available'").group('serial_numbers.id')
}

.generate_super_label_pdf(serial_numbers) ⇒ Object



171
172
173
174
175
176
177
178
179
# File 'app/models/serial_number.rb', line 171

def self.generate_super_label_pdf(serial_numbers)
  file_name = "super_serial_number_label_#{Time.current.strftime('%m_%d_%Y_%I_%M%p')}.pdf".downcase
  pdf = Pdf::Label::SerialNumber.call(serial_numbers).pdf
  path = Upload.temp_location(file_name)
  File.open(path, 'wb') { |f| f.write(pdf); f.flush; f.fsync }
  upload = Upload.uploadify(path, 'super_serial_number_label_pdf')
  SerialNumber.where(id: serial_numbers.collect(&:id)).update_all(print_state: 'printed')
  upload
end

.pending_printActiveRecord::Relation<SerialNumber>

A relation of SerialNumbers that are pending print. Active Record Scope

Returns:

See Also:



49
# File 'app/models/serial_number.rb', line 49

scope :pending_print, -> { where(print_state: 'pending_print') }

Instance Method Details

#generate_barcodeObject



145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'app/models/serial_number.rb', line 145

def generate_barcode
  require 'barby'
  require 'barby/barcode/code_128'
  require 'barby/outputter/png_outputter'
  barcode = Barby::Code128B.new("SN: #{number} / SKU: #{store_item.item.sku} / QTY: #{qty}")
  path = File.join(Rails.application.config.x.temp_storage_path.to_s, "#{number}_generated_barcode_#{Time.current.strftime('%m_%d_%Y_%I_%M%p')}.png")
  File.open(path, 'wb') do |f|
    f.write barcode.to_png(height: 50)
    f.flush
    f.fsync
  end
  path
end

#generate_label_pdfObject



163
164
165
166
167
168
169
# File 'app/models/serial_number.rb', line 163

def generate_label_pdf
  file_name = label_file_name
  pdf = Pdf::Label::SerialNumber.call(self).pdf
  path = Upload.temp_location(file_name)
  File.open(path, 'wb') { |f| f.write(pdf); f.flush; f.fsync }
  Upload.uploadify(path, 'serial_number_label_pdf', self, file_name)
end

#item_ledger_entriesActiveRecord::Relation<ItemLedgerEntry>

Returns:

See Also:



37
# File 'app/models/serial_number.rb', line 37

has_and_belongs_to_many :item_ledger_entries

#label_file_nameObject



159
160
161
# File 'app/models/serial_number.rb', line 159

def label_file_name
  "#{number}_generated_serial_number_label_#{Time.current.strftime('%m_%d_%Y_%I_%M%p')}.pdf"
end

#line_itemsActiveRecord::Relation<LineItem>

Returns:

See Also:



36
# File 'app/models/serial_number.rb', line 36

has_and_belongs_to_many :line_items, dependent: :nullify

#number_and_qtyObject



114
115
116
# File 'app/models/serial_number.rb', line 114

def number_and_qty
  "#{number} (#{qty})"
end

#parent_serial_numberSerialNumber



32
# File 'app/models/serial_number.rb', line 32

belongs_to :parent_serial_number, class_name: 'SerialNumber', optional: true

#possible_eventsObject



90
91
92
# File 'app/models/serial_number.rb', line 90

def possible_events
  state_transitions.map(&:event).sort
end

#possible_events_for_selectObject



94
95
96
# File 'app/models/serial_number.rb', line 94

def possible_events_for_select
  possible_events.map { |evt| [evt.to_s.titleize, evt] }
end

#possible_print_state_eventsObject



102
103
104
# File 'app/models/serial_number.rb', line 102

def possible_print_state_events
  print_state_transitions.map(&:event).sort
end

#possible_print_state_events_for_selectObject



106
107
108
# File 'app/models/serial_number.rb', line 106

def possible_print_state_events_for_select
  possible_print_state_events.map { |evt| [evt.to_s.titleize, evt] }
end


110
111
112
# File 'app/models/serial_number.rb', line 110

def print_state_events_for_select
  [["#{print_state.to_s.titleize} (Current)", '']] + possible_print_state_events_for_select
end

#qty_availableObject



126
127
128
# File 'app/models/serial_number.rb', line 126

def qty_available
  qty - qty_committed
end

#qty_committedObject



122
123
124
# File 'app/models/serial_number.rb', line 122

def qty_committed
  reserved_serial_numbers.committed.sum(:qty)
end

#qty_reservedObject



118
119
120
# File 'app/models/serial_number.rb', line 118

def qty_reserved
  reserved_serial_numbers.sum(:qty)
end

#qty_unreservedObject



130
131
132
# File 'app/models/serial_number.rb', line 130

def qty_unreserved
  qty - qty_reserved
end

#rejoin(child_serial_number) ⇒ Object



140
141
142
143
# File 'app/models/serial_number.rb', line 140

def rejoin(child_serial_number)
  update(qty: qty + child_serial_number.qty)
  child_serial_number.destroy!
end

#reserved_serial_numbersActiveRecord::Relation<ReservedSerialNumber>

Returns:

See Also:



34
# File 'app/models/serial_number.rb', line 34

has_many :reserved_serial_numbers, dependent: :destroy

#shipment_receipt_itemShipmentReceiptItem



33
# File 'app/models/serial_number.rb', line 33

belongs_to :shipment_receipt_item, optional: true

#split(new_qty) ⇒ Object



134
135
136
137
138
# File 'app/models/serial_number.rb', line 134

def split(new_qty)
  new_serial_number = SerialNumber.create!(store_item:, qty: new_qty, number: "#{number}-#{split_serial_numbers.count + 1}", parent_serial_number_id: id)
  update(qty: qty - new_qty)
  new_serial_number
end

#split_serial_numbersActiveRecord::Relation<SerialNumber>

Returns:

See Also:



35
# File 'app/models/serial_number.rb', line 35

has_many :split_serial_numbers, class_name: 'SerialNumber', foreign_key: 'parent_serial_number_id'

#state_events_for_selectObject



98
99
100
# File 'app/models/serial_number.rb', line 98

def state_events_for_select
  [["#{state.to_s.titleize} (Current)", '']] + possible_events_for_select
end

#store_itemStoreItem

Returns:

See Also:

Validations:



31
# File 'app/models/serial_number.rb', line 31

belongs_to :store_item, optional: true

#to_sObject



86
87
88
# File 'app/models/serial_number.rb', line 86

def to_s
  "#{store_item} - SN:#{number}"
end