481 lines
20 KiB
Ruby
Executable File
481 lines
20 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
|
|
has_one :booking_order
|
|
has_one :booking, through: :booking_order
|
|
|
|
#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
|
|
#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.update_attributes(status:"occupied")
|
|
# 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(checkout_at: new_time)
|
|
end
|
|
end
|
|
#end extra time
|
|
end
|
|
|
|
self.default_values
|
|
|
|
# cashier already opened?
|
|
if self.save!
|
|
|
|
self.adding_line_items
|
|
#Add Order Table and Room relation afrer order creation
|
|
booking.orders << 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
|
|
booking.orders << 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
|
|
items = re_order_items(self.items)
|
|
#loop to add all items to order
|
|
item_instance_codes = items.map { |i| i[:item_instance_code] }
|
|
menu_items = MenuItem.search_by_item_code(item_instance_codes)
|
|
menu_items += Product.search_by_product_code(item_instance_codes) if menu_items.length < item_instance_codes.length
|
|
|
|
items.each do |order_item|
|
|
menu_item = menu_items.find { |i| i[:item_instance_code].downcase == order_item[:item_instance_code].downcase }
|
|
sub_order_items = []
|
|
if order_item[:sub_items].length > 0
|
|
sub_menu_items = MenuItem.search_by_item_code(order_item[:sub_items].map { |i| i[:item_instance_code] })
|
|
order_item[:sub_items].each do |sub_order_item|
|
|
sub_menu_item = sub_menu_items.find { |i| i[:item_instance_code] == sub_order_item[:item_instance_code] }
|
|
sub_order_items << { item_instance_code: sub_order_item[:item_instance_code], item_instance_name: sub_menu_item[:name], quantity: sub_order_item[:quantity], price: sub_menu_item[:price], options: sub_order_item[:options] }
|
|
end
|
|
end
|
|
sub_order_items = sub_order_items.to_json
|
|
self.order_items.build({
|
|
item_code: menu_item[:item_code],
|
|
item_instance_code: order_item[:item_instance_code],
|
|
item_name: menu_item[:name],
|
|
alt_name: menu_item[:alt_name],
|
|
account_id: menu_item[:account_id],
|
|
qty: order_item[:quantity],
|
|
price: menu_item[:price],
|
|
options: order_item[:options],
|
|
set_menu_items: sub_order_items,
|
|
item_order_by: employee_name,
|
|
taxable: menu_item[:taxable]
|
|
})
|
|
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?)
|
|
OrderItem.where({ order_items_id: '#{self.order_items.pluck(:order_items_id)}'}).update_all(order_item_status: "billed")
|
|
##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
|
|
OrderItem.where({ order_items_id: '#{items.pluck(:order_items_id)}'}).update_all(order_item_status: "billed")
|
|
# items.each do |item|
|
|
# item.order_item_status = "billed"
|
|
# item.save
|
|
# end
|
|
end
|
|
end
|
|
|
|
def default_values
|
|
self.customer = Customer.walkin 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(items) #reorder inputs items as parents and child
|
|
new_items = items.select { |i| i[:parent_order_item_id].blank? }.map { |x| x[:sub_items] = items.select { |y| x[:order_item_id] == y[:parent_order_item_id] }; x }
|
|
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 self.pay_process_order_queue(id,table_id)
|
|
# if ENV["SERVER_MODE"] != 'cloud'
|
|
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
|
|
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)
|
|
if ENV["SERVER_MODE"] == 'cloud'
|
|
from = request.subdomain + "." + request.domain
|
|
else
|
|
from = ""
|
|
end
|
|
ActionCable.server.broadcast "order_channel",table: table,type:type,from:from
|
|
|
|
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
|
|
if ENV["SERVER_MODE"] == 'cloud'
|
|
from = request.subdomain + "." + request.domain
|
|
else
|
|
from = ""
|
|
end
|
|
ActionCable.server.broadcast "second_display_channel",data: @data_array,status:@status,from:from
|
|
end
|
|
|
|
#Process order items and send to order queue
|
|
def self.process_order_queue(order_id,table_id,source)
|
|
print_status = nil
|
|
cup_status = nil
|
|
|
|
#Send to background job for processing
|
|
order = Order.find(order_id)
|
|
sidekiq = Lookup.find_by_lookup_type("sidekiq")
|
|
|
|
if ENV["SERVER_MODE"] != 'cloud'
|
|
if Printer::PrinterWorker.printers.blank?
|
|
msg = 'Print Error ! Please contact to service'
|
|
ActionCable.server.broadcast "call_waiter_channel", table: msg, time:'print_error', from: ''
|
|
end
|
|
end
|
|
|
|
if !sidekiq.nil?
|
|
OrderQueueProcessorJob.perform_later(order_id, table_id)
|
|
else
|
|
if order
|
|
oqs = OrderQueueStation.new
|
|
oqs.process_order(order, table_id, order_source)
|
|
end
|
|
from = getCloudDomain #get sub domain in cloud mode
|
|
assign_order = AssignedOrderItem.assigned_order_item_by_job(order_id)
|
|
ActionCable.server.broadcast "order_queue_station_channel", order: assign_order, from: from
|
|
end
|
|
end
|
|
|
|
def self.check_cup_status(status)
|
|
if status.include? "Active: active (running)" || "Active: active (exited)" #"Cup Server is already running"
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
def self.env
|
|
return ENV["SERVER_MODE"]
|
|
end
|
|
|
|
private
|
|
|
|
def generate_custom_id
|
|
if self.order_id.nil?
|
|
self.order_id = SeedGenerator.generate_id(self.class.name, "ODR")
|
|
end
|
|
end
|
|
|
|
def set_order_date
|
|
self.date = Time.now.utc
|
|
end
|
|
|
|
def self.sync_order_records(orders)
|
|
if !orders.nil?
|
|
orders.each do |o|
|
|
order = Order.find_by_order_id(o['order_id'])
|
|
# unless Order.exists?(o['order_id'])
|
|
if order.nil?
|
|
order = Order.new
|
|
end
|
|
order.order_id = o['order_id']
|
|
order.date = o['date']
|
|
order.source = o['source']
|
|
order.order_type = o['order_type']
|
|
order.customer_id = o['customer_id']
|
|
order.item_count = o['item_count']
|
|
order.quantity_count = o['quantity_count']
|
|
order.status = o['status']
|
|
order.waiters = o['waiters']
|
|
order.guest_info = o['guest_info']
|
|
order.save
|
|
end
|
|
Rails.logger.debug '...... order sync completed .....'
|
|
end
|
|
end
|
|
|
|
end
|