fixed conflict

This commit is contained in:
Nweni
2017-06-28 15:33:27 +06:30
254 changed files with 11596 additions and 2224 deletions

87
app/models/ability.rb Normal file
View File

@@ -0,0 +1,87 @@
class Ability
include CanCan::Ability
def initialize(user)
user ||= Employee.new
if user.role == "administrator"
can :manage, :all
elsif user.role == "manager"
can :manage, Menu
can :manage, MenuCategory
can :manage, MenuItemAttribute
can :manage, MenuItemInstance
can :manage, MenuItemOption
can :manage, SetMenuItem
can :manage, OrderQueueStation
can :manage, Zone
can :manage, CashierTerminal
can :manage, Employee
# can :manage, MembershipSetting
# can :manage, MembershipAction
# can :manage, PaymentMethodSetting
can :manage, TaxProfile
can :manage, PrintSetting
can :manage, Account
can :manage, Order
can :manage, Sale
can :manage, Customer
can :index, :dailysale
can :index, :saleitem
can :add_customer, Customer
can :update_sale_by_customer, Customer
can :index, :discount
can :create, :discount
can :show, :payment
can :create, :payment
can :reprint, :payment
can :move_dining, :movetable
can :moving, :movetable
can :move_dining, :moveroom
elsif user.role == "cashier"
can :read, Order
can :update, Order
can :read, Sale
can :update, Sale
can :add_customer, Customer
can :update_sale_by_customer, Customer
can :index, :discount
can :create, :discount
can :show, :payment
can :create, :payment
can :reprint, :payment
can :move_dining, :movetable
can :moving, :movetable
can :move_dining, :moveroom
elsif user.role == "accountant"
can :index, :dailysale
can :index, :saleitem
can :index, :receiptno
can :show, :dailysale
can :show, :saleitem
can :show, :receiptno
end
end
end

View File

@@ -9,6 +9,37 @@ class Booking < ApplicationRecord
belongs_to :sale, :optional => true
has_many :booking_orders
has_many :orders, :through => :booking_orders
scope :active, -> {where("booking_status != 'moved'")}
def self.update_dining_facility(booking_arr, newd, old)
table = DiningFacility.find(newd)
exist = table.get_booking
if exist
# order exists
booking_arr.each do |booking|
booking.dining_facility_id = newd
booking.booking_status = 'moved'
booking.save
booking.booking_orders.each do |bo|
bo.booking_id = exist.booking_id
bo.save
end
end
else
# new table
booking_arr.each do |booking|
booking.dining_facility_id = newd
booking.save
end
end
new_dining = DiningFacility.find(newd)
new_dining.make_occupied
old_dining = DiningFacility.find(old)
old_dining.make_available
return new_dining.type
end
private
def generate_custom_id

View File

@@ -1,5 +1,5 @@
class BookingOrder < ApplicationRecord
#primary key - need to be unique
#primary key - need to be unique
belongs_to :booking
belongs_to :order

View File

@@ -6,9 +6,10 @@ class Customer < ApplicationRecord
has_many :orders
has_many :sales
validates_presence_of :name, :contact_no, :email
validates_presence_of :name, :contact_no, :email,:card_no
validates :contact_no, uniqueness: true
validates :email, uniqueness: true
validates :card_no, uniqueness: true
paginates_per 50
@@ -33,55 +34,55 @@ class Customer < ApplicationRecord
end
return response;
end
def self.get_membership_transactions(customer)
membership = MembershipSetting.find_by_membership_type("paypar_url")
memberaction = MembershipAction.find_by_membership_type("get_member_transactions")
merchant_uid = memberaction.merchant_account_id.to_s
auth_token = memberaction.auth_token.to_s
url = membership.gateway_url.to_s + memberaction.gateway_url.to_s
# urltest =self.url_exist?(url)
begin
response = HTTParty.get(url, :body => { membership_id: customer.membership_id,merchant_uid:merchant_uid,auth_token:auth_token}.to_json,
:headers => {
'Content-Type' => 'application/json',
'Accept' => 'application/json'
},
:timeout => 10
)
rescue Net::OpenTimeout
response = { status: false }
end
return response;
end
def self.search(search)
if search
# find(:all, :conditions => ['name LIKE ? OR contact_no LIKE ?', "%#{search}%", "%#{search}%"])
where("name LIKE ? OR contact_no LIKE ?", "%#{search}%", "%#{search}%",)
where("name LIKE ? OR contact_no LIKE ? OR card_no LIKE ?", "%#{search}%", "%#{search}%", "%#{search}%",)
else
find(:all)
end
end
# require "net/http"
# def self.url_exist?(url_string)
# url = URI.parse(url_string)
# req = Net::HTTP.new(url.host, url.port)
# puts "hhhhhhhhhhhh"
# puts req.to_json
# req.use_ssl = (url.scheme == 'https')
# puts "aaaaaaaaaaaa"
# puts req.use_ssl?
# path = url.path if url.path.present?
# puts "bbbbbbbbbbbbb"
# puts path
# res = req.request_head(path || '/')
# puts "cccccccccccccc"
# puts res.to_json
# puts "ddddddddd"
# puts res.kind_of?(Net::HTTPRedirection)
# if res.kind_of?(Net::HTTPRedirection)
# url_exist?(res['location']) # Go after any redirect and make sure you can access the redirected URL
# else
# ! %W(4 5).include?(res.code[0]) # Not from 4xx or 5xx families
# end
# rescue Errno::ENOENT
# false #false if can't find the server
# end
# def self.search(search)
# where("name LIKE ? OR contact_no LIKE ?", "%#{search}%", "%#{search}%",)
# end
def lastest_invoices
sales.where(:customer_id => self.id).order("created_at desc").limit(5)
end
def self.count_customer
all = self.all.count+1
count = all-2
end
WALKIN = "CUS-000000000001"
TAKEAWAY = "CUS-000000000002"
private
def generate_custom_id
self.customer_id = SeedGenerator.generate_id(self.class.name, "CUS")

