sale receipt generation and bill api

This commit is contained in:
Min Zeya Phyo
2017-04-17 13:09:54 +06:30
parent 3e9a2a0ce7
commit 6a84a34a9f
15 changed files with 177 additions and 71 deletions

View File

@@ -1,7 +1,9 @@
class Api::ApiController < ActionController::API
include TokenVerification
helper_method :current_token
helper_method :current_token, :current_login_employee
private
#this is base api base controller to need to inherit.
#all token authentication must be done here
#response format must be set to JSON
@@ -10,4 +12,8 @@ class Api::ApiController < ActionController::API
return token
end
end
def current_login_employee
@employee = Employee.find_by_token_session(current_token)
end
end

View File

@@ -1,10 +1,21 @@
class Api::Restaurant::BillController < Api::ApiController
class Api::BillController < Api::ApiController
#Create invoice based on booking
#Output and invoice
def create
@status = false
@error_message = "Order ID or Booking ID is require to request for a bill."
#create Bill by Booking ID
if (params[:booking_id])
@sale = Sale.new
@sale.generate_invoice_from_booking(params[:booking_id], current_login_employee.name)
elsif (params[:order_id])
@sale = Sale.new
@sale.generate_invoice_from_order(params[:order_id], current_login_employee.name)
end
end

View File

@@ -20,6 +20,7 @@ class MenuItem < ApplicationRecord
menu_item_hash[:promotion_price] = mt_instance.promotion_price
menu_item_hash[:is_on_promotion] = mt_instance.is_on_promotion
menu_item_hash[:is_available] = mt_instance.is_available
menu_item_hash[:taxable] = menu_item.taxable
return menu_item_hash
end

View File

@@ -70,7 +70,7 @@ class Order < ApplicationRecord
if (menu_item)
OrderItem.processs_item(menu_item[:item_instance_code], menu_item[:name],
item[:qty], item[:options], set_order_items, self.id,
item[:qty],item[:price], item[:options], set_order_items, self.id,
self.employee_name)
end
end
@@ -86,6 +86,20 @@ class Order < ApplicationRecord
end
def update_items_status_to_billed(items)
if (items)
##Update the order status to ensure that reflect the stage
order.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?

View File

