Files
sx-fc/app/models/order.rb
2018-03-16 09:42:56 +06:30

537 lines
22 KiB
Ruby
Executable File

class Order < ApplicationRecord
self.primary_key = "order_id"
#primary key - need to be unique
before_create :generate_custom_id
before_create :set_order_date
has_many :sale_orders
belongs_to :customer
has_many :order_items, autosave: true , inverse_of: :order
has_many :assigned_order_items
#internal references attributes for business logic control
attr_accessor :items, :guest, :table_id, :new_booking, :booking_type, :employee_name, :booking_id, :extra_time, :is_extra_time
scope :active, -> { where("date BETWEEN '#{DateTime.now.utc.end_of_day}' AND '#{DateTime.now.utc.beginning_of_day}'") }
#Main Controller method to create new order - validate all inputs and generate new order
# order_item : {
# order_item_code : "",
# item_instance_code : "",
# quantity : 0,
# option_values : [],
# sub_order_items : [],
# }
def generate
booking = nil
if self.new_booking
if self.table_id.to_i > 0
table_id = self.table_id
else
table_id = nil
end
#add extra time
if self.is_extra_time && self.extra_time
booking = Booking.create({:dining_facility_id => table_id,:type => "TableBooking",
:checkin_at => Time.now.utc,:checkout_at => Time.now.utc + self.extra_time.to_i,
:checkin_by => self.employee_name,
:booking_status => "assign" })
else
booking = Booking.create({:dining_facility_id => table_id,:type => "TableBooking",
:checkin_at => Time.now.utc, :checkin_by => self.employee_name,
:booking_status => "assign" })
end
#end extra time
if self.table_id.to_i > 0
table = DiningFacility.find(self.table_id)
table.status = "occupied"
table.save
end
else
booking = Booking.find(self.booking_id)
#add extra time
if self.is_extra_time
if !booking.checkout_at.nil?
new_time = booking.checkout_at + self.extra_time.to_i
booking.update_attributes(checkout_at: new_time)
end
end
#end extra time
end
booking.save!
self.default_values
# cashier already opened?
if self.save!
self.adding_line_items
#Add Order Table and Room relation afrer order creation
BookingOrder.create({:booking_id => booking.booking_id, :order => self})
#Send order to queue one it done!
if self.source != "quick_service"
process_order_queue
end
#send order to broadcast job
send_order_broadcast(booking)
return true, booking
end
return false
end
def custom_generate
booking = nil
if self.new_booking
booking = Booking.create({:dining_facility_id => self.table_id,:type => "TableBooking",
:checkin_at => Time.now.utc, :checkin_by => self.employee_name,
:booking_status => "assign" })
table = DiningFacility.find(self.table_id)
table.status = "occupied"
table.save
else
booking = Booking.find(self.booking_id)
end
booking.save!
self.default_values
# cashier already opened?
if self.save!
self.adding_line_items
#Add Order Table and Room relation afrer order creation
BookingOrder.create({:booking_id => booking.booking_id, :order => self})
#Send order to queue one it done!
if self.source != "quick_service"
process_order_queue
end
#send order to broadcast job
send_order_broadcast(booking)
return true, booking
end
return false
end
#Main Method - to update order / add items
def modify
end
def adding_line_items
if self.items
#re-order to
ordered_list = re_order_items(self.items)
#loop to add all items to order
ordered_list.each do |item|
menu_item = MenuItem.search_by_item_code(item[:item_instance_code])
# For Product while item code not in menu item
if menu_item.nil?
menu_item = Product.search_by_product_code(item[:item_instance_code])
end
#if (!menu_item.nil?)
Rails.logger.debug menu_item
set_order_items = Array.new
##If menu Item set item - must add child items to order as well, where price is only take from menu_item
if (menu_item[:type] == "SetMenuItem")
if (item.include? 'sub_items') || (item.include? :sub_items)
item[:sub_items].each do |si|
# Retrive instance's Price
set_item = MenuItem.search_by_item_code(si[:item_instance_code])
set_order_items.push({"item_instance_code"=>si[:item_instance_code], "item_instance_name"=>set_item[:name], "quantity"=>si[:quantity], "price"=>set_item[:price], "options"=>si[:options]})
end
end
set_order_items = set_order_items.to_json
else
set_order_items = nil
end
# not insert with price 0
# puts item[:price]
# puts item
# if(item[:price] != 0 )
# OrderItem.processs_item(menu_item[:item_code], menu_item[:name], menu_item[:account_id],
# item[:quantity],menu_item[:price], item[:options], set_order_items, self.id,
# self.employee_name)
# end
OrderItem.processs_item(menu_item[:item_code], item[:item_instance_code], menu_item[:name], menu_item[:alt_name], menu_item[:account_id],
item[:quantity],menu_item[:price], item[:options], set_order_items, self.id,
self.employee_name, menu_item[:taxable])
#end
end
self.item_count = self.order_items.count
self.save!
return true
else
self.errors.add(:order_items, :blank, message: "Order items cannot be blank")
return false
end
end
def update_items_status_to_billed(items)
if (items.nil?)
##Update the order status to ensure that reflect the stage
self.order_items.each do |item|
item.order_item_status = "billed"
item.save
end
else
items.each do |item|
item.order_item_status = "billed"
item.save
end
end
end
def default_values
self.customer = Customer.find(1) if self.customer_id.nil?
self.source = "emenu" if self.source.nil?
self.order_type = "dine-in" if self.order_type.nil?
end
protected
def re_order_items(form_items) #reorder inputs items as parents and child
parent_id = Array.new
parents = Array.new
parents_and_children_items = Array.new
new_items_list = Array.new
form_items.each do |parent|
if !parent[:parent_order_item_id].nil?
if (!parent_id.include?(parent[:parent_order_item_id]))
parent_id.push(parent[:parent_order_item_id])
end
end
end
Rails.logger.debug "Parent Id count -> " + parent_id.count.to_s
parent_id.each do |pid|
form_items.each do |item|
Rails.logger.debug "Adding - Parents -> " + pid.to_s + " - " + item[:order_item_id].to_s
if (pid == item[:order_item_id])
parents.push(item)
end
end
end
Rails.logger.debug "Parents count -> " + parents.count.to_s
parents.each do |parent|
children = Array.new
form_items.each do |item|
if (parent[:order_item_id] == item[:parent_order_item_id] )
children.push(item)
#Items to remove for new list
parents_and_children_items.push(item)
end
end
parent[:sub_items] = children
end
Rails.logger.debug "Parent/children Items to remove -> " + parents_and_children_items.count.to_s
#Remove process items
#c = a.reject{ |e| b.include? e }
new_items_list = form_items - parents_and_children_items
Rails.logger.debug "New list count -> " + new_items_list.count.to_s
#Add parent to the list
#new_items_list = new_items_list + parents
Rails.logger.debug "Re-Order List (Parent)-"
Rails.logger.debug parents
Rails.logger.debug "Re-Order List -"
Rails.logger.debug new_items_list
return new_items_list
end
#Update Items Count and Quantity changes whenever there is changes
def update_products_and_quantity_count
item_count = 0
quantity_count = 0
# Count number of different items
self.item_count = self.order_items.item_count
self.quantity_count = quantity_count
# Counter number of quantityf
end
#Process order items and send to order queue
def process_order_queue
#Send to background job for processing
order = Order.find(self.id)
cup_status = `#{"sudo service cups status"}`
print_status = check_cup_status(cup_status)
sidekiq = Lookup.find_by_lookup_type("sidekiq")
if print_status
if !sidekiq.nil?
OrderQueueProcessorJob.perform_later(self.id, self.table_id)
else
if order
oqs = OrderQueueStation.new
oqs.process_order(order, self.table_id)
end
assign_order = AssignedOrderItem.assigned_order_item_by_job(self.id)
ActionCable.server.broadcast "order_queue_station_channel",order: assign_order
end
else
cup_start = `#{"sudo service cups start"}`
cup_status = `#{"sudo service cups status"}`
print_status = check_cup_status(cup_status)
if print_status
if !sidekiq.nil?
OrderQueueProcessorJob.perform_later(self.id, self.table_id)
else
if order
oqs = OrderQueueStation.new
oqs.process_order(order, self.table_id)
end
assign_order = AssignedOrderItem.assigned_order_item_by_job(self.id)
ActionCable.server.broadcast "order_queue_station_channel",order: assign_order
end
else
msg = ' Print Error ! Please contact to service'
ActionCable.server.broadcast "call_waiter_channel",table: msg,time:'print_error'
if !sidekiq.nil?
OrderQueueProcessorJob.perform_later(self.id, self.table_id)
else
if order
oqs = OrderQueueStation.new
oqs.process_order(order, self.table_id)
end
assign_order = AssignedOrderItem.assigned_order_item_by_job(self.id)
ActionCable.server.broadcast "order_queue_station_channel",order: assign_order
end
end
end
end
#Process order items and send to order queue
def self.pay_process_order_queue(id,table_id)
sidekiq = Lookup.find_by_lookup_type("sidekiq")
if !sidekiq.nil?
OrderQueueProcessorJob.perform_later(id, table_id)
else
order = Order.find(id)
if order
oqs = OrderQueueStation.new
oqs.process_order(order, table_id)
end
assign_order = AssignedOrderItem.assigned_order_item_by_job(id)
ActionCable.server.broadcast "order_queue_station_channel",order: assign_order
end
end
def check_cup_status(status)
if status.include? "Active: active (running)" || "Active: active (exited)" #"Cup Server is already running"
return true
end
return false
end
#send order items and send to order queue
def send_order_broadcast(booking)
if self.table_id.to_i > 0
table = DiningFacility.find(booking.dining_facility_id)
type = 'order'
#Send to background job for processing
# OrderBroadcastJob.perform_later(table,type)
ActionCable.server.broadcast "order_channel",table: table,type:type
end
end
#Origami: Cashier : to view order Table
def self.get_order_table
order_table = Order.select("orders.order_id as order_id,sum(order_items.qty*order_items.price) as total_price,
order_items.order_items_id as order_items_id,dining_facilities.name as table_name")
.joins("left join booking_orders on booking_orders.order_id = orders.order_id
left join bookings on bookings.booking_id = booking_orders.booking_order_id
left join dining_facilities on dining_facilities.id = bookings.dining_facility_id
left join order_items on order_items.order_id = orders.order_id")
.where("dining_facilities.type=? and orders.order_type=? and dining_facilities.is_active=?",DiningFacility::TABLE_TYPE,"dine_in",true)
.group("orders.order_id, order_items.order_items_id,dining_facilities.name")
end
#Origami: Cashier : to view booking order Table
def self.get_booking_order_table
booking_orders = Booking.select("sales.receipt_no,orders.status as order_status, sales.sale_status as sale_status,
orders.order_id as order_id,sales.customer_id as sale_customer_id,orders.customer_id as order_customer_id,
bookings.booking_id,sales.sale_id as sale_id,dining_facilities.name as table_name")
.joins("left join booking_orders on booking_orders.booking_id = bookings.booking_id")
.joins("left join dining_facilities on dining_facilities.id = bookings.dining_facility_id")
.joins("left join orders on orders.order_id = booking_orders.order_id")
.joins("left join sales on sales.sale_id = bookings.sale_id")
.where("(orders.status = 'new' or orders.status = 'billed') and (dining_facilities.type=? and dining_facilities.is_active=?)",DiningFacility::TABLE_TYPE,true)
.group("bookings.booking_id,sales.receipt_no,orders.status,sales.sale_id,dining_facilities.name,orders.status,orders.order_id")
# For PG
# booking_orders.order_id IS NOT NULL and dining_facilities.type=? and dining_facilities.is_active=?",DiningFacility::TABLE_TYPE,true
# sales.receipt_no,orders.status,sales.sale_id,dining_facilities.name,orders.status,orders.order_id
end
#Origami: Cashier : to view booking order Table
def self.get_completed_order
completed_orders = Booking.select("sales.receipt_no, sales.sale_status, orders.status as order_status,orders.order_id,
bookings.booking_id,sales.sale_id as sale_id,dining_facilities.name as table_name,sales.customer_id as sale_customer_id,orders.customer_id as order_customer_id")
.joins("left join booking_orders on booking_orders.booking_id = bookings.booking_id")
.joins("left join dining_facilities on dining_facilities.id = bookings.dining_facility_id")
.joins("left join orders on orders.order_id = booking_orders.order_id")
.joins("left join sales on sales.sale_id = bookings.sale_id")
.where("sales.sale_status='completed'")
.group("sales.sale_id,bookings.booking_id,sales.receipt_no,orders.status,sales.sale_id,dining_facilities.name,orders.status,orders.order_id")
# For PG
#bookings.booking_id,sales.receipt_no,orders.status,sales.sale_id,dining_facilities.name,orders.status,orders.order_id
end
#Origami: Cashier : to view order type Room
def self.get_booking_order_rooms
booking_rooms = Booking.select("sales.receipt_no,orders.status as order_status, sales.sale_status as sale_status,
orders.order_id as order_id,sales.customer_id as sale_customer_id,orders.customer_id as order_customer_id,
bookings.booking_id,orders.customer_id as customer_id,
sales.sale_id as sale_id,dining_facilities.name as room_name")
.joins("left join booking_orders on booking_orders.booking_id = bookings.booking_id")
.joins("left join dining_facilities on dining_facilities.id = bookings.dining_facility_id")
.joins("left join orders on orders.order_id = booking_orders.order_id")
.joins("left join sales on sales.sale_id = bookings.sale_id")
.where("(orders.status = 'new' or orders.status = 'billed') and (dining_facilities.type=? and dining_facilities.is_active=?)",DiningFacility::ROOM_TYPE,true)
.group("bookings.booking_id,sales.receipt_no,orders.status,sales.sale_id,dining_facilities.name,orders.customer_id,orders.order_id")
# For PG
# booking_orders.order_id IS NOT NULL and dining_facilities.type=? and dining_facilities.is_active=?",DiningFacility::ROOM_TYPE,true
# sales.receipt_no,orders.status,sales.sale_id,dining_facilities.name,orders.customer_id,orders.order_id
end
#Origami: Cashier : to view order type Room
def self.get_order_rooms
order_rooms = Order.select("orders.order_id as order_id,sum(order_items.qty*order_items.price) as total_price,
order_items.id as order_items_id,dining_facilities.name as room_name")
.joins("left join booking_orders on booking_orders.order_id = orders.order_id
left join bookings on bookings.booking_id = booking_orders.order_id
left join dining_facilities on dining_facilities.id = bookings.dining_facility_id
left join order_items on order_items.order_id = orders.order_id")
.where("dining_facilities.type=? and orders.order_type=? and dining_facilities.is_active=?",DiningFacility::ROOM_TYPE,"dine_in",true)
.group("orders.order_id")
end
#Origami: Cashier : to view orders
def self.get_orders
from = Time.now.beginning_of_day.utc
to = Time.now.end_of_day.utc
orders=Booking.select("sales.receipt_no, sales.sale_status as sale_status, orders.status as order_status,
orders.order_id as order_id,sales.customer_id as sale_customer_id,orders.customer_id as order_customer_id,
bookings.booking_id,orders.customer_id as customer_id,
sales.sale_id as sale_id,dining_facilities.name as table_name")
.joins("left join booking_orders on booking_orders.booking_id = bookings.booking_id")
.joins("left join dining_facilities on dining_facilities.id = bookings.dining_facility_id")
.joins("left join orders on orders.order_id = booking_orders.order_id")
.joins("left join sales on sales.sale_id = bookings.sale_id")
.where("(orders.status = 'new' or orders.status = 'billed') AND orders.date between #{ from } and #{ to }")
# orders = Order.select("orders.order_id as order_id,sales.receipt_no,orders.status as order_status, sales.sale_status as sale_status,
# orders.order_id as order_id,sales.customer_id as sale_customer_id,orders.customer_id as order_customer_id
# ,bookings.booking_id,sales.sale_id as sale_id,dining_facilities.name as table_name")
# .joins("left join booking_orders on booking_orders.order_id = orders.order_id
# left join bookings on bookings.booking_id = booking_orders.order_id
# left join dining_facilities on dining_facilities.id = bookings.dining_facility_id
# left join order_items on order_items.order_id = orders.order_id
# left join sale_orders on sale_orders.order_id = orders.order_id
# left join sales on sales.sale_id = sale_orders.sale_id")
# .where("(orders.status = 'new' or orders.status = 'billed')")
# .group("orders.order_id")
# For PG
# .where("dining_facilities.is_active=? and orders.date between ? and ?",true,from,to)
# .group("orders.order_id,order_items.order_items_id,dining_facilities.name,sales.receipt_no,bookings.booking_id,sales.sale_id,orders.customer_id")
end
def self.search(filter,from,to)
if filter.blank?
keyword = ''
else
keyword = "order_id LIKE ? OR status LIKE ? OR order_type LIKE ? OR source='#{filter}'","%#{filter}%","%#{filter}%","%#{filter}%"
end
if from.present? && to.present?
order = Order.where("DATE_FORMAT(date,'%d-%m-%Y') >= ?" + " AND DATE_FORMAT(date,'%d-%m-%Y') <= ?", from,to)
query = order.where(keyword)
else
where("order_id LIKE ? OR status LIKE ? OR order_type LIKE ? OR source='#{filter}'","%#{filter}%","%#{filter}%","%#{filter}%")
end
end
def self.send_customer_view(booking)
@status = ""
@data_array = Array.new
if(!booking.sale_id.nil?)
sale = Sale.find(booking.sale_id)
if sale.sale_status != "completed" && sale.sale_status != 'void'
@data_array.push(sale)
@status = "sale"
@data_obj = sale
end
else
@status = "order"
booking.booking_orders.each do |booking_order|
@data_obj = Order.find(booking_order.order_id)
if (@data_obj.status == "new")
@data_obj.order_items.each do |item|
if !item.set_menu_items.nil?
instance_item_sets = JSON.parse(item.set_menu_items)
arr_instance_item_sets = Array.new
instance_item_sets.each do |instance_item|
item_instance_name = MenuItemInstance.find_by_item_instance_code(instance_item["item_instance_code"]).item_instance_name
arr_instance_item_sets.push(item_instance_name)
item.price = item.price.to_f + instance_item["price"].to_f
end
item.set_menu_items = arr_instance_item_sets
end
@data_array.push(item)
end
end
end
end
ActionCable.server.broadcast "second_display_channel",data: @data_array,status:@status
end
private
def generate_custom_id
self.order_id = SeedGenerator.generate_id(self.class.name, "ODR")
end
def set_order_date
self.date = Time.now.utc
end
end