Created
July 25, 2017 13:12
-
-
Save j3ck/f0314656c15783ae5b736b6ad9844362 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Chesters | |
class Invoice | |
attr_accessor :number, :phone, :fax, :account_code, | |
:date, :payment_due, :sub_total, :total, | |
:gst, :sales_despatch, :sales_order, | |
:customer_order, :staff, :gst_no | |
attr_accessor :line_items | |
def initialize | |
@line_items = [] | |
end | |
end | |
class LineItem | |
attr_accessor :item_code, :description, :quantity, | |
:unit_amount, :price, :line_value, :list_price | |
end | |
class << self | |
def parse(file_path) | |
pdf_doc = PDF::Reader.new(file_path) | |
@invoices = [] | |
pdf_doc.pages.each do |page| | |
@invoice = Chesters::Invoice.new | |
clean_page_lines = page.text.split("\n").delete_if { |val| val == "" } | |
@table_start = false | |
@table_end = false | |
@table_meta_done = false | |
clean_page_lines.each do |line| | |
@invoice.date ||= invoice_date(line) | |
@invoice.number ||= invoice_number(line, @invoice.number) | |
@invoice.payment_due ||= payment_date(line) | |
@invoice.account_code ||= customer(line) | |
@invoice.gst_no ||= gst_number(line) | |
@invoice.phone ||= phone(line) | |
@invoice.fax ||= fax(line) | |
table_start?(line) | |
table_end?(line) | |
if @table_end | |
@invoice.sub_total ||= sub_total(line) | |
@invoice.gst ||= gst(line) | |
@invoice.total ||= total(line) | |
end | |
# break if @table_end | |
unless @invoice.total.nil? | |
@page_end = true | |
break | |
end | |
@invoice.sales_despatch ||= sales_despatch(line) if @table_start && !@table_meta_done | |
if @table_start && !@table_meta_done | |
table_meta(line, @invoice) | |
next if @table_meta_done | |
end | |
if @table_start && @table_meta_done && !@table_end | |
li = build_line_item(line) | |
@invoice.line_items << li if li | |
end | |
end | |
@invoices << @invoice | |
end | |
@invoices | |
end | |
private | |
def table_start?(line) | |
if line.include_each?(['Item', 'Description', 'Quantity', 'Unit', 'Unit Price', 'Line valu', 'List Price']) || | |
(!@table_start && line.include_each?(['Quantity Unit', 'Unit Price', 'Line value', 'List Price'])) | |
@table_start = true | |
return true | |
end | |
false | |
end | |
def table_end?(line) | |
if line.include? 'For paying by Direct Credit, our bank details are' | |
@table_end = true | |
return true | |
end | |
false | |
end | |
def table_meta(line, invoice) | |
return nil unless line.include_each? ['Sales order', 'Customer order', 'CreatedBy'] | |
params = line.split(/ {2,}/) | |
invoice.sales_order = params[1] | |
invoice.customer_order = params[3] | |
invoice.staff = params[5] | |
@table_meta_done = true | |
end | |
def compile(long, short) | |
str = long.dup | |
vals = short.strip.split(/ {2,}/) | |
vals.each do |val| | |
pos = short.index(val) | |
val.each_char do |chr| | |
str[pos] = chr | |
pos += 1 | |
end | |
end | |
str | |
end | |
def build_line_item(line) | |
values = line.strip.split(/ {2,}/) | |
if @tmp_line | |
new_line = line.size > @tmp_line.size ? compile(line, @tmp_line) : compile(@tmp_line, line) | |
values = new_line.strip.split(/ {2,}/) | |
@tmp_line = nil | |
end | |
if values.size < 6 && values.size > 1 | |
@tmp_line = line | |
return nil | |
end | |
return nil if values.size < 2 | |
line_item = Chesters::LineItem.new | |
line_item.item_code = values[0] | |
line_item.description = values[1] | |
line_item.quantity = values[2].split(' ').first | |
line_item.unit_amount = values[2].split(' ').last | |
line_item.price = values[3] | |
line_item.line_value = values[4] | |
line_item.list_price = values[5] | |
defined?(line_item) ? line_item : nil | |
end | |
def invoice_number(line, invoice_number) | |
line[/[0-9]+/] if line.include?('Tax Invoice Number') || | |
(invoice_number.nil? && | |
line.split(' ').size == 2 && | |
line[/ [A-Z]{2} /] && | |
line[/ [0-9]+/]) | |
end | |
def invoice_date(line) | |
line[/([0-9]{1,2}\/){2}[0-9]{4}/] if line[/Invoice date/i] | |
end | |
def payment_date(line) | |
line[/([0-9]{1,2}\/){2}[0-9]{4}/] if line.include? 'Payment due' | |
end | |
def customer(line) | |
line.split(' ').last if line.include? 'Customer' | |
end | |
def gst_number(line) | |
line[/[0-9]*-[0-9]*-[0-9]*/] if line.include? 'GST Number' | |
end | |
def phone(line) | |
line[/[0-9]{1} [0-9]{3} [0-9]{4}/] if line.include? 'Phone:' | |
end | |
def fax(line) | |
line[/[0-9]{1} [0-9]{3} [0-9]{4}/] if line.include? 'Fax:' | |
end | |
def sales_despatch(line) | |
line.split(' ').last if line.include? 'Sales despatch' | |
end | |
def sub_total(line) | |
line.split(' ').last(2).first if line.include?('Subtotal') | |
end | |
def gst(line) | |
line.split(' ').last(2).first if line.include?('GST') | |
end | |
def total(line) | |
line.split(' ').last(2).first if line.include?('Total') | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment