cleaned up code and DB schema
This commit is contained in:
parent
c0d85dd941
commit
9d2ca3fec9
130
invoice.rb
130
invoice.rb
|
@ -1,5 +1,4 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
require 'CSV'
|
|
||||||
require 'yaml'
|
require 'yaml'
|
||||||
require 'mysql2'
|
require 'mysql2'
|
||||||
require 'optparse'
|
require 'optparse'
|
||||||
|
@ -22,99 +21,109 @@ OptionParser.new do |opts|
|
||||||
end
|
end
|
||||||
end.parse!
|
end.parse!
|
||||||
|
|
||||||
db = Mysql2::Client.new(:host => DB_HOST, :username => DB_USER, :database => DB_DB)
|
class Transaction
|
||||||
|
def initialize(time, person, product, amount: 1)
|
||||||
YAML_BASE = {"author": "Christoffer Müller Madsen", "city": "Aarhus", "from": ["Falstersgade 18, 4. th", "8000 Aarhus C"], 'currency': 'DKK', 'commasep': true, 'lang': 'danish', 'seriffont': 'Linux Libertine', 'sansfont': 'Linux Biolinum', 'fontsize': '10pt', 'geometry': 'a4paper, left=43mm, right=43mm, top=51mm, bottom=17mm', 'closingnote': %Q[Overfør venligst det anførte beløb via MobilePay til følgende telefonnummer i løbet af de næste 14 dage:
|
|
||||||
|
|
||||||
+45 81 73 02 02
|
|
||||||
|
|
||||||
Med venlig hilsen
|
|
||||||
] }
|
|
||||||
|
|
||||||
Products = Hash.new
|
|
||||||
Names = Hash.new
|
|
||||||
Prices = Hash.new
|
|
||||||
|
|
||||||
# Initialize product and member hashses
|
|
||||||
db.query("SELECT * FROM products").each do |product|
|
|
||||||
id = product['id']
|
|
||||||
pretty_name = product['pretty_name']
|
|
||||||
price = product['price']
|
|
||||||
if Options[:verbose]
|
|
||||||
puts "Found product: #{id} => #{pretty_name}, #{price}"
|
|
||||||
end
|
|
||||||
Products[id] = pretty_name
|
|
||||||
Prices[id] = price
|
|
||||||
end
|
|
||||||
|
|
||||||
db.query("SELECT * FROM members").each do |member|
|
|
||||||
Names[member['id']] = member['name']
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
class LogItem
|
|
||||||
def initialize(time,person,product,amount: 1)
|
|
||||||
@time = time
|
@time = time
|
||||||
@person = person
|
@person = person
|
||||||
@product = product
|
@product = product
|
||||||
@amount = amount
|
@amount = amount
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_accessor :time, :person, :product, :amount
|
attr_accessor :time, :person, :product, :amount
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class Product
|
||||||
|
def initialize(id, description, price)
|
||||||
|
@id = id
|
||||||
|
@description = description
|
||||||
|
@price = price
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"#{@id} => #{@description}, #{@price}"
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_accessor :id, :description, :price
|
||||||
|
end
|
||||||
|
|
||||||
def read_file(file)
|
def read_file(file)
|
||||||
rows = Array.new
|
rows = Array.new
|
||||||
CSV.foreach(file, col_sep: ';', converters: :float) do |row|
|
CSV.foreach(file, col_sep: ';', converters: :float) do |row|
|
||||||
rows << LogItem.new(row[0],row[1],row[2],amount: row[3])
|
rows << Transaction.new(row[0],row[1],row[2],amount: row[3])
|
||||||
end
|
end
|
||||||
rows
|
rows
|
||||||
end
|
end
|
||||||
|
|
||||||
def read_db(db)
|
def read_db(db)
|
||||||
rows = Array.new
|
transactions = Array.new
|
||||||
db.query("SELECT * FROM transactions").each do |row|
|
db.query("SELECT * FROM Transactions").each do |trans|
|
||||||
if date_of_prev('monday').to_time < row["time"]
|
if date_of_prev('monday').to_time < trans["time"]
|
||||||
rows << LogItem.new(row["time"], row["buyer"], row["product"], amount: row["amount"])
|
transactions << Transaction.new(trans["time"], trans["buyer"],
|
||||||
|
trans["product"], amount: trans["amount"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rows
|
return transactions
|
||||||
end
|
end
|
||||||
|
|
||||||
def partition_rows(rows)
|
# Partition transactions into the persons who they belong to
|
||||||
skyldnere = Hash.new
|
def partition_transactions(transactions)
|
||||||
rows.each do |row|
|
persons = Hash.new
|
||||||
skyldnere[row.person] = Hash.new unless skyldnere[row.person]
|
transactions.each do |trans|
|
||||||
skyldnere[row.person][row.product] = 0 unless skyldnere[row.person][row.product]
|
# Initialize data structures if not already done
|
||||||
skyldnere[row.person][row.product] += row.amount
|
if !(persons[trans.person])
|
||||||
|
persons[trans.person] = {}
|
||||||
end
|
end
|
||||||
skyldnere
|
if !(persons[trans.person][trans.product])
|
||||||
|
persons[trans.person][trans.product] = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
persons[trans.person][trans.product] += trans.amount
|
||||||
|
end
|
||||||
|
|
||||||
|
return persons
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_receipt(skyldnere,draft)
|
def generate_receipt(persons,draft)
|
||||||
counter = 0
|
counter = 0
|
||||||
skyldnere.each do |person, products|
|
|
||||||
|
# Iterate through persons who have purchased something in the given timeframe
|
||||||
|
persons.each do |person, products|
|
||||||
counter += 1
|
counter += 1
|
||||||
|
|
||||||
yaml = YAML_BASE.clone
|
yaml = YAML_BASE.clone
|
||||||
yaml["to"] = Names[person]
|
yaml["to"] = Names[person]
|
||||||
products.each do |product, amount|
|
|
||||||
yaml["invoice-nr"] = Time.now.strftime('%Y%W') + "-" + counter.to_s
|
yaml["invoice-nr"] = Time.now.strftime('%Y%W') + "-" + counter.to_s
|
||||||
|
|
||||||
|
# Iterate through products purchased and write data to yaml hash
|
||||||
|
products.each do |id, amount|
|
||||||
yaml["service"] = Array.new unless yaml["service"]
|
yaml["service"] = Array.new unless yaml["service"]
|
||||||
hash = {description: Products[product], pieceprice: Prices[product].to_i, price: Prices[product].to_i*amount, amount: amount}
|
hash = {description: Products[id].description,
|
||||||
|
pieceprice: Products[id].price.to_i,
|
||||||
|
price: Products[id].price.to_i*amount, amount: amount}
|
||||||
|
|
||||||
|
# Convert Symbols to Strings to ensure compatibility with pandoc
|
||||||
yaml["service"] << Hash[hash.map{ |k, v| [k.to_s, v] }]
|
yaml["service"] << Hash[hash.map{ |k, v| [k.to_s, v] }]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Write draft watermark on invoice if marked as draft
|
||||||
if draft
|
if draft
|
||||||
yaml["draft"] = "true"
|
yaml["draft"] = "true"
|
||||||
yaml["drafttext"] = "Udkast"
|
yaml["drafttext"] = "Udkast"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Convert Symbols to Strings to ensure compatibility with pandoc
|
||||||
output = Hash[yaml.map{ |k, v| [k.to_s, v] }].to_yaml
|
output = Hash[yaml.map{ |k, v| [k.to_s, v] }].to_yaml
|
||||||
output += "---\n"
|
output += "---\n"
|
||||||
|
|
||||||
|
# Write output to file
|
||||||
File.open("./pandoc/details.yml","w") do |file|
|
File.open("./pandoc/details.yml","w") do |file|
|
||||||
file << output
|
file << output
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Generate PDF using pandoc
|
||||||
`cd pandoc/; make -B`
|
`cd pandoc/; make -B`
|
||||||
`cp pandoc/output.pdf #{OUTPUT_PATH}/#{yaml["invoice-nr"]}.pdf`
|
`cp pandoc/output.pdf #{OUTPUT_PATH}/#{yaml["invoice-nr"]}.pdf`
|
||||||
|
|
||||||
puts "#{person}: #{yaml["invoice-nr"]}.pdf" unless Options[:silent]
|
puts "#{person}: #{yaml["invoice-nr"]}.pdf" unless Options[:silent]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -133,5 +142,24 @@ def date_of_prev(day)
|
||||||
date - delta
|
date - delta
|
||||||
end
|
end
|
||||||
|
|
||||||
partition = partition_rows(read_db(db))
|
db = Mysql2::Client.new(:host => DB_HOST, :username => DB_USER, :database => DB_DB)
|
||||||
|
|
||||||
|
# Initialize product and member hashses
|
||||||
|
Products = Hash.new
|
||||||
|
Names = Hash.new
|
||||||
|
Prices = Hash.new
|
||||||
|
db.query("SELECT * FROM Products").each do |p|
|
||||||
|
product = Product.new(p['id'], p['description'], p['price'])
|
||||||
|
Products[p['id']] = product
|
||||||
|
|
||||||
|
if Options[:verbose]
|
||||||
|
puts "Found product: #{product}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
db.query("SELECT * FROM Persons").each do |member|
|
||||||
|
Names[member['id']] = member['name']
|
||||||
|
end
|
||||||
|
|
||||||
|
partition = partition_transactions(read_db(db))
|
||||||
generate_receipt(partition,Options[:draft])
|
generate_receipt(partition,Options[:draft])
|
||||||
|
|
|
@ -12,7 +12,7 @@ log_dir = "./log/"
|
||||||
amount = 1.0 unless amount
|
amount = 1.0 unless amount
|
||||||
|
|
||||||
valid_products = []
|
valid_products = []
|
||||||
db.query("SELECT * FROM products").each do |product|
|
db.query("SELECT * FROM Products").each do |product|
|
||||||
valid_products << product['id']
|
valid_products << product['id']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ unless valid_products.include? product
|
||||||
raise "Product not found in table\nValid products are: #{valid_products}"
|
raise "Product not found in table\nValid products are: #{valid_products}"
|
||||||
end
|
end
|
||||||
|
|
||||||
statement = db.prepare("INSERT INTO transactions (buyer, product, amount) VALUES (?, ?, ?)")
|
statement = db.prepare("INSERT INTO Transactions (buyer, product, amount) VALUES (?, ?, ?)")
|
||||||
result = statement.execute(person,product,amount)
|
result = statement.execute(person,product,amount)
|
||||||
puts result
|
puts result
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user