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 '#{Time.current.utc.end_of_day}' AND '#{Time.current.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.current, :checkout_at => Time.current + 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.current, :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.current, :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' order = Order.find(id) sidekiq = Lookup.find_by_lookup_type("sidekiq") if !sidekiq.nil? OrderQueueProcessorJob.perform_later(id, table_id) else 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.current.beginning_of_day.utc to = Time.current.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 BETWEEN ? AND ?", 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, source) end assign_order = AssignedOrderItem.assigned_order_item_by_job(order_id) ActionCable.server.broadcast "order_queue_station_channel", order: assign_order 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.current 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 def self.send_message(phone, order_id,shop_name) url = "http://smspoh.com/api/http/send?key=5QfyN0OtGsFXnOqwtpVAGZCyPGP28nbX_Nm_oPsUw2ybq714T_951ycz3Ypl5URA&message=Your order "+order_id.to_s+" is ready to pick up ,thanks from "+shop_name.to_s+"&recipients="+ phone.to_s begin @result = HTTParty.get(url.to_str) rescue HTTParty::Error response = {status: false, message: "Can't open membership server "} rescue Net::OpenTimeout response = { status: false , message: "Can't open membership server "} rescue OpenURI::HTTPError response = { status: false, message: "Can't open membership server "} rescue SocketError response = { status: false, message: "Can't open membership server "} end end end