class Sale < ApplicationRecord #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 has_many :sale_taxes has_many :sale_payments has_many :sale_orders scope :open_invoices, -> { where("sale_status = 'new' and receipt_date BETWEEN '#{DateTime.now.utc.end_of_day}' AND '#{DateTime.now.utc.beginning_of_day}'") } 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_id, sale_id, requested_by) taxable = true #if sale_id is exsit and validate #add order to that invoice if (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 order = Order.find(order_id) #Default - Values self.tax_type = "execlusive" self.requested_by = requested_by self.requested_at = DateTime.now.utc Rails.logger.debug "Order -> #{order.id} | order_status -> #{order.status}" if order self.customer_id = order.customer_id Rails.logger.debug "Order -> #{order.id} | Items Count -> #{order.order_items.count}" order.order_items.each do |item| add_item(item) end link_order_sale(order.id) end self.save! #compute summary compute #Update the order items that is billed order.update_items_status_to_billed(nil) return true, self.id end return false, nil end #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 def add_item (item) #check if the item is on promotion #save sale_audit sale_item = SaleItem.new #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 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 def update_item (item) #save sale_audit end def apply_item_discount (item_code, discount_type, discount_amount) end def apply_discount (discount_type, discount_code) #save action to sale_audit end def void_sales (void_by, reason, approval_code, request_by) #save sale_audit self.sale_status = "void" end #compute - invoice total def compute sales_items = self.sale_items #Computation Fields 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 (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 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 total_tax_amount = 0 #tax_profile - list by order_by tax_profiles = TaxProfile.all.order("order_by asc") #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_taxable * tax.rate #new taxable 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_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) #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 def adjust_rounding self.grand_total self.rounding_adjustment = 0.00 end #Generate new Receipt No when it is not assigned def generate_receipt_no #Date-Shift- if self.receipt_no.nil? prefix = DateTime.now().utc #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