From 9d2ca3fec96720a8b3b2639f3f864a7e4ad6c3b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoffer=20M=C3=BCller=20Madsen?= Date: Wed, 1 Feb 2017 12:37:43 +0100 Subject: [PATCH] cleaned up code and DB schema --- invoice.rb | 134 ++++++++++++++++++++++++++++++++--------------------- update.rb | 4 +- 2 files changed, 83 insertions(+), 55 deletions(-) diff --git a/invoice.rb b/invoice.rb index 79018db..5fd4947 100644 --- a/invoice.rb +++ b/invoice.rb @@ -1,5 +1,4 @@ # coding: utf-8 -require 'CSV' require 'yaml' require 'mysql2' require 'optparse' @@ -22,99 +21,109 @@ OptionParser.new do |opts| end end.parse! -db = Mysql2::Client.new(:host => DB_HOST, :username => DB_USER, :database => DB_DB) - -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) +class Transaction + def initialize(time, person, product, amount: 1) @time = time @person = person @product = product @amount = amount end + attr_accessor :time, :person, :product, :amount 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) rows = Array.new 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 rows end def read_db(db) - rows = Array.new - db.query("SELECT * FROM transactions").each do |row| - if date_of_prev('monday').to_time < row["time"] - rows << LogItem.new(row["time"], row["buyer"], row["product"], amount: row["amount"]) + transactions = Array.new + db.query("SELECT * FROM Transactions").each do |trans| + if date_of_prev('monday').to_time < trans["time"] + transactions << Transaction.new(trans["time"], trans["buyer"], + trans["product"], amount: trans["amount"]) end end - rows + return transactions end -def partition_rows(rows) - skyldnere = Hash.new - rows.each do |row| - skyldnere[row.person] = Hash.new unless skyldnere[row.person] - skyldnere[row.person][row.product] = 0 unless skyldnere[row.person][row.product] - skyldnere[row.person][row.product] += row.amount +# Partition transactions into the persons who they belong to +def partition_transactions(transactions) + persons = Hash.new + transactions.each do |trans| + # Initialize data structures if not already done + if !(persons[trans.person]) + persons[trans.person] = {} + end + if !(persons[trans.person][trans.product]) + persons[trans.person][trans.product] = 0 + end + + persons[trans.person][trans.product] += trans.amount end - skyldnere + + return persons end -def generate_receipt(skyldnere,draft) +def generate_receipt(persons,draft) 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 + yaml = YAML_BASE.clone 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"] - 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] }] end + # Write draft watermark on invoice if marked as draft if draft yaml["draft"] = "true" yaml["drafttext"] = "Udkast" end - + + # Convert Symbols to Strings to ensure compatibility with pandoc output = Hash[yaml.map{ |k, v| [k.to_s, v] }].to_yaml output += "---\n" + + # Write output to file File.open("./pandoc/details.yml","w") do |file| file << output end + + # Generate PDF using pandoc `cd pandoc/; make -B` `cp pandoc/output.pdf #{OUTPUT_PATH}/#{yaml["invoice-nr"]}.pdf` + puts "#{person}: #{yaml["invoice-nr"]}.pdf" unless Options[:silent] end end @@ -133,5 +142,24 @@ def date_of_prev(day) date - delta 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]) diff --git a/update.rb b/update.rb index c239d3c..b8cbadb 100644 --- a/update.rb +++ b/update.rb @@ -12,7 +12,7 @@ log_dir = "./log/" amount = 1.0 unless amount valid_products = [] -db.query("SELECT * FROM products").each do |product| +db.query("SELECT * FROM Products").each do |product| valid_products << product['id'] end @@ -20,7 +20,7 @@ unless valid_products.include? product raise "Product not found in table\nValid products are: #{valid_products}" 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) puts result