View File

@@ -8,12 +8,32 @@ class DiningFacility < ApplicationRecord
scope :active, -> {where(is_active: true)}
def make_available
self.status = 'available'
self.save
end
def make_occupied
self.status = 'occupied'
self.save
end
def get_booking
booking = self.get_current_booking
if booking
if booking.dining_facility_id.to_i == self.id
if booking.booking_status == 'assign'
return booking
end
end
end
end
def get_current_booking
puts "enter booking"
booking = Booking.where("dining_facility_id = #{self.id} and booking_status ='assign' and checkin_at between '#{DateTime.now.utc - 5.hours}' and '#{DateTime.now.utc}' and checkout_at is null").limit(1)
booking = Booking.where("dining_facility_id = #{self.id} and booking_status ='assign' and checkin_at between '#{DateTime.now.utc - 5.hours}' and '#{DateTime.now.utc}' and checkout_at is null").limit(1)
if booking.count > 0 then
return booking[0].booking_id
return booking[0]
else
return nil
end
@@ -21,10 +41,10 @@ class DiningFacility < ApplicationRecord
def get_new_booking
# query for new
# if status
# if status
# to ask when req bill booking_status?
booking = Booking.where("dining_facility_id = #{self.id} and booking_status ='assign' and sale_id is null and checkout_at is null").limit(1)
# else
# else
# booking = Booking.where("dining_facility_id = #{self.id} and booking_status ='assign' and sale_id not null").limit(1)
# end

View File

@@ -6,6 +6,10 @@ class Employee < ApplicationRecord
validates :emp_id, uniqueness: true, numericality: true, length: {in: 1..4}, allow_blank: true
validates :password, numericality: true, length: {in: 3..9}, allow_blank: true
def self.all_emp_except_waiter
Employee.where('role!=?','waiter')
end
def self.collection
Employee.select("id, name").map { |e| [e.name, e.id] }
end
@@ -13,9 +17,9 @@ class Employee < ApplicationRecord
def self.login(emp_id, password)
user = Employee.find_by_emp_id(emp_id)
if (user)
user.authenticate(password)
#user.authenticate(password)
if (user)
if (user.authenticate(password))
user.generate_token
user.session_expiry = DateTime.now.utc + 30.minutes
user.session_last_login = DateTime.now.utc

View File

@@ -24,6 +24,7 @@ class MenuItem < ApplicationRecord
if (!mt_instance.nil?)
menu_item = MenuItem.find(mt_instance.menu_item_id)
menu_item_hash[:type] = menu_item.type
menu_item_hash[:account_id] = menu_item.account_id
menu_item_hash[:item_code] = menu_item.item_code
menu_item_hash[:item_instance_code] = mt_instance.item_instance_code
menu_item_hash[:name] = menu_item.name.to_s + " - " + mt_instance.item_instance_name.to_s

View File

@@ -4,14 +4,14 @@ class Order < ApplicationRecord
#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
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 : "",
@@ -27,7 +27,7 @@ class Order < ApplicationRecord
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,
:checkin_at => Time.now.utc.getlocal, :checkin_by => self.employee_name,
:booking_status => "assign" })
table = DiningFacility.find(self.table_id)
table.status = "occupied"
@@ -82,7 +82,16 @@ class Order < ApplicationRecord
set_order_items
end
OrderItem.processs_item(menu_item[:item_code], menu_item[:name],
# 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], menu_item[:name], menu_item[:account_id],
item[:quantity],menu_item[:price], item[:options], set_order_items, self.id,
self.employee_name)

View File

@@ -20,12 +20,13 @@ class OrderItem < ApplicationRecord
# option_values : [],
# sub_order_items : [],
# }
def self.processs_item (item_code, menu_name, qty,price, options, set_menu_items, order_id, item_order_by)
def self.processs_item (item_code, menu_name, account_id, qty,price, options, set_menu_items, order_id, item_order_by)
orderitem = OrderItem.create do |oitem|
oitem.order_id = order_id
oitem.item_code = item_code
oitem.item_name = menu_name
oitem.account_id = account_id
oitem.qty = qty
oitem.price = price
oitem.options = options

View File

