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 =

States.

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

Constants included from Models::Auditable

Models::Auditable::ALWAYS_IGNORED

Constants included from Schedulable

Schedulable::SIMPLE_FORM_OPTIONS

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 Schedulable

config

Methods included from Models::AfterCommittable

#after_commit

Methods included from Models::EventPublishable

#publish_event

Instance Attribute Details

#numberObject (readonly)



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

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

#qtyObject (readonly)



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

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:



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

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



178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'app/models/serial_number.rb', line 178

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') do |f|
    f.write(pdf)
    f.flush
    f.fsync
  end
  upload = Upload.uploadify(path, 'super_serial_number_label_pdf')
  SerialNumber.where(id: serial_numbers.map(&: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:



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

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

Instance Method Details

#generate_barcodeObject



148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'app/models/serial_number.rb', line 148

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



166
167
168
169
170
171
172
173
174
175
176
# File 'app/models/serial_number.rb', line 166

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') do |f|
    f.write(pdf)
    f.flush
    f.fsync
  end
  Upload.uploadify(path, 'serial_number_label_pdf', self, file_name)
end

#item_ledger_entriesActiveRecord::Relation<ItemLedgerEntry>

Returns:

See Also:



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

has_and_belongs_to_many :item_ledger_entries

#label_file_nameObject



162
163
164
# File 'app/models/serial_number.rb', line 162

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:



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

has_and_belongs_to_many :line_items, dependent: :nullify

#number_and_qtyObject



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

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

#parent_serial_numberSerialNumber



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

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

#possible_eventsObject



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

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

#possible_events_for_selectObject



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

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

#possible_print_state_eventsObject



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

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

#possible_print_state_events_for_selectObject



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

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


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

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

#qty_availableObject



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

def qty_available
  qty - qty_committed
end

#qty_committedObject



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

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

#qty_reservedObject



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

def qty_reserved
  reserved_serial_numbers.sum(:qty)
end

#qty_unreservedObject



133
134
135
# File 'app/models/serial_number.rb', line 133

def qty_unreserved
  qty - qty_reserved
end

#rejoin(child_serial_number) ⇒ Object



143
144
145
146
# File 'app/models/serial_number.rb', line 143

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:



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

has_many :reserved_serial_numbers, dependent: :destroy

#shipment_receipt_itemShipmentReceiptItem



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

belongs_to :shipment_receipt_item, optional: true

#split(new_qty) ⇒ Object



137
138
139
140
141
# File 'app/models/serial_number.rb', line 137

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:



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

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

#state_events_for_selectObject



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

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

#store_itemStoreItem

Returns:

See Also:

Validations:



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

belongs_to :store_item, optional: true

#to_sObject



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

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