@@ -15,14 +15,15 @@ class OrderItem < ApplicationRecord
# option_values : [],
# sub_order_items : [],
# }
def self.processs_item (item_code, menu_name, qty, options, set_menu_items, order_id, item_order_by)
def self.processs_item (item_code, menu_name, 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.qty = qty
oitem.options = options
oitem.price = price
oitem.options = options
oitem.set_menu_items = set_menu_items
oitem.item_order_by = item_order_by #person who order this. * If emenu - it will be login user on the app
end

View File

@@ -1,7 +1,7 @@
class Sale < ApplicationRecord
before_create :generate_receipt_no
belongs_to :cashier
belongs_to :customer
#before_create :generate_receipt_no
belongs_to :cashier, :optional => true
belongs_to :customer, :optional => true
has_many :sale_items
has_many :sale_discount_items
has_many :sale_discounts
@@ -9,32 +9,93 @@ class Sale < ApplicationRecord
has_many :sale_payments
has_many :sale_orders
def generate_invoice_from_order (order_no, sale_id)
def generate_invoice_from_booking(booking_id, requested_by)
booking = Booking.find(booking_id)
status = false
Rails.logger.debug "Booking -> " + booking.id.to_s
if (booking)
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
booking.booking_orders.each do |order|
if booking.sale_id
status, sale_id = generate_invoice_from_order(order.order_id, nil, requested_by)
else
status, sale_id = generate_invoice_from_order(order.order_id, booking.sale_id, requested_by)
end
booking.sale_id = sale_id
end
return status
end
end
def generate_invoice_from_order (order_no, sale_id, requested_by)
taxable = true
#if sale_id is exsit and validate
#add order to that invoice
if (sale_id)
self = Sale.find(sale_id)
self.find(sale_id)
end
Rails.logger.debug "Does it have Existing Sale -> [#{self.id.to_s}] - Status [#{self.sale_status}]"
if self.sale_status == "void"
return false, "Invoice is void. Cannot be edited"
else
#if this is new sale generate_receipt_no
generate_receipt_no
#Default - Values
self.tax_type = "execlusive"
self.requested_by = requested_by
self.requested_at = DateTime.now.utc
order = Order.find(order_no)
Rails.logger.debug "Order -> #{order.id} | order_status -> #{order.status}"
if order
Rails.logger.debug "Order -> #{order.id} | Items Count -> #{order.order_items.count}"
order.order_items.each do |item|
self.sale_items.add(add_item(item))
add_item(item)
end
end
link_order_sale(order.id)
return self.save!
self.save!
#compute summary
compute
#Update the order items that is billed
order.update_items_status_to_billed
return true, self.id
end
return false, nil
end
def generate_invoice_by_items (items)
#This is when spilt bill is request - then we cannot link order to invoice
#Cos there will be multiple orders - and items are spilt from there.
#Unless order is spilt by then it is possible.
def generate_invoice_by_items (items, requested_by)
taxable = true
self.requested_by = requested_by
self.requested_at = DateTime.now.utc
items.each do |item|
add_item(item)
#this will result in multiple orders belonging in multiple invoices - because of spilt invoices.
link_order_sale(item.order_id, taxable)
end
#Update item status as billed
order.update_items_status_to_billed(items)
status = self.save!
return status, self.id
end
@@ -43,11 +104,20 @@ class Sale < ApplicationRecord
#save sale_audit
sale_item = SaleItem.new
sale_item.sale = self
#pull
sale_item.product_code = item.item_code
sale_item.product_name = item.item_name
sale_item.remark = item.remark
sale_item.qty = item.qty
return sale_item
sale_item.unit_price = item.price
sale_item.taxable_price = item.price
sale_item.is_taxable = item.taxable
sale_item.price = sale_item.qty * sale_item.unit_price
self.sale_items << sale_item
end
@@ -56,7 +126,8 @@ class Sale < ApplicationRecord
end
def apply_item_discount (promotion_id, item)
def apply_item_discount (item_code, discount_type, discount_amount)
end
def apply_discount (discount_type, discount_code)
@@ -64,15 +135,12 @@ class Sale < ApplicationRecord
end
def accept_payment (payment_method, amount, payment_ref, payment_external_result)
end
def void_sales (void_by, reason, approval_code, request_by)
#save sale_audit
self.sale_status = "void"
self.
end
#compute - invoice total
@@ -80,65 +148,87 @@ class Sale < ApplicationRecord
sales_items = self.sale_items
#Computation Fields
total_items_price = 0
total_discounts = 0
subtotal_price = 0
total_taxable = 0
rounding_adjustment = 0
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
end
apply_tax
apply_tax (total_taxable)
self.total_amount = subtotal_price
self.total_discount = total_discount
self.save!
end
def apply_tax
def apply_tax(total_taxable)
#if tax is not apply create new record
self.sale_taxes.each |existing_tax|
self.sale_taxes.each do |existing_tax|
#delete existing and create new
existing_tax.delete
end
total_tax_amount = 0
#tax_profile - list by order_by
tax_profiles = TaxProfile.all.order("order_by asc")
total_amount = self.total_amount
#Creat new tax records
tax_profiles.each do |tax|
sale_tax = SaleTax.new(:sale => self)
sale_tax.tax_name = tax.name
sale_tax.tax_rate = tax.rate
#include or execulive
sale_tax.tax_payable_amount = total_amount * tax.rate
sale_tax.tax_payable_amount = total_taxable * tax.rate
#new taxable amount
total_amount = total_amount + sale_tax.tax_payable_amount
total_taxable = total_taxable + sale_tax.tax_payable_amount
sale_tax.inclusive = tax.inclusive
sale_tax.save
total_tax_amount = total_tax_amount + sale_tax.tax_payable_amount
end
self.total_tax = total_tax_amount
end
private
def product_get_unit_price(item.item_code)
menu_instance_code = MenuInstanceCode.find_by_item_instance_code(item.item_code)
def product_get_unit_price(item_code)
menu_item_hash =MenuItem.search_by_item_code(item_code)
if (menu_instance_code)
return menu_ item_hash[:item_instance_code], menu_item_hash[:price]
end
return nil,nil
end
def link_order_sale(order.id)
def link_order_sale(order_id)
#create if it doesn't exist
if (SaleOrder.where("sale_id = #{self.id} and order_id=#{order_id}").nil?)
SaleOrder.create(:sale_id => self.id, :order_id => order_id)
end
#dosomrting here
#puts Time.now.format(":short")
end
#Generate new Receipt No when it is not assigned
def generate_receipt_no
#Date-Shift-
if !self.receipt_no.nil?
prefix = Date.now()
self.receipt_no = prefix.to_s + "/" + self.shit_id.to_s + "/" + SeedGenerator.new_receipt_no().to_s
if self.receipt_no.nil?
prefix = DateTime.now()
#self.receipt_no = prefix.to_s + "/" + self.shit_id.to_s + "/" + SeedGenerator.new_receipt_no().to_s
self.receipt_no = prefix.strftime("%Y%m%d") + "/" + SeedGenerator.new_receipt_no().to_s
self.receipt_date = prefix
Rails.logger.debug "Receipt No #{self.receipt_no} | Date #{ self.receipt_date.to_s}"
end
end
end

View File

@@ -1,3 +0,0 @@
class SaleDiscountItem < ApplicationRecord
belongs_to :sale
end

View File

@@ -0,0 +1,7 @@
if @status == true
#show invoice number and stuff
json.status @status
else
json.status @status
json.error_message @error_message
end