@@ -16,37 +16,76 @@ class OrderQueueStation < ApplicationRecord
oqpbz = OrderQueueProcessByZone.find_by_zone_id(dining.zone_id)
order_items = order.order_items
# get dining
booking = Booking.find_by_dining_facility_id(dining.id)
#Assign OQS id to order Items
oqs_stations.each do |oqs|
oqs_stations.each do |oqs|
is_auto_printed = false
oqs_order_items = []
#Get List of items -
pq_items = JSON.parse(oqs.processing_items)
#Loop through the processing items
#Loop through the processing items
pq_items.each do |pq_item|
#Processing through the looping items
order_items.each do |order_item|
if (pq_item == order_item.item_code)
if oqs.id == oqpbz.order_queue_station_id
#Same Order_items can appear in two location.
AssignedOrderItem.assigned_order_item(order, order_item.item_code, oqs)
end
# if oqs.id == oqpbz.order_queue_station_id
# #Same Order_items can appear in two location.
# AssignedOrderItem.assigned_order_item(order, order_item.item_code, oqs)
# else
if (order_item.price != 0)
AssignedOrderItem.assigned_order_item(order, order_item.item_code, oqs)
oqs_order_items.push(order_item)
end
# end
end
end
end
# Auto Printing
# ToDo per item per printer
if oqs.auto_print && is_auto_printed == false
if oqs_order_items.length > 0
print_slip(oqs, order, oqs_order_items)
is_auto_printed = true
end
end
end
#Print OQS where printing is require
end
private
#Print order_items in 1 slip
def print_slip
def print_slip(oqs, order, order_items)
unique_code="OrderSummaryPdf"
print_settings=PrintSetting.find_by_unique_code(unique_code)
order_queue_printer= Printer::OrderQueuePrinter.new(print_settings)
order_queue_printer.print_order_summary(oqs,order.order_id, order_items, print_status="")
AssignedOrderItem.where("order_id = '#{ order.order_id }'").find_each do |ai|
# update print status for order items
ai.print_status=true
ai.save
end
end
#Print order_items in 1 slip per item
def print_slip_item
#Print order_item in 1 slip per item
def print_slip_item(oqs, assigned_order_item)
unique_code="OrderItemPdf"
# print when complete click
print_settings=PrintSetting.find_by_unique_code(unique_code)
order_queue_printer= Printer::OrderQueuePrinter.new(print_settings)
order_queue_printer.print_order_item(oqs,item.order_id, item.item_code, print_status="" )
# update print status for completed same order items
assigned_order_item.each do |ai|
ai.print_status=true
ai.save
end
end
end

View File

@@ -0,0 +1,2 @@
class PaymentJournal < ApplicationRecord
end

View File

@@ -1,66 +1,145 @@
class Printer::OrderQueuePrinter < Printer::PrinterWorker
def print_order_item(oqs,order_id, item_code)
def print_order_item(oqs,order_id, item_code, print_status, options="")
#Use CUPS service
#Generate PDF
#Print
order_item= print_query('order_item', item_code) #OrderItem.find_by_item_code(item_code)
pdf = OrderItemPdf.new(order_item[0])
pdf.render_file "tmp/receipt.pdf"
if oqs.print_copy
self.print("tmp/receipt.pdf", oqs.printer_name)
self.print("tmp/receipt.pdf", oqs.printer_name)
else
self.print("tmp/receipt.pdf", oqs.printer_name)
end
order_item = print_query('order_item', item_code) #OrderItem.find_by_item_code(item_code)
filename = "tmp/order_item_#{order_item[0].item_name}" + ".pdf"
# check for item not to show
if order_item[0].price != 0
pdf = OrderItemPdf.new(order_item[0], print_status, options)
pdf.render_file filename
if oqs.print_copy
self.print(filename, oqs.printer_name)
#For print copy
pdf.render_file filename.gsub(".","-copy.")
self.print(filename.gsub(".","-copy."), oqs.printer_name)
else
self.print(filename, oqs.printer_name)
end
end
end
def print_order_summary(oqs,order_id)
# Query for per order
def print_order_summary(oqs, order_id, order_items, print_status)
#Use CUPS service
#Generate PDF
#Print
order=print_query('order_summary',order_id)
#Print
order=print_query('order_summary', order_id)
# For Print Per Item
if oqs.cut_per_item
order.each do|odi|
pdf = OrderItemPdf.new(odi)
pdf.render_file "tmp/receipt.pdf"
if oqs.print_copy
self.print("tmp/receipt.pdf", oqs.printer_name)
self.print("tmp/receipt.pdf", oqs.printer_name)
else
self.print("tmp/receipt.pdf", oqs.printer_name)
order_items.each do|odi|
filename = "tmp/order_item_#{odi.item_name}" + ".pdf"
# For Item Options
options = odi.options == "[]"? "" : odi.options
# check for item not to show
if odi.price != 0 || odi.price != 10
pdf = OrderItemPdf.new(odi, print_status, options)
# pdf.render_file "tmp/order_item.pdf"
pdf.render_file filename
if oqs.print_copy
self.print(filename, oqs.printer_name)
self.print(filename.gsub(".","-copy."), oqs.printer_name)
else
self.print(filename, oqs.printer_name)
end
end
end
# For Print Order Summary
else
filename = "tmp/order_summary_#{order_id}" + ".pdf"
pdf = OrderSummaryPdf.new(order)
filename = "tmp/order_summary_#{ order_id }" + ".pdf"
pdf = OrderSummaryPdf.new(order, print_status, order_items)
pdf.render_file filename
self.print(filename, oqs.printer_name)
if oqs.print_copy
self.print(filename, oqs.printer_name)
#For print copy
pdf.render_file filename.gsub(".","-copy.")
self.print(filename.gsub(".","-copy."), oqs.printer_name)
else
self.print(filename, oqs.printer_name)
end
end
end
# Print for orders in booking
def print_booking_summary(oqs, booking_id, print_status)
order=print_query('booking_summary', booking_id)
# For Print Per Item
if oqs.cut_per_item
order.each do|odi|
filename = "tmp/order_item_#{odi.item_name}" + ".pdf"
# For Item Options
options = odi.options == "[]"? "" : odi.options
# check for item not to show
if odi.price != 0
pdf = OrderItemPdf.new(odi, print_status, options)
pdf.render_file filename
if oqs.print_copy
self.print(filename, oqs.printer_name)
#For print copy
pdf.render_file filename.gsub(".","-copy.")
self.print(filename.gsub(".","-copy."), oqs.printer_name)
else
self.print(filename, oqs.printer_name)
end
end
end
# For Print Order Summary
else
filename = "tmp/booking_summary_#{ booking_id }" + ".pdf"
pdf = OrderSummaryPdf.new(order, print_status)
pdf.render_file filename
if oqs.print_copy
self.print(filename, oqs.printer_name)
#For print copy
pdf.render_file filename.gsub(".","-copy.")
self.print(filename.gsub(".","-copy."), oqs.printer_name)
else
self.print(filename, oqs.printer_name)
end
end
end
# Query for OQS with status
def print_query(type, code)
if type == 'order_item'
OrderItem.select("order_items.item_code, order_items.item_name, order_items.qty, order_items.price, order_items.item_order_by as order_by, order_items.created_at as order_at, cus.name as customer, df.name as dining")
def print_query(type, id)
if type == "order_item"
OrderItem.select("order_items.order_id, order_items.item_code, order_items.item_name, order_items.qty, order_items.price, order_items.options, order_items.item_order_by as order_by, order_items.created_at as order_at, cus.name as customer, df.type, df.name as dining")
.joins("left join orders ON orders.order_id = order_items.order_id
left join booking_orders AS bo ON bo.order_id=order_items.order_id
left join bookings AS b ON b.booking_id = bo.booking_id
left join dining_facilities AS df ON df.id = b.dining_facility_id
left join customers as cus ON cus.customer_id = orders.customer_id")
.where("order_items.item_code='" + code + "'")
.where("order_items.item_code = '#{ id }' AND order_items.price != 0")
.group("order_items.item_code")
else
OrderItem.select("order_items.item_code, order_items.item_name, order_items.qty, order_items.price, order_items.item_order_by as order_by, order_items.created_at as order_at, cus.name as customer, df.name as dining")
elsif type == "order_summary"
OrderItem.select("order_items.order_id, order_items.item_code, order_items.item_name, order_items.qty, order_items.price, order_items.options, order_items.item_order_by as order_by, order_items.created_at as order_at, cus.name as customer, df.type, df.name as dining")
.joins("left join orders ON orders.order_id = order_items.order_id
left join booking_orders AS bo ON bo.order_id=order_items.order_id
left join bookings AS b ON b.booking_id = bo.booking_id
left join dining_facilities AS df ON df.id = b.dining_facility_id
left join customers as cus ON cus.customer_id = orders.customer_id")
.where("orders.order_id='" + code + "'")
.group("order_items.item_code")
.where("orders.order_id = '#{ id }' AND order_items.price != 0")
.group("order_items.order_items_id")
else
# order summary for booking
OrderItem.select("order_items.order_id, order_items.item_code, order_items.item_name, order_items.qty, order_items.price, order_items.options, order_items.item_order_by as order_by, order_items.created_at as order_at, cus.name as customer, df.type, df.name as dining")
.joins("left join orders ON orders.order_id = order_items.order_id
left join booking_orders AS bo ON bo.order_id=order_items.order_id
left join bookings AS b ON b.booking_id = bo.booking_id
left join dining_facilities AS df ON df.id = b.dining_facility_id
left join customers as cus ON cus.customer_id = orders.customer_id")
.where("b.booking_id = '#{ id }' AND order_items.price != 0")
end
end

View File

@@ -65,11 +65,11 @@ class Printer::ReceiptPrinter < Printer::PrinterWorker
end
#Bill Receipt Print
def print_receipt_bill(printer_settings,sale_items,sale_data, customer_name, food_total, beverage_total, member_info = nil)
def print_receipt_bill(printer_settings,sale_items,sale_data, customer_name, item_price_by_accounts, member_info = nil,rebate_amount=nil,shop_details)
#Use CUPS service
#Generate PDF
#Print
pdf = ReceiptBillPdf.new(printer_settings, sale_items, sale_data, customer_name, food_total, beverage_total, member_info)
pdf = ReceiptBillPdf.new(printer_settings, sale_items, sale_data, customer_name, item_price_by_accounts, member_info,rebate_amount,shop_details)
pdf.render_file "tmp/receipt_bill.pdf"
self.print("tmp/receipt_bill.pdf")

View File

@@ -1,3 +1,4 @@
class Room < DiningFacility
has_many :bookings, :foreign_key => 'dining_facility_id'
end

View File

@@ -15,6 +15,15 @@ class Sale < ApplicationRecord
has_many :bookings
scope :open_invoices, -> { where("sale_status = 'new' and receipt_date BETWEEN '#{DateTime.now.utc.end_of_day}' AND '#{DateTime.now.utc.beginning_of_day}'") }
scope :complete_sale, -> { where("sale_status = 'completed' and receipt_date BETWEEN '#{DateTime.now.utc.beginning_of_day}' AND '#{DateTime.now.utc.end_of_day}'") }
REPORT_TYPE = {
"daily" => 0,
"monthly" => 1,
"yearly" => 2
}
SALE_STATUS_OUTSTANDING = "outstanding"
SALE_STATUS_COMPLETED = "completed"
def generate_invoice_from_booking(booking_id, requested_by)
booking = Booking.find(booking_id)
@@ -24,7 +33,6 @@ class Sale < ApplicationRecord
Rails.logger.debug "Booking -> Booking Order Count -> " + booking.booking_orders.count.to_s
#get all order attached to this booking and combine into 1 invoice
puts booking.booking_orders.length
booking.booking_orders.each do |order|
if booking.sale_id
status, sale_id = generate_invoice_from_order(order.order_id, nil, booking, requested_by)
@@ -90,6 +98,8 @@ class Sale < ApplicationRecord
order.save
booking.sale_id = self.id
booking.checkout_at = Time.now.utc.getlocal
booking.checkout_by = requested_by.name
booking.save
return true, self.id
@@ -105,7 +115,7 @@ class Sale < ApplicationRecord
def generate_invoice_by_items (items, requested_by)
taxable = true
self.requested_by = requested_by
self.requested_at = DateTime.now.utc
self.requested_at = DateTime.now.utc.getlocal
items.each do |item|
add_item(item)
@@ -131,6 +141,7 @@ class Sale < ApplicationRecord
#pull
sale_item.product_code = item.item_code
sale_item.product_name = item.item_name
sale_item.account_id = item.account_id
sale_item.remark = item.remark
sale_item.qty = item.qty
@@ -174,7 +185,7 @@ class Sale < ApplicationRecord
sales_items.each do |item|
#compute each item and added to total
subtotal_price = subtotal_price + item.price
total_taxable = total_taxable + item.taxable_price
total_taxable = total_taxable + (item.taxable_price * item.qty)
end
apply_tax (total_taxable)
@@ -188,11 +199,41 @@ class Sale < ApplicationRecord
end
def compute_without_void
sales_items = self.sale_items
#Computation Fields
subtotal_price = 0
total_taxable = 0
rounding_adjustment = 0
sales_items.each do |item|
if item.remark != 'void'
#compute each item and added to total
subtotal_price = subtotal_price + item.price
total_taxable = total_taxable + item.taxable_price
end
end
apply_tax (total_taxable)
self.total_amount = subtotal_price
self.total_discount = total_discount
self.grand_total = (self.total_amount - self.total_discount) + self.total_tax
#compute rounding adjustment
adjust_rounding
self.save!
end
# Tax Calculate
def apply_tax(total_taxable)
#if tax is not apply create new record
# self.sale_taxes.each do |existing_tax|
# #delete existing and create new
# existing_tax.delete
# end
#if tax is not apply create new record
self.sale_taxes.each do |existing_tax|
SaleTax.where("sale_id='#{self.sale_id}'").find_each do |existing_tax|
#delete existing and create new
existing_tax.delete
end
@@ -275,6 +316,93 @@ class Sale < ApplicationRecord
end
end
def self.daily_sales_list(from,to)
payments_total = Sale.select("CAST((CONVERT_TZ(sales.receipt_date,'+00:00','+06:30')) AS DATE) as sale_date,
SUM(case when (sale_payments.payment_method='mpu') then sale_payments.payment_amount else 0 end) as mpu_amount,
SUM(case when (sale_payments.payment_method='master') then sale_payments.payment_amount else 0 end) as master_amount,
SUM(case when (sale_payments.payment_method='visa') then sale_payments.payment_amount else 0 end) as visa_amount,
SUM(case when (sale_payments.payment_method='jcb') then sale_payments.payment_amount else 0 end) as jcb_amount,
SUM(case when (sale_payments.payment_method='paypar') then sale_payments.payment_amount else 0 end) as paypar_amount,
SUM(case when (sale_payments.payment_method='cash') then sale_payments.payment_amount else 0 end) as cash_amount,
SUM(case when (sale_payments.payment_method='credit') then sale_payments.payment_amount else 0 end) as credit_amount,
SUM(case when (sale_payments.payment_method='foc') then sale_payments.payment_amount else 0 end) as foc_amount")
.joins("join (select * from sale_payments group by sale_payments.sale_id, sale_payments.payment_method) sale_payments on sale_payments.sale_id = sales.sale_id")
.where("sale_status = ? AND sales.receipt_date between ? and ? AND total_amount != 0", 'completed', from, to)
.group("DATE_FORMAT((CONVERT_TZ(sales.receipt_date,'+00:00','+06:30')),'%Y-%m-%d')")
daily_total = Array.new
payments_total.each do |pay|
sale_date = pay.sale_date
diff_time = payments_total.first.sale_date.beginning_of_day.utc - from
diff = diff_time % 86400
from_date = sale_date.beginning_of_day.utc - diff
to_date = sale_date.end_of_day.utc - diff
total_sale = Sale.select("IFNULL(SUM(case when (sale_status='completed') then grand_total else 0 end),0) as grand_total,
IFNULL(SUM(case when (sale_status='completed') then total_discount else 0 end),0) as total_discount,
IFNULL(SUM(case when (sale_status='void') then grand_total else 0 end),0) as void_amount,
IFNULL(SUM(case when (sale_status='completed') then rounding_adjustment else 0 end),0) as rounding_adj")
.where("(sale_status = ? OR sale_status = ?) AND receipt_date between ? and ? AND total_amount != 0", 'completed', 'void', from_date, to_date)
total_sale.each do |sale|
grand_total = sale.grand_total
total_discount = sale.total_discount
void_amount = sale.void_amount
total = {:sale_date => pay.sale_date,
:mpu_amount => pay.mpu_amount,
:master_amount => pay.master_amount,
:visa_amount => pay.visa_amount,
:jcb_amount => pay.jcb_amount,
:paypar_amount => pay.paypar_amount,
:cash_amount => pay.cash_amount,
:credit_amount => pay.credit_amount,
:foc_amount => pay.foc_amount,
:total_discount => total_discount,
:grand_total => grand_total,
:void_amount => void_amount,
:rounding_adj => sale.rounding_adj}
daily_total.push(total)
end
end
return daily_total
end
def self.get_by_range_by_saleitems(from,to,status,report_type)
query = Sale.select("
mi.item_code as code,(SUM(i.qty) * i.unit_price) as grand_total,
SUM(i.qty) as total_item," +
" i.unit_price as unit_price,
mi.name as product_name,
mc.name as menu_category_name,
mc.id as menu_category_id ")
.group('mi.id')
.order("mi.menu_category_id")
query = query.joins("JOIN sale_items i ON i.sale_id = sales.sale_id
JOIN menu_items mi ON i.product_code = mi.item_code" +
" JOIN menu_categories mc ON mc.id = mi.menu_category_id
JOIN employees ea ON ea.id = sales.cashier_id")
query = query.where("receipt_date between ? and ? and sale_status=?",from,to,status)
case report_type.to_i
when REPORT_TYPE["daily"]
return query
when REPORT_TYPE["monthly"]
return query.group("MONTH(date)")
when REPORT_TYPE["yearly"]
return query.group("YEAR(date)")
end
end
private
def generate_custom_id

View File

@@ -30,37 +30,66 @@ class SaleItem < ApplicationRecord
# end
end
# Calculate food total and beverage total
def self.calculate_food_beverage(sale_items)
food_prices=0
beverage_prices=0
def self.calculate_price_by_accounts(sale_items)
price_accounts = []
Account.all.each do |a|
account_price = {:name => a.title, :price => 0}
sale_items.each do |si|
food_price, beverage_price = self.get_price(si.sale_item_id)
food_prices = food_prices + food_price
beverage_prices = beverage_prices + beverage_price
sale_items.each do |si|
if si.account_id == a.id
account_price[:price] = account_price[:price] + si.price
end
end
price_accounts.push(account_price)
end
return food_prices, beverage_prices
return price_accounts
end
# Calculate rebate_by_account
def self.calculate_rebate_by_account(sale_items)
rebateacc = Account.where("rebate=?",true)
puts "Account that can rebate"
rebateacc.each do |i|
puts i.title
end
prices=0
sale_items.each do |si|
price = self.get_rebate_price(si.sale_item_id,rebateacc)
prices = prices + price
end
return prices
end
# get food price or beverage price for item
def self.get_price(sale_item_id)
food_price=0
beverage_price=0
def self.get_rebate_price(sale_item_id,rebateacc)
price=0
item=SaleItem.select("sale_items.price , menu_items.account_id")
.joins("left join menu_items on menu_items.item_code = sale_items.product_code")
.where("sale_items.sale_item_id=?", sale_item_id.to_s)
if item[0].account_id == 1
food_price = item[0].price
else
beverage_price = item[0].price
rebateacc.each do |i|
if item[0].account_id == i.id
price = item[0].price
end
end
return food_price, beverage_price
return price
end
# def self.get_overall_discount(sale_id)
# price = 0.0
# item=SaleItem.where("product_code=?", sale_id)
#
# item.each do|i|
# price += i.price
# end
#
# return price
# end
private
def generate_custom_id
self.sale_item_id = SeedGenerator.generate_id(self.class.name, "SLI")

View File

@@ -9,7 +9,6 @@ class SalePayment < ApplicationRecord
attr_accessor :received_amount, :card_payment_reference, :voucher_no, :giftcard_no, :customer_id, :external_payment_status
def process_payment(invoice, action_by, cash_amount, payment_method)
self.sale = invoice
self.received_amount = cash_amount
amount_due = invoice.grand_total
@@ -28,7 +27,7 @@ class SalePayment < ApplicationRecord
when "cash"
payment_status = cash_payment
when "creditnote"
if !self.customer_id.nil?
if !self.sale.customer_id.nil?
payment_status = creditnote_payment(self.customer_id)
end
when "visa"
@@ -55,7 +54,7 @@ class SalePayment < ApplicationRecord
remark = "Payment #{payment_method}- for Invoice #{invoice.receipt_no} Due [#{amount_due}]| pay amount -> #{cash_amount} | Payment Status ->#{payment_status}"
sale_audit = SaleAudit.record_payment(invoice.id, remark, action_by)
return true, self.sale
return true, self.save
else
#record an payment in sale-audit
remark = "No outstanding Amount - Grand Total [#{invoice.grand_total}] | Due [#{amount_due}] | Paid [#{invoice.amount_received}]"
@@ -66,34 +65,52 @@ class SalePayment < ApplicationRecord
end
def self.get_paypar_account(url,token,membership_id,campaign_type_id,merchant_uid,auth_token)
def self.get_paypar_account(url,token,membership_id,campaign_type_id,merchant_uid,auth_token)
# Control for Paypar Cloud
begin
response = HTTParty.get(url,
:body => { app_token: token,membership_id:membership_id,campaign_type_id:campaign_type_id,merchant_uid:merchant_uid,auth_token:auth_token}.to_json,
:headers => {
'Content-Type' => 'application/json',
'Accept' => 'application/json'
}
)
return response;
:body => { app_token: token,membership_id:membership_id,campaign_type_id:campaign_type_id,merchant_uid:merchant_uid,auth_token:auth_token}.to_json,
:headers => {
'Content-Type' => 'application/json',
'Accept' => 'application/json'
}, :timeout => 10
)
rescue Net::OpenTimeout
response = { status: false }
end
return response;
end
def self.redeem(paypar_url,token,membership_id,received_amount,sale_id)
membership_actions_data = MembershipAction.find_by_membership_type("redeem");
if !membership_actions_data.nil?
url = paypar_url.to_s + membership_actions_data.gateway_url.to_s
merchant_uid = membership_actions_data.merchant_account_id
auth_token = membership_actions_data.auth_token
campaign_type_id = membership_actions_data.additional_parameter["campaign_type_id"]
sale_data = Sale.find_by_sale_id(sale_id)
if sale_data
response = HTTParty.post(url,
:body => { generic_customer_id:membership_id,redeem_amount:received_amount,receipt_no:sale_data.receipt_no,campaign_type_id:campaign_type_id,account_no:"",merchant_uid:merchant_uid,auth_token:auth_token}.to_json,
:headers => {
'Content-Type' => 'application/json',
'Accept' => 'application/json'
}
)
others = 0
sale_data.sale_payments.each do |sale_payment|
others = others + sale_payment.payment_amount
end
redeem_prices = sale_data.grand_total - others
# Control for Paypar Cloud
begin
response = HTTParty.post(url,
:body => { generic_customer_id:membership_id,total_amount: redeem_prices,total_sale_transaction_amount: sale_data.grand_total,redeem_amount:received_amount,receipt_no:sale_data.receipt_no,campaign_type_id:campaign_type_id,account_no:"",merchant_uid:merchant_uid,auth_token:auth_token}.to_json,
:headers => {
'Content-Type' => 'application/json',
'Accept' => 'application/json'
},
:timeout => 10
)
rescue Net::OpenTimeout
response = false
end
else
response = false;
end
@@ -119,13 +136,12 @@ class SalePayment < ApplicationRecord
end
def creditnote_payment(customer_id)
payment_status = false
self.payment_method = "creditnote"
self.payment_amount = self.received_amount
self.customer_id = self.customer_id
self.outstanding_amount = 0 - self.received_amount
self.outstanding_amount = 0 - self.received_amount.to_f
self.payment_status = "outstanding"
payment_method = self.save!
@@ -187,17 +203,17 @@ class SalePayment < ApplicationRecord
payment_status = false
#Next time - validate if the vochure number is valid - within
self.payment_method = "paypar"
self.payment_amount = self.received_amount
self.payment_reference = self.voucher_no
self.outstanding_amount = self.sale.grand_total.to_f - self.received_amount.to_f
self.payment_status = "pending"
payment_method = self.save!
customer_data = Customer.find_by_customer_id(self.sale.customer_id)
membership_setting = MembershipSetting.find_by_membership_type("paypar_url")
membership_data = SalePayment.redeem(membership_setting.gateway_url,membership_setting.auth_token,customer_data.membership_id,self.received_amount,self.sale.sale_id)
if membership_data["status"]==true
self.payment_method = "paypar"
self.payment_amount = self.received_amount
self.payment_reference = self.voucher_no
self.outstanding_amount = self.sale.grand_total.to_f - self.received_amount.to_f
self.payment_status = "pending"
payment_method = self.save!
SalePayment.where(:sale_payment_id => self.sale_payment_id).update_all(:payment_status => 'paid')
sale_update_payment_status(self.received_amount.to_f)
@@ -216,11 +232,19 @@ class SalePayment < ApplicationRecord
self.sale.amount_changed = self.sale.amount_received.to_f - self.sale.grand_total.to_f
all_received_amount = 0.0
sObj = Sale.find(self.sale_id)
is_credit = 0
sObj.sale_payments.each do |spay|
all_received_amount += spay.payment_amount.to_f
if spay.payment_method == "creditnote"
is_credit = 1
end
end
if (self.sale.grand_total <= all_received_amount)
self.sale.payment_status = "paid"
if is_credit == 0
self.sale.payment_status = "paid"
else
self.sale.payment_status = "outstanding"
end
self.sale.sale_status = "completed"
self.sale.save!
table_update_status(sObj)
@@ -230,10 +254,19 @@ class SalePayment < ApplicationRecord
end
def table_update_status(sale_obj)
booking = Booking.find_by_sale_id(sale_obj.id)
status = true
booking = Booking.find_by_sale_id(sale_obj.id)
if booking
table = DiningFacility.find(booking.dining_facility_id)
if table
bookings = table.bookings
bookings.each do |tablebooking|
if tablebooking.booking_status != 'moved'
if tablebooking.sale.sale_status != 'completed'
status = false
end
end
end
if status
table.status = "available"
table.save
end
@@ -241,7 +274,8 @@ class SalePayment < ApplicationRecord
end
def rebat(sObj)
food_prices, beverage_prices = SaleItem.calculate_food_beverage(sObj.sale_items)
rebate_prices = SaleItem.calculate_rebate_by_account(sObj.sale_items)
generic_customer_id = sObj.customer.membership_id
if generic_customer_id != nil || generic_customer_id != "" || generic_customer_id != 0
paypar = sObj.sale_payments
@@ -251,7 +285,10 @@ class SalePayment < ApplicationRecord
payparcost = payparcost + pp.payment_amount
end
end
total_amount = food_prices - payparcost
# overall_dis = SaleItem.get_overall_discount(sObj.id)
overall_dis = sObj.total_discount
total_amount = rebate_prices - payparcost + overall_dis
if total_amount > 0
receipt_no = sObj.receipt_no
membership = MembershipSetting.find_by_membership_type("paypar_url")
@@ -261,8 +298,9 @@ class SalePayment < ApplicationRecord
auth_token = memberaction.auth_token.to_s
url = membership.gateway_url.to_s + memberaction.gateway_url.to_s
# Control for Paypar Cloud
begin
response = HTTParty.post(url, :body => { generic_customer_id:generic_customer_id ,merchant_uid:merchant_uid,total_amount: total_amount,campaign_type_id: campaign_type_id,
response = HTTParty.post(url, :body => { generic_customer_id:generic_customer_id ,total_sale_transaction_amount: sObj.grand_total,merchant_uid:merchant_uid,total_amount: total_amount,campaign_type_id: campaign_type_id,
receipt_no: receipt_no,auth_token:auth_token}.to_json,
:headers => {
'Content-Type' => 'application/json',
@@ -271,8 +309,8 @@ class SalePayment < ApplicationRecord
rescue Net::OpenTimeout
response = { status: false }
end
puts response.to_json
return response
# puts response.to_json
end
end
end

View File

@@ -5,6 +5,10 @@ class SaleTax < ApplicationRecord
before_create :generate_custom_id
belongs_to :sale
def self.get_tax(from,to)
query = SaleTax.select("sale_taxes.tax_name,SUM(sale_taxes.tax_payable_amount) as tax_amount").joins("join sales on sales.sale_id = sale_taxes.sale_id").where("sale_status = ? AND sales.receipt_date between ? and ? AND total_amount != 0", 'completed', from, to).group("sale_taxes.tax_name")
end
private
def generate_custom_id
self.sale_tax_id = SeedGenerator.generate_id(self.class.name, "STI")

51
app/models/shift_sale.rb Normal file
View File

@@ -0,0 +1,51 @@
#Description
#total_revenue = sum of all sub-total from sales table
#total_discounts = sum of all discount (overall) from sales tables
#total_taxes = sum of all taxes from sales table (Service + Goverment Tax (commercial_taxes))
#grand_total = total_revenue - total_discounts + total_taxes
#nett_sales = grand_total - commercial_taxes
#cash_sales = cash payment total revenue
#credit_sales = credit payment total revenue
#others_sales = [Sum of each of other payment type --- mpu, jcb, visa,master, rebate, vochure]
#commercial_taxes = Total Goverment tax due
#cash_in = Payment receive
#Cash_out = Payment issues for misc payments
class ShiftSale < ApplicationRecord
belongs_to :cashier_terminal
belongs_to :employee
def self.current_open_shift(current_user)
#if current_user
#find open shift where is open today and is not closed and login by current cashier
today_date = DateTime.now.strftime("%Y-%m-%d")
shift = ShiftSale.where("TO_CHAR(shift_started_at, 'YYYY-MM-DD')=? and shift_started_at is not null and shift_closed_at is null and employee_id = #{current_user.id}",today_date).take
return shift
#end
end
def create(opening_balance,current_user)
self.cashier_terminal_id = CashierTerminal.first.id
self.shift_started_at = DateTime.now
self.employee_id = current_user.id
self.opening_balance = opening_balance
self.save
end
def update(sale)
saleobj = Sale.find(sale)
self.total_revenue = self.total_revenue + saleobj.total_amount
self.total_discounts = self.total_discounts + saleobj.total_discount
self.total_taxes = self.total_taxes + saleobj.total_tax
self.grand_total = self.grand_total + saleobj.grand_total
# self.nett_sales =
# self.cash_sales =
# self.credit_sales =
# self.other_sales =
# self.commercial_taxes =
self.save
end
end

View File

@@ -1,4 +1,4 @@
class Table < DiningFacility
has_many :dining_ins
has_many :bookings, :foreign_key => 'dining_facility_id'
end

View File

@@ -1,3 +1,2 @@
class TableBooking < Booking
end