Created
July 2, 2015 06:49
-
-
Save klippx/70aa60403bf6ab5ef7bc to your computer and use it in GitHub Desktop.
1. Original version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A pouch order is ordered to a ward for a patient from a prescriber. These | |
# will be produces as pouches through the HD-Medi system. | |
class PouchOrder < ActiveRecord::Base | |
include Workflow | |
belongs_to :ward | |
belongs_to :patient | |
belongs_to :file, class_name: 'MachineFile', foreign_key: 'machine_file_id' | |
belongs_to :transport_label | |
has_one :replaced, class_name: 'PouchOrder', foreign_key: 'replacement_id' | |
belongs_to :replacement, class_name: 'PouchOrder', foreign_key: 'replacement_id' | |
has_many :lines, class_name: 'PouchOrderLine', foreign_key: 'pouch_order_id', inverse_of: :order, dependent: :destroy | |
has_many :interactions, dependent: :destroy | |
has_many :overdoses, dependent: :destroy | |
validates :ward, :patient, presence: true | |
validates :number, uniqueness: true | |
before_save :set_default_delivery_at, on: :create | |
before_save :calculate_and_set_lock_at, on: :create | |
scope :sent_to_machine, -> { where(status: 'sent_to_machine') } | |
delegate :ordering_deadlines, to: :ward | |
workflow_column :status | |
audited only: [:status], on: [:update], allow_mass_assignment: true | |
workflow do | |
state :new do | |
event :confirm_receiving, transitions_to: :received | |
end | |
state :received do | |
event :make_interaction, transitions_to: :interaction | |
event :make_dosage_control, transitions_to: :dosage_control | |
event :replace, transitions_to: :replaced | |
end | |
state :interaction do | |
event :make_dosage_control, transitions_to: :dosage_control | |
end | |
state :dosage_control do | |
event :confirm_dosage, transitions_to: :awaiting_approval | |
end | |
state :awaiting_approval do | |
event :approve, transitions_to: :approved | |
event :reject, transitions_to: :rejected | |
event :replace, transitions_to: :replaced | |
end | |
state :approved do | |
event :upload, transitions_to: :uploading | |
event :replace, transitions_to: :replaced | |
end | |
state :uploading do | |
event :uploaded, transitions_to: :sent_to_machine | |
end | |
state :sent_to_machine do | |
event :sort, transitions_to: :sorted | |
end | |
state :sorted do | |
event :ship, transitions_to: :shipped | |
end | |
state :shipped do | |
event :unship, transitions_to: :unshipped | |
end | |
state :unshipped do | |
event :ship, transitions_to: :shipped | |
end | |
state :rejected | |
state :replaced | |
on_transition do |from, to, triggering_event, *event_args| | |
write_audit( | |
action: 'update', | |
audited_changes: { | |
status: [from, to] | |
} | |
) | |
end | |
end | |
def self.from_attachment(attachment) | |
PouchOrder.new do |order| | |
order.number = attachment.header.order_number | |
order.phone_number = attachment.contact_telephone | |
order.issued_at = attachment.issued_at | |
order.delivery_at = attachment.delivery_at | |
parse_patient_for(order, attachment) | |
parse_ward_for(order, attachment) | |
parse_items_for(order, attachment) | |
end | |
end | |
def self.auto_approval_enabled? | |
Settings.pouch_order_auto_approval == "true" | |
end | |
def number | |
super || "apoex_#{self.id}".upcase | |
end | |
def loading_dock | |
ward.loading_dock | |
end | |
def contains_licensed_item? | |
lines.any? { |line| line.item.license_required? } | |
end | |
def suitable_transport_label | |
TransportLabel.with_open_state.where(ward: ward).order(:created_at).last | |
end | |
def dangerous_interactions? | |
interactions.any? { |i| i.dangerous? } | |
end | |
def unknown_interactions? | |
interactions.any? { |i| i.unknown? } | |
end | |
def make_interaction | |
Resque.enqueue(InteractionJob, self.id) | |
end | |
def make_dosage_control | |
Resque.enqueue(DosageControlJob, self.id) | |
end | |
def can_be_auto_approved? | |
return false unless PouchOrder.auto_approval_enabled? | |
!(self.contains_licensed_item? || self.interactions.any? || self.overdoses.any?) | |
end | |
def on_received_entry(new_state, event, *args) | |
if InteractionService.enabled? | |
self.make_interaction! | |
else | |
self.make_dosage_control! | |
end | |
end | |
def on_awaiting_approval_entry(new_state, event, *args) | |
self.approve! if can_be_auto_approved? | |
end | |
def sort(label) | |
label.orders << self | |
end | |
### Order lock time and replacement | |
def set_default_delivery_at | |
self.delivery_at ||= loading_dock.latest_delivery_time | |
end | |
def calculate_and_set_lock_at | |
delivery_time = self.delivery_at.dup | |
lock_time = ward.loading_dock.ordering_deadlines.for_delivery_time(delivery_time) | |
self.lock_at = delivery_time.change({ hour: lock_time.hour, min: lock_time.min, sec: lock_time.sec }) | |
end | |
def self.to_replace(order) | |
replaceable_at(order.issued_at) | |
.where.not(id: order.id) | |
.where.not(status: :replaced) | |
.find_by(patient: order.patient) | |
end | |
def self.replaceable_at(time = Time.now) | |
where("lock_at > ?", time) | |
end | |
def issued_in_time? | |
!self.locked_at?(self.issued_at) | |
end | |
def locked_at?(time = Time.now) | |
self.lock_at < time | |
end | |
def replace(order) | |
self.replacement = order | |
self.save! | |
end | |
private | |
def self.parse_patient_for(order, attachment) | |
patient = Patient.where(ssn: attachment.patient_ssn).first_or_initialize | |
patient.first_name = attachment.patient_first_name | |
patient.last_name = attachment.patient_last_name | |
order.patient = patient | |
end | |
def self.parse_ward_for(order, attachment) | |
ward = Ward.find_by_consignee_gln(attachment.delivery_customer_gln) | |
order.ward = ward | |
end | |
def self.parse_items_for(order, attachment) | |
attachment.items.group_by(&:periodic_start).each do |date, order_items_on_date| | |
intakes_on_date = order_items_on_date.flat_map(&:intakes) | |
intakes_on_date.group_by(&:time).each do |time_string, intake_on_time| | |
time = Time.parse(time_string) | |
admin_time = date.change({ hour: time.hour, min: time.min, sec: time.sec }) | |
intake_on_time.each do |intake| | |
order.lines.new do |line| | |
line.item = Item.find_by(npl_id: intake.item.npl_id) | |
line.prescriber_name = intake.item.prescriber_name | |
line.admin_time = admin_time | |
line.quantity = intake.quantity | |
end